From e66ce4f37f98af2e23c800c7dc6fd8fc83d07353 Mon Sep 17 00:00:00 2001
From: Victor Chahuneau <vchahune@cs.cmu.edu>
Date: Sun, 23 Dec 2012 23:07:31 +0100
Subject: Memory mapping for IntList/FloatList

+ vocabulary class for DataArray & BiLex
---
 python/src/sa/_sa.c              | 15865 +++++++++++++++++++------------------
 python/src/sa/_sa.pxd            |    16 +-
 python/src/sa/_sa.pyx            |     2 +
 python/src/sa/alignment.pxi      |    21 +-
 python/src/sa/bilex.pxi          |   148 +-
 python/src/sa/data_array.pxi     |    84 +-
 python/src/sa/float_list.pxi     |    24 +-
 python/src/sa/int_list.pxi       |    81 +-
 python/src/sa/mmap.pxi           |    53 +
 python/src/sa/precomputation.pxi |    55 +-
 python/src/sa/rulefactory.pxi    |     8 +-
 python/src/sa/suffix_array.pxi   |    26 +-
 python/src/sa/vocabulary.pxi     |    64 +
 13 files changed, 8648 insertions(+), 7799 deletions(-)
 create mode 100644 python/src/sa/mmap.pxi
 create mode 100644 python/src/sa/vocabulary.pxi

(limited to 'python/src/sa')

diff --git a/python/src/sa/_sa.c b/python/src/sa/_sa.c
index 9c8dc2cd..f0690237 100644
--- a/python/src/sa/_sa.c
+++ b/python/src/sa/_sa.c
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.17.1 on Thu Dec 13 00:17:27 2012 */
+/* Generated by Cython 0.17.1 on Sun Dec 23 22:31:04 2012 */
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
@@ -249,6 +249,10 @@
 #define __PYX_HAVE___sa
 #define __PYX_HAVE_API___sa
 #include "stdio.h"
+#include "unistd.h"
+#include "fcntl.h"
+#include "sys/mman.h"
+#include "sys/stat.h"
 #include "stdlib.h"
 #include "string.h"
 #include "strmap.h"
@@ -348,6 +352,8 @@ static const char *__pyx_f[] = {
   "veb.pxi",
   "rule.pxi",
   "rulefactory.pxi",
+  "mmap.pxi",
+  "vocabulary.pxi",
   "lcp.pxi",
   "sym.pxi",
   "precomputation.pxi",
@@ -375,6 +381,7 @@ struct __pyx_obj_3_sa_Alphabet;
 struct __pyx_obj_3_sa_Rule;
 struct __pyx_obj_3_sa___pyx_scope_struct_6_genexpr;
 struct __pyx_obj_3_sa___pyx_scope_struct_2_genexpr;
+struct __pyx_obj_3_sa_MemoryMap;
 struct __pyx_obj_3_sa_PhraseLocation;
 struct __pyx_obj_3_sa___pyx_scope_struct_16___iter__;
 struct __pyx_obj_3_sa___pyx_scope_struct_1_read_bitext;
@@ -392,6 +399,7 @@ struct __pyx_obj_3_sa_TrieMap;
 struct __pyx_obj_3_sa___pyx_scope_struct_8_genexpr;
 struct __pyx_obj_3_sa___pyx_scope_struct_4_make_lattice;
 struct __pyx_obj_3_sa___pyx_scope_struct_12___str__;
+struct __pyx_obj_3_sa_Vocabulary;
 struct __pyx_obj_3_sa___pyx_scope_struct_15_input;
 struct __pyx_obj_3_sa___pyx_scope_struct_13_genexpr;
 struct __pyx_obj_3_sa_Phrase;
@@ -401,6 +409,7 @@ struct __pyx_obj_3_sa___pyx_scope_struct_11___iter__;
 struct __pyx_obj_3_sa___pyx_scope_struct_5_genexpr;
 struct __pyx_obj_3_sa___pyx_scope_struct_10_genexpr;
 struct __pyx_obj_3_sa_FloatList;
+struct __pyx_opt_args_3_sa_10Vocabulary_write_handle;
 struct __pyx_t_3_sa__node;
 struct __pyx_t_3_sa__BitSet;
 struct __pyx_t_3_sa__VEB;
@@ -409,6 +418,18 @@ struct __pyx_t_3_sa__Trie_Node;
 struct __pyx_t_3_sa_match_node;
 struct __pyx_t_3_sa_Matching;
 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":29
+ *         return len(self.id2word)
+ * 
+ *     cdef void write_handle(self, FILE* f, int offset=0):             # <<<<<<<<<<<<<<
+ *         cdef int word_len
+ *         cdef int num_words
+ */
+struct __pyx_opt_args_3_sa_10Vocabulary_write_handle {
+  int __pyx_n;
+  int offset;
+};
+
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":9
  * from libc.string cimport memset, strcpy
  * 
@@ -617,8 +638,8 @@ struct __pyx_obj_3_sa___pyx_scope_struct_18_genexpr {
 };
 
 
-/* "_sa.pxd":12
- *     cdef void read_handle(self, FILE* f)
+/* "_sa.pxd":25
+ *     cdef void read_mmaped(self, MemoryMap buf)
  * 
  * cdef class IntList:             # <<<<<<<<<<<<<<
  *     cdef int size
@@ -631,6 +652,7 @@ struct __pyx_obj_3_sa_IntList {
   int increment;
   int len;
   int *arr;
+  PyObject *memory;
 };
 
 
@@ -648,12 +670,12 @@ struct __pyx_obj_3_sa_VEBIterator {
 };
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":47
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":48
+ * cdef int NULL_WORD = 0
  * 
  * cdef class BiLex:             # <<<<<<<<<<<<<<
- *     cdef FloatList col1
- *     cdef FloatList col2
+ *     cdef FloatList col1, col2
+ *     cdef IntList f_index, e_index
  */
 struct __pyx_obj_3_sa_BiLex {
   PyObject_HEAD
@@ -662,10 +684,8 @@ struct __pyx_obj_3_sa_BiLex {
   struct __pyx_obj_3_sa_FloatList *col2;
   struct __pyx_obj_3_sa_IntList *f_index;
   struct __pyx_obj_3_sa_IntList *e_index;
-  PyObject *id2eword;
-  PyObject *id2fword;
-  PyObject *eword2id;
-  PyObject *fword2id;
+  struct __pyx_obj_3_sa_Vocabulary *f_voc;
+  struct __pyx_obj_3_sa_Vocabulary *e_voc;
 };
 
 
@@ -697,18 +717,17 @@ struct __pyx_obj_3_sa_LCP {
 };
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":9
- * from libc.string cimport memset, strcpy
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":12
+ * INIT_VOCABULARY = ('NULL', 'END_OF_LINE')
  * 
  * cdef class DataArray:             # <<<<<<<<<<<<<<
- *     cdef public word2id
- *     cdef public id2word
+ *     cdef public Vocabulary voc
+ *     cdef public IntList data
  */
 struct __pyx_obj_3_sa_DataArray {
   PyObject_HEAD
   struct __pyx_vtabstruct_3_sa_DataArray *__pyx_vtab;
-  PyObject *word2id;
-  PyObject *id2word;
+  struct __pyx_obj_3_sa_Vocabulary *voc;
   struct __pyx_obj_3_sa_IntList *data;
   struct __pyx_obj_3_sa_IntList *sent_id;
   struct __pyx_obj_3_sa_IntList *sent_index;
@@ -747,8 +766,8 @@ struct __pyx_obj_3_sa___pyx_scope_struct_14_alignments {
 };
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":188
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":183
+ *         return result
  * 
  * cdef class Precomputation:             # <<<<<<<<<<<<<<
  *     cdef int precompute_rank
@@ -802,7 +821,7 @@ struct __pyx_obj_3_sa_Alphabet {
 };
 
 
-/* "_sa.pxd":35
+/* "_sa.pxd":49
  *     cdef public int chunklen(self, int k)
  * 
  * cdef class Rule:             # <<<<<<<<<<<<<<
@@ -838,7 +857,7 @@ struct __pyx_obj_3_sa___pyx_scope_struct_6_genexpr {
 
 
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":74
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)             # <<<<<<<<<<<<<<
  *             self.read_text_data(data)
@@ -853,6 +872,31 @@ struct __pyx_obj_3_sa___pyx_scope_struct_2_genexpr {
   PyObject *(*__pyx_t_2)(PyObject *);
 };
 
+
+/* "_sa.pxd":4
+ * from posix.unistd cimport off_t
+ * 
+ * cdef class MemoryMap:             # <<<<<<<<<<<<<<
+ *     cdef int fd
+ *     cdef off_t fs
+ */
+struct __pyx_obj_3_sa_MemoryMap {
+  PyObject_HEAD
+  struct __pyx_vtabstruct_3_sa_MemoryMap *__pyx_vtab;
+  int fd;
+  off_t fs;
+  void *map_start;
+  void *map_ptr;
+};
+
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":74
+ * # in the suffix array; if discontiguous, it is the set of
+ * # actual locations (packed into an array)
+ * cdef class PhraseLocation:             # <<<<<<<<<<<<<<
+ *     cdef int sa_low
+ *     cdef int sa_high
+ */
 struct __pyx_obj_3_sa_PhraseLocation {
   PyObject_HEAD
   struct __pyx_vtabstruct_3_sa_PhraseLocation *__pyx_vtab;
@@ -884,7 +928,7 @@ struct __pyx_obj_3_sa___pyx_scope_struct_16___iter__ {
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":72
  *             self.read_text_data(fp)
  * 
- *     def read_bitext(self, char* filename, int side):             # <<<<<<<<<<<<<<
+ *     def read_bitext(self, bytes filename, int side):             # <<<<<<<<<<<<<<
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)
  */
@@ -895,8 +939,8 @@ struct __pyx_obj_3_sa___pyx_scope_struct_1_read_bitext {
 };
 
 
-/* "_sa.pxd":25
- *     cdef void read_handle(self, FILE* f)
+/* "_sa.pxd":39
+ *     cdef void read_mmaped(self, MemoryMap buf)
  * 
  * cdef class FeatureVector:             # <<<<<<<<<<<<<<
  *     cdef IntList names
@@ -1033,7 +1077,7 @@ struct __pyx_obj_3_sa_ExtendedTrieNode {
 };
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":109
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":108
  *         trie_node_to_map(edge.node, result, prefix, include_zeros)
  * 
  * cdef class TrieMap:             # <<<<<<<<<<<<<<
@@ -1102,6 +1146,19 @@ struct __pyx_obj_3_sa___pyx_scope_struct_12___str__ {
 };
 
 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":1
+ * cdef class Vocabulary:             # <<<<<<<<<<<<<<
+ *     cdef object id2word, word2id
+ * 
+ */
+struct __pyx_obj_3_sa_Vocabulary {
+  PyObject_HEAD
+  struct __pyx_vtabstruct_3_sa_Vocabulary *__pyx_vtab;
+  PyObject *id2word;
+  PyObject *word2id;
+};
+
+
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":933
  *         return sorted(result);
  * 
@@ -1205,7 +1262,7 @@ struct __pyx_obj_3_sa___pyx_scope_struct_13_genexpr {
 };
 
 
-/* "_sa.pxd":29
+/* "_sa.pxd":43
  *     cdef FloatList values
  * 
  * cdef class Phrase:             # <<<<<<<<<<<<<<
@@ -1222,8 +1279,8 @@ struct __pyx_obj_3_sa_Phrase {
 };
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":81
- *         free(self.arr)
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":38
+ *             free(self.arr)
  * 
  *     def __iter__(self):             # <<<<<<<<<<<<<<
  *         cdef int i
@@ -1301,8 +1358,8 @@ struct __pyx_obj_3_sa___pyx_scope_struct_10_genexpr {
 };
 
 
-/* "_sa.pxd":3
- * from libc.stdio cimport FILE
+/* "_sa.pxd":14
+ *     cdef float* read_float_array(self, int size)
  * 
  * cdef class FloatList:             # <<<<<<<<<<<<<<
  *     cdef int size
@@ -1315,6 +1372,7 @@ struct __pyx_obj_3_sa_FloatList {
   int increment;
   int len;
   float *arr;
+  PyObject *memory;
 };
 
 
@@ -1334,22 +1392,23 @@ struct __pyx_vtabstruct_3_sa_StringMap {
 static struct __pyx_vtabstruct_3_sa_StringMap *__pyx_vtabptr_3_sa_StringMap;
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":9
- * from libc.string cimport memset, strcpy
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":12
+ * INIT_VOCABULARY = ('NULL', 'END_OF_LINE')
  * 
  * cdef class DataArray:             # <<<<<<<<<<<<<<
- *     cdef public word2id
- *     cdef public id2word
+ *     cdef public Vocabulary voc
+ *     cdef public IntList data
  */
 
 struct __pyx_vtabstruct_3_sa_DataArray {
+  void (*read_mmaped)(struct __pyx_obj_3_sa_DataArray *, struct __pyx_obj_3_sa_MemoryMap *);
   void (*read_handle)(struct __pyx_obj_3_sa_DataArray *, FILE *);
   void (*write_handle)(struct __pyx_obj_3_sa_DataArray *, FILE *);
 };
 static struct __pyx_vtabstruct_3_sa_DataArray *__pyx_vtabptr_3_sa_DataArray;
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":109
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":108
  *         trie_node_to_map(edge.node, result, prefix, include_zeros)
  * 
  * cdef class TrieMap:             # <<<<<<<<<<<<<<
@@ -1364,6 +1423,20 @@ struct __pyx_vtabstruct_3_sa_TrieMap {
 static struct __pyx_vtabstruct_3_sa_TrieMap *__pyx_vtabptr_3_sa_TrieMap;
 
 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":1
+ * cdef class Vocabulary:             # <<<<<<<<<<<<<<
+ *     cdef object id2word, word2id
+ * 
+ */
+
+struct __pyx_vtabstruct_3_sa_Vocabulary {
+  void (*write_handle)(struct __pyx_obj_3_sa_Vocabulary *, FILE *, struct __pyx_opt_args_3_sa_10Vocabulary_write_handle *__pyx_optional_args);
+  void (*read_handle)(struct __pyx_obj_3_sa_Vocabulary *, FILE *);
+  void (*read_mmaped)(struct __pyx_obj_3_sa_Vocabulary *, struct __pyx_obj_3_sa_MemoryMap *);
+};
+static struct __pyx_vtabstruct_3_sa_Vocabulary *__pyx_vtabptr_3_sa_Vocabulary;
+
+
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":8
  * # May need to revisit if things get really tight, though.
  * 
@@ -1380,21 +1453,19 @@ struct __pyx_vtabstruct_3_sa_Alignment {
 static struct __pyx_vtabstruct_3_sa_Alignment *__pyx_vtabptr_3_sa_Alignment;
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":47
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":48
+ * cdef int NULL_WORD = 0
  * 
  * cdef class BiLex:             # <<<<<<<<<<<<<<
- *     cdef FloatList col1
- *     cdef FloatList col2
+ *     cdef FloatList col1, col2
+ *     cdef IntList f_index, e_index
  */
 
 struct __pyx_vtabstruct_3_sa_BiLex {
   PyObject *(*compute_from_data)(struct __pyx_obj_3_sa_BiLex *, struct __pyx_obj_3_sa_SuffixArray *, struct __pyx_obj_3_sa_DataArray *, struct __pyx_obj_3_sa_Alignment *);
   PyObject *(*_add_node)(struct __pyx_obj_3_sa_BiLex *, struct __pyx_t_3_sa__node *, int *, float, int *);
-  PyObject *(*write_wordlist)(struct __pyx_obj_3_sa_BiLex *, PyObject *, FILE *);
-  PyObject *(*read_wordlist)(struct __pyx_obj_3_sa_BiLex *, PyObject *, PyObject *, FILE *);
   PyObject *(*swap)(struct __pyx_obj_3_sa_BiLex *, int, int);
-  PyObject *(*qsort)(struct __pyx_obj_3_sa_BiLex *, int, int, PyObject *);
+  PyObject *(*qsort)(struct __pyx_obj_3_sa_BiLex *, int, int);
 };
 static struct __pyx_vtabstruct_3_sa_BiLex *__pyx_vtabptr_3_sa_BiLex;
 
@@ -1410,11 +1481,11 @@ static struct __pyx_vtabstruct_3_sa_BiLex *__pyx_vtabptr_3_sa_BiLex;
 struct __pyx_vtabstruct_3_sa_IntList {
   void (*set)(struct __pyx_obj_3_sa_IntList *, int, int);
   void (*_append)(struct __pyx_obj_3_sa_IntList *, int);
-  void (*_extend)(struct __pyx_obj_3_sa_IntList *, struct __pyx_obj_3_sa_IntList *);
   void (*_extend_arr)(struct __pyx_obj_3_sa_IntList *, int *, int);
   void (*_clear)(struct __pyx_obj_3_sa_IntList *);
   void (*write_handle)(struct __pyx_obj_3_sa_IntList *, FILE *);
   void (*read_handle)(struct __pyx_obj_3_sa_IntList *, FILE *);
+  void (*read_mmaped)(struct __pyx_obj_3_sa_IntList *, struct __pyx_obj_3_sa_MemoryMap *);
 };
 static struct __pyx_vtabstruct_3_sa_IntList *__pyx_vtabptr_3_sa_IntList;
 
@@ -1448,8 +1519,8 @@ struct __pyx_vtabstruct_3_sa_PhraseLocation {
 static struct __pyx_vtabstruct_3_sa_PhraseLocation *__pyx_vtabptr_3_sa_PhraseLocation;
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":188
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":183
+ *         return result
  * 
  * cdef class Precomputation:             # <<<<<<<<<<<<<<
  *     cdef int precompute_rank
@@ -1457,8 +1528,9 @@ static struct __pyx_vtabstruct_3_sa_PhraseLocation *__pyx_vtabptr_3_sa_PhraseLoc
  */
 
 struct __pyx_vtabstruct_3_sa_Precomputation {
-  PyObject *(*read_map)(struct __pyx_obj_3_sa_Precomputation *, FILE *);
   PyObject *(*write_map)(struct __pyx_obj_3_sa_Precomputation *, PyObject *, FILE *);
+  PyObject *(*read_map)(struct __pyx_obj_3_sa_Precomputation *, FILE *);
+  PyObject *(*read_mmaped_map)(struct __pyx_obj_3_sa_Precomputation *, struct __pyx_obj_3_sa_MemoryMap *);
 };
 static struct __pyx_vtabstruct_3_sa_Precomputation *__pyx_vtabptr_3_sa_Precomputation;
 
@@ -1489,24 +1561,26 @@ struct __pyx_vtabstruct_3_sa_FloatList {
   void (*set)(struct __pyx_obj_3_sa_FloatList *, int, float);
   void (*write_handle)(struct __pyx_obj_3_sa_FloatList *, FILE *);
   void (*read_handle)(struct __pyx_obj_3_sa_FloatList *, FILE *);
+  void (*read_mmaped)(struct __pyx_obj_3_sa_FloatList *, struct __pyx_obj_3_sa_MemoryMap *);
 };
 static struct __pyx_vtabstruct_3_sa_FloatList *__pyx_vtabptr_3_sa_FloatList;
 
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/veb.pxi":354
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":19
+ *     int fstat(int fildes, stat *buf)
  * 
- * cdef class VEB:             # <<<<<<<<<<<<<<
- *     cdef _VEB* veb
- *     cdef int _findsucc(self, int i)
+ * cdef class MemoryMap:             # <<<<<<<<<<<<<<
+ *     def __init__(self, filename):
+ *         self.fd = posix.fcntl.open(filename, posix.fcntl.O_RDONLY)
  */
 
-struct __pyx_vtabstruct_3_sa_VEB {
-  int (*_findsucc)(struct __pyx_obj_3_sa_VEB *, int);
-  int (*_insert)(struct __pyx_obj_3_sa_VEB *, int);
-  int (*_first)(struct __pyx_obj_3_sa_VEB *);
+struct __pyx_vtabstruct_3_sa_MemoryMap {
+  int (*read_int)(struct __pyx_obj_3_sa_MemoryMap *);
+  int *(*read_int_array)(struct __pyx_obj_3_sa_MemoryMap *, int);
+  char *(*read_char_array)(struct __pyx_obj_3_sa_MemoryMap *, int);
+  float *(*read_float_array)(struct __pyx_obj_3_sa_MemoryMap *, int);
 };
-static struct __pyx_vtabstruct_3_sa_VEB *__pyx_vtabptr_3_sa_VEB;
+static struct __pyx_vtabstruct_3_sa_MemoryMap *__pyx_vtabptr_3_sa_MemoryMap;
 
 
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":7
@@ -1532,6 +1606,22 @@ struct __pyx_vtabstruct_3_sa_Alphabet {
 static struct __pyx_vtabstruct_3_sa_Alphabet *__pyx_vtabptr_3_sa_Alphabet;
 
 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/veb.pxi":354
+ * 
+ * 
+ * cdef class VEB:             # <<<<<<<<<<<<<<
+ *     cdef _VEB* veb
+ *     cdef int _findsucc(self, int i)
+ */
+
+struct __pyx_vtabstruct_3_sa_VEB {
+  int (*_findsucc)(struct __pyx_obj_3_sa_VEB *, int);
+  int (*_insert)(struct __pyx_obj_3_sa_VEB *, int);
+  int (*_first)(struct __pyx_obj_3_sa_VEB *);
+};
+static struct __pyx_vtabstruct_3_sa_VEB *__pyx_vtabptr_3_sa_VEB;
+
+
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":218
  * 
  * 
@@ -1726,10 +1816,42 @@ static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyOb
 
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/
 
-static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact); /*proto*/
 
 static CYTHON_INLINE int __Pyx_CheckKeywordStrings(PyObject *kwdict, const char* function_name, int kw_allowed); /*proto*/
 
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
+    if (likely(PyList_CheckExact(L))) {
+        if (unlikely(PyList_Append(L, x) < 0)) return NULL;
+        Py_INCREF(Py_None);
+        return Py_None; /* this is just to have an accurate signature */
+    } else {
+        PyObject *r, *m;
+        m = __Pyx_GetAttrString(L, "append");
+        if (!m) return NULL;
+        r = PyObject_CallFunctionObjArgs(m, x, NULL);
+        Py_DECREF(m);
+        return r;
+    }
+}
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) {
+    PyListObject* L = (PyListObject*) list;
+    Py_ssize_t len = Py_SIZE(list);
+    if (likely(L->allocated > len)) {
+        Py_INCREF(x);
+        PyList_SET_ITEM(list, len, x);
+        Py_SIZE(list) = len+1;
+        return 0;
+    }
+    return PyList_Append(list, x);
+}
+#else
+#define __Pyx_PyList_Append(L,x) PyList_Append(L,x)
+#endif
+
 static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
     PyObject *r;
     if (!j) return NULL;
@@ -1816,30 +1938,12 @@ static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i)
     return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
 }
 
-static CYTHON_INLINE int __Pyx_PySequence_Contains(PyObject* item, PyObject* seq, int eq) {
-    int result = PySequence_Contains(seq, item);
-    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
-}
-
-static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
-    if (likely(PyList_CheckExact(L))) {
-        if (unlikely(PyList_Append(L, x) < 0)) return NULL;
-        Py_INCREF(Py_None);
-        return Py_None; /* this is just to have an accurate signature */
-    } else {
-        PyObject *r, *m;
-        m = __Pyx_GetAttrString(L, "append");
-        if (!m) return NULL;
-        r = PyObject_CallFunctionObjArgs(m, x, NULL);
-        Py_DECREF(m);
-        return r;
-    }
-}
-
 static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
 
 static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname);
 
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
+
 static CYTHON_INLINE long __Pyx_div_long(long, long); /* proto */
 
 static CYTHON_INLINE long __Pyx_mod_long(long, long); /* proto */
@@ -1852,6 +1956,25 @@ static CYTHON_INLINE int __Pyx_IterFinish(void); /*proto*/
 
 static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); /*proto*/
 
+static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
+#if CYTHON_COMPILING_IN_PYPY
+#define __Pyx_PyObject_AsDouble(obj) \
+(likely(PyFloat_CheckExact(obj)) ? PyFloat_AS_DOUBLE(obj) : \
+ likely(PyInt_CheckExact(obj)) ? \
+ PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
+#else
+#define __Pyx_PyObject_AsDouble(obj) \
+((likely(PyFloat_CheckExact(obj))) ? \
+ PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+#endif
+
+static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);
+
+static CYTHON_INLINE int __Pyx_PyDict_Contains(PyObject* item, PyObject* dict, int eq) {
+    int result = PyDict_Contains(dict, item);
+    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
+}
+
 #define __Pyx_SetItemInt(o, i, v, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \
                                                     __Pyx_SetItemInt_Fast(o, i, v) : \
                                                     __Pyx_SetItemInt_Generic(o, to_py_func(i), v))
@@ -1896,44 +2019,6 @@ static CYTHON_INLINE int __Pyx_SetItemInt_Fast(PyObject *o, Py_ssize_t i, PyObje
     return __Pyx_SetItemInt_Generic(o, PyInt_FromSsize_t(i), v);
 }
 
-static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
-#if CYTHON_COMPILING_IN_PYPY
-#define __Pyx_PyObject_AsDouble(obj) \
-(likely(PyFloat_CheckExact(obj)) ? PyFloat_AS_DOUBLE(obj) : \
- likely(PyInt_CheckExact(obj)) ? \
- PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
-#else
-#define __Pyx_PyObject_AsDouble(obj) \
-((likely(PyFloat_CheckExact(obj))) ? \
- PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
-#endif
-
-static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname);
-
-static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
-    const char *name, int exact); /*proto*/
-
-#if CYTHON_COMPILING_IN_CPYTHON
-static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) {
-    PyListObject* L = (PyListObject*) list;
-    Py_ssize_t len = Py_SIZE(list);
-    if (likely(L->allocated > len)) {
-        Py_INCREF(x);
-        PyList_SET_ITEM(list, len, x);
-        Py_SIZE(list) = len+1;
-        return 0;
-    }
-    return PyList_Append(list, x);
-}
-#else
-#define __Pyx_PyList_Append(L,x) PyList_Append(L,x)
-#endif
-
-static CYTHON_INLINE int __Pyx_PyDict_Contains(PyObject* item, PyObject* dict, int eq) {
-    int result = PyDict_Contains(dict, item);
-    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
-}
-
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
 
 static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index); /*proto*/
@@ -1979,6 +2064,11 @@ static CYTHON_INLINE int PySet_Add(PyObject *set, PyObject *key) {
 #endif /* PyAnySet_CheckExact (<= Py2.4) */
 #endif /* < Py2.5  */
 
+static CYTHON_INLINE int __Pyx_PySequence_Contains(PyObject* item, PyObject* seq, int eq) {
+    int result = PySequence_Contains(seq, item);
+    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
+}
+
 #if PY_MAJOR_VERSION >= 3
 static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
     PyObject *value;
@@ -2156,6 +2246,12 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
 /* Module declarations from 'libc.stdio' */
 
+/* Module declarations from 'posix.unistd' */
+
+/* Module declarations from 'posix.fcntl' */
+
+/* Module declarations from 'posix' */
+
 /* Module declarations from 'libc.stdlib' */
 
 /* Module declarations from 'libc.string' */
@@ -2163,12 +2259,14 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 /* Module declarations from 'libc.math' */
 
 /* Module declarations from '_sa' */
+static PyTypeObject *__pyx_ptype_3_sa_MemoryMap = 0;
 static PyTypeObject *__pyx_ptype_3_sa_FloatList = 0;
 static PyTypeObject *__pyx_ptype_3_sa_IntList = 0;
 static PyTypeObject *__pyx_ptype_3_sa_FeatureVector = 0;
 static PyTypeObject *__pyx_ptype_3_sa_Phrase = 0;
 static PyTypeObject *__pyx_ptype_3_sa_Rule = 0;
 static PyTypeObject *__pyx_ptype_3_sa_StringMap = 0;
+static PyTypeObject *__pyx_ptype_3_sa_Vocabulary = 0;
 static PyTypeObject *__pyx_ptype_3_sa_DataArray = 0;
 static PyTypeObject *__pyx_ptype_3_sa_Alignment = 0;
 static PyTypeObject *__pyx_ptype_3_sa_BiLex = 0;
@@ -2207,6 +2305,7 @@ static PyTypeObject *__pyx_ptype_3_sa___pyx_scope_struct_15_input = 0;
 static PyTypeObject *__pyx_ptype_3_sa___pyx_scope_struct_16___iter__ = 0;
 static PyTypeObject *__pyx_ptype_3_sa___pyx_scope_struct_17___str__ = 0;
 static PyTypeObject *__pyx_ptype_3_sa___pyx_scope_struct_18_genexpr = 0;
+static int __pyx_v_3_sa_NULL_WORD;
 static int __pyx_v_3_sa_MIN_BOTTOM_SIZE;
 static int __pyx_v_3_sa_MIN_BOTTOM_BITS;
 static int __pyx_v_3_sa_LOWER_MASK[32];
@@ -2259,6 +2358,7 @@ int __pyx_module_is_main__sa = 0;
 static PyObject *__pyx_builtin_open;
 static PyObject *__pyx_builtin_IndexError;
 static PyObject *__pyx_builtin_range;
+static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_TypeError;
 static PyObject *__pyx_builtin_enumerate;
 static PyObject *__pyx_builtin_map;
@@ -2269,55 +2369,52 @@ static PyObject *__pyx_builtin_cmp;
 static PyObject *__pyx_builtin_sorted;
 static PyObject *__pyx_builtin_max;
 static PyObject *__pyx_pf_3_sa_gzip_or_text(CYTHON_UNUSED PyObject *__pyx_self, char *__pyx_v_filename); /* proto */
+static int __pyx_pf_3_sa_9MemoryMap___init__(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static void __pyx_pf_3_sa_9MemoryMap_2__dealloc__(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self); /* proto */
 static int __pyx_pf_3_sa_9FloatList___cinit__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, int __pyx_v_size, int __pyx_v_increment, int __pyx_v_initial_len); /* proto */
 static void __pyx_pf_3_sa_9FloatList_2__dealloc__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
 static int __pyx_pf_3_sa_9FloatList_6__setitem__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val); /* proto */
 static Py_ssize_t __pyx_pf_3_sa_9FloatList_8__len__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, float __pyx_v_val); /* proto */
-static PyObject *__pyx_pf_3_sa_9FloatList_12write(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9FloatList_14read(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, char *__pyx_v_filename); /* proto */
 static int __pyx_pf_3_sa_7IntList___cinit__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, int __pyx_v_size, int __pyx_v_increment, int __pyx_v_initial_len); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_2__str__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_2__repr__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_7IntList_4index(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_val); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_6partition(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_start, PyObject *__pyx_v_end); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_8_doquicksort(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_start, PyObject *__pyx_v_end); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_10sort(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_12reset(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static void __pyx_pf_3_sa_7IntList_14__dealloc__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_16__iter__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */
-static int __pyx_pf_3_sa_7IntList_21__setitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val); /* proto */
-static Py_ssize_t __pyx_pf_3_sa_7IntList_23__len__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_25get_size(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_27append(struct __pyx_obj_3_sa_IntList *__pyx_v_self, int __pyx_v_val); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_29extend(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_other); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_31write(struct __pyx_obj_3_sa_IntList *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_7IntList_33read(struct __pyx_obj_3_sa_IntList *__pyx_v_self, char *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_6reset(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
+static void __pyx_pf_3_sa_7IntList_8__dealloc__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_10__iter__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_13__getitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_index); /* proto */
+static int __pyx_pf_3_sa_7IntList_15__setitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val); /* proto */
+static Py_ssize_t __pyx_pf_3_sa_7IntList_17__len__(struct __pyx_obj_3_sa_IntList *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_19append(struct __pyx_obj_3_sa_IntList *__pyx_v_self, int __pyx_v_val); /* proto */
+static PyObject *__pyx_pf_3_sa_7IntList_21extend(struct __pyx_obj_3_sa_IntList *__pyx_v_self, struct __pyx_obj_3_sa_IntList *__pyx_v_other); /* proto */
 static int __pyx_pf_3_sa_9StringMap___cinit__(struct __pyx_obj_3_sa_StringMap *__pyx_v_self); /* proto */
 static void __pyx_pf_3_sa_9StringMap_2__dealloc__(struct __pyx_obj_3_sa_StringMap *__pyx_v_self); /* proto */
-static int __pyx_pf_3_sa_9DataArray___cinit__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side, int __pyx_v_use_sent_id); /* proto */
+static int __pyx_pf_3_sa_10Vocabulary___init__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v_from_vocabulary); /* proto */
+static PyObject *__pyx_pf_3_sa_10Vocabulary_2extend(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_vocabulary); /* proto */
+static PyObject *__pyx_pf_3_sa_10Vocabulary_4__iter__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_10Vocabulary_6__getitem__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_word); /* proto */
+static PyObject *__pyx_pf_3_sa_10Vocabulary_8get(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_word, PyObject *__pyx_v_default); /* proto */
+static Py_ssize_t __pyx_pf_3_sa_10Vocabulary_10__len__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self); /* proto */
+static int __pyx_pf_3_sa_9DataArray___cinit__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side, int __pyx_v_use_sent_id, PyObject *__pyx_v_mmaped); /* proto */
 static Py_ssize_t __pyx_pf_3_sa_9DataArray_2__len__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_4get_sentence_id(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_6get_sentence(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_8get_id(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_word); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_10__getitem__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_loc); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_12get_sentence_bounds(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_loc); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_11read_bitext_genexpr(PyObject *__pyx_self); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename, int __pyx_v_side); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_v_side); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_20read_text_data(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_data); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_22read_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_22read_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_f); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_7word2id___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
-static int __pyx_pf_3_sa_9DataArray_7word2id_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
-static int __pyx_pf_3_sa_9DataArray_7word2id_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_3_sa_9DataArray_7id2word___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
-static int __pyx_pf_3_sa_9DataArray_7id2word_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
-static int __pyx_pf_3_sa_9DataArray_7id2word_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9DataArray_3voc___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
+static int __pyx_pf_3_sa_9DataArray_3voc_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
+static int __pyx_pf_3_sa_9DataArray_3voc_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_9DataArray_4data___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
 static int __pyx_pf_3_sa_9DataArray_4data_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
 static int __pyx_pf_3_sa_9DataArray_4data_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
@@ -2329,22 +2426,24 @@ static int __pyx_pf_3_sa_9DataArray_10sent_index_2__set__(struct __pyx_obj_3_sa_
 static int __pyx_pf_3_sa_9DataArray_10sent_index_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_9Alignment_unlink(CYTHON_UNUSED struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_link); /* proto */
 static PyObject *__pyx_pf_3_sa_9Alignment_2get_sent_links(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, int __pyx_v_sent_id); /* proto */
-static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_12write_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_9Alignment_16alignment(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
-static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_from_text, PyObject *__pyx_v_from_data, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_earray, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_alignment); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_6get_e_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_eword); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_8get_f_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword, PyObject *__pyx_v_eword, PyObject *__pyx_v_col); /* proto */
-static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename); /* proto */
+static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_mmaped); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_10read_mmaped(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_12write_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_14write_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_16write_enhanced(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_9Alignment_18alignment(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
+static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_from_text, PyObject *__pyx_v_from_data, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_earray, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_alignment, PyObject *__pyx_v_mmaped); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_6read_mmaped(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_8get_e_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_eword); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_10get_f_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_12read_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_14write_enhanced(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_16get_score(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword, PyObject *__pyx_v_eword, PyObject *__pyx_v_col); /* proto */
+static PyObject *__pyx_pf_3_sa_5BiLex_18write_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
 static PyObject *__pyx_pf_3_sa_14BitSetIterator___next__(struct __pyx_obj_3_sa_BitSetIterator *__pyx_v_self); /* proto */
 static int __pyx_pf_3_sa_6BitSet___cinit__(struct __pyx_obj_3_sa_BitSet *__pyx_v_self); /* proto */
 static void __pyx_pf_3_sa_6BitSet_2__dealloc__(struct __pyx_obj_3_sa_BitSet *__pyx_v_self); /* proto */
@@ -2413,19 +2512,21 @@ static void __pyx_pf_3_sa_7TrieMap_2__dealloc__(struct __pyx_obj_3_sa_TrieMap *_
 static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *__pyx_v_self, PyObject *__pyx_v_pattern); /* proto */
 static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap *__pyx_v_self, PyObject *__pyx_v_pattern); /* proto */
 static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__pyx_v_self, PyObject *__pyx_v_flag); /* proto */
-static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_from_stats, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_precompute_rank, PyObject *__pyx_v_precompute_secondary_rank, PyObject *__pyx_v_max_length, PyObject *__pyx_v_max_nonterminals, PyObject *__pyx_v_train_max_initial_size, PyObject *__pyx_v_train_min_gap_size); /* proto */
-static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_stats, struct __pyx_obj_3_sa_SuffixArray *__pyx_v_sarray); /* proto */
-static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side); /* proto */
+static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_from_stats, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_mmaped, PyObject *__pyx_v_precompute_rank, PyObject *__pyx_v_precompute_secondary_rank, PyObject *__pyx_v_max_length, PyObject *__pyx_v_max_nonterminals, PyObject *__pyx_v_train_max_initial_size, PyObject *__pyx_v_train_min_gap_size); /* proto */
+static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_14Precomputation_4read_mmaped(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf); /* proto */
+static PyObject *__pyx_pf_3_sa_14Precomputation_6write_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_14Precomputation_8precompute(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_stats, struct __pyx_obj_3_sa_SuffixArray *__pyx_v_sarray); /* proto */
+static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_mmaped, PyObject *__pyx_v_side); /* proto */
 static PyObject *__pyx_pf_3_sa_11SuffixArray_2__getitem__(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_i); /* proto */
 static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename, PyObject *__pyx_v_side); /* proto */
 static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, int __pyx_v_i, int __pyx_v_j, int __pyx_v_h, struct __pyx_obj_3_sa_IntList *__pyx_v_isa, PyObject *__pyx_v_pad); /* proto */
-static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_11SuffixArray_12write_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_3_sa_11SuffixArray_16lookup(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_word, int __pyx_v_offset, int __pyx_v_low, int __pyx_v_high); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_12read_mmaped(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_16write_enhanced(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_3_sa_11SuffixArray_18lookup(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_word, int __pyx_v_offset, int __pyx_v_low, int __pyx_v_high); /* proto */
 static int __pyx_pf_3_sa_8TrieNode___cinit__(struct __pyx_obj_3_sa_TrieNode *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_3_sa_8TrieNode_8children___get__(struct __pyx_obj_3_sa_TrieNode *__pyx_v_self); /* proto */
 static int __pyx_pf_3_sa_8TrieNode_8children_2__set__(struct __pyx_obj_3_sa_TrieNode *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
@@ -2474,56 +2575,55 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_7__str__(struct __pyx_obj_3_sa_Fe
 static int __pyx_pf_3_sa_6Scorer___init__(struct __pyx_obj_3_sa_Scorer *__pyx_v_self, PyObject *__pyx_v_models); /* proto */
 static char __pyx_k_1[] = ".gz";
 static char __pyx_k_2[] = "Requested index %d of %d-length FloatList";
-static char __pyx_k_3[] = "IntList[";
-static char __pyx_k_4[] = ",";
-static char __pyx_k_5[] = "]";
-static char __pyx_k_6[] = "len=";
-static char __pyx_k_7[] = "Requested index %d of %d-length IntList";
-static char __pyx_k_8[] = "Requested index %d:%d of %d-length IntList";
-static char __pyx_k_9[] = "Illegal key type %s for IntList";
-static char __pyx_k_13[] = "%s ";
-static char __pyx_k_14[] = "\n";
-static char __pyx_k_18[] = " ||| ";
-static char __pyx_k_21[] = "%d ";
-static char __pyx_k_25[] = "%s %d ";
-static char __pyx_k_27[] = "write_enhanced_handle";
+static char __pyx_k_3[] = "IntList(%s)";
+static char __pyx_k_4[] = "%s not in list";
+static char __pyx_k_5[] = "Requested index %d of %d-length IntList";
+static char __pyx_k_6[] = "Requested index %d:%d of %d-length IntList";
+static char __pyx_k_7[] = "Illegal key type %s for IntList";
+static char __pyx_k_12[] = "%s ";
+static char __pyx_k_13[] = "\n";
+static char __pyx_k_17[] = " ||| ";
+static char __pyx_k_20[] = "%d ";
+static char __pyx_k_24[] = "%s %d ";
+static char __pyx_k_26[] = "write_enhanced_handle";
 static char __pyx_k_31[] = "-";
 static char __pyx_k_35[] = "%d-%d ";
-static char __pyx_k_42[] = "%d-%d out of bounds (I=%d,J=%d) in line %d\n";
-static char __pyx_k_45[] = "";
+static char __pyx_k_43[] = "%d-%d out of bounds (I=%d,J=%d) in line %d\n";
 static char __pyx_k_46[] = "Sort error in CLex";
-static char __pyx_k_48[] = "    ";
-static char __pyx_k_50[] = "%d %f %f ";
-static char __pyx_k_52[] = "%d %s ";
-static char __pyx_k_56[] = "%s %s %.6f %.6f\n";
-static char __pyx_k_58[] = "  (";
+static char __pyx_k_49[] = "%d %f %f ";
+static char __pyx_k_51[] = "%d %s ";
+static char __pyx_k_55[] = "%s %s %.6f %.6f\n";
+static char __pyx_k_57[] = "  (";
+static char __pyx_k_58[] = ",";
 static char __pyx_k_59[] = ")";
-static char __pyx_k_60[] = "Constructing LCP array";
-static char __pyx_k_62[] = "LCP array completed";
-static char __pyx_k_64[] = "[%s,%d]";
-static char __pyx_k_65[] = "[%s]";
-static char __pyx_k_66[] = "\\";
-static char __pyx_k_67[] = " ";
-static char __pyx_k_68[] = "Invalid LHS symbol: %d";
-static char __pyx_k_69[] = "%d-%d";
-static char __pyx_k_70[] = "precompute_secondary_rank";
-static char __pyx_k_71[] = "train_max_initial_size";
-static char __pyx_k_72[] = "Precomputing frequent intersections";
-static char __pyx_k_74[] = "    Computing inverted indexes...";
-static char __pyx_k_76[] = "    Computing collocations...";
-static char __pyx_k_78[] = "        %d sentences";
-static char __pyx_k_83[] = "X ";
-static char __pyx_k_84[] = "ERROR: unexpected pattern %s in set of precomputed collocations";
-static char __pyx_k_85[] = "RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d";
-static char __pyx_k_86[] = "Precomputed collocations for %d patterns out of %d possible (upper bound %d)";
-static char __pyx_k_87[] = "Precomputed inverted index for %d patterns ";
-static char __pyx_k_88[] = "Precomputation took %f seconds";
-static char __pyx_k_89[] = "    Bucket sort took %f seconds";
-static char __pyx_k_90[] = "    Refining, sort depth = %d";
-static char __pyx_k_91[] = "    Refinement took %f seconds";
-static char __pyx_k_92[] = "    Finalizing sort...";
-static char __pyx_k_94[] = "Suffix array construction took %f seconds";
-static char __pyx_k_95[] = "Unexpected condition found in q3sort: sort from %d to %d";
+static char __pyx_k_60[] = "";
+static char __pyx_k_61[] = "Constructing LCP array";
+static char __pyx_k_63[] = "LCP array completed";
+static char __pyx_k_65[] = "[%s,%d]";
+static char __pyx_k_66[] = "[%s]";
+static char __pyx_k_67[] = "\\";
+static char __pyx_k_68[] = " ";
+static char __pyx_k_69[] = "Invalid LHS symbol: %d";
+static char __pyx_k_70[] = "%d-%d";
+static char __pyx_k_71[] = "precompute_secondary_rank";
+static char __pyx_k_72[] = "train_max_initial_size";
+static char __pyx_k_74[] = "Precomputing frequent intersections";
+static char __pyx_k_76[] = "    Computing inverted indexes...";
+static char __pyx_k_78[] = "    Computing collocations...";
+static char __pyx_k_80[] = "        %d sentences";
+static char __pyx_k_85[] = "X ";
+static char __pyx_k_86[] = "ERROR: unexpected pattern %s in set of precomputed collocations";
+static char __pyx_k_87[] = "RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d";
+static char __pyx_k_88[] = "Precomputed collocations for %d patterns out of %d possible (upper bound %d)";
+static char __pyx_k_89[] = "Precomputed inverted index for %d patterns ";
+static char __pyx_k_90[] = "Precomputation took %f seconds";
+static char __pyx_k_92[] = "    Bucket sort took %f seconds";
+static char __pyx_k_93[] = "    Refining, sort depth = %d";
+static char __pyx_k_94[] = "    Refinement took %f seconds";
+static char __pyx_k_95[] = "    Finalizing sort...";
+static char __pyx_k_97[] = "Suffix array construction took %f seconds";
+static char __pyx_k_98[] = "Unexpected condition found in q3sort: sort from %d to %d";
+static char __pyx_k_99[] = "    ";
 static char __pyx_k__0[] = "0";
 static char __pyx_k__1[] = "1";
 static char __pyx_k__e[] = "e";
@@ -2533,49 +2633,49 @@ static char __pyx_k__i[] = "i";
 static char __pyx_k__j[] = "j";
 static char __pyx_k__r[] = "r";
 static char __pyx_k__w[] = "w";
-static char __pyx_k_100[] = "Sampling strategy: uniform, max sample size = %d";
-static char __pyx_k_101[] = "Sampling strategy: no sampling";
-static char __pyx_k_103[] = "require_aligned_terminal";
-static char __pyx_k_104[] = "require_aligned_chunks";
-static char __pyx_k_105[] = "[X]";
-static char __pyx_k_106[] = "Must specify an alignment object";
-static char __pyx_k_108[] = "Reading precomputed data from file %s... ";
-static char __pyx_k_109[] = "Precomputation done with max nonterminals %d, decoder uses %d";
-static char __pyx_k_110[] = "Precomputation done with max terminals %d, decoder uses %d";
-static char __pyx_k_111[] = "Precomputation done with max initial size %d, decoder uses %d";
-static char __pyx_k_112[] = "Precomputation done with min gap size %d, decoder uses %d";
-static char __pyx_k_113[] = "Converting %d hash keys on precomputed inverted index... ";
-static char __pyx_k_114[] = "Converting %d hash keys on precomputed collocations... ";
-static char __pyx_k_115[] = "Processing precomputations took %f seconds";
-static char __pyx_k_116[] = "{";
-  static char __pyx_k_117[] = "(";
-static char __pyx_k_118[] = "}";
-static char __pyx_k_119[] = "get_precomputed_collocation";
-static char __pyx_k_120[] = "double binary";
-static char __pyx_k_121[] = "Keyword trie error";
-static char __pyx_k_123[] = "get_all_nodes_isteps_away";
-static char __pyx_k_124[] = "Total time for rule lookup, extraction, and scoring = %f seconds";
-static char __pyx_k_125[] = "    Extract time = %f seconds";
-static char __pyx_k_126[] = "No aligned terminals";
-static char __pyx_k_127[] = "Unaligned chunk";
-static char __pyx_k_128[] = "Gaps are not tight phrases";
-static char __pyx_k_129[] = "Inside edges of preceding subphrase are not tight";
-static char __pyx_k_130[] = "Inside edges of following subphrase are not tight";
-static char __pyx_k_131[] = "Subphrase [%d, %d] failed integrity check";
-static char __pyx_k_132[] = "Didn't extract anything from [%d, %d] -> [%d, %d]";
-static char __pyx_k_133[] = "Unable to extract basic phrase";
-static char __pyx_k_134[] = "%s=%s";
-static char __pyx_k_137[] = "/Users/vchahun/Sandbox/cdec/python/src/sa/_sa.pyx";
-static char __pyx_k_138[] = "cdec.sa";
-static char __pyx_k_142[] = "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi";
-static char __pyx_k_147[] = "*EPS*";
+static char __pyx_k_104[] = "Sampling strategy: uniform, max sample size = %d";
+static char __pyx_k_105[] = "Sampling strategy: no sampling";
+static char __pyx_k_107[] = "require_aligned_terminal";
+static char __pyx_k_108[] = "require_aligned_chunks";
+static char __pyx_k_109[] = "[X]";
+static char __pyx_k_110[] = "Must specify an alignment object";
+static char __pyx_k_112[] = "Reading precomputed data from file %s... ";
+static char __pyx_k_113[] = "Precomputation done with max nonterminals %d, decoder uses %d";
+static char __pyx_k_114[] = "Precomputation done with max terminals %d, decoder uses %d";
+static char __pyx_k_115[] = "Precomputation done with max initial size %d, decoder uses %d";
+static char __pyx_k_116[] = "Precomputation done with min gap size %d, decoder uses %d";
+static char __pyx_k_117[] = "Converting %d hash keys on precomputed inverted index... ";
+static char __pyx_k_118[] = "Converting %d hash keys on precomputed collocations... ";
+static char __pyx_k_119[] = "Processing precomputations took %f seconds";
+static char __pyx_k_120[] = "{";
+  static char __pyx_k_121[] = "(";
+static char __pyx_k_122[] = "}";
+static char __pyx_k_123[] = "get_precomputed_collocation";
+static char __pyx_k_124[] = "double binary";
+static char __pyx_k_125[] = "Keyword trie error";
+static char __pyx_k_127[] = "get_all_nodes_isteps_away";
+static char __pyx_k_128[] = "Total time for rule lookup, extraction, and scoring = %f seconds";
+static char __pyx_k_129[] = "    Extract time = %f seconds";
+static char __pyx_k_130[] = "No aligned terminals";
+static char __pyx_k_131[] = "Unaligned chunk";
+static char __pyx_k_132[] = "Gaps are not tight phrases";
+static char __pyx_k_133[] = "Inside edges of preceding subphrase are not tight";
+static char __pyx_k_134[] = "Inside edges of following subphrase are not tight";
+static char __pyx_k_135[] = "Subphrase [%d, %d] failed integrity check";
+static char __pyx_k_136[] = "Didn't extract anything from [%d, %d] -> [%d, %d]";
+static char __pyx_k_137[] = "Unable to extract basic phrase";
+static char __pyx_k_138[] = "%s=%s";
+static char __pyx_k_141[] = "/Users/vchahun/Sandbox/cdec/python/src/sa/_sa.pyx";
+static char __pyx_k_142[] = "cdec.sa";
+static char __pyx_k_147[] = "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi";
+static char __pyx_k_152[] = "*EPS*";
 static char __pyx_k__gc[] = "gc";
 static char __pyx_k__sa[] = "sa";
 static char __pyx_k___sa[] = "_sa";
 static char __pyx_k__arr[] = "arr";
 static char __pyx_k__cmp[] = "cmp";
 static char __pyx_k__col[] = "col";
-static char __pyx_k__end[] = "end";
+static char __pyx_k__get[] = "get";
 static char __pyx_k__isa[] = "isa";
 static char __pyx_k__ito[] = "ito";
 static char __pyx_k__key[] = "key";
@@ -2631,6 +2731,7 @@ static char __pyx_k__get_id[] = "get_id";
 static char __pyx_k__insert[] = "insert";
 static char __pyx_k__logger[] = "logger";
 static char __pyx_k__lookup[] = "lookup";
+static char __pyx_k__mmaped[] = "mmaped";
 static char __pyx_k__offset[] = "offset";
 static char __pyx_k__phrase[] = "phrase";
 static char __pyx_k__q3sort[] = "q3sort";
@@ -2646,6 +2747,7 @@ static char __pyx_k__Counter[] = "Counter";
 static char __pyx_k__advance[] = "advance";
 static char __pyx_k__arr_low[] = "arr_low";
 static char __pyx_k__collect[] = "collect";
+static char __pyx_k__default[] = "default";
 static char __pyx_k__edarray[] = "edarray";
 static char __pyx_k__ephrase[] = "ephrase";
 static char __pyx_k__fphrase[] = "fphrase";
@@ -2695,11 +2797,11 @@ static char __pyx_k__increment[] = "increment";
 static char __pyx_k__iteritems[] = "iteritems";
 static char __pyx_k__itertools[] = "itertools";
 static char __pyx_k__paircount[] = "paircount";
-static char __pyx_k__partition[] = "partition";
 static char __pyx_k__reachable[] = "reachable";
 static char __pyx_k__read_text[] = "read_text";
 static char __pyx_k__use_index[] = "use_index";
 static char __pyx_k__IndexError[] = "IndexError";
+static char __pyx_k__ValueError[] = "ValueError";
 static char __pyx_k__alignments[] = "alignments";
 static char __pyx_k__from_stats[] = "from_stats";
 static char __pyx_k__input_span[] = "input_span";
@@ -2709,7 +2811,6 @@ static char __pyx_k__max_length[] = "max_length";
 static char __pyx_k__namedtuple[] = "namedtuple";
 static char __pyx_k__precompute[] = "precompute";
 static char __pyx_k__write_text[] = "write_text";
-static char __pyx_k__END_OF_FILE[] = "END_OF_FILE";
 static char __pyx_k__END_OF_LINE[] = "END_OF_LINE";
 static char __pyx_k__RUSAGE_SELF[] = "RUSAGE_SELF";
 static char __pyx_k__collections[] = "collections";
@@ -2721,10 +2822,10 @@ static char __pyx_k__next_states[] = "next_states";
 static char __pyx_k__precomputed[] = "precomputed";
 static char __pyx_k__read_binary[] = "read_binary";
 static char __pyx_k__read_bitext[] = "read_bitext";
+static char __pyx_k__read_mmaped[] = "read_mmaped";
 static char __pyx_k__sample_size[] = "sample_size";
 static char __pyx_k__suffix_link[] = "suffix_link";
 static char __pyx_k__use_sent_id[] = "use_sent_id";
-static char __pyx_k___doquicksort[] = "_doquicksort";
 static char __pyx_k__gzip_or_text[] = "gzip_or_text";
 static char __pyx_k__make_lattice[] = "make_lattice";
 static char __pyx_k__min_gap_size[] = "min_gap_size";
@@ -2738,8 +2839,10 @@ static char __pyx_k__FeatureContext[] = "FeatureContext";
 static char __pyx_k__decode_lattice[] = "decode_lattice";
 static char __pyx_k__pattern2phrase[] = "pattern2phrase";
 static char __pyx_k__read_text_data[] = "read_text_data";
+static char __pyx_k__INIT_VOCABULARY[] = "INIT_VOCABULARY";
 static char __pyx_k__by_slack_factor[] = "by_slack_factor";
 static char __pyx_k__decode_sentence[] = "decode_sentence";
+static char __pyx_k__from_vocabulary[] = "from_vocabulary";
 static char __pyx_k__get_next_states[] = "get_next_states";
 static char __pyx_k__num_subpatterns[] = "num_subpatterns";
 static char __pyx_k__phrase_location[] = "phrase_location";
@@ -2757,15 +2860,11 @@ static char __pyx_k__max_target_length[] = "max_target_length";
 static char __pyx_k__train_min_gap_size[] = "train_min_gap_size";
 static char __pyx_k__pattern2phrase_plus[] = "pattern2phrase_plus";
 static PyObject *__pyx_kp_s_1;
-static PyObject *__pyx_kp_s_100;
-static PyObject *__pyx_kp_s_101;
-static PyObject *__pyx_n_s_103;
-static PyObject *__pyx_n_s_104;
-static PyObject *__pyx_kp_s_106;
-static PyObject *__pyx_kp_s_108;
-static PyObject *__pyx_kp_s_109;
+static PyObject *__pyx_kp_s_104;
+static PyObject *__pyx_kp_s_105;
+static PyObject *__pyx_n_s_107;
+static PyObject *__pyx_n_s_108;
 static PyObject *__pyx_kp_s_110;
-static PyObject *__pyx_kp_s_111;
 static PyObject *__pyx_kp_s_112;
 static PyObject *__pyx_kp_s_113;
 static PyObject *__pyx_kp_s_114;
@@ -2773,14 +2872,15 @@ static PyObject *__pyx_kp_s_115;
 static PyObject *__pyx_kp_s_116;
 static PyObject *__pyx_kp_s_117;
 static PyObject *__pyx_kp_s_118;
-static PyObject *__pyx_n_s_119;
+static PyObject *__pyx_kp_s_119;
+static PyObject *__pyx_kp_s_12;
 static PyObject *__pyx_kp_s_120;
 static PyObject *__pyx_kp_s_121;
+static PyObject *__pyx_kp_s_122;
 static PyObject *__pyx_n_s_123;
 static PyObject *__pyx_kp_s_124;
 static PyObject *__pyx_kp_s_125;
-static PyObject *__pyx_kp_s_126;
-static PyObject *__pyx_kp_s_127;
+static PyObject *__pyx_n_s_127;
 static PyObject *__pyx_kp_s_128;
 static PyObject *__pyx_kp_s_129;
 static PyObject *__pyx_kp_s_13;
@@ -2789,81 +2889,83 @@ static PyObject *__pyx_kp_s_131;
 static PyObject *__pyx_kp_s_132;
 static PyObject *__pyx_kp_s_133;
 static PyObject *__pyx_kp_s_134;
+static PyObject *__pyx_kp_s_135;
+static PyObject *__pyx_kp_s_136;
 static PyObject *__pyx_kp_s_137;
 static PyObject *__pyx_kp_s_138;
-static PyObject *__pyx_kp_s_14;
+static PyObject *__pyx_kp_s_141;
 static PyObject *__pyx_kp_s_142;
-static PyObject *__pyx_kp_s_18;
+static PyObject *__pyx_kp_s_147;
+static PyObject *__pyx_kp_s_17;
 static PyObject *__pyx_kp_s_2;
-static PyObject *__pyx_kp_s_21;
-static PyObject *__pyx_kp_s_25;
-static PyObject *__pyx_n_s_27;
+static PyObject *__pyx_kp_s_20;
+static PyObject *__pyx_kp_s_24;
+static PyObject *__pyx_n_s_26;
 static PyObject *__pyx_kp_s_3;
 static PyObject *__pyx_kp_s_31;
 static PyObject *__pyx_kp_s_35;
 static PyObject *__pyx_kp_s_4;
-static PyObject *__pyx_kp_s_42;
-static PyObject *__pyx_kp_s_45;
+static PyObject *__pyx_kp_s_43;
 static PyObject *__pyx_kp_s_46;
-static PyObject *__pyx_kp_s_48;
+static PyObject *__pyx_kp_s_49;
 static PyObject *__pyx_kp_s_5;
-static PyObject *__pyx_kp_s_50;
-static PyObject *__pyx_kp_s_52;
-static PyObject *__pyx_kp_s_56;
+static PyObject *__pyx_kp_s_51;
+static PyObject *__pyx_kp_s_55;
+static PyObject *__pyx_kp_s_57;
 static PyObject *__pyx_kp_s_58;
 static PyObject *__pyx_kp_s_59;
 static PyObject *__pyx_kp_s_6;
 static PyObject *__pyx_kp_s_60;
-static PyObject *__pyx_kp_s_62;
-static PyObject *__pyx_kp_s_64;
+static PyObject *__pyx_kp_s_61;
+static PyObject *__pyx_kp_s_63;
 static PyObject *__pyx_kp_s_65;
 static PyObject *__pyx_kp_s_66;
 static PyObject *__pyx_kp_s_67;
 static PyObject *__pyx_kp_s_68;
 static PyObject *__pyx_kp_s_69;
 static PyObject *__pyx_kp_s_7;
-static PyObject *__pyx_n_s_70;
+static PyObject *__pyx_kp_s_70;
 static PyObject *__pyx_n_s_71;
-static PyObject *__pyx_kp_s_72;
+static PyObject *__pyx_n_s_72;
 static PyObject *__pyx_kp_s_74;
 static PyObject *__pyx_kp_s_76;
 static PyObject *__pyx_kp_s_78;
-static PyObject *__pyx_kp_s_8;
-static PyObject *__pyx_kp_s_83;
-static PyObject *__pyx_kp_s_84;
+static PyObject *__pyx_kp_s_80;
 static PyObject *__pyx_kp_s_85;
 static PyObject *__pyx_kp_s_86;
 static PyObject *__pyx_kp_s_87;
 static PyObject *__pyx_kp_s_88;
 static PyObject *__pyx_kp_s_89;
-static PyObject *__pyx_kp_s_9;
 static PyObject *__pyx_kp_s_90;
-static PyObject *__pyx_kp_s_91;
 static PyObject *__pyx_kp_s_92;
+static PyObject *__pyx_kp_s_93;
 static PyObject *__pyx_kp_s_94;
 static PyObject *__pyx_kp_s_95;
+static PyObject *__pyx_kp_s_97;
+static PyObject *__pyx_kp_s_98;
+static PyObject *__pyx_kp_s_99;
 static PyObject *__pyx_kp_s__0;
 static PyObject *__pyx_kp_s__1;
 static PyObject *__pyx_n_s__Counter;
-static PyObject *__pyx_n_s__END_OF_FILE;
 static PyObject *__pyx_n_s__END_OF_LINE;
 static PyObject *__pyx_n_s__Exception;
 static PyObject *__pyx_n_s__FeatureContext;
 static PyObject *__pyx_n_s__GzipFile;
 static PyObject *__pyx_n_s__INCREMENT;
 static PyObject *__pyx_n_s__INITIAL_CAPACITY;
+static PyObject *__pyx_n_s__INIT_VOCABULARY;
 static PyObject *__pyx_n_s__IndexError;
 static PyObject *__pyx_n_s__NULL;
 static PyObject *__pyx_n_s__RUSAGE_SELF;
 static PyObject *__pyx_n_s__StopIteration;
 static PyObject *__pyx_n_s__TypeError;
+static PyObject *__pyx_n_s__ValueError;
 static PyObject *__pyx_n_s____enter__;
 static PyObject *__pyx_n_s____exit__;
 static PyObject *__pyx_n_s____main__;
 static PyObject *__pyx_n_s____name__;
 static PyObject *__pyx_n_s____test__;
 static PyObject *__pyx_n_s___columns;
-static PyObject *__pyx_n_s___doquicksort;
 static PyObject *__pyx_n_s___sa;
 static PyObject *__pyx_n_s__advance;
 static PyObject *__pyx_n_s__alignment;
@@ -2885,13 +2987,13 @@ static PyObject *__pyx_n_s__curr_idx;
 static PyObject *__pyx_n_s__debug;
 static PyObject *__pyx_n_s__decode_lattice;
 static PyObject *__pyx_n_s__decode_sentence;
+static PyObject *__pyx_n_s__default;
 static PyObject *__pyx_n_s__defaultdict;
 static PyObject *__pyx_n_s__dist;
 static PyObject *__pyx_n_s__e;
 static PyObject *__pyx_n_s__e_text;
 static PyObject *__pyx_n_s__earray;
 static PyObject *__pyx_n_s__edarray;
-static PyObject *__pyx_n_s__end;
 static PyObject *__pyx_n_s__enumerate;
 static PyObject *__pyx_n_s__ephrase;
 static PyObject *__pyx_n_s__eword;
@@ -2907,6 +3009,7 @@ static PyObject *__pyx_n_s__from_data;
 static PyObject *__pyx_n_s__from_iterable;
 static PyObject *__pyx_n_s__from_stats;
 static PyObject *__pyx_n_s__from_text;
+static PyObject *__pyx_n_s__from_vocabulary;
 static PyObject *__pyx_n_s__frontier;
 static PyObject *__pyx_n_s__fsample_count;
 static PyObject *__pyx_n_s__fsarray;
@@ -2914,6 +3017,7 @@ static PyObject *__pyx_n_s__fword;
 static PyObject *__pyx_n_s__fwords;
 static PyObject *__pyx_n_s__gc;
 static PyObject *__pyx_n_s__genexpr;
+static PyObject *__pyx_n_s__get;
 static PyObject *__pyx_n_s__getLogger;
 static PyObject *__pyx_n_s__get_e_id;
 static PyObject *__pyx_n_s__get_f_id;
@@ -2963,6 +3067,7 @@ static PyObject *__pyx_n_s__merge;
 static PyObject *__pyx_n_s__meta;
 static PyObject *__pyx_n_s__min_dist;
 static PyObject *__pyx_n_s__min_gap_size;
+static PyObject *__pyx_n_s__mmaped;
 static PyObject *__pyx_n_s__name;
 static PyObject *__pyx_n_s__namedtuple;
 static PyObject *__pyx_n_s__next_states;
@@ -2971,7 +3076,6 @@ static PyObject *__pyx_n_s__offset;
 static PyObject *__pyx_n_s__open;
 static PyObject *__pyx_n_s__pad;
 static PyObject *__pyx_n_s__paircount;
-static PyObject *__pyx_n_s__partition;
 static PyObject *__pyx_n_s__pathlen;
 static PyObject *__pyx_n_s__pattern2phrase;
 static PyObject *__pyx_n_s__pattern2phrase_plus;
@@ -2987,6 +3091,7 @@ static PyObject *__pyx_n_s__reachable;
 static PyObject *__pyx_n_s__reachable_buffer;
 static PyObject *__pyx_n_s__read_binary;
 static PyObject *__pyx_n_s__read_bitext;
+static PyObject *__pyx_n_s__read_mmaped;
 static PyObject *__pyx_n_s__read_text;
 static PyObject *__pyx_n_s__read_text_data;
 static PyObject *__pyx_n_s__res;
@@ -3046,21 +3151,26 @@ static PyObject *__pyx_int_10;
 static PyObject *__pyx_int_20;
 static PyObject *__pyx_int_1000;
 static PyObject *__pyx_int_65536;
+static PyObject *__pyx_k_8;
+static PyObject *__pyx_k_28;
 static PyObject *__pyx_k_41;
-static PyObject *__pyx_k_99;
+static PyObject *__pyx_k_42;
+static PyObject *__pyx_k_73;
+static PyObject *__pyx_k_91;
+static PyObject *__pyx_k_103;
+static PyObject *__pyx_k_tuple_9;
 static PyObject *__pyx_k_tuple_10;
 static PyObject *__pyx_k_tuple_11;
-static PyObject *__pyx_k_tuple_12;
+static PyObject *__pyx_k_tuple_14;
 static PyObject *__pyx_k_tuple_15;
 static PyObject *__pyx_k_tuple_16;
-static PyObject *__pyx_k_tuple_17;
+static PyObject *__pyx_k_tuple_18;
 static PyObject *__pyx_k_tuple_19;
-static PyObject *__pyx_k_tuple_20;
+static PyObject *__pyx_k_tuple_21;
 static PyObject *__pyx_k_tuple_22;
 static PyObject *__pyx_k_tuple_23;
-static PyObject *__pyx_k_tuple_24;
-static PyObject *__pyx_k_tuple_26;
-static PyObject *__pyx_k_tuple_28;
+static PyObject *__pyx_k_tuple_25;
+static PyObject *__pyx_k_tuple_27;
 static PyObject *__pyx_k_tuple_29;
 static PyObject *__pyx_k_tuple_30;
 static PyObject *__pyx_k_tuple_32;
@@ -3071,40 +3181,41 @@ static PyObject *__pyx_k_tuple_37;
 static PyObject *__pyx_k_tuple_38;
 static PyObject *__pyx_k_tuple_39;
 static PyObject *__pyx_k_tuple_40;
-static PyObject *__pyx_k_tuple_43;
 static PyObject *__pyx_k_tuple_44;
+static PyObject *__pyx_k_tuple_45;
 static PyObject *__pyx_k_tuple_47;
-static PyObject *__pyx_k_tuple_49;
-static PyObject *__pyx_k_tuple_51;
+static PyObject *__pyx_k_tuple_48;
+static PyObject *__pyx_k_tuple_50;
+static PyObject *__pyx_k_tuple_52;
 static PyObject *__pyx_k_tuple_53;
 static PyObject *__pyx_k_tuple_54;
-static PyObject *__pyx_k_tuple_55;
-static PyObject *__pyx_k_tuple_57;
-static PyObject *__pyx_k_tuple_61;
-static PyObject *__pyx_k_tuple_63;
-static PyObject *__pyx_k_tuple_73;
+static PyObject *__pyx_k_tuple_56;
+static PyObject *__pyx_k_tuple_62;
+static PyObject *__pyx_k_tuple_64;
 static PyObject *__pyx_k_tuple_75;
 static PyObject *__pyx_k_tuple_77;
 static PyObject *__pyx_k_tuple_79;
-static PyObject *__pyx_k_tuple_80;
 static PyObject *__pyx_k_tuple_81;
 static PyObject *__pyx_k_tuple_82;
-static PyObject *__pyx_k_tuple_93;
+static PyObject *__pyx_k_tuple_83;
+static PyObject *__pyx_k_tuple_84;
 static PyObject *__pyx_k_tuple_96;
-static PyObject *__pyx_k_tuple_97;
-static PyObject *__pyx_k_tuple_98;
+static PyObject *__pyx_k_tuple_100;
+static PyObject *__pyx_k_tuple_101;
 static PyObject *__pyx_k_tuple_102;
-static PyObject *__pyx_k_tuple_107;
-static PyObject *__pyx_k_tuple_122;
-static PyObject *__pyx_k_tuple_135;
+static PyObject *__pyx_k_tuple_106;
+static PyObject *__pyx_k_tuple_111;
+static PyObject *__pyx_k_tuple_126;
 static PyObject *__pyx_k_tuple_139;
-static PyObject *__pyx_k_tuple_140;
 static PyObject *__pyx_k_tuple_143;
+static PyObject *__pyx_k_tuple_144;
 static PyObject *__pyx_k_tuple_145;
-static PyObject *__pyx_k_codeobj_136;
-static PyObject *__pyx_k_codeobj_141;
-static PyObject *__pyx_k_codeobj_144;
+static PyObject *__pyx_k_tuple_148;
+static PyObject *__pyx_k_tuple_150;
+static PyObject *__pyx_k_codeobj_140;
 static PyObject *__pyx_k_codeobj_146;
+static PyObject *__pyx_k_codeobj_149;
+static PyObject *__pyx_k_codeobj_151;
 
 /* "_sa.pyx":5
  * import gzip
@@ -3333,6 +3444,372 @@ static PyObject *__pyx_pf_3_sa_gzip_or_text(CYTHON_UNUSED PyObject *__pyx_self,
   return __pyx_r;
 }
 
+/* Python wrapper */
+static int __pyx_pw_3_sa_9MemoryMap_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_3_sa_9MemoryMap_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_filename = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__filename,0};
+    PyObject* values[1] = {0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__filename)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+    }
+    __pyx_v_filename = values[0];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[9]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("_sa.MemoryMap.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_3_sa_9MemoryMap___init__(((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_self), __pyx_v_filename);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":20
+ * 
+ * cdef class MemoryMap:
+ *     def __init__(self, filename):             # <<<<<<<<<<<<<<
+ *         self.fd = posix.fcntl.open(filename, posix.fcntl.O_RDONLY)
+ *         assert self.fd >= 0
+ */
+
+static int __pyx_pf_3_sa_9MemoryMap___init__(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self, PyObject *__pyx_v_filename) {
+  struct stat __pyx_v_statbuf;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":21
+ * cdef class MemoryMap:
+ *     def __init__(self, filename):
+ *         self.fd = posix.fcntl.open(filename, posix.fcntl.O_RDONLY)             # <<<<<<<<<<<<<<
+ *         assert self.fd >= 0
+ *         # Get file size
+ */
+  __pyx_t_1 = PyBytes_AsString(__pyx_v_filename); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_self->fd = open(__pyx_t_1, O_RDONLY);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":22
+ *     def __init__(self, filename):
+ *         self.fd = posix.fcntl.open(filename, posix.fcntl.O_RDONLY)
+ *         assert self.fd >= 0             # <<<<<<<<<<<<<<
+ *         # Get file size
+ *         cdef stat statbuf
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!(__pyx_v_self->fd >= 0))) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[9]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  }
+  #endif
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":25
+ *         # Get file size
+ *         cdef stat statbuf
+ *         fstat(self.fd, &statbuf)             # <<<<<<<<<<<<<<
+ *         self.fs = statbuf.st_size
+ *         # Memory map file
+ */
+  fstat(__pyx_v_self->fd, (&__pyx_v_statbuf));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":26
+ *         cdef stat statbuf
+ *         fstat(self.fd, &statbuf)
+ *         self.fs = statbuf.st_size             # <<<<<<<<<<<<<<
+ *         # Memory map file
+ *         self.map_start = mmap(NULL, self.fs, PROT_READ, MAP_FILE|MAP_SHARED, self.fd, 0)
+ */
+  __pyx_v_self->fs = __pyx_v_statbuf.st_size;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":28
+ *         self.fs = statbuf.st_size
+ *         # Memory map file
+ *         self.map_start = mmap(NULL, self.fs, PROT_READ, MAP_FILE|MAP_SHARED, self.fd, 0)             # <<<<<<<<<<<<<<
+ *         self.map_ptr = self.map_start
+ * 
+ */
+  __pyx_v_self->map_start = mmap(NULL, __pyx_v_self->fs, PROT_READ, (MAP_FILE | MAP_SHARED), __pyx_v_self->fd, 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":29
+ *         # Memory map file
+ *         self.map_start = mmap(NULL, self.fs, PROT_READ, MAP_FILE|MAP_SHARED, self.fd, 0)
+ *         self.map_ptr = self.map_start             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
+ */
+  __pyx_v_self->map_ptr = __pyx_v_self->map_start;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.MemoryMap.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static void __pyx_pw_3_sa_9MemoryMap_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_3_sa_9MemoryMap_3__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_3_sa_9MemoryMap_2__dealloc__(((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":31
+ *         self.map_ptr = self.map_start
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         posix.unistd.close(self.fd)
+ *         munmap(self.map_start, self.fs)
+ */
+
+static void __pyx_pf_3_sa_9MemoryMap_2__dealloc__(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":32
+ * 
+ *     def __dealloc__(self):
+ *         posix.unistd.close(self.fd)             # <<<<<<<<<<<<<<
+ *         munmap(self.map_start, self.fs)
+ * 
+ */
+  close(__pyx_v_self->fd);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":33
+ *     def __dealloc__(self):
+ *         posix.unistd.close(self.fd)
+ *         munmap(self.map_start, self.fs)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef int read_int(self):
+ */
+  munmap(__pyx_v_self->map_start, __pyx_v_self->fs);
+
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":35
+ *         munmap(self.map_start, self.fs)
+ * 
+ *     cdef int read_int(self):             # <<<<<<<<<<<<<<
+ *         cdef int v = (<int*> self.map_ptr)[0]
+ *         self.map_ptr = &(<int*> self.map_ptr)[1]
+ */
+
+static int __pyx_f_3_sa_9MemoryMap_read_int(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self) {
+  int __pyx_v_v;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_int", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":36
+ * 
+ *     cdef int read_int(self):
+ *         cdef int v = (<int*> self.map_ptr)[0]             # <<<<<<<<<<<<<<
+ *         self.map_ptr = &(<int*> self.map_ptr)[1]
+ *         return v
+ */
+  __pyx_v_v = (((int *)__pyx_v_self->map_ptr)[0]);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":37
+ *     cdef int read_int(self):
+ *         cdef int v = (<int*> self.map_ptr)[0]
+ *         self.map_ptr = &(<int*> self.map_ptr)[1]             # <<<<<<<<<<<<<<
+ *         return v
+ * 
+ */
+  __pyx_v_self->map_ptr = (&(((int *)__pyx_v_self->map_ptr)[1]));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":38
+ *         cdef int v = (<int*> self.map_ptr)[0]
+ *         self.map_ptr = &(<int*> self.map_ptr)[1]
+ *         return v             # <<<<<<<<<<<<<<
+ * 
+ *     cdef int* read_int_array(self, int size):
+ */
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":40
+ *         return v
+ * 
+ *     cdef int* read_int_array(self, int size):             # <<<<<<<<<<<<<<
+ *         cdef int* v = <int*> self.map_ptr
+ *         self.map_ptr = &(<int*> self.map_ptr)[size]
+ */
+
+static int *__pyx_f_3_sa_9MemoryMap_read_int_array(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self, int __pyx_v_size) {
+  int *__pyx_v_v;
+  int *__pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_int_array", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":41
+ * 
+ *     cdef int* read_int_array(self, int size):
+ *         cdef int* v = <int*> self.map_ptr             # <<<<<<<<<<<<<<
+ *         self.map_ptr = &(<int*> self.map_ptr)[size]
+ *         return v
+ */
+  __pyx_v_v = ((int *)__pyx_v_self->map_ptr);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":42
+ *     cdef int* read_int_array(self, int size):
+ *         cdef int* v = <int*> self.map_ptr
+ *         self.map_ptr = &(<int*> self.map_ptr)[size]             # <<<<<<<<<<<<<<
+ *         return v
+ * 
+ */
+  __pyx_v_self->map_ptr = (&(((int *)__pyx_v_self->map_ptr)[__pyx_v_size]));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":43
+ *         cdef int* v = <int*> self.map_ptr
+ *         self.map_ptr = &(<int*> self.map_ptr)[size]
+ *         return v             # <<<<<<<<<<<<<<
+ * 
+ *     cdef char* read_char_array(self, int size):
+ */
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":45
+ *         return v
+ * 
+ *     cdef char* read_char_array(self, int size):             # <<<<<<<<<<<<<<
+ *         cdef char* v = <char*> self.map_ptr
+ *         self.map_ptr = &(<char*> self.map_ptr)[size]
+ */
+
+static char *__pyx_f_3_sa_9MemoryMap_read_char_array(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self, int __pyx_v_size) {
+  char *__pyx_v_v;
+  char *__pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_char_array", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":46
+ * 
+ *     cdef char* read_char_array(self, int size):
+ *         cdef char* v = <char*> self.map_ptr             # <<<<<<<<<<<<<<
+ *         self.map_ptr = &(<char*> self.map_ptr)[size]
+ *         return v
+ */
+  __pyx_v_v = ((char *)__pyx_v_self->map_ptr);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":47
+ *     cdef char* read_char_array(self, int size):
+ *         cdef char* v = <char*> self.map_ptr
+ *         self.map_ptr = &(<char*> self.map_ptr)[size]             # <<<<<<<<<<<<<<
+ *         return v
+ * 
+ */
+  __pyx_v_self->map_ptr = (&(((char *)__pyx_v_self->map_ptr)[__pyx_v_size]));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":48
+ *         cdef char* v = <char*> self.map_ptr
+ *         self.map_ptr = &(<char*> self.map_ptr)[size]
+ *         return v             # <<<<<<<<<<<<<<
+ * 
+ *     cdef float* read_float_array(self, int size):
+ */
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":50
+ *         return v
+ * 
+ *     cdef float* read_float_array(self, int size):             # <<<<<<<<<<<<<<
+ *         cdef float* v = <float*> self.map_ptr
+ *         self.map_ptr = &(<float*> self.map_ptr)[size]
+ */
+
+static float *__pyx_f_3_sa_9MemoryMap_read_float_array(struct __pyx_obj_3_sa_MemoryMap *__pyx_v_self, int __pyx_v_size) {
+  float *__pyx_v_v;
+  float *__pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_float_array", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":51
+ * 
+ *     cdef float* read_float_array(self, int size):
+ *         cdef float* v = <float*> self.map_ptr             # <<<<<<<<<<<<<<
+ *         self.map_ptr = &(<float*> self.map_ptr)[size]
+ *         return v
+ */
+  __pyx_v_v = ((float *)__pyx_v_self->map_ptr);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":52
+ *     cdef float* read_float_array(self, int size):
+ *         cdef float* v = <float*> self.map_ptr
+ *         self.map_ptr = &(<float*> self.map_ptr)[size]             # <<<<<<<<<<<<<<
+ *         return v
+ */
+  __pyx_v_self->map_ptr = (&(((float *)__pyx_v_self->map_ptr)[__pyx_v_size]));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/mmap.pxi":53
+ *         cdef float* v = <float*> self.map_ptr
+ *         self.map_ptr = &(<float*> self.map_ptr)[size]
+ *         return v             # <<<<<<<<<<<<<<
+ */
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 /* Python wrapper */
 static int __pyx_pw_3_sa_9FloatList_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static int __pyx_pw_3_sa_9FloatList_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
@@ -3482,7 +3959,7 @@ static int __pyx_pf_3_sa_9FloatList___cinit__(struct __pyx_obj_3_sa_FloatList *_
  *         self.len = initial_len
  *         self.arr = <float*> malloc(size*sizeof(float))             # <<<<<<<<<<<<<<
  *         memset(self.arr, 0, initial_len*sizeof(float))
- * 
+ *         self.memory = self
  */
   __pyx_v_self->arr = ((float *)malloc((__pyx_v_size * (sizeof(float)))));
 
@@ -3490,11 +3967,24 @@ static int __pyx_pf_3_sa_9FloatList___cinit__(struct __pyx_obj_3_sa_FloatList *_
  *         self.len = initial_len
  *         self.arr = <float*> malloc(size*sizeof(float))
  *         memset(self.arr, 0, initial_len*sizeof(float))             # <<<<<<<<<<<<<<
+ *         self.memory = self
  * 
- *     def __dealloc__(self):
  */
   memset(__pyx_v_self->arr, 0, (__pyx_v_initial_len * (sizeof(float))));
 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":19
+ *         self.arr = <float*> malloc(size*sizeof(float))
+ *         memset(self.arr, 0, initial_len*sizeof(float))
+ *         self.memory = self             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __Pyx_GOTREF(__pyx_v_self->memory);
+  __Pyx_DECREF(__pyx_v_self->memory);
+  __pyx_v_self->memory = ((PyObject *)__pyx_v_self);
+
   __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
@@ -3509,26 +3999,40 @@ static void __pyx_pw_3_sa_9FloatList_3__dealloc__(PyObject *__pyx_v_self) {
   __Pyx_RefNannyFinishContext();
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":20
- *         memset(self.arr, 0, initial_len*sizeof(float))
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":21
+ *         self.memory = self
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
- *         free(self.arr)
- * 
+ *         if self.memory is self:
+ *             free(self.arr)
  */
 
 static void __pyx_pf_3_sa_9FloatList_2__dealloc__(struct __pyx_obj_3_sa_FloatList *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
   __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":21
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":22
  * 
  *     def __dealloc__(self):
- *         free(self.arr)             # <<<<<<<<<<<<<<
+ *         if self.memory is self:             # <<<<<<<<<<<<<<
+ *             free(self.arr)
+ * 
+ */
+  __pyx_t_1 = (__pyx_v_self->memory == ((PyObject *)__pyx_v_self));
+  if (__pyx_t_1) {
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":23
+ *     def __dealloc__(self):
+ *         if self.memory is self:
+ *             free(self.arr)             # <<<<<<<<<<<<<<
  * 
  *     def __getitem__(self, i):
  */
-  free(__pyx_v_self->arr);
+    free(__pyx_v_self->arr);
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
 
   __Pyx_RefNannyFinishContext();
 }
@@ -3544,8 +4048,8 @@ static PyObject *__pyx_pw_3_sa_9FloatList_5__getitem__(PyObject *__pyx_v_self, P
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":23
- *         free(self.arr)
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":25
+ *             free(self.arr)
  * 
  *     def __getitem__(self, i):             # <<<<<<<<<<<<<<
  *         j = i
@@ -3567,7 +4071,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":24
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":26
  * 
  *     def __getitem__(self, i):
  *         j = i             # <<<<<<<<<<<<<<
@@ -3577,28 +4081,28 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
   __Pyx_INCREF(__pyx_v_i);
   __pyx_v_j = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":25
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":27
  *     def __getitem__(self, i):
  *         j = i
  *         if i<0:             # <<<<<<<<<<<<<<
  *             j = self.len + i
  *         if j<0 or j>=self.len:
  */
-  __pyx_t_1 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_RichCompare(__pyx_v_i, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":26
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":28
  *         j = i
  *         if i<0:
  *             j = self.len + i             # <<<<<<<<<<<<<<
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))
  */
-    __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(__pyx_v_j);
@@ -3608,22 +4112,22 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":27
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":29
  *         if i<0:
  *             j = self.len + i
  *         if j<0 or j>=self.len:             # <<<<<<<<<<<<<<
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))
  *         return self.arr[j]
  */
-  __pyx_t_3 = PyObject_RichCompare(__pyx_v_j, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_RichCompare(__pyx_v_j, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   if (!__pyx_t_2) {
-    __pyx_t_3 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_RichCompare(__pyx_v_j, __pyx_t_3, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_RichCompare(__pyx_v_j, __pyx_t_3, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_t_5 = __pyx_t_4;
   } else {
@@ -3631,16 +4135,16 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
   }
   if (__pyx_t_5) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":28
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":30
  *             j = self.len + i
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))             # <<<<<<<<<<<<<<
  *         return self.arr[j]
  * 
  */
-    __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_INCREF(__pyx_v_i);
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_i);
@@ -3648,25 +4152,25 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
     PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
     __Pyx_GIVEREF(__pyx_t_1);
     __pyx_t_1 = 0;
-    __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_1));
     __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_1));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
     __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
     __Pyx_Raise(__pyx_t_1, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L4;
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":29
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":31
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))
  *         return self.arr[j]             # <<<<<<<<<<<<<<
@@ -3674,8 +4178,8 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
  *     cdef void set(self, int i, float v):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_v_j); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->arr[__pyx_t_6])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = __Pyx_PyIndex_AsSsize_t(__pyx_v_j); if (unlikely((__pyx_t_6 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->arr[__pyx_t_6])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
@@ -3695,7 +4199,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_4__getitem__(struct __pyx_obj_3_sa_Flo
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":31
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":33
  *         return self.arr[j]
  * 
  *     cdef void set(self, int i, float v):             # <<<<<<<<<<<<<<
@@ -3717,7 +4221,7 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("set", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":32
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":34
  * 
  *     cdef void set(self, int i, float v):
  *         j = i             # <<<<<<<<<<<<<<
@@ -3726,7 +4230,7 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
  */
   __pyx_v_j = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":33
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":35
  *     cdef void set(self, int i, float v):
  *         j = i
  *         if i<0:             # <<<<<<<<<<<<<<
@@ -3736,7 +4240,7 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
   __pyx_t_1 = (__pyx_v_i < 0);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":34
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":36
  *         j = i
  *         if i<0:
  *             j = self.len + i             # <<<<<<<<<<<<<<
@@ -3748,7 +4252,7 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":35
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":37
  *         if i<0:
  *             j = self.len + i
  *         if j<0 or j>=self.len:             # <<<<<<<<<<<<<<
@@ -3764,18 +4268,18 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
   }
   if (__pyx_t_3) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":36
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":38
  *             j = self.len + i
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))             # <<<<<<<<<<<<<<
  *         self.arr[j] = v
  * 
  */
-    __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
     __Pyx_GIVEREF(__pyx_t_4);
@@ -3783,25 +4287,25 @@ static void __pyx_f_3_sa_9FloatList_set(struct __pyx_obj_3_sa_FloatList *__pyx_v
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_4 = 0;
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_2), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_5));
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
-    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[1]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L4;
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":37
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":39
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length FloatList" % (i, self.len))
  *         self.arr[j] = v             # <<<<<<<<<<<<<<
@@ -3831,7 +4335,7 @@ static int __pyx_pw_3_sa_9FloatList_7__setitem__(PyObject *__pyx_v_self, PyObjec
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":39
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":41
  *         self.arr[j] = v
  * 
  *     def __setitem__(self, i, val):             # <<<<<<<<<<<<<<
@@ -3849,15 +4353,15 @@ static int __pyx_pf_3_sa_9FloatList_6__setitem__(struct __pyx_obj_3_sa_FloatList
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setitem__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":40
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":42
  * 
  *     def __setitem__(self, i, val):
  *         self.set(i, val)             # <<<<<<<<<<<<<<
  * 
  *     def __len__(self):
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_v_val); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __pyx_PyFloat_AsFloat(__pyx_v_val); if (unlikely((__pyx_t_2 == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->__pyx_vtab)->set(__pyx_v_self, __pyx_t_1, __pyx_t_2);
 
   __pyx_r = 0;
@@ -3881,7 +4385,7 @@ static Py_ssize_t __pyx_pw_3_sa_9FloatList_9__len__(PyObject *__pyx_v_self) {
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":42
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":44
  *         self.set(i, val)
  * 
  *     def __len__(self):             # <<<<<<<<<<<<<<
@@ -3894,7 +4398,7 @@ static Py_ssize_t __pyx_pf_3_sa_9FloatList_8__len__(struct __pyx_obj_3_sa_FloatL
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__len__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":43
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":45
  * 
  *     def __len__(self):
  *         return self.len             # <<<<<<<<<<<<<<
@@ -3918,7 +4422,7 @@ static PyObject *__pyx_pw_3_sa_9FloatList_11append(PyObject *__pyx_v_self, PyObj
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("append (wrapper)", 0);
   assert(__pyx_arg_val); {
-    __pyx_v_val = __pyx_PyFloat_AsFloat(__pyx_arg_val); if (unlikely((__pyx_v_val == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_val = __pyx_PyFloat_AsFloat(__pyx_arg_val); if (unlikely((__pyx_v_val == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -3931,7 +4435,7 @@ static PyObject *__pyx_pw_3_sa_9FloatList_11append(PyObject *__pyx_v_self, PyObj
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":45
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":47
  *         return self.len
  * 
  *     def append(self, float val):             # <<<<<<<<<<<<<<
@@ -3945,7 +4449,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("append", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":46
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":48
  * 
  *     def append(self, float val):
  *         if self.len == self.size:             # <<<<<<<<<<<<<<
@@ -3955,7 +4459,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
   __pyx_t_1 = (__pyx_v_self->len == __pyx_v_self->size);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":47
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":49
  *     def append(self, float val):
  *         if self.len == self.size:
  *             self.size = self.size + self.increment             # <<<<<<<<<<<<<<
@@ -3964,7 +4468,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
  */
     __pyx_v_self->size = (__pyx_v_self->size + __pyx_v_self->increment);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":48
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":50
  *         if self.len == self.size:
  *             self.size = self.size + self.increment
  *             self.arr = <float*> realloc(self.arr, self.size*sizeof(float))             # <<<<<<<<<<<<<<
@@ -3976,7 +4480,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":49
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":51
  *             self.size = self.size + self.increment
  *             self.arr = <float*> realloc(self.arr, self.size*sizeof(float))
  *         self.arr[self.len] = val             # <<<<<<<<<<<<<<
@@ -3985,7 +4489,7 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
  */
   (__pyx_v_self->arr[__pyx_v_self->len]) = __pyx_v_val;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":50
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":52
  *             self.arr = <float*> realloc(self.arr, self.size*sizeof(float))
  *         self.arr[self.len] = val
  *         self.len = self.len + 1             # <<<<<<<<<<<<<<
@@ -4000,11 +4504,11 @@ static PyObject *__pyx_pf_3_sa_9FloatList_10append(struct __pyx_obj_3_sa_FloatLi
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":52
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":54
  *         self.len = self.len + 1
  * 
  *     cdef void write_handle(self, FILE* f):             # <<<<<<<<<<<<<<
- *         fwrite(&(self.len), sizeof(float), 1, f)
+ *         fwrite(&(self.len), sizeof(int), 1, f)
  *         fwrite(self.arr, sizeof(float), self.len, f)
  */
 
@@ -4012,136 +4516,68 @@ static void __pyx_f_3_sa_9FloatList_write_handle(struct __pyx_obj_3_sa_FloatList
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":53
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":55
  * 
  *     cdef void write_handle(self, FILE* f):
- *         fwrite(&(self.len), sizeof(float), 1, f)             # <<<<<<<<<<<<<<
+ *         fwrite(&(self.len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
  *         fwrite(self.arr, sizeof(float), self.len, f)
  * 
  */
-  fwrite((&__pyx_v_self->len), (sizeof(float)), 1, __pyx_v_f);
+  fwrite((&__pyx_v_self->len), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":54
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":56
  *     cdef void write_handle(self, FILE* f):
- *         fwrite(&(self.len), sizeof(float), 1, f)
+ *         fwrite(&(self.len), sizeof(int), 1, f)
  *         fwrite(self.arr, sizeof(float), self.len, f)             # <<<<<<<<<<<<<<
  * 
- *     def write(self, char* filename):
+ *     cdef void read_handle(self, FILE* f):
  */
   fwrite(__pyx_v_self->arr, (sizeof(float)), __pyx_v_self->len, __pyx_v_f);
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9FloatList_13write(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9FloatList_13write(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.FloatList.write", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9FloatList_12write(((struct __pyx_obj_3_sa_FloatList *)__pyx_v_self), ((char *)__pyx_v_filename));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":56
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":58
  *         fwrite(self.arr, sizeof(float), self.len, f)
  * 
- *     def write(self, char* filename):             # <<<<<<<<<<<<<<
- *         cdef FILE* f
- *         f = fopen(filename, "w")
- */
-
-static PyObject *__pyx_pf_3_sa_9FloatList_12write(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, char *__pyx_v_filename) {
-  FILE *__pyx_v_f;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":58
- *     def write(self, char* filename):
- *         cdef FILE* f
- *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
- *         self.write_handle(f)
- *         fclose(f)
- */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":59
- *         cdef FILE* f
- *         f = fopen(filename, "w")
- *         self.write_handle(f)             # <<<<<<<<<<<<<<
- *         fclose(f)
- * 
- */
-  ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->__pyx_vtab)->write_handle(__pyx_v_self, __pyx_v_f);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":60
- *         f = fopen(filename, "w")
- *         self.write_handle(f)
- *         fclose(f)             # <<<<<<<<<<<<<<
- * 
- *     cdef void read_handle(self, FILE* f):
- */
-  fclose(__pyx_v_f);
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":62
- *         fclose(f)
- * 
  *     cdef void read_handle(self, FILE* f):             # <<<<<<<<<<<<<<
  *         free(self.arr)
- *         fread(&(self.len), sizeof(float), 1, f)
+ *         fread(&(self.len), sizeof(int), 1, f)
  */
 
 static void __pyx_f_3_sa_9FloatList_read_handle(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, FILE *__pyx_v_f) {
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":63
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":59
  * 
  *     cdef void read_handle(self, FILE* f):
  *         free(self.arr)             # <<<<<<<<<<<<<<
- *         fread(&(self.len), sizeof(float), 1, f)
+ *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <float*> malloc(self.len * sizeof(float))
  */
   free(__pyx_v_self->arr);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":64
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":60
  *     cdef void read_handle(self, FILE* f):
  *         free(self.arr)
- *         fread(&(self.len), sizeof(float), 1, f)             # <<<<<<<<<<<<<<
+ *         fread(&(self.len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
  *         self.arr = <float*> malloc(self.len * sizeof(float))
  *         self.size = self.len
  */
-  fread((&__pyx_v_self->len), (sizeof(float)), 1, __pyx_v_f);
+  fread((&__pyx_v_self->len), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":65
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":61
  *         free(self.arr)
- *         fread(&(self.len), sizeof(float), 1, f)
+ *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <float*> malloc(self.len * sizeof(float))             # <<<<<<<<<<<<<<
  *         self.size = self.len
  *         fread(self.arr, sizeof(float), self.len, f)
  */
   __pyx_v_self->arr = ((float *)malloc((__pyx_v_self->len * (sizeof(float)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":66
- *         fread(&(self.len), sizeof(float), 1, f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":62
+ *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <float*> malloc(self.len * sizeof(float))
  *         self.size = self.len             # <<<<<<<<<<<<<<
  *         fread(self.arr, sizeof(float), self.len, f)
@@ -4149,81 +4585,71 @@ static void __pyx_f_3_sa_9FloatList_read_handle(struct __pyx_obj_3_sa_FloatList
  */
   __pyx_v_self->size = __pyx_v_self->len;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":67
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":63
  *         self.arr = <float*> malloc(self.len * sizeof(float))
  *         self.size = self.len
  *         fread(self.arr, sizeof(float), self.len, f)             # <<<<<<<<<<<<<<
  * 
- *     def read(self, char* filename):
+ *     cdef void read_mmaped(self, MemoryMap buf):
  */
   fread(__pyx_v_self->arr, (sizeof(float)), __pyx_v_self->len, __pyx_v_f);
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9FloatList_15read(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9FloatList_15read(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("read (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.FloatList.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9FloatList_14read(((struct __pyx_obj_3_sa_FloatList *)__pyx_v_self), ((char *)__pyx_v_filename));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":69
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":65
  *         fread(self.arr, sizeof(float), self.len, f)
  * 
- *     def read(self, char* filename):             # <<<<<<<<<<<<<<
- *         cdef FILE* f
- *         f = fopen(filename, "r")
+ *     cdef void read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()
  */
 
-static PyObject *__pyx_pf_3_sa_9FloatList_14read(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, char *__pyx_v_filename) {
-  FILE *__pyx_v_f;
-  PyObject *__pyx_r = NULL;
+static void __pyx_f_3_sa_9FloatList_read_mmaped(struct __pyx_obj_3_sa_FloatList *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("read", 0);
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":71
- *     def read(self, char* filename):
- *         cdef FILE* f
- *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
- *         self.read_handle(f)
- *         fclose(f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":66
+ * 
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         free(self.arr)             # <<<<<<<<<<<<<<
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_float_array(self.len)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  free(__pyx_v_self->arr);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":72
- *         cdef FILE* f
- *         f = fopen(filename, "r")
- *         self.read_handle(f)             # <<<<<<<<<<<<<<
- *         fclose(f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":67
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.arr = buf.read_float_array(self.len)
+ *         self.memory = buf
  */
-  ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->__pyx_vtab)->read_handle(__pyx_v_self, __pyx_v_f);
+  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+  __pyx_v_self->size = __pyx_t_1;
+  __pyx_v_self->len = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":73
- *         f = fopen(filename, "r")
- *         self.read_handle(f)
- *         fclose(f)             # <<<<<<<<<<<<<<
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":68
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_float_array(self.len)             # <<<<<<<<<<<<<<
+ *         self.memory = buf
  */
-  fclose(__pyx_v_f);
+  __pyx_v_self->arr = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_float_array(__pyx_v_buf, __pyx_v_self->len);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/float_list.pxi":69
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_float_array(self.len)
+ *         self.memory = buf             # <<<<<<<<<<<<<<
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GOTREF(__pyx_v_self->memory);
+  __Pyx_DECREF(__pyx_v_self->memory);
+  __pyx_v_self->memory = ((PyObject *)__pyx_v_buf);
 
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
 }
 
 /* Python wrapper */
@@ -4375,7 +4801,7 @@ static int __pyx_pf_3_sa_7IntList___cinit__(struct __pyx_obj_3_sa_IntList *__pyx
  *         self.len = initial_len
  *         self.arr = <int*> malloc(size*sizeof(int))             # <<<<<<<<<<<<<<
  *         memset(self.arr, 0, initial_len*sizeof(int))
- * 
+ *         self.memory = self
  */
   __pyx_v_self->arr = ((int *)malloc((__pyx_v_size * (sizeof(int)))));
 
@@ -4383,185 +4809,89 @@ static int __pyx_pf_3_sa_7IntList___cinit__(struct __pyx_obj_3_sa_IntList *__pyx
  *         self.len = initial_len
  *         self.arr = <int*> malloc(size*sizeof(int))
  *         memset(self.arr, 0, initial_len*sizeof(int))             # <<<<<<<<<<<<<<
+ *         self.memory = self
  * 
- *     def __str__(self):
  */
   memset(__pyx_v_self->arr, 0, (__pyx_v_initial_len * (sizeof(int))));
 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":19
+ *         self.arr = <int*> malloc(size*sizeof(int))
+ *         memset(self.arr, 0, initial_len*sizeof(int))
+ *         self.memory = self             # <<<<<<<<<<<<<<
+ * 
+ *     def __repr__(self):
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __Pyx_GOTREF(__pyx_v_self->memory);
+  __Pyx_DECREF(__pyx_v_self->memory);
+  __pyx_v_self->memory = ((PyObject *)__pyx_v_self);
+
   __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_3__str__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_3__str__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_3_sa_7IntList_3__repr__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_3__repr__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__str__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_2__str__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__repr__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_7IntList_2__repr__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":20
- *         memset(self.arr, 0, initial_len*sizeof(int))
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":21
+ *         self.memory = self
+ * 
+ *     def __repr__(self):             # <<<<<<<<<<<<<<
+ *         return 'IntList(%s)' % list(self)
  * 
- *     def __str__(self):             # <<<<<<<<<<<<<<
- *         cdef unsigned i
- *         ret = "IntList["
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_2__str__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  PyObject *__pyx_v_ret = NULL;
-  int __pyx_v_idx;
+static PyObject *__pyx_pf_3_sa_7IntList_2__repr__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__str__", 0);
+  __Pyx_RefNannySetupContext("__repr__", 0);
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":22
- *     def __str__(self):
- *         cdef unsigned i
- *         ret = "IntList["             # <<<<<<<<<<<<<<
- *         for idx in range(self.size):
- *             if idx>0:
- */
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_3));
-  __pyx_v_ret = ((PyObject *)__pyx_kp_s_3);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":23
- *         cdef unsigned i
- *         ret = "IntList["
- *         for idx in range(self.size):             # <<<<<<<<<<<<<<
- *             if idx>0:
- *                 ret += ","
- */
-  __pyx_t_1 = __pyx_v_self->size;
-  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
-    __pyx_v_idx = __pyx_t_2;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":24
- *         ret = "IntList["
- *         for idx in range(self.size):
- *             if idx>0:             # <<<<<<<<<<<<<<
- *                 ret += ","
- *             ret += str(self.arr[idx])
- */
-    __pyx_t_3 = (__pyx_v_idx > 0);
-    if (__pyx_t_3) {
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":25
- *         for idx in range(self.size):
- *             if idx>0:
- *                 ret += ","             # <<<<<<<<<<<<<<
- *             ret += str(self.arr[idx])
- *         ret += "]"
- */
-      __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_ret, ((PyObject *)__pyx_kp_s_4)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_v_ret);
-      __pyx_v_ret = __pyx_t_4;
-      __pyx_t_4 = 0;
-      goto __pyx_L5;
-    }
-    __pyx_L5:;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":26
- *             if idx>0:
- *                 ret += ","
- *             ret += str(self.arr[idx])             # <<<<<<<<<<<<<<
- *         ret += "]"
- *         ret += "len="
- */
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_idx])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
-    __Pyx_GIVEREF(__pyx_t_4);
-    __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_Call(((PyObject *)((PyObject*)(&PyString_Type))), ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-    __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_v_ret, __pyx_t_4); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_v_ret);
-    __pyx_v_ret = __pyx_t_5;
-    __pyx_t_5 = 0;
-  }
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":27
- *                 ret += ","
- *             ret += str(self.arr[idx])
- *         ret += "]"             # <<<<<<<<<<<<<<
- *         ret += "len="
- *         ret += self.len
- */
-  __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_v_ret, ((PyObject *)__pyx_kp_s_5)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_v_ret);
-  __pyx_v_ret = __pyx_t_5;
-  __pyx_t_5 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":28
- *             ret += str(self.arr[idx])
- *         ret += "]"
- *         ret += "len="             # <<<<<<<<<<<<<<
- *         ret += self.len
- *         return ret
- */
-  __pyx_t_5 = PyNumber_InPlaceAdd(__pyx_v_ret, ((PyObject *)__pyx_kp_s_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_v_ret);
-  __pyx_v_ret = __pyx_t_5;
-  __pyx_t_5 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":29
- *         ret += "]"
- *         ret += "len="
- *         ret += self.len             # <<<<<<<<<<<<<<
- *         return ret
  * 
- */
-  __pyx_t_5 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_ret, __pyx_t_5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __Pyx_DECREF(__pyx_v_ret);
-  __pyx_v_ret = __pyx_t_4;
-  __pyx_t_4 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":30
- *         ret += "len="
- *         ret += self.len
- *         return ret             # <<<<<<<<<<<<<<
+ *     def __repr__(self):
+ *         return 'IntList(%s)' % list(self)             # <<<<<<<<<<<<<<
  * 
  *     def index(self, val):
  */
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_ret);
-  __pyx_r = __pyx_v_ret;
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyList_Type))), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_3), __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_r = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("_sa.IntList.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("_sa.IntList.__repr__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_ret);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
@@ -4578,8 +4908,8 @@ static PyObject *__pyx_pw_3_sa_7IntList_5index(PyObject *__pyx_v_self, PyObject
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":32
- *         return ret
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":24
+ *         return 'IntList(%s)' % list(self)
  * 
  *     def index(self, val):             # <<<<<<<<<<<<<<
  *         cdef unsigned i
@@ -4600,7 +4930,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_4index(struct __pyx_obj_3_sa_IntList *__
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("index", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":34
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":26
  *     def index(self, val):
  *         cdef unsigned i
  *         for i in range(self.len):             # <<<<<<<<<<<<<<
@@ -4611,30 +4941,30 @@ static PyObject *__pyx_pf_3_sa_7IntList_4index(struct __pyx_obj_3_sa_IntList *__
   for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
     __pyx_v_i = __pyx_t_2;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":35
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":27
  *         cdef unsigned i
  *         for i in range(self.len):
  *             if self.arr[i] == val:             # <<<<<<<<<<<<<<
  *                 return i
- *         return IndexError
+ *         raise ValueError('%s not in list' % val)
  */
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_val, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_v_val, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     if (__pyx_t_5) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":36
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":28
  *         for i in range(self.len):
  *             if self.arr[i] == val:
  *                 return i             # <<<<<<<<<<<<<<
- *         return IndexError
+ *         raise ValueError('%s not in list' % val)
  * 
  */
       __Pyx_XDECREF(__pyx_r);
-      __pyx_t_4 = PyLong_FromUnsignedLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyLong_FromUnsignedLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __pyx_r = __pyx_t_4;
       __pyx_t_4 = 0;
@@ -4644,17 +4974,26 @@ static PyObject *__pyx_pf_3_sa_7IntList_4index(struct __pyx_obj_3_sa_IntList *__
     __pyx_L5:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":37
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":29
  *             if self.arr[i] == val:
  *                 return i
- *         return IndexError             # <<<<<<<<<<<<<<
+ *         raise ValueError('%s not in list' % val)             # <<<<<<<<<<<<<<
  * 
- *     def partition(self,start,end):
+ *     def reset(self):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_builtin_IndexError);
-  __pyx_r = __pyx_builtin_IndexError;
-  goto __pyx_L0;
+  __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_4), __pyx_v_val); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_4));
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_4));
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
+  __pyx_t_4 = 0;
+  __pyx_t_4 = PyObject_Call(__pyx_builtin_ValueError, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_Raise(__pyx_t_4, 0, 0, 0);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
@@ -4670,756 +5009,134 @@ static PyObject *__pyx_pf_3_sa_7IntList_4index(struct __pyx_obj_3_sa_IntList *__
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_7partition(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_7partition(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_start = 0;
-  PyObject *__pyx_v_end = 0;
+static PyObject *__pyx_pw_3_sa_7IntList_7reset(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_7reset(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("partition (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__start,&__pyx_n_s__end,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__start)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__end)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("partition", 1, 2, 2, 1); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "partition") < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_start = values[0];
-    __pyx_v_end = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("partition", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.IntList.partition", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_7IntList_6partition(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), __pyx_v_start, __pyx_v_end);
+  __Pyx_RefNannySetupContext("reset (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_7IntList_6reset(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":39
- *         return IndexError
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":31
+ *         raise ValueError('%s not in list' % val)
+ * 
+ *     def reset(self):             # <<<<<<<<<<<<<<
+ *         self.len = 0
  * 
- *     def partition(self,start,end):             # <<<<<<<<<<<<<<
- *         pivot = self.arr[end]
- *         bottom = start-1
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_6partition(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_start, PyObject *__pyx_v_end) {
-  PyObject *__pyx_v_pivot = NULL;
-  PyObject *__pyx_v_bottom = NULL;
-  PyObject *__pyx_v_top = NULL;
-  long __pyx_v_done;
+static PyObject *__pyx_pf_3_sa_7IntList_6reset(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  Py_ssize_t __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  Py_ssize_t __pyx_t_5;
-  int __pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("partition", 0);
+  __Pyx_RefNannySetupContext("reset", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":40
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":32
  * 
- *     def partition(self,start,end):
- *         pivot = self.arr[end]             # <<<<<<<<<<<<<<
- *         bottom = start-1
- *         top = end
- */
-  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_end); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_pivot = __pyx_t_2;
-  __pyx_t_2 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":41
- *     def partition(self,start,end):
- *         pivot = self.arr[end]
- *         bottom = start-1             # <<<<<<<<<<<<<<
- *         top = end
- *         done = 0
- */
-  __pyx_t_2 = PyNumber_Subtract(__pyx_v_start, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_bottom = __pyx_t_2;
-  __pyx_t_2 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":42
- *         pivot = self.arr[end]
- *         bottom = start-1
- *         top = end             # <<<<<<<<<<<<<<
- *         done = 0
- *         while not done:
- */
-  __Pyx_INCREF(__pyx_v_end);
-  __pyx_v_top = __pyx_v_end;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":43
- *         bottom = start-1
- *         top = end
- *         done = 0             # <<<<<<<<<<<<<<
- *         while not done:
- *             while not done:
- */
-  __pyx_v_done = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":44
- *         top = end
- *         done = 0
- *         while not done:             # <<<<<<<<<<<<<<
- *             while not done:
- *                 bottom += 1
- */
-  while (1) {
-    __pyx_t_3 = (!__pyx_v_done);
-    if (!__pyx_t_3) break;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":45
- *         done = 0
- *         while not done:
- *             while not done:             # <<<<<<<<<<<<<<
- *                 bottom += 1
- *                 if bottom == top:
- */
-    while (1) {
-      __pyx_t_3 = (!__pyx_v_done);
-      if (!__pyx_t_3) break;
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":46
- *         while not done:
- *             while not done:
- *                 bottom += 1             # <<<<<<<<<<<<<<
- *                 if bottom == top:
- *                     done = 1
- */
-      __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_bottom, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_v_bottom);
-      __pyx_v_bottom = __pyx_t_2;
-      __pyx_t_2 = 0;
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":47
- *             while not done:
- *                 bottom += 1
- *                 if bottom == top:             # <<<<<<<<<<<<<<
- *                     done = 1
- *                     break
- */
-      __pyx_t_2 = PyObject_RichCompare(__pyx_v_bottom, __pyx_v_top, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__pyx_t_3) {
-
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":48
- *                 bottom += 1
- *                 if bottom == top:
- *                     done = 1             # <<<<<<<<<<<<<<
- *                     break
- *                 if self.arr[bottom] > pivot:
- */
-        __pyx_v_done = 1;
-
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":49
- *                 if bottom == top:
- *                     done = 1
- *                     break             # <<<<<<<<<<<<<<
- *                 if self.arr[bottom] > pivot:
- *                     self.arr[top] = self.arr[bottom]
- */
-        goto __pyx_L6_break;
-        goto __pyx_L7;
-      }
-      __pyx_L7:;
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":50
- *                     done = 1
- *                     break
- *                 if self.arr[bottom] > pivot:             # <<<<<<<<<<<<<<
- *                     self.arr[top] = self.arr[bottom]
- *                     break
- */
-      __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_bottom); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_2 = PyInt_FromLong((__pyx_v_self->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = PyObject_RichCompare(__pyx_t_2, __pyx_v_pivot, Py_GT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (__pyx_t_3) {
-
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":51
- *                     break
- *                 if self.arr[bottom] > pivot:
- *                     self.arr[top] = self.arr[bottom]             # <<<<<<<<<<<<<<
- *                     break
- *             while not done:
- */
-        __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_bottom); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_top); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        (__pyx_v_self->arr[__pyx_t_5]) = (__pyx_v_self->arr[__pyx_t_1]);
-
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":52
- *                 if self.arr[bottom] > pivot:
- *                     self.arr[top] = self.arr[bottom]
- *                     break             # <<<<<<<<<<<<<<
- *             while not done:
- *                 top -= 1
- */
-        goto __pyx_L6_break;
-        goto __pyx_L8;
-      }
-      __pyx_L8:;
-    }
-    __pyx_L6_break:;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":53
- *                     self.arr[top] = self.arr[bottom]
- *                     break
- *             while not done:             # <<<<<<<<<<<<<<
- *                 top -= 1
- *                 if top == bottom:
- */
-    while (1) {
-      __pyx_t_3 = (!__pyx_v_done);
-      if (!__pyx_t_3) break;
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":54
- *                     break
- *             while not done:
- *                 top -= 1             # <<<<<<<<<<<<<<
- *                 if top == bottom:
- *                     done = 1
- */
-      __pyx_t_4 = PyNumber_InPlaceSubtract(__pyx_v_top, __pyx_int_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_v_top);
-      __pyx_v_top = __pyx_t_4;
-      __pyx_t_4 = 0;
-
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":55
- *             while not done:
- *                 top -= 1
- *                 if top == bottom:             # <<<<<<<<<<<<<<
- *                     done = 1
- *                     break
- */
-      __pyx_t_4 = PyObject_RichCompare(__pyx_v_top, __pyx_v_bottom, Py_EQ); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (__pyx_t_3) {
-
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":56
- *                 top -= 1
- *                 if top == bottom:
- *                     done = 1             # <<<<<<<<<<<<<<
- *                     break
- *                 if self.arr[top] < pivot:
+ *     def reset(self):
+ *         self.len = 0             # <<<<<<<<<<<<<<
+ * 
+ *     def __dealloc__(self):
  */
-        __pyx_v_done = 1;
+  __pyx_v_self->len = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":57
- *                 if top == bottom:
- *                     done = 1
- *                     break             # <<<<<<<<<<<<<<
- *                 if self.arr[top] < pivot:
- *                     self.arr[bottom] = self.arr[top]
- */
-        goto __pyx_L10_break;
-        goto __pyx_L11;
-      }
-      __pyx_L11:;
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":58
- *                     done = 1
- *                     break
- *                 if self.arr[top] < pivot:             # <<<<<<<<<<<<<<
- *                     self.arr[bottom] = self.arr[top]
- *                     break
- */
-      __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_top); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_4 = PyInt_FromLong((__pyx_v_self->arr[__pyx_t_1])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_2 = PyObject_RichCompare(__pyx_t_4, __pyx_v_pivot, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__pyx_t_3) {
+/* Python wrapper */
+static void __pyx_pw_3_sa_7IntList_9__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_3_sa_7IntList_9__dealloc__(PyObject *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_3_sa_7IntList_8__dealloc__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+}
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":59
- *                     break
- *                 if self.arr[top] < pivot:
- *                     self.arr[bottom] = self.arr[top]             # <<<<<<<<<<<<<<
- *                     break
- *         self.arr[top] = pivot
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":34
+ *         self.len = 0
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         if self.memory is self:
+ *             free(self.arr)
  */
-        __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_top); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_5 = __Pyx_PyIndex_AsSsize_t(__pyx_v_bottom); if (unlikely((__pyx_t_5 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        (__pyx_v_self->arr[__pyx_t_5]) = (__pyx_v_self->arr[__pyx_t_1]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":60
- *                 if self.arr[top] < pivot:
- *                     self.arr[bottom] = self.arr[top]
- *                     break             # <<<<<<<<<<<<<<
- *         self.arr[top] = pivot
- *         return top
- */
-        goto __pyx_L10_break;
-        goto __pyx_L12;
-      }
-      __pyx_L12:;
-    }
-    __pyx_L10_break:;
-  }
+static void __pyx_pf_3_sa_7IntList_8__dealloc__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":61
- *                     self.arr[bottom] = self.arr[top]
- *                     break
- *         self.arr[top] = pivot             # <<<<<<<<<<<<<<
- *         return top
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":35
+ * 
+ *     def __dealloc__(self):
+ *         if self.memory is self:             # <<<<<<<<<<<<<<
+ *             free(self.arr)
  * 
  */
-  __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_v_pivot); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_top); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  (__pyx_v_self->arr[__pyx_t_1]) = __pyx_t_6;
+  __pyx_t_1 = (__pyx_v_self->memory == ((PyObject *)__pyx_v_self));
+  if (__pyx_t_1) {
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":62
- *                     break
- *         self.arr[top] = pivot
- *         return top             # <<<<<<<<<<<<<<
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":36
+ *     def __dealloc__(self):
+ *         if self.memory is self:
+ *             free(self.arr)             # <<<<<<<<<<<<<<
  * 
- *     def _doquicksort(self,start,end):
+ *     def __iter__(self):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_top);
-  __pyx_r = __pyx_v_top;
-  goto __pyx_L0;
+    free(__pyx_v_self->arr);
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
 
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("_sa.IntList.partition", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_pivot);
-  __Pyx_XDECREF(__pyx_v_bottom);
-  __Pyx_XDECREF(__pyx_v_top);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
 }
+static PyObject *__pyx_gb_3_sa_7IntList_12generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_9_doquicksort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_9_doquicksort(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_start = 0;
-  PyObject *__pyx_v_end = 0;
+static PyObject *__pyx_pw_3_sa_7IntList_11__iter__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_11__iter__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_doquicksort (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__start,&__pyx_n_s__end,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__start)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        case  1:
-        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__end)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_doquicksort", 1, 2, 2, 1); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_doquicksort") < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_start = values[0];
-    __pyx_v_end = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_doquicksort", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[2]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.IntList._doquicksort", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_7IntList_8_doquicksort(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), __pyx_v_start, __pyx_v_end);
+  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_7IntList_10__iter__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":64
- *         return top
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":38
+ *             free(self.arr)
  * 
- *     def _doquicksort(self,start,end):             # <<<<<<<<<<<<<<
- *         if start < end:
- *             split = self.partition(start,end)
+ *     def __iter__(self):             # <<<<<<<<<<<<<<
+ *         cdef int i
+ *         for i in range(self.len):
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_8_doquicksort(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_start, PyObject *__pyx_v_end) {
-  PyObject *__pyx_v_split = NULL;
+static PyObject *__pyx_pf_3_sa_7IntList_10__iter__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
+  struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *__pyx_cur_scope;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_doquicksort", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":65
- * 
- *     def _doquicksort(self,start,end):
- *         if start < end:             # <<<<<<<<<<<<<<
- *             split = self.partition(start,end)
- *             self._doquicksort(start,split-1)
- */
-  __pyx_t_1 = PyObject_RichCompare(__pyx_v_start, __pyx_v_end, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__pyx_t_2) {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":66
- *     def _doquicksort(self,start,end):
- *         if start < end:
- *             split = self.partition(start,end)             # <<<<<<<<<<<<<<
- *             self._doquicksort(start,split-1)
- *             self._doquicksort(split+1,end)
- */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__partition); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_start);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_start);
-    __Pyx_GIVEREF(__pyx_v_start);
-    __Pyx_INCREF(__pyx_v_end);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_end);
-    __Pyx_GIVEREF(__pyx_v_end);
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_v_split = __pyx_t_4;
-    __pyx_t_4 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":67
- *         if start < end:
- *             split = self.partition(start,end)
- *             self._doquicksort(start,split-1)             # <<<<<<<<<<<<<<
- *             self._doquicksort(split+1,end)
- *         else:
- */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s___doquicksort); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyNumber_Subtract(__pyx_v_split, __pyx_int_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(__pyx_v_start);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_start);
-    __Pyx_GIVEREF(__pyx_v_start);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_3);
-    __pyx_t_3 = 0;
-    __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":68
- *             split = self.partition(start,end)
- *             self._doquicksort(start,split-1)
- *             self._doquicksort(split+1,end)             # <<<<<<<<<<<<<<
- *         else:
- *             return
- */
-    __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s___doquicksort); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyNumber_Add(__pyx_v_split, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
-    __Pyx_GIVEREF(__pyx_t_1);
-    __Pyx_INCREF(__pyx_v_end);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_end);
-    __Pyx_GIVEREF(__pyx_v_end);
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    goto __pyx_L3;
-  }
-  /*else*/ {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":70
- *             self._doquicksort(split+1,end)
- *         else:
- *             return             # <<<<<<<<<<<<<<
- * 
- *     def sort(self):
- */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-    goto __pyx_L0;
-  }
-  __pyx_L3:;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("_sa.IntList._doquicksort", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_split);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_11sort(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_11sort(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("sort (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_10sort(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":72
- *             return
- * 
- *     def sort(self):             # <<<<<<<<<<<<<<
- *         self._doquicksort(0,self.len-1)
- * 
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_10sort(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("sort", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":73
- * 
- *     def sort(self):
- *         self._doquicksort(0,self.len-1)             # <<<<<<<<<<<<<<
- * 
- *     def reset(self):
- */
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s___doquicksort); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->len - 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_int_0);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_0);
-  __Pyx_GIVEREF(__pyx_int_0);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
-  __Pyx_GIVEREF(__pyx_t_2);
-  __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("_sa.IntList.sort", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_13reset(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_13reset(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("reset (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_12reset(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":75
- *         self._doquicksort(0,self.len-1)
- * 
- *     def reset(self):             # <<<<<<<<<<<<<<
- *         self.len = 0
- * 
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_12reset(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("reset", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":76
- * 
- *     def reset(self):
- *         self.len = 0             # <<<<<<<<<<<<<<
- * 
- *     def __dealloc__(self):
- */
-  __pyx_v_self->len = 0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static void __pyx_pw_3_sa_7IntList_15__dealloc__(PyObject *__pyx_v_self); /*proto*/
-static void __pyx_pw_3_sa_7IntList_15__dealloc__(PyObject *__pyx_v_self) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
-  __pyx_pf_3_sa_7IntList_14__dealloc__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":78
- *         self.len = 0
- * 
- *     def __dealloc__(self):             # <<<<<<<<<<<<<<
- *         free(self.arr)
- * 
- */
-
-static void __pyx_pf_3_sa_7IntList_14__dealloc__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__dealloc__", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":79
- * 
- *     def __dealloc__(self):
- *         free(self.arr)             # <<<<<<<<<<<<<<
- * 
- *     def __iter__(self):
- */
-  free(__pyx_v_self->arr);
-
-  __Pyx_RefNannyFinishContext();
-}
-static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_17__iter__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_17__iter__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_16__iter__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":81
- *         free(self.arr)
- * 
- *     def __iter__(self):             # <<<<<<<<<<<<<<
- *         cdef int i
- *         for i in range(self.len):
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_16__iter__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *__pyx_cur_scope;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__iter__", 0);
-  __pyx_cur_scope = (struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *)__pyx_ptype_3_sa___pyx_scope_struct____iter__->tp_new(__pyx_ptype_3_sa___pyx_scope_struct____iter__, __pyx_empty_tuple, NULL);
-  if (unlikely(!__pyx_cur_scope)) {
-    __Pyx_RefNannyFinishContext();
-    return NULL;
-  }
-  __Pyx_GOTREF(__pyx_cur_scope);
-  __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
-  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
-  __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
-  {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_7IntList_18generator, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_cur_scope);
-    __Pyx_RefNannyFinishContext();
-    return (PyObject *) gen;
-  }
+  __Pyx_RefNannySetupContext("__iter__", 0);
+  __pyx_cur_scope = (struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *)__pyx_ptype_3_sa___pyx_scope_struct____iter__->tp_new(__pyx_ptype_3_sa___pyx_scope_struct____iter__, __pyx_empty_tuple, NULL);
+  if (unlikely(!__pyx_cur_scope)) {
+    __Pyx_RefNannyFinishContext();
+    return NULL;
+  }
+  __Pyx_GOTREF(__pyx_cur_scope);
+  __pyx_cur_scope->__pyx_v_self = __pyx_v_self;
+  __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
+  {
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_7IntList_12generator, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_cur_scope);
+    __Pyx_RefNannyFinishContext();
+    return (PyObject *) gen;
+  }
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
@@ -5433,7 +5150,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_16__iter__(struct __pyx_obj_3_sa_IntList
   return __pyx_r;
 }
 
-static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
+static PyObject *__pyx_gb_3_sa_7IntList_12generator(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value) /* generator body */
 {
   struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *__pyx_cur_scope = ((struct __pyx_obj_3_sa___pyx_scope_struct____iter__ *)__pyx_generator->closure);
   PyObject *__pyx_r = NULL;
@@ -5450,9 +5167,9 @@ static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":83
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":40
  *     def __iter__(self):
  *         cdef int i
  *         for i in range(self.len):             # <<<<<<<<<<<<<<
@@ -5463,14 +5180,14 @@ static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx
   for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
     __pyx_cur_scope->__pyx_v_i = __pyx_t_2;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":84
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":41
  *         cdef int i
  *         for i in range(self.len):
  *             yield self.arr[i]             # <<<<<<<<<<<<<<
  * 
  *     def __getitem__(self, index):
  */
-    __pyx_t_3 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_self->arr[__pyx_cur_scope->__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_self->arr[__pyx_cur_scope->__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_r = __pyx_t_3;
     __pyx_t_3 = 0;
@@ -5484,7 +5201,7 @@ static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx
     __pyx_L6_resume_from_yield:;
     __pyx_t_1 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
@@ -5500,17 +5217,17 @@ static PyObject *__pyx_gb_3_sa_7IntList_18generator(__pyx_GeneratorObject *__pyx
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_20__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_20__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) {
+static PyObject *__pyx_pw_3_sa_7IntList_14__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_14__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_index) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_19__getitem__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((PyObject *)__pyx_v_index));
+  __pyx_r = __pyx_pf_3_sa_7IntList_13__getitem__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((PyObject *)__pyx_v_index));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":86
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":43
  *             yield self.arr[i]
  * 
  *     def __getitem__(self, index):             # <<<<<<<<<<<<<<
@@ -5518,7 +5235,7 @@ static PyObject *__pyx_pw_3_sa_7IntList_20__getitem__(PyObject *__pyx_v_self, Py
  *         if isinstance(index, int):
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_index) {
+static PyObject *__pyx_pf_3_sa_7IntList_13__getitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_index) {
   int __pyx_v_i;
   int __pyx_v_j;
   int __pyx_v_k;
@@ -5540,7 +5257,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":88
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":45
  *     def __getitem__(self, index):
  *         cdef int i, j, k
  *         if isinstance(index, int):             # <<<<<<<<<<<<<<
@@ -5553,17 +5270,17 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":89
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":46
  *         cdef int i, j, k
  *         if isinstance(index, int):
  *             j = index             # <<<<<<<<<<<<<<
  *             if j < 0:
  *                 j = self.len + j
  */
-    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_v_index); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_v_index); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_j = __pyx_t_3;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":90
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":47
  *         if isinstance(index, int):
  *             j = index
  *             if j < 0:             # <<<<<<<<<<<<<<
@@ -5573,7 +5290,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     __pyx_t_2 = (__pyx_v_j < 0);
     if (__pyx_t_2) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":91
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":48
  *             j = index
  *             if j < 0:
  *                 j = self.len + j             # <<<<<<<<<<<<<<
@@ -5585,7 +5302,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     }
     __pyx_L4:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":92
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":49
  *             if j < 0:
  *                 j = self.len + j
  *             if j<0 or j>=self.len:             # <<<<<<<<<<<<<<
@@ -5601,16 +5318,16 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     }
     if (__pyx_t_5) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":93
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":50
  *                 j = self.len + j
  *             if j<0 or j>=self.len:
  *                 raise IndexError("Requested index %d of %d-length IntList" % (index, self.len))             # <<<<<<<<<<<<<<
  *             return self.arr[j]
  *         elif isinstance(index, slice):
  */
-      __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       __Pyx_INCREF(__pyx_v_index);
       PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_index);
@@ -5618,25 +5335,25 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
       PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_7), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_5), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_1));
       __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
-      __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_1));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
       __Pyx_Raise(__pyx_t_1, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      {__pyx_filename = __pyx_f[2]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[2]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L5;
     }
     __pyx_L5:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":94
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":51
  *             if j<0 or j>=self.len:
  *                 raise IndexError("Requested index %d of %d-length IntList" % (index, self.len))
  *             return self.arr[j]             # <<<<<<<<<<<<<<
@@ -5644,7 +5361,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
  *             i = index.start
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_j])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_j])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_r = __pyx_t_1;
     __pyx_t_1 = 0;
@@ -5652,7 +5369,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     goto __pyx_L3;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":95
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":52
  *                 raise IndexError("Requested index %d of %d-length IntList" % (index, self.len))
  *             return self.arr[j]
  *         elif isinstance(index, slice):             # <<<<<<<<<<<<<<
@@ -5665,33 +5382,33 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   if (__pyx_t_5) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":96
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":53
  *             return self.arr[j]
  *         elif isinstance(index, slice):
  *             i = index.start             # <<<<<<<<<<<<<<
  *             j = index.stop
  *             if i < 0:
  */
-    __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__start); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__start); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 96; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_v_i = __pyx_t_3;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":97
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":54
  *         elif isinstance(index, slice):
  *             i = index.start
  *             j = index.stop             # <<<<<<<<<<<<<<
  *             if i < 0:
  *                 i = self.len + i
  */
-    __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__stop); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__stop); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __pyx_v_j = __pyx_t_3;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":98
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":55
  *             i = index.start
  *             j = index.stop
  *             if i < 0:             # <<<<<<<<<<<<<<
@@ -5701,7 +5418,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     __pyx_t_5 = (__pyx_v_i < 0);
     if (__pyx_t_5) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":99
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":56
  *             j = index.stop
  *             if i < 0:
  *                 i = self.len + i             # <<<<<<<<<<<<<<
@@ -5713,7 +5430,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     }
     __pyx_L6:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":100
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":57
  *             if i < 0:
  *                 i = self.len + i
  *             if j < 0:             # <<<<<<<<<<<<<<
@@ -5723,7 +5440,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     __pyx_t_5 = (__pyx_v_j < 0);
     if (__pyx_t_5) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":101
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":58
  *                 i = self.len + i
  *             if j < 0:
  *                 j = self.len + j             # <<<<<<<<<<<<<<
@@ -5735,7 +5452,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     }
     __pyx_L7:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":102
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":59
  *             if j < 0:
  *                 j = self.len + j
  *             if i < 0 or i >= self.len or j < 0 or j > self.len:             # <<<<<<<<<<<<<<
@@ -5763,20 +5480,20 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     }
     if (__pyx_t_2) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":103
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":60
  *                 j = self.len + j
  *             if i < 0 or i >= self.len or j < 0 or j > self.len:
  *                 raise IndexError("Requested index %d:%d of %d-length IntList" % (index.start, index.stop, self.len))             # <<<<<<<<<<<<<<
  *             result = ()
  *             for k from i <= k < j:
  */
-      __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__start); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__start); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_6 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__stop); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyObject_GetAttr(__pyx_v_index, __pyx_n_s__stop); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_9 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_10);
       PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
@@ -5787,25 +5504,25 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
       __pyx_t_1 = 0;
       __pyx_t_6 = 0;
       __pyx_t_9 = 0;
-      __pyx_t_9 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_8), ((PyObject *)__pyx_t_10)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_6), ((PyObject *)__pyx_t_10)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_9));
       __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
-      __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_10);
       PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_9));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
       __pyx_t_9 = 0;
-      __pyx_t_9 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
       __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
       __Pyx_Raise(__pyx_t_9, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      {__pyx_filename = __pyx_f[2]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[2]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L8;
     }
     __pyx_L8:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":104
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":61
  *             if i < 0 or i >= self.len or j < 0 or j > self.len:
  *                 raise IndexError("Requested index %d:%d of %d-length IntList" % (index.start, index.stop, self.len))
  *             result = ()             # <<<<<<<<<<<<<<
@@ -5815,7 +5532,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     __Pyx_INCREF(((PyObject *)__pyx_empty_tuple));
     __pyx_v_result = __pyx_empty_tuple;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":105
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":62
  *                 raise IndexError("Requested index %d:%d of %d-length IntList" % (index.start, index.stop, self.len))
  *             result = ()
  *             for k from i <= k < j:             # <<<<<<<<<<<<<<
@@ -5825,21 +5542,21 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
     __pyx_t_3 = __pyx_v_j;
     for (__pyx_v_k = __pyx_v_i; __pyx_v_k < __pyx_t_3; __pyx_v_k++) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":106
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":63
  *             result = ()
  *             for k from i <= k < j:
  *                 result = result + (self.arr[k],)             # <<<<<<<<<<<<<<
  *             return result
  *         else:
  */
-      __pyx_t_9 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_k])); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyInt_FromLong((__pyx_v_self->arr[__pyx_v_k])); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_10);
       PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_9);
       __Pyx_GIVEREF(__pyx_t_9);
       __pyx_t_9 = 0;
-      __pyx_t_9 = PyNumber_Add(((PyObject *)__pyx_v_result), ((PyObject *)__pyx_t_10)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyNumber_Add(((PyObject *)__pyx_v_result), ((PyObject *)__pyx_t_10)); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_9));
       __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_v_result));
@@ -5847,7 +5564,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
       __pyx_t_9 = 0;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":107
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":64
  *             for k from i <= k < j:
  *                 result = result + (self.arr[k],)
  *             return result             # <<<<<<<<<<<<<<
@@ -5862,26 +5579,26 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":109
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":66
  *             return result
  *         else:
  *             raise TypeError("Illegal key type %s for IntList" % type(index))             # <<<<<<<<<<<<<<
  * 
  *     cdef void set(self, int i, int val):
  */
-    __pyx_t_9 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_9), ((PyObject *)Py_TYPE(__pyx_v_index))); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_7), ((PyObject *)Py_TYPE(__pyx_v_index))); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_9));
-    __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_10);
     PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_9));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_9));
     __pyx_t_9 = 0;
-    __pyx_t_9 = PyObject_Call(__pyx_builtin_TypeError, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyObject_Call(__pyx_builtin_TypeError, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
     __Pyx_Raise(__pyx_t_9, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    {__pyx_filename = __pyx_f[2]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_L3:;
 
@@ -5901,7 +5618,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_19__getitem__(struct __pyx_obj_3_sa_IntL
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":111
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":68
  *             raise TypeError("Illegal key type %s for IntList" % type(index))
  * 
  *     cdef void set(self, int i, int val):             # <<<<<<<<<<<<<<
@@ -5923,7 +5640,7 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("set", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":112
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":69
  * 
  *     cdef void set(self, int i, int val):
  *         j = i             # <<<<<<<<<<<<<<
@@ -5932,7 +5649,7 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
  */
   __pyx_v_j = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":113
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":70
  *     cdef void set(self, int i, int val):
  *         j = i
  *         if i<0:             # <<<<<<<<<<<<<<
@@ -5942,7 +5659,7 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
   __pyx_t_1 = (__pyx_v_i < 0);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":114
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":71
  *         j = i
  *         if i<0:
  *             j = self.len + i             # <<<<<<<<<<<<<<
@@ -5954,7 +5671,7 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":115
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":72
  *         if i<0:
  *             j = self.len + i
  *         if j<0 or j>=self.len:             # <<<<<<<<<<<<<<
@@ -5970,18 +5687,18 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
   }
   if (__pyx_t_3) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":116
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":73
  *             j = self.len + i
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length IntList" % (i, self.len))             # <<<<<<<<<<<<<<
  *         self.arr[j] = val
  * 
  */
-    __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->len); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
     __Pyx_GIVEREF(__pyx_t_4);
@@ -5989,25 +5706,25 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_4 = 0;
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_7), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_5), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_5));
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
-    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_builtin_IndexError, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
     __Pyx_Raise(__pyx_t_5, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    {__pyx_filename = __pyx_f[2]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[2]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L4;
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":117
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":74
  *         if j<0 or j>=self.len:
  *             raise IndexError("Requested index %d of %d-length IntList" % (i, self.len))
  *         self.arr[j] = val             # <<<<<<<<<<<<<<
@@ -6027,17 +5744,17 @@ static void __pyx_f_3_sa_7IntList_set(struct __pyx_obj_3_sa_IntList *__pyx_v_sel
 }
 
 /* Python wrapper */
-static int __pyx_pw_3_sa_7IntList_22__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val); /*proto*/
-static int __pyx_pw_3_sa_7IntList_22__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val) {
+static int __pyx_pw_3_sa_7IntList_16__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val); /*proto*/
+static int __pyx_pw_3_sa_7IntList_16__setitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__setitem__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_21__setitem__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((PyObject *)__pyx_v_i), ((PyObject *)__pyx_v_val));
+  __pyx_r = __pyx_pf_3_sa_7IntList_15__setitem__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((PyObject *)__pyx_v_i), ((PyObject *)__pyx_v_val));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":119
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":76
  *         self.arr[j] = val
  * 
  *     def __setitem__(self, i, val):             # <<<<<<<<<<<<<<
@@ -6045,7 +5762,7 @@ static int __pyx_pw_3_sa_7IntList_22__setitem__(PyObject *__pyx_v_self, PyObject
  * 
  */
 
-static int __pyx_pf_3_sa_7IntList_21__setitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val) {
+static int __pyx_pf_3_sa_7IntList_15__setitem__(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_i, PyObject *__pyx_v_val) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -6055,15 +5772,15 @@ static int __pyx_pf_3_sa_7IntList_21__setitem__(struct __pyx_obj_3_sa_IntList *_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__setitem__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":120
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":77
  * 
  *     def __setitem__(self, i, val):
  *         self.set(i, val)             # <<<<<<<<<<<<<<
  * 
  *     def __len__(self):
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_v_val); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 120; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyInt_AsInt(__pyx_v_val); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->__pyx_vtab)->set(__pyx_v_self, __pyx_t_1, __pyx_t_2);
 
   __pyx_r = 0;
@@ -6077,17 +5794,17 @@ static int __pyx_pf_3_sa_7IntList_21__setitem__(struct __pyx_obj_3_sa_IntList *_
 }
 
 /* Python wrapper */
-static Py_ssize_t __pyx_pw_3_sa_7IntList_24__len__(PyObject *__pyx_v_self); /*proto*/
-static Py_ssize_t __pyx_pw_3_sa_7IntList_24__len__(PyObject *__pyx_v_self) {
+static Py_ssize_t __pyx_pw_3_sa_7IntList_18__len__(PyObject *__pyx_v_self); /*proto*/
+static Py_ssize_t __pyx_pw_3_sa_7IntList_18__len__(PyObject *__pyx_v_self) {
   Py_ssize_t __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__len__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_23__len__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
+  __pyx_r = __pyx_pf_3_sa_7IntList_17__len__(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":122
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":79
  *         self.set(i, val)
  * 
  *     def __len__(self):             # <<<<<<<<<<<<<<
@@ -6095,17 +5812,17 @@ static Py_ssize_t __pyx_pw_3_sa_7IntList_24__len__(PyObject *__pyx_v_self) {
  * 
  */
 
-static Py_ssize_t __pyx_pf_3_sa_7IntList_23__len__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
+static Py_ssize_t __pyx_pf_3_sa_7IntList_17__len__(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
   Py_ssize_t __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__len__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":123
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":80
  * 
  *     def __len__(self):
  *         return self.len             # <<<<<<<<<<<<<<
  * 
- *     def get_size(self):
+ *     def append(self, int val):
  */
   __pyx_r = __pyx_v_self->len;
   goto __pyx_L0;
@@ -6117,68 +5834,14 @@ static Py_ssize_t __pyx_pf_3_sa_7IntList_23__len__(struct __pyx_obj_3_sa_IntList
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_26get_size(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_26get_size(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("get_size (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_25get_size(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":125
- *         return self.len
- * 
- *     def get_size(self):             # <<<<<<<<<<<<<<
- *         return self.size
- * 
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_25get_size(struct __pyx_obj_3_sa_IntList *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("get_size", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":126
- * 
- *     def get_size(self):
- *         return self.size             # <<<<<<<<<<<<<<
- * 
- *     def append(self, int val):
- */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_self->size); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("_sa.IntList.get_size", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_28append(PyObject *__pyx_v_self, PyObject *__pyx_arg_val); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_28append(PyObject *__pyx_v_self, PyObject *__pyx_arg_val) {
+static PyObject *__pyx_pw_3_sa_7IntList_20append(PyObject *__pyx_v_self, PyObject *__pyx_arg_val); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_20append(PyObject *__pyx_v_self, PyObject *__pyx_arg_val) {
   int __pyx_v_val;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("append (wrapper)", 0);
   assert(__pyx_arg_val); {
-    __pyx_v_val = __Pyx_PyInt_AsInt(__pyx_arg_val); if (unlikely((__pyx_v_val == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_val = __Pyx_PyInt_AsInt(__pyx_arg_val); if (unlikely((__pyx_v_val == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -6186,25 +5849,25 @@ static PyObject *__pyx_pw_3_sa_7IntList_28append(PyObject *__pyx_v_self, PyObjec
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_7IntList_27append(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((int)__pyx_v_val));
+  __pyx_r = __pyx_pf_3_sa_7IntList_19append(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((int)__pyx_v_val));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":128
- *         return self.size
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":82
+ *         return self.len
  * 
  *     def append(self, int val):             # <<<<<<<<<<<<<<
  *         self._append(val)
  * 
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_27append(struct __pyx_obj_3_sa_IntList *__pyx_v_self, int __pyx_v_val) {
+static PyObject *__pyx_pf_3_sa_7IntList_19append(struct __pyx_obj_3_sa_IntList *__pyx_v_self, int __pyx_v_val) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("append", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":129
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":83
  * 
  *     def append(self, int val):
  *         self._append(val)             # <<<<<<<<<<<<<<
@@ -6219,7 +5882,7 @@ static PyObject *__pyx_pf_3_sa_7IntList_27append(struct __pyx_obj_3_sa_IntList *
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":131
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":85
  *         self._append(val)
  * 
  *     cdef void _append(self, int val):             # <<<<<<<<<<<<<<
@@ -6232,7 +5895,7 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("_append", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":132
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":86
  * 
  *     cdef void _append(self, int val):
  *         if self.len == self.size:             # <<<<<<<<<<<<<<
@@ -6242,7 +5905,7 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
   __pyx_t_1 = (__pyx_v_self->len == __pyx_v_self->size);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":133
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":87
  *     cdef void _append(self, int val):
  *         if self.len == self.size:
  *             self.size = self.size + self.increment             # <<<<<<<<<<<<<<
@@ -6251,7 +5914,7 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
  */
     __pyx_v_self->size = (__pyx_v_self->size + __pyx_v_self->increment);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":134
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":88
  *         if self.len == self.size:
  *             self.size = self.size + self.increment
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))             # <<<<<<<<<<<<<<
@@ -6263,7 +5926,7 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":135
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":89
  *             self.size = self.size + self.increment
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))
  *         self.arr[self.len] = val             # <<<<<<<<<<<<<<
@@ -6272,12 +5935,12 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
  */
   (__pyx_v_self->arr[__pyx_v_self->len]) = __pyx_v_val;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":136
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":90
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))
  *         self.arr[self.len] = val
  *         self.len = self.len + 1             # <<<<<<<<<<<<<<
  * 
- *     def extend(self, other):
+ *     def extend(self, IntList other):
  */
   __pyx_v_self->len = (__pyx_v_self->len + 1);
 
@@ -6285,83 +5948,50 @@ static void __pyx_f_3_sa_7IntList__append(struct __pyx_obj_3_sa_IntList *__pyx_v
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_30extend(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_30extend(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
+static PyObject *__pyx_pw_3_sa_7IntList_22extend(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
+static PyObject *__pyx_pw_3_sa_7IntList_22extend(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("extend (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_7IntList_29extend(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((PyObject *)__pyx_v_other));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":138
- *         self.len = self.len + 1
- * 
- *     def extend(self, other):             # <<<<<<<<<<<<<<
- *         self._extend(other)
- * 
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_29extend(struct __pyx_obj_3_sa_IntList *__pyx_v_self, PyObject *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("extend", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":139
- * 
- *     def extend(self, other):
- *         self._extend(other)             # <<<<<<<<<<<<<<
- * 
- *     cdef void _extend(self, IntList other):
- */
-  if (!(likely(((__pyx_v_other) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_other, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_1 = __pyx_v_other;
-  __Pyx_INCREF(__pyx_t_1);
-  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->__pyx_vtab)->_extend(__pyx_v_self, ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1));
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_3_sa_IntList, 1, "other", 0))) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_7IntList_21extend(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((struct __pyx_obj_3_sa_IntList *)__pyx_v_other));
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("_sa.IntList.extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":141
- *         self._extend(other)
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":92
+ *         self.len = self.len + 1
  * 
- *     cdef void _extend(self, IntList other):             # <<<<<<<<<<<<<<
+ *     def extend(self, IntList other):             # <<<<<<<<<<<<<<
  *         self._extend_arr(other.arr, other.len)
  * 
  */
 
-static void __pyx_f_3_sa_7IntList__extend(struct __pyx_obj_3_sa_IntList *__pyx_v_self, struct __pyx_obj_3_sa_IntList *__pyx_v_other) {
+static PyObject *__pyx_pf_3_sa_7IntList_21extend(struct __pyx_obj_3_sa_IntList *__pyx_v_self, struct __pyx_obj_3_sa_IntList *__pyx_v_other) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_extend", 0);
+  __Pyx_RefNannySetupContext("extend", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":142
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":93
  * 
- *     cdef void _extend(self, IntList other):
+ *     def extend(self, IntList other):
  *         self._extend_arr(other.arr, other.len)             # <<<<<<<<<<<<<<
  * 
  *     cdef void _extend_arr(self, int* other, int other_len):
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->__pyx_vtab)->_extend_arr(__pyx_v_self, __pyx_v_other->arr, __pyx_v_other->len);
 
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
+  return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":144
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":95
  *         self._extend_arr(other.arr, other.len)
  * 
  *     cdef void _extend_arr(self, int* other, int other_len):             # <<<<<<<<<<<<<<
@@ -6374,7 +6004,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("_extend_arr", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":145
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":96
  * 
  *     cdef void _extend_arr(self, int* other, int other_len):
  *         if self.size < self.len + other_len:             # <<<<<<<<<<<<<<
@@ -6384,7 +6014,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
   __pyx_t_1 = (__pyx_v_self->size < (__pyx_v_self->len + __pyx_v_other_len));
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":146
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":97
  *     cdef void _extend_arr(self, int* other, int other_len):
  *         if self.size < self.len + other_len:
  *             self.size = self.len + other_len             # <<<<<<<<<<<<<<
@@ -6393,7 +6023,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
  */
     __pyx_v_self->size = (__pyx_v_self->len + __pyx_v_other_len);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":147
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":98
  *         if self.size < self.len + other_len:
  *             self.size = self.len + other_len
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))             # <<<<<<<<<<<<<<
@@ -6405,7 +6035,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":148
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":99
  *             self.size = self.len + other_len
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))
  *         memcpy(self.arr+self.len, other, other_len*sizeof(int))             # <<<<<<<<<<<<<<
@@ -6414,7 +6044,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
  */
   memcpy((__pyx_v_self->arr + __pyx_v_self->len), __pyx_v_other, (__pyx_v_other_len * (sizeof(int))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":149
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":100
  *             self.arr = <int*> realloc(self.arr, self.size*sizeof(int))
  *         memcpy(self.arr+self.len, other, other_len*sizeof(int))
  *         self.len = self.len + other_len             # <<<<<<<<<<<<<<
@@ -6426,7 +6056,7 @@ static void __pyx_f_3_sa_7IntList__extend_arr(struct __pyx_obj_3_sa_IntList *__p
   __Pyx_RefNannyFinishContext();
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":151
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":102
  *         self.len = self.len + other_len
  * 
  *     cdef void _clear(self):             # <<<<<<<<<<<<<<
@@ -6438,7 +6068,7 @@ static void __pyx_f_3_sa_7IntList__clear(struct __pyx_obj_3_sa_IntList *__pyx_v_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_clear", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":152
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":103
  * 
  *     cdef void _clear(self):
  *         free(self.arr)             # <<<<<<<<<<<<<<
@@ -6447,7 +6077,7 @@ static void __pyx_f_3_sa_7IntList__clear(struct __pyx_obj_3_sa_IntList *__pyx_v_
  */
   free(__pyx_v_self->arr);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":153
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":104
  *     cdef void _clear(self):
  *         free(self.arr)
  *         self.len = 0             # <<<<<<<<<<<<<<
@@ -6456,7 +6086,7 @@ static void __pyx_f_3_sa_7IntList__clear(struct __pyx_obj_3_sa_IntList *__pyx_v_
  */
   __pyx_v_self->len = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":154
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":105
  *         free(self.arr)
  *         self.len = 0
  *         self.size = 0             # <<<<<<<<<<<<<<
@@ -6465,7 +6095,7 @@ static void __pyx_f_3_sa_7IntList__clear(struct __pyx_obj_3_sa_IntList *__pyx_v_
  */
   __pyx_v_self->size = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":155
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":106
  *         self.len = 0
  *         self.size = 0
  *         self.arr = <int*> malloc(0)             # <<<<<<<<<<<<<<
@@ -6477,7 +6107,7 @@ static void __pyx_f_3_sa_7IntList__clear(struct __pyx_obj_3_sa_IntList *__pyx_v_
   __Pyx_RefNannyFinishContext();
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":157
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":108
  *         self.arr = <int*> malloc(0)
  * 
  *     cdef void write_handle(self, FILE* f):             # <<<<<<<<<<<<<<
@@ -6489,7 +6119,7 @@ static void __pyx_f_3_sa_7IntList_write_handle(struct __pyx_obj_3_sa_IntList *__
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":158
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":109
  * 
  *     cdef void write_handle(self, FILE* f):
  *         fwrite(&(self.len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -6498,91 +6128,23 @@ static void __pyx_f_3_sa_7IntList_write_handle(struct __pyx_obj_3_sa_IntList *__
  */
   fwrite((&__pyx_v_self->len), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":159
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":110
  *     cdef void write_handle(self, FILE* f):
  *         fwrite(&(self.len), sizeof(int), 1, f)
  *         fwrite(self.arr, sizeof(int), self.len, f)             # <<<<<<<<<<<<<<
  * 
- *     def write(self, char* filename):
+ *     cdef void read_handle(self, FILE* f):
  */
   fwrite(__pyx_v_self->arr, (sizeof(int)), __pyx_v_self->len, __pyx_v_f);
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_32write(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_32write(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.IntList.write", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_7IntList_31write(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((char *)__pyx_v_filename));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":161
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":112
  *         fwrite(self.arr, sizeof(int), self.len, f)
  * 
- *     def write(self, char* filename):             # <<<<<<<<<<<<<<
- *         cdef FILE* f
- *         f = fopen(filename, "w")
- */
-
-static PyObject *__pyx_pf_3_sa_7IntList_31write(struct __pyx_obj_3_sa_IntList *__pyx_v_self, char *__pyx_v_filename) {
-  FILE *__pyx_v_f;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":163
- *     def write(self, char* filename):
- *         cdef FILE* f
- *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
- *         self.write_handle(f)
- *         fclose(f)
- */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":164
- *         cdef FILE* f
- *         f = fopen(filename, "w")
- *         self.write_handle(f)             # <<<<<<<<<<<<<<
- *         fclose(f)
- * 
- */
-  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->__pyx_vtab)->write_handle(__pyx_v_self, __pyx_v_f);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":165
- *         f = fopen(filename, "w")
- *         self.write_handle(f)
- *         fclose(f)             # <<<<<<<<<<<<<<
- * 
- *     cdef void read_handle(self, FILE* f):
- */
-  fclose(__pyx_v_f);
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":167
- *         fclose(f)
- * 
  *     cdef void read_handle(self, FILE* f):             # <<<<<<<<<<<<<<
- *         (self.arr)
+ *         free(self.arr)
  *         fread(&(self.len), sizeof(int), 1, f)
  */
 
@@ -6590,26 +6152,26 @@ static void __pyx_f_3_sa_7IntList_read_handle(struct __pyx_obj_3_sa_IntList *__p
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":168
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":113
  * 
  *     cdef void read_handle(self, FILE* f):
- *         (self.arr)             # <<<<<<<<<<<<<<
+ *         free(self.arr)             # <<<<<<<<<<<<<<
  *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <int*> malloc(self.len * sizeof(int))
  */
-  __pyx_v_self->arr;
+  free(__pyx_v_self->arr);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":169
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":114
  *     cdef void read_handle(self, FILE* f):
- *         (self.arr)
+ *         free(self.arr)
  *         fread(&(self.len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
  *         self.arr = <int*> malloc(self.len * sizeof(int))
  *         self.size = self.len
  */
   fread((&__pyx_v_self->len), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":170
- *         (self.arr)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":115
+ *         free(self.arr)
  *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <int*> malloc(self.len * sizeof(int))             # <<<<<<<<<<<<<<
  *         self.size = self.len
@@ -6617,7 +6179,7 @@ static void __pyx_f_3_sa_7IntList_read_handle(struct __pyx_obj_3_sa_IntList *__p
  */
   __pyx_v_self->arr = ((int *)malloc((__pyx_v_self->len * (sizeof(int)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":171
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":116
  *         fread(&(self.len), sizeof(int), 1, f)
  *         self.arr = <int*> malloc(self.len * sizeof(int))
  *         self.size = self.len             # <<<<<<<<<<<<<<
@@ -6626,81 +6188,71 @@ static void __pyx_f_3_sa_7IntList_read_handle(struct __pyx_obj_3_sa_IntList *__p
  */
   __pyx_v_self->size = __pyx_v_self->len;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":172
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":117
  *         self.arr = <int*> malloc(self.len * sizeof(int))
  *         self.size = self.len
  *         fread(self.arr, sizeof(int), self.len, f)             # <<<<<<<<<<<<<<
  * 
- *     def read(self, char* filename):
+ *     cdef void read_mmaped(self, MemoryMap buf):
  */
   fread(__pyx_v_self->arr, (sizeof(int)), __pyx_v_self->len, __pyx_v_f);
 
   __Pyx_RefNannyFinishContext();
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_7IntList_34read(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_7IntList_34read(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("read (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.IntList.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_7IntList_33read(((struct __pyx_obj_3_sa_IntList *)__pyx_v_self), ((char *)__pyx_v_filename));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":174
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":119
  *         fread(self.arr, sizeof(int), self.len, f)
  * 
- *     def read(self, char* filename):             # <<<<<<<<<<<<<<
- *         cdef FILE* f
- *         f = fopen(filename, "r")
+ *     cdef void read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()
  */
 
-static PyObject *__pyx_pf_3_sa_7IntList_33read(struct __pyx_obj_3_sa_IntList *__pyx_v_self, char *__pyx_v_filename) {
-  FILE *__pyx_v_f;
-  PyObject *__pyx_r = NULL;
+static void __pyx_f_3_sa_7IntList_read_mmaped(struct __pyx_obj_3_sa_IntList *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("read", 0);
+  int __pyx_t_1;
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":176
- *     def read(self, char* filename):
- *         cdef FILE* f
- *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
- *         self.read_handle(f)
- *         fclose(f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":120
+ * 
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         free(self.arr)             # <<<<<<<<<<<<<<
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_int_array(self.len)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  free(__pyx_v_self->arr);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":177
- *         cdef FILE* f
- *         f = fopen(filename, "r")
- *         self.read_handle(f)             # <<<<<<<<<<<<<<
- *         fclose(f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":121
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.arr = buf.read_int_array(self.len)
+ *         self.memory = buf
  */
-  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->__pyx_vtab)->read_handle(__pyx_v_self, __pyx_v_f);
+  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+  __pyx_v_self->size = __pyx_t_1;
+  __pyx_v_self->len = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":178
- *         f = fopen(filename, "r")
- *         self.read_handle(f)
- *         fclose(f)             # <<<<<<<<<<<<<<
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":122
+ *         free(self.arr)
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_int_array(self.len)             # <<<<<<<<<<<<<<
+ *         self.memory = buf
  */
-  fclose(__pyx_v_f);
+  __pyx_v_self->arr = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int_array(__pyx_v_buf, __pyx_v_self->len);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/int_list.pxi":123
+ *         self.size = self.len = buf.read_int()
+ *         self.arr = buf.read_int_array(self.len)
+ *         self.memory = buf             # <<<<<<<<<<<<<<
+ */
+  __Pyx_INCREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_buf));
+  __Pyx_GOTREF(__pyx_v_self->memory);
+  __Pyx_DECREF(__pyx_v_self->memory);
+  __pyx_v_self->memory = ((PyObject *)__pyx_v_buf);
 
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
 }
 
 /* Python wrapper */
@@ -6832,6 +6384,950 @@ static int __pyx_f_3_sa_9StringMap_index(struct __pyx_obj_3_sa_StringMap *__pyx_
   return __pyx_r;
 }
 
+/* Python wrapper */
+static int __pyx_pw_3_sa_10Vocabulary_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_3_sa_10Vocabulary_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  CYTHON_UNUSED PyObject *__pyx_v_from_vocabulary = 0;
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_vocabulary,0};
+    PyObject* values[1] = {0};
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":4
+ *     cdef object id2word, word2id
+ * 
+ *     def __init__(self, from_vocabulary=None):             # <<<<<<<<<<<<<<
+ *         self.id2word = []
+ *         self.word2id = {}
+ */
+    values[0] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__from_vocabulary);
+          if (value) { values[0] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_from_vocabulary = values[0];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("_sa.Vocabulary.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary___init__(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self), __pyx_v_from_vocabulary);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_3_sa_10Vocabulary___init__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v_from_vocabulary) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":5
+ * 
+ *     def __init__(self, from_vocabulary=None):
+ *         self.id2word = []             # <<<<<<<<<<<<<<
+ *         self.word2id = {}
+ * 
+ */
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+  __Pyx_GOTREF(__pyx_v_self->id2word);
+  __Pyx_DECREF(__pyx_v_self->id2word);
+  __pyx_v_self->id2word = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":6
+ *     def __init__(self, from_vocabulary=None):
+ *         self.id2word = []
+ *         self.word2id = {}             # <<<<<<<<<<<<<<
+ * 
+ *     def extend(self, vocabulary):
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+  __Pyx_GOTREF(__pyx_v_self->word2id);
+  __Pyx_DECREF(__pyx_v_self->word2id);
+  __pyx_v_self->word2id = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("_sa.Vocabulary.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_10Vocabulary_3extend(PyObject *__pyx_v_self, PyObject *__pyx_v_vocabulary); /*proto*/
+static PyObject *__pyx_pw_3_sa_10Vocabulary_3extend(PyObject *__pyx_v_self, PyObject *__pyx_v_vocabulary) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("extend (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary_2extend(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self), ((PyObject *)__pyx_v_vocabulary));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":8
+ *         self.word2id = {}
+ * 
+ *     def extend(self, vocabulary):             # <<<<<<<<<<<<<<
+ *         for word in vocabulary:
+ *             self[word]
+ */
+
+static PyObject *__pyx_pf_3_sa_10Vocabulary_2extend(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_vocabulary) {
+  PyObject *__pyx_v_word = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  PyObject *(*__pyx_t_3)(PyObject *);
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("extend", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":9
+ * 
+ *     def extend(self, vocabulary):
+ *         for word in vocabulary:             # <<<<<<<<<<<<<<
+ *             self[word]
+ * 
+ */
+  if (PyList_CheckExact(__pyx_v_vocabulary) || PyTuple_CheckExact(__pyx_v_vocabulary)) {
+    __pyx_t_1 = __pyx_v_vocabulary; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
+    __pyx_t_3 = NULL;
+  } else {
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_vocabulary); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
+  }
+  for (;;) {
+    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
+      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
+      #if CYTHON_COMPILING_IN_CPYTHON
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #else
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #endif
+    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
+      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
+      #if CYTHON_COMPILING_IN_CPYTHON
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #else
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #endif
+    } else {
+      __pyx_t_4 = __pyx_t_3(__pyx_t_1);
+      if (unlikely(!__pyx_t_4)) {
+        if (PyErr_Occurred()) {
+          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
+          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_4);
+    }
+    __Pyx_XDECREF(__pyx_v_word);
+    __pyx_v_word = __pyx_t_4;
+    __pyx_t_4 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":10
+ *     def extend(self, vocabulary):
+ *         for word in vocabulary:
+ *             self[word]             # <<<<<<<<<<<<<<
+ * 
+ *     def __iter__(self):
+ */
+    __pyx_t_4 = PyObject_GetItem(((PyObject *)__pyx_v_self), __pyx_v_word); if (!__pyx_t_4) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("_sa.Vocabulary.extend", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_word);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_10Vocabulary_5__iter__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_3_sa_10Vocabulary_5__iter__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__iter__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary_4__iter__(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":12
+ *             self[word]
+ * 
+ *     def __iter__(self):             # <<<<<<<<<<<<<<
+ *         return iter(self.id2word)
+ * 
+ */
+
+static PyObject *__pyx_pf_3_sa_10Vocabulary_4__iter__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__iter__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":13
+ * 
+ *     def __iter__(self):
+ *         return iter(self.id2word)             # <<<<<<<<<<<<<<
+ * 
+ *     def __getitem__(self, word):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __pyx_v_self->id2word;
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("_sa.Vocabulary.__iter__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_10Vocabulary_7__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_word); /*proto*/
+static PyObject *__pyx_pw_3_sa_10Vocabulary_7__getitem__(PyObject *__pyx_v_self, PyObject *__pyx_v_word) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary_6__getitem__(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self), ((PyObject *)__pyx_v_word));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":15
+ *         return iter(self.id2word)
+ * 
+ *     def __getitem__(self, word):             # <<<<<<<<<<<<<<
+ *         v = self.word2id.get(word, -1)
+ *         if v == -1:
+ */
+
+static PyObject *__pyx_pf_3_sa_10Vocabulary_6__getitem__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_word) {
+  PyObject *__pyx_v_v = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  Py_ssize_t __pyx_t_5;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__getitem__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":16
+ * 
+ *     def __getitem__(self, word):
+ *         v = self.word2id.get(word, -1)             # <<<<<<<<<<<<<<
+ *         if v == -1:
+ *             v = len(self.id2word)
+ */
+  __pyx_t_1 = PyObject_GetAttr(__pyx_v_self->word2id, __pyx_n_s__get); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_word);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_word);
+  __Pyx_GIVEREF(__pyx_v_word);
+  __Pyx_INCREF(__pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_neg_1);
+  __Pyx_GIVEREF(__pyx_int_neg_1);
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __pyx_v_v = __pyx_t_3;
+  __pyx_t_3 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":17
+ *     def __getitem__(self, word):
+ *         v = self.word2id.get(word, -1)
+ *         if v == -1:             # <<<<<<<<<<<<<<
+ *             v = len(self.id2word)
+ *             self.id2word.append(word)
+ */
+  __pyx_t_3 = PyObject_RichCompare(__pyx_v_v, __pyx_int_neg_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (__pyx_t_4) {
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":18
+ *         v = self.word2id.get(word, -1)
+ *         if v == -1:
+ *             v = len(self.id2word)             # <<<<<<<<<<<<<<
+ *             self.id2word.append(word)
+ *             self.word2id[word] = v
+ */
+    __pyx_t_3 = __pyx_v_self->id2word;
+    __Pyx_INCREF(__pyx_t_3);
+    __pyx_t_5 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_v_v);
+    __pyx_v_v = __pyx_t_3;
+    __pyx_t_3 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":19
+ *         if v == -1:
+ *             v = len(self.id2word)
+ *             self.id2word.append(word)             # <<<<<<<<<<<<<<
+ *             self.word2id[word] = v
+ *         return v
+ */
+    __pyx_t_3 = __Pyx_PyObject_Append(__pyx_v_self->id2word, __pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":20
+ *             v = len(self.id2word)
+ *             self.id2word.append(word)
+ *             self.word2id[word] = v             # <<<<<<<<<<<<<<
+ *         return v
+ * 
+ */
+    if (PyObject_SetItem(__pyx_v_self->word2id, __pyx_v_word, __pyx_v_v) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    goto __pyx_L3;
+  }
+  __pyx_L3:;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":21
+ *             self.id2word.append(word)
+ *             self.word2id[word] = v
+ *         return v             # <<<<<<<<<<<<<<
+ * 
+ *     def get(self, word, default):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_v);
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("_sa.Vocabulary.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_v);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_10Vocabulary_9get(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_3_sa_10Vocabulary_9get(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_word = 0;
+  PyObject *__pyx_v_default = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("get (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__word,&__pyx_n_s__default,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__word)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        case  1:
+        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__default)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("get", 1, 2, 2, 1); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get") < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_word = values[0];
+    __pyx_v_default = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("get", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("_sa.Vocabulary.get", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary_8get(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self), __pyx_v_word, __pyx_v_default);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":23
+ *         return v
+ * 
+ *     def get(self, word, default):             # <<<<<<<<<<<<<<
+ *         return self.word2id.get(word, default)
+ * 
+ */
+
+static PyObject *__pyx_pf_3_sa_10Vocabulary_8get(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, PyObject *__pyx_v_word, PyObject *__pyx_v_default) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("get", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":24
+ * 
+ *     def get(self, word, default):
+ *         return self.word2id.get(word, default)             # <<<<<<<<<<<<<<
+ * 
+ *     def __len__(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = PyObject_GetAttr(__pyx_v_self->word2id, __pyx_n_s__get); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_word);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_word);
+  __Pyx_GIVEREF(__pyx_v_word);
+  __Pyx_INCREF(__pyx_v_default);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_default);
+  __Pyx_GIVEREF(__pyx_v_default);
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __pyx_r = __pyx_t_3;
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("_sa.Vocabulary.get", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static Py_ssize_t __pyx_pw_3_sa_10Vocabulary_11__len__(PyObject *__pyx_v_self); /*proto*/
+static Py_ssize_t __pyx_pw_3_sa_10Vocabulary_11__len__(PyObject *__pyx_v_self) {
+  Py_ssize_t __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__len__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_10Vocabulary_10__len__(((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_self));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":26
+ *         return self.word2id.get(word, default)
+ * 
+ *     def __len__(self):             # <<<<<<<<<<<<<<
+ *         return len(self.id2word)
+ * 
+ */
+
+static Py_ssize_t __pyx_pf_3_sa_10Vocabulary_10__len__(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self) {
+  Py_ssize_t __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__len__", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":27
+ * 
+ *     def __len__(self):
+ *         return len(self.id2word)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void write_handle(self, FILE* f, int offset=0):
+ */
+  __pyx_t_1 = __pyx_v_self->id2word;
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_r = __pyx_t_2;
+  goto __pyx_L0;
+
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("_sa.Vocabulary.__len__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":29
+ *         return len(self.id2word)
+ * 
+ *     cdef void write_handle(self, FILE* f, int offset=0):             # <<<<<<<<<<<<<<
+ *         cdef int word_len
+ *         cdef int num_words
+ */
+
+static void __pyx_f_3_sa_10Vocabulary_write_handle(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, FILE *__pyx_v_f, struct __pyx_opt_args_3_sa_10Vocabulary_write_handle *__pyx_optional_args) {
+  int __pyx_v_offset = ((int)0);
+  int __pyx_v_word_len;
+  int __pyx_v_num_words;
+  PyObject *__pyx_v_word = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *(*__pyx_t_4)(PyObject *);
+  Py_ssize_t __pyx_t_5;
+  char *__pyx_t_6;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("write_handle", 0);
+  if (__pyx_optional_args) {
+    if (__pyx_optional_args->__pyx_n > 0) {
+      __pyx_v_offset = __pyx_optional_args->offset;
+    }
+  }
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":33
+ *         cdef int num_words
+ * 
+ *         num_words = len(self.id2word) - offset             # <<<<<<<<<<<<<<
+ *         fwrite(&(num_words), sizeof(int), 1, f)
+ *         for word in self.id2word[offset:]:
+ */
+  __pyx_t_1 = __pyx_v_self->id2word;
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_num_words = (__pyx_t_2 - __pyx_v_offset);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":34
+ * 
+ *         num_words = len(self.id2word) - offset
+ *         fwrite(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
+ *         for word in self.id2word[offset:]:
+ *             word_len = len(word) + 1
+ */
+  fwrite((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":35
+ *         num_words = len(self.id2word) - offset
+ *         fwrite(&(num_words), sizeof(int), 1, f)
+ *         for word in self.id2word[offset:]:             # <<<<<<<<<<<<<<
+ *             word_len = len(word) + 1
+ *             fwrite(&(word_len), sizeof(int), 1, f)
+ */
+  __pyx_t_1 = __Pyx_PySequence_GetSlice(__pyx_v_self->id2word, __pyx_v_offset, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyList_CheckExact(__pyx_t_1) || PyTuple_CheckExact(__pyx_t_1)) {
+    __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_2 = 0;
+    __pyx_t_4 = NULL;
+  } else {
+    __pyx_t_2 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = Py_TYPE(__pyx_t_3)->tp_iternext;
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  for (;;) {
+    if (!__pyx_t_4 && PyList_CheckExact(__pyx_t_3)) {
+      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_3)) break;
+      #if CYTHON_COMPILING_IN_CPYTHON
+      __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #else
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #endif
+    } else if (!__pyx_t_4 && PyTuple_CheckExact(__pyx_t_3)) {
+      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
+      #if CYTHON_COMPILING_IN_CPYTHON
+      __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #else
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      #endif
+    } else {
+      __pyx_t_1 = __pyx_t_4(__pyx_t_3);
+      if (unlikely(!__pyx_t_1)) {
+        if (PyErr_Occurred()) {
+          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
+          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 35; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_1);
+    }
+    __Pyx_XDECREF(__pyx_v_word);
+    __pyx_v_word = __pyx_t_1;
+    __pyx_t_1 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":36
+ *         fwrite(&(num_words), sizeof(int), 1, f)
+ *         for word in self.id2word[offset:]:
+ *             word_len = len(word) + 1             # <<<<<<<<<<<<<<
+ *             fwrite(&(word_len), sizeof(int), 1, f)
+ *             fwrite(<char *>word, sizeof(char), word_len, f)
+ */
+    __pyx_t_5 = PyObject_Length(__pyx_v_word); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_v_word_len = (__pyx_t_5 + 1);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":37
+ *         for word in self.id2word[offset:]:
+ *             word_len = len(word) + 1
+ *             fwrite(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
+ *             fwrite(<char *>word, sizeof(char), word_len, f)
+ * 
+ */
+    fwrite((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":38
+ *             word_len = len(word) + 1
+ *             fwrite(&(word_len), sizeof(int), 1, f)
+ *             fwrite(<char *>word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void read_handle(self, FILE* f):
+ */
+    __pyx_t_6 = PyBytes_AsString(__pyx_v_word); if (unlikely((!__pyx_t_6) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    fwrite(((char *)__pyx_t_6), (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_WriteUnraisable("_sa.Vocabulary.write_handle", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_word);
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":40
+ *             fwrite(<char *>word, sizeof(char), word_len, f)
+ * 
+ *     cdef void read_handle(self, FILE* f):             # <<<<<<<<<<<<<<
+ *         cdef int num_words, word_len
+ *         cdef char* word
+ */
+
+static void __pyx_f_3_sa_10Vocabulary_read_handle(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, FILE *__pyx_v_f) {
+  int __pyx_v_num_words;
+  int __pyx_v_word_len;
+  char *__pyx_v_word;
+  CYTHON_UNUSED unsigned int __pyx_v_i;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  unsigned int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  Py_ssize_t __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("read_handle", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":45
+ *         cdef unsigned i
+ * 
+ *         fread(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
+ *         for i in range(num_words):
+ *             fread(&(word_len), sizeof(int), 1, f)
+ */
+  fread((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":46
+ * 
+ *         fread(&(num_words), sizeof(int), 1, f)
+ *         for i in range(num_words):             # <<<<<<<<<<<<<<
+ *             fread(&(word_len), sizeof(int), 1, f)
+ *             word = <char*> malloc (word_len * sizeof(char))
+ */
+  __pyx_t_1 = __pyx_v_num_words;
+  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
+    __pyx_v_i = __pyx_t_2;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":47
+ *         fread(&(num_words), sizeof(int), 1, f)
+ *         for i in range(num_words):
+ *             fread(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
+ *             word = <char*> malloc (word_len * sizeof(char))
+ *             fread(word, sizeof(char), word_len, f)
+ */
+    fread((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":48
+ *         for i in range(num_words):
+ *             fread(&(word_len), sizeof(int), 1, f)
+ *             word = <char*> malloc (word_len * sizeof(char))             # <<<<<<<<<<<<<<
+ *             fread(word, sizeof(char), word_len, f)
+ *             self.word2id[word] = len(self.id2word)
+ */
+    __pyx_v_word = ((char *)malloc((__pyx_v_word_len * (sizeof(char)))));
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":49
+ *             fread(&(word_len), sizeof(int), 1, f)
+ *             word = <char*> malloc (word_len * sizeof(char))
+ *             fread(word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
+ *             self.word2id[word] = len(self.id2word)
+ *             self.id2word.append(word)
+ */
+    fread(__pyx_v_word, (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":50
+ *             word = <char*> malloc (word_len * sizeof(char))
+ *             fread(word, sizeof(char), word_len, f)
+ *             self.word2id[word] = len(self.id2word)             # <<<<<<<<<<<<<<
+ *             self.id2word.append(word)
+ *             free(word)
+ */
+    __pyx_t_3 = __pyx_v_self->id2word;
+    __Pyx_INCREF(__pyx_t_3);
+    __pyx_t_4 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+    if (PyObject_SetItem(__pyx_v_self->word2id, ((PyObject *)__pyx_t_5), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":51
+ *             fread(word, sizeof(char), word_len, f)
+ *             self.word2id[word] = len(self.id2word)
+ *             self.id2word.append(word)             # <<<<<<<<<<<<<<
+ *             free(word)
+ * 
+ */
+    __pyx_t_3 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    __pyx_t_5 = __Pyx_PyObject_Append(__pyx_v_self->id2word, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":52
+ *             self.word2id[word] = len(self.id2word)
+ *             self.id2word.append(word)
+ *             free(word)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ */
+    free(__pyx_v_word);
+  }
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_WriteUnraisable("_sa.Vocabulary.read_handle", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":54
+ *             free(word)
+ * 
+ *     cdef void read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         cdef int num_words, word_len
+ *         cdef char* word
+ */
+
+static void __pyx_f_3_sa_10Vocabulary_read_mmaped(struct __pyx_obj_3_sa_Vocabulary *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  int __pyx_v_num_words;
+  int __pyx_v_word_len;
+  char *__pyx_v_word;
+  CYTHON_UNUSED unsigned int __pyx_v_i;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  unsigned int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  Py_ssize_t __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":59
+ *         cdef unsigned i
+ * 
+ *         num_words = buf.read_int()             # <<<<<<<<<<<<<<
+ *         for i in range(num_words):
+ *             word_len = buf.read_int()
+ */
+  __pyx_v_num_words = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":60
+ * 
+ *         num_words = buf.read_int()
+ *         for i in range(num_words):             # <<<<<<<<<<<<<<
+ *             word_len = buf.read_int()
+ *             word = buf.read_char_array(word_len)
+ */
+  __pyx_t_1 = __pyx_v_num_words;
+  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
+    __pyx_v_i = __pyx_t_2;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":61
+ *         num_words = buf.read_int()
+ *         for i in range(num_words):
+ *             word_len = buf.read_int()             # <<<<<<<<<<<<<<
+ *             word = buf.read_char_array(word_len)
+ *             self.word2id[word] = len(self.id2word)
+ */
+    __pyx_v_word_len = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":62
+ *         for i in range(num_words):
+ *             word_len = buf.read_int()
+ *             word = buf.read_char_array(word_len)             # <<<<<<<<<<<<<<
+ *             self.word2id[word] = len(self.id2word)
+ *             self.id2word.append(word)
+ */
+    __pyx_v_word = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_char_array(__pyx_v_buf, __pyx_v_word_len);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":63
+ *             word_len = buf.read_int()
+ *             word = buf.read_char_array(word_len)
+ *             self.word2id[word] = len(self.id2word)             # <<<<<<<<<<<<<<
+ *             self.id2word.append(word)
+ */
+    __pyx_t_3 = __pyx_v_self->id2word;
+    __Pyx_INCREF(__pyx_t_3);
+    __pyx_t_4 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_5 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
+    if (PyObject_SetItem(__pyx_v_self->word2id, ((PyObject *)__pyx_t_5), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/vocabulary.pxi":64
+ *             word = buf.read_char_array(word_len)
+ *             self.word2id[word] = len(self.id2word)
+ *             self.id2word.append(word)             # <<<<<<<<<<<<<<
+ */
+    __pyx_t_3 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
+    __pyx_t_5 = __Pyx_PyObject_Append(__pyx_v_self->id2word, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_WriteUnraisable("_sa.Vocabulary.read_mmaped", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+}
+
 /* Python wrapper */
 static int __pyx_pw_3_sa_9DataArray_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static int __pyx_pw_3_sa_9DataArray_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
@@ -6839,27 +7335,30 @@ static int __pyx_pw_3_sa_9DataArray_1__cinit__(PyObject *__pyx_v_self, PyObject
   PyObject *__pyx_v_from_text = 0;
   PyObject *__pyx_v_side = 0;
   int __pyx_v_use_sent_id;
+  PyObject *__pyx_v_mmaped = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,&__pyx_n_s__side,&__pyx_n_s__use_sent_id,0};
-    PyObject* values[4] = {0,0,0,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,&__pyx_n_s__side,&__pyx_n_s__use_sent_id,&__pyx_n_s__mmaped,0};
+    PyObject* values[5] = {0,0,0,0,0};
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":17
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":19
  *     cdef bint use_sent_id
  * 
- *     def __cinit__(self, from_binary=None, from_text=None, side=None, bint use_sent_id=False):             # <<<<<<<<<<<<<<
- *         self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+ *     def __cinit__(self, from_binary=None, from_text=None, side=None,             # <<<<<<<<<<<<<<
+ *             bint use_sent_id=False, mmaped=False):
+ *         self.voc = Vocabulary()
  */
     values[0] = ((PyObject *)Py_None);
     values[1] = ((PyObject *)Py_None);
     values[2] = ((PyObject *)Py_None);
+    values[4] = __pyx_k_8;
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
         case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
         case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
@@ -6889,12 +7388,18 @@ static int __pyx_pw_3_sa_9DataArray_1__cinit__(PyObject *__pyx_v_self, PyObject
           PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__use_sent_id);
           if (value) { values[3] = value; kw_args--; }
         }
+        case  4:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__mmaped);
+          if (value) { values[4] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
         case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
         case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
@@ -6907,238 +7412,287 @@ static int __pyx_pw_3_sa_9DataArray_1__cinit__(PyObject *__pyx_v_self, PyObject
     __pyx_v_from_text = values[1];
     __pyx_v_side = values[2];
     if (values[3]) {
-      __pyx_v_use_sent_id = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_use_sent_id == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+      __pyx_v_use_sent_id = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_use_sent_id == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     } else {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":20
+ * 
+ *     def __cinit__(self, from_binary=None, from_text=None, side=None,
+ *             bint use_sent_id=False, mmaped=False):             # <<<<<<<<<<<<<<
+ *         self.voc = Vocabulary()
+ *         self.voc.extend(INIT_VOCABULARY)
+ */
       __pyx_v_use_sent_id = ((int)0);
     }
+    __pyx_v_mmaped = values[4];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[3]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.DataArray.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray___cinit__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text, __pyx_v_side, __pyx_v_use_sent_id);
+  __pyx_r = __pyx_pf_3_sa_9DataArray___cinit__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text, __pyx_v_side, __pyx_v_use_sent_id, __pyx_v_mmaped);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_9DataArray___cinit__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side, int __pyx_v_use_sent_id) {
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":19
+ *     cdef bint use_sent_id
+ * 
+ *     def __cinit__(self, from_binary=None, from_text=None, side=None,             # <<<<<<<<<<<<<<
+ *             bint use_sent_id=False, mmaped=False):
+ *         self.voc = Vocabulary()
+ */
+
+static int __pyx_pf_3_sa_9DataArray___cinit__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side, int __pyx_v_use_sent_id, PyObject *__pyx_v_mmaped) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
+  PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_4;
   long __pyx_t_5;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":18
- * 
- *     def __cinit__(self, from_binary=None, from_text=None, side=None, bint use_sent_id=False):
- *         self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}             # <<<<<<<<<<<<<<
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":21
+ *     def __cinit__(self, from_binary=None, from_text=None, side=None,
+ *             bint use_sent_id=False, mmaped=False):
+ *         self.voc = Vocabulary()             # <<<<<<<<<<<<<<
+ *         self.voc.extend(INIT_VOCABULARY)
  *         self.data = IntList(1000,1000)
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__END_OF_FILE), __pyx_int_0) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__END_OF_LINE), __pyx_int_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->word2id);
-  __Pyx_DECREF(__pyx_v_self->word2id);
-  __pyx_v_self->word2id = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_Vocabulary)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->voc);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->voc));
+  __pyx_v_self->voc = ((struct __pyx_obj_3_sa_Vocabulary *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":19
- *     def __cinit__(self, from_binary=None, from_text=None, side=None, bint use_sent_id=False):
- *         self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]             # <<<<<<<<<<<<<<
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":22
+ *             bint use_sent_id=False, mmaped=False):
+ *         self.voc = Vocabulary()
+ *         self.voc.extend(INIT_VOCABULARY)             # <<<<<<<<<<<<<<
  *         self.data = IntList(1000,1000)
  *         self.sent_id = IntList(1000,1000)
  */
-  __pyx_t_1 = PyList_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self->voc), __pyx_n_s__extend); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__END_OF_FILE));
-  PyList_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_n_s__END_OF_FILE));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__END_OF_FILE));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__END_OF_LINE));
-  PyList_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__END_OF_LINE));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__END_OF_LINE));
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->id2word);
-  __Pyx_DECREF(__pyx_v_self->id2word);
-  __pyx_v_self->id2word = ((PyObject *)__pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__INIT_VOCABULARY); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
+  __pyx_t_2 = 0;
+  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":20
- *         self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":23
+ *         self.voc = Vocabulary()
+ *         self.voc.extend(INIT_VOCABULARY)
  *         self.data = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_id = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_9), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
   __Pyx_GOTREF(__pyx_v_self->data);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->data));
-  __pyx_v_self->data = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_v_self->data = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_2);
+  __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":21
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":24
+ *         self.voc.extend(INIT_VOCABULARY)
  *         self.data = IntList(1000,1000)
  *         self.sent_id = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_index = IntList(1000,1000)
  *         self.use_sent_id = use_sent_id
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_11), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_10), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
   __Pyx_GOTREF(__pyx_v_self->sent_id);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->sent_id));
-  __pyx_v_self->sent_id = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_v_self->sent_id = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_2);
+  __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":22
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":25
  *         self.data = IntList(1000,1000)
  *         self.sent_id = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.use_sent_id = use_sent_id
  *         if from_binary:
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_12), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_11), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
   __Pyx_GOTREF(__pyx_v_self->sent_index);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->sent_index));
-  __pyx_v_self->sent_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_v_self->sent_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_2);
+  __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":23
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":26
  *         self.sent_id = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)
  *         self.use_sent_id = use_sent_id             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
   __pyx_v_self->use_sent_id = __pyx_v_use_sent_id;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":24
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":27
  *         self.sent_index = IntList(1000,1000)
  *         self.use_sent_id = use_sent_id
  *         if from_binary:             # <<<<<<<<<<<<<<
- *             self.read_binary(from_binary)
- *         elif from_text:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_2) {
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_t_4) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":25
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":28
  *         self.use_sent_id = use_sent_id
  *         if from_binary:
- *             self.read_binary(from_binary)             # <<<<<<<<<<<<<<
+ *             if mmaped:             # <<<<<<<<<<<<<<
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ */
+    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_mmaped); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_4) {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":29
+ *         if from_binary:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.read_binary(from_binary)
+ */
+      __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_MemoryMap)), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+      ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->__pyx_vtab)->read_mmaped(__pyx_v_self, ((struct __pyx_obj_3_sa_MemoryMap *)__pyx_t_3));
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":31
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ *                 self.read_binary(from_binary)             # <<<<<<<<<<<<<<
  *         elif from_text:
  *             if side:
  */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_from_binary);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
-    __Pyx_GIVEREF(__pyx_v_from_binary);
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
+    __pyx_L4:;
     goto __pyx_L3;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":26
- *         if from_binary:
- *             self.read_binary(from_binary)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":32
+ *             else:
+ *                 self.read_binary(from_binary)
  *         elif from_text:             # <<<<<<<<<<<<<<
  *             if side:
  *                 self.read_bitext(from_text, (0 if side == 'source' else 1))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_2) {
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__pyx_t_4) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":27
- *             self.read_binary(from_binary)
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":33
+ *                 self.read_binary(from_binary)
  *         elif from_text:
  *             if side:             # <<<<<<<<<<<<<<
  *                 self.read_bitext(from_text, (0 if side == 'source' else 1))
  *             else:
  */
-    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_side); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    if (__pyx_t_2) {
+    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_side); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_4) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":28
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":34
  *         elif from_text:
  *             if side:
  *                 self.read_bitext(from_text, (0 if side == 'source' else 1))             # <<<<<<<<<<<<<<
  *             else:
  *                 self.read_text(from_text)
  */
-      __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_bitext); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_3 = PyObject_RichCompare(__pyx_v_side, ((PyObject *)__pyx_n_s__source), Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (__pyx_t_2) {
+      __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_bitext); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_2 = PyObject_RichCompare(__pyx_v_side, ((PyObject *)__pyx_n_s__source), Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      if (__pyx_t_4) {
         __pyx_t_5 = 0;
       } else {
         __pyx_t_5 = 1;
       }
-      __pyx_t_3 = PyInt_FromLong(__pyx_t_5); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyInt_FromLong(__pyx_t_5); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_1);
       __Pyx_INCREF(__pyx_v_from_text);
-      PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_from_text);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_text);
       __Pyx_GIVEREF(__pyx_v_from_text);
-      PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
-      __Pyx_GIVEREF(__pyx_t_3);
-      __pyx_t_3 = 0;
-      __pyx_t_3 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      goto __pyx_L4;
+      PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);
+      __Pyx_GIVEREF(__pyx_t_2);
+      __pyx_t_2 = 0;
+      __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      goto __pyx_L5;
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":30
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":36
  *                 self.read_bitext(from_text, (0 if side == 'source' else 1))
  *             else:
  *                 self.read_text(from_text)             # <<<<<<<<<<<<<<
  * 
  *     def __len__(self):
  */
-      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_1);
       __Pyx_INCREF(__pyx_v_from_text);
-      PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_from_text);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_text);
       __Pyx_GIVEREF(__pyx_v_from_text);
-      __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     }
-    __pyx_L4:;
+    __pyx_L5:;
     goto __pyx_L3;
   }
   __pyx_L3:;
@@ -7147,8 +7701,8 @@ static int __pyx_pf_3_sa_9DataArray___cinit__(struct __pyx_obj_3_sa_DataArray *_
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("_sa.DataArray.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __pyx_L0:;
@@ -7167,7 +7721,7 @@ static Py_ssize_t __pyx_pw_3_sa_9DataArray_3__len__(PyObject *__pyx_v_self) {
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":32
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":38
  *                 self.read_text(from_text)
  * 
  *     def __len__(self):             # <<<<<<<<<<<<<<
@@ -7185,7 +7739,7 @@ static Py_ssize_t __pyx_pf_3_sa_9DataArray_2__len__(struct __pyx_obj_3_sa_DataAr
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__len__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":33
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":39
  * 
  *     def __len__(self):
  *         return len(self.data)             # <<<<<<<<<<<<<<
@@ -7194,7 +7748,7 @@ static Py_ssize_t __pyx_pf_3_sa_9DataArray_2__len__(struct __pyx_obj_3_sa_DataAr
  */
   __pyx_t_1 = ((PyObject *)__pyx_v_self->data);
   __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_r = __pyx_t_2;
   goto __pyx_L0;
@@ -7221,7 +7775,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_5get_sentence_id(PyObject *__pyx_v_sel
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":35
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":41
  *         return len(self.data)
  * 
  *     def get_sentence_id(self, i):             # <<<<<<<<<<<<<<
@@ -7239,7 +7793,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_4get_sentence_id(struct __pyx_obj_3_sa
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_sentence_id", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":36
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":42
  * 
  *     def get_sentence_id(self, i):
  *         return self.sent_id.arr[i]             # <<<<<<<<<<<<<<
@@ -7247,8 +7801,8 @@ static PyObject *__pyx_pf_3_sa_9DataArray_4get_sentence_id(struct __pyx_obj_3_sa
  *     def get_sentence(self, i):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->sent_id->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->sent_id->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -7277,130 +7831,84 @@ static PyObject *__pyx_pw_3_sa_9DataArray_7get_sentence(PyObject *__pyx_v_self,
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":38
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":44
  *         return self.sent_id.arr[i]
  * 
  *     def get_sentence(self, i):             # <<<<<<<<<<<<<<
  *         cdef int j, start, stop
- *         sent = []
+ *         start = self.sent_index.arr[i]
  */
 
 static PyObject *__pyx_pf_3_sa_9DataArray_6get_sentence(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_i) {
+  int __pyx_v_j;
   int __pyx_v_start;
   int __pyx_v_stop;
-  PyObject *__pyx_v_sent = NULL;
+  CYTHON_UNUSED PyObject *__pyx_v_sent = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  Py_ssize_t __pyx_t_2;
+  Py_ssize_t __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
   int __pyx_t_3;
   int __pyx_t_4;
-  int __pyx_t_5;
+  PyObject *__pyx_t_5 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_sentence", 0);
-  __Pyx_INCREF(__pyx_v_i);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":40
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":46
  *     def get_sentence(self, i):
  *         cdef int j, start, stop
- *         sent = []             # <<<<<<<<<<<<<<
- *         start = self.sent_index.arr[i]
- *         stop = self.sent_index.arr[i+1]
- */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_sent = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":41
- *         cdef int j, start, stop
- *         sent = []
  *         start = self.sent_index.arr[i]             # <<<<<<<<<<<<<<
  *         stop = self.sent_index.arr[i+1]
- *         for i from start <= i < stop:
+ *         sent = [self.voc.id2word[self.data.arr[j]] for j in range(start, stop)]
  */
-  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 41; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_v_start = (__pyx_v_self->sent_index->arr[__pyx_t_2]);
+  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_start = (__pyx_v_self->sent_index->arr[__pyx_t_1]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":42
- *         sent = []
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":47
+ *         cdef int j, start, stop
  *         start = self.sent_index.arr[i]
  *         stop = self.sent_index.arr[i+1]             # <<<<<<<<<<<<<<
- *         for i from start <= i < stop:
- *             sent.append(self.id2word[self.data.arr[i]])
- */
-  __pyx_t_1 = PyNumber_Add(__pyx_v_i, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 42; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_stop = (__pyx_v_self->sent_index->arr[__pyx_t_2]);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":43
- *         start = self.sent_index.arr[i]
- *         stop = self.sent_index.arr[i+1]
- *         for i from start <= i < stop:             # <<<<<<<<<<<<<<
- *             sent.append(self.id2word[self.data.arr[i]])
- *         return sent
- */
-  __pyx_t_3 = __pyx_v_stop;
-  for (__pyx_t_4 = __pyx_v_start; __pyx_t_4 < __pyx_t_3; __pyx_t_4++) {
-    __pyx_t_1 = PyInt_FromLong(__pyx_t_4); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_v_i);
-    __pyx_v_i = __pyx_t_1;
-    __pyx_t_1 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":44
- *         stop = self.sent_index.arr[i+1]
- *         for i from start <= i < stop:
- *             sent.append(self.id2word[self.data.arr[i]])             # <<<<<<<<<<<<<<
- *         return sent
+ *         sent = [self.voc.id2word[self.data.arr[j]] for j in range(start, stop)]
  * 
  */
-    __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_self->id2word, (__pyx_v_self->data->arr[__pyx_t_2]), sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_5 = PyList_Append(__pyx_v_sent, __pyx_t_1); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 44; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  }
+  __pyx_t_2 = PyNumber_Add(__pyx_v_i, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_t_2); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_stop = (__pyx_v_self->sent_index->arr[__pyx_t_1]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":43
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":48
  *         start = self.sent_index.arr[i]
  *         stop = self.sent_index.arr[i+1]
- *         for i from start <= i < stop:             # <<<<<<<<<<<<<<
- *             sent.append(self.id2word[self.data.arr[i]])
- *         return sent
- */
-  __pyx_t_1 = PyInt_FromLong(__pyx_t_4); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 43; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_v_i);
-  __pyx_v_i = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":45
- *         for i from start <= i < stop:
- *             sent.append(self.id2word[self.data.arr[i]])
- *         return sent             # <<<<<<<<<<<<<<
+ *         sent = [self.voc.id2word[self.data.arr[j]] for j in range(start, stop)]             # <<<<<<<<<<<<<<
  * 
  *     def get_id(self, word):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)__pyx_v_sent));
-  __pyx_r = ((PyObject *)__pyx_v_sent);
-  goto __pyx_L0;
+  __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __pyx_v_stop;
+  for (__pyx_t_4 = __pyx_v_start; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
+    __pyx_v_j = __pyx_t_4;
+    __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_self->voc->id2word, (__pyx_v_self->data->arr[__pyx_v_j]), sizeof(int), PyInt_FromLong); if (!__pyx_t_5) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    if (unlikely(__Pyx_PyList_Append(__pyx_t_2, (PyObject*)__pyx_t_5))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  }
+  __Pyx_INCREF(((PyObject *)__pyx_t_2));
+  __pyx_v_sent = __pyx_t_2;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("_sa.DataArray.get_sentence", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_v_sent);
-  __Pyx_XDECREF(__pyx_v_i);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
@@ -7417,85 +7925,41 @@ static PyObject *__pyx_pw_3_sa_9DataArray_9get_id(PyObject *__pyx_v_self, PyObje
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":47
- *         return sent
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":50
+ *         sent = [self.voc.id2word[self.data.arr[j]] for j in range(start, stop)]
  * 
  *     def get_id(self, word):             # <<<<<<<<<<<<<<
- *         if not word in self.word2id:
- *             self.word2id[word] = len(self.id2word)
+ *         return self.voc[word]
+ * 
  */
 
 static PyObject *__pyx_pf_3_sa_9DataArray_8get_id(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_word) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  Py_ssize_t __pyx_t_4;
+  PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_id", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":48
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":51
  * 
  *     def get_id(self, word):
- *         if not word in self.word2id:             # <<<<<<<<<<<<<<
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)
- */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_word, __pyx_v_self->word2id, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = (!__pyx_t_1);
-  if (__pyx_t_2) {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":49
- *     def get_id(self, word):
- *         if not word in self.word2id:
- *             self.word2id[word] = len(self.id2word)             # <<<<<<<<<<<<<<
- *             self.id2word.append(word)
- *         return self.word2id[word]
- */
-    __pyx_t_3 = __pyx_v_self->id2word;
-    __Pyx_INCREF(__pyx_t_3);
-    __pyx_t_4 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    if (PyObject_SetItem(__pyx_v_self->word2id, __pyx_v_word, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":50
- *         if not word in self.word2id:
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)             # <<<<<<<<<<<<<<
- *         return self.word2id[word]
- * 
- */
-    __pyx_t_3 = __Pyx_PyObject_Append(__pyx_v_self->id2word, __pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    goto __pyx_L3;
-  }
-  __pyx_L3:;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":51
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)
- *         return self.word2id[word]             # <<<<<<<<<<<<<<
+ *         return self.voc[word]             # <<<<<<<<<<<<<<
  * 
  *     def __getitem__(self, loc):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = PyObject_GetItem(__pyx_v_self->word2id, __pyx_v_word); if (!__pyx_t_3) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_r = __pyx_t_3;
-  __pyx_t_3 = 0;
+  __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_self->voc), __pyx_v_word); if (!__pyx_t_1) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_AddTraceback("_sa.DataArray.get_id", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -7516,10 +7980,10 @@ static PyObject *__pyx_pw_3_sa_9DataArray_11__getitem__(PyObject *__pyx_v_self,
 }
 
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":53
- *         return self.word2id[word]
+ *         return self.voc[word]
  * 
  *     def __getitem__(self, loc):             # <<<<<<<<<<<<<<
- *         return self.id2word[self.data.arr[loc]]
+ *         return self.voc.id2word[self.data.arr[loc]]
  * 
  */
 
@@ -7536,13 +8000,13 @@ static PyObject *__pyx_pf_3_sa_9DataArray_10__getitem__(struct __pyx_obj_3_sa_Da
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":54
  * 
  *     def __getitem__(self, loc):
- *         return self.id2word[self.data.arr[loc]]             # <<<<<<<<<<<<<<
+ *         return self.voc.id2word[self.data.arr[loc]]             # <<<<<<<<<<<<<<
  * 
  *     def get_sentence_bounds(self, loc):
  */
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_loc); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_self->id2word, (__pyx_v_self->data->arr[__pyx_t_1]), sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_self->voc->id2word, (__pyx_v_self->data->arr[__pyx_t_1]), sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -7572,7 +8036,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_13get_sentence_bounds(PyObject *__pyx_
 }
 
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":56
- *         return self.id2word[self.data.arr[loc]]
+ *         return self.voc.id2word[self.data.arr[loc]]
  * 
  *     def get_sentence_bounds(self, loc):             # <<<<<<<<<<<<<<
  *         cdef int sid = self.sent_id.arr[loc]
@@ -7607,7 +8071,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_12get_sentence_bounds(struct __pyx_obj
  *         cdef int sid = self.sent_id.arr[loc]
  *         return (self.sent_index.arr[sid], self.sent_index.arr[sid+1])             # <<<<<<<<<<<<<<
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  */
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_2 = PyInt_FromLong((__pyx_v_self->sent_index->arr[__pyx_v_sid])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -7641,22 +8105,17 @@ static PyObject *__pyx_pf_3_sa_9DataArray_12get_sentence_bounds(struct __pyx_obj
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_15write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_15write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9DataArray_15write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_15write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.DataArray.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray_14write_text(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9DataArray_14write_text(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
@@ -7664,12 +8123,12 @@ static PyObject *__pyx_pw_3_sa_9DataArray_15write_text(PyObject *__pyx_v_self, P
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":60
  *         return (self.sent_index.arr[sid], self.sent_index.arr[sid+1])
  * 
- *     def write_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             for w_id in self.data:
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_v_w_id = NULL;
   PyObject *__pyx_r = NULL;
@@ -7695,33 +8154,31 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":61
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for w_id in self.data:
  *                 if w_id > 1:
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -7734,7 +8191,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
           /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":62
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:
  *             for w_id in self.data:             # <<<<<<<<<<<<<<
  *                 if w_id > 1:
@@ -7752,31 +8209,31 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_1 = __pyx_t_9(__pyx_t_4);
-              if (unlikely(!__pyx_t_1)) {
+              __pyx_t_2 = __pyx_t_9(__pyx_t_4);
+              if (unlikely(!__pyx_t_2)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
                   else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_1);
+              __Pyx_GOTREF(__pyx_t_2);
             }
             __Pyx_XDECREF(__pyx_v_w_id);
-            __pyx_v_w_id = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_w_id = __pyx_t_2;
+            __pyx_t_2 = 0;
 
             /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":63
  *         with open(filename, "w") as f:
@@ -7785,9 +8242,9 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
  *                     f.write("%s " % self.get_word(w_id))
  *                 if w_id == 1:
  */
-            __pyx_t_1 = PyObject_RichCompare(__pyx_v_w_id, __pyx_int_1, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_10 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __pyx_t_2 = PyObject_RichCompare(__pyx_v_w_id, __pyx_int_1, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_10 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             if (__pyx_t_10) {
 
               /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":64
@@ -7797,20 +8254,20 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
  *                 if w_id == 1:
  *                     f.write("\n")
  */
-              __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_1);
-              __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_word); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_2);
+              __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_word); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_1);
               __pyx_t_11 = PyTuple_New(1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_11);
               __Pyx_INCREF(__pyx_v_w_id);
               PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_v_w_id);
               __Pyx_GIVEREF(__pyx_v_w_id);
-              __pyx_t_12 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
-              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
               __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
-              __pyx_t_11 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_13), __pyx_t_12); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_12), __pyx_t_12); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(((PyObject *)__pyx_t_11));
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
@@ -7818,9 +8275,9 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
               PyTuple_SET_ITEM(__pyx_t_12, 0, ((PyObject *)__pyx_t_11));
               __Pyx_GIVEREF(((PyObject *)__pyx_t_11));
               __pyx_t_11 = 0;
-              __pyx_t_11 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_11);
-              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
               __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
               __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
               goto __pyx_L18;
@@ -7844,11 +8301,11 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
  *                 if w_id == 1:
  *                     f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  */
               __pyx_t_11 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_11);
-              __pyx_t_12 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_k_tuple_15), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_k_tuple_14), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
               __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
@@ -7863,15 +8320,15 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
         __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
         __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
 
         /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":61
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for w_id in self.data:
  *                 if w_id > 1:
@@ -7882,18 +8339,18 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
           __Pyx_GOTREF(__pyx_t_4);
           __Pyx_GOTREF(__pyx_t_12);
           __Pyx_GOTREF(__pyx_t_11);
-          __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_4);
-          PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4);
           __Pyx_GIVEREF(__pyx_t_4);
           __Pyx_INCREF(__pyx_t_12);
-          PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_12);
+          PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_12);
           __Pyx_GIVEREF(__pyx_t_12);
           __Pyx_INCREF(__pyx_t_11);
-          PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_11);
+          PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_11);
           __Pyx_GIVEREF(__pyx_t_11);
-          __pyx_t_13 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL);
+          __pyx_t_13 = PyObject_Call(__pyx_t_3, __pyx_t_2, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_13);
@@ -7911,7 +8368,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
             goto __pyx_L22;
           }
           __pyx_L22:;
-          __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
           __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
@@ -7933,7 +8390,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_16, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_15, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
         if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
@@ -7968,22 +8425,17 @@ static PyObject *__pyx_pf_3_sa_9DataArray_14write_text(struct __pyx_obj_3_sa_Dat
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_17read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_17read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9DataArray_17read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_17read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.DataArray.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray_16read_text(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9DataArray_16read_text(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
@@ -7991,12 +8443,12 @@ static PyObject *__pyx_pw_3_sa_9DataArray_17read_text(PyObject *__pyx_v_self, Py
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":68
  *                     f.write("\n")
  * 
- *     def read_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with gzip_or_text(filename) as fp:
  *             self.read_text_data(fp)
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_fp = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -8018,7 +8470,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":69
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             self.read_text_data(fp)
  * 
@@ -8026,25 +8478,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
   /*with:*/ {
     __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-    __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
+    __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -8057,24 +8507,24 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
           /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":70
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as fp:
  *             self.read_text_data(fp)             # <<<<<<<<<<<<<<
  * 
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  */
           __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_v_fp);
-          PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_fp);
+          PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_fp);
           __Pyx_GIVEREF(__pyx_v_fp);
-          __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_3);
+          __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -8082,30 +8532,30 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
 
         /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":69
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             self.read_text_data(fp)
  * 
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.DataArray.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_3);
+          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_3, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_GOTREF(__pyx_t_1);
           __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
-          __Pyx_GIVEREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2);
           __Pyx_GIVEREF(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_t_1);
           PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
@@ -8118,18 +8568,18 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
           if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_11 = (!__pyx_t_9);
           if (__pyx_t_11) {
-            __Pyx_GIVEREF(__pyx_t_3);
             __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_GIVEREF(__pyx_t_3);
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_3, __pyx_t_2, __pyx_t_1);
-            __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; 
+            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_3, __pyx_t_1);
+            __pyx_t_2 = 0; __pyx_t_3 = 0; __pyx_t_1 = 0; 
             {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L18;
           }
           __pyx_L18:;
           __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           goto __pyx_L8_exception_handled;
         }
@@ -8149,7 +8599,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
     }
     /*finally:*/ {
       if (__pyx_t_4) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_17, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_16, NULL);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
         if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
@@ -8184,7 +8634,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_16read_text(struct __pyx_obj_3_sa_Data
 /* Python wrapper */
 static PyObject *__pyx_pw_3_sa_9DataArray_19read_bitext(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
 static PyObject *__pyx_pw_3_sa_9DataArray_19read_bitext(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  char *__pyx_v_filename;
+  PyObject *__pyx_v_filename = 0;
   int __pyx_v_side;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
@@ -8221,7 +8671,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_19read_bitext(PyObject *__pyx_v_self,
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_filename = PyBytes_AsString(values[0]); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_filename = ((PyObject*)values[0]);
     __pyx_v_side = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_side == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
@@ -8232,14 +8682,19 @@ static PyObject *__pyx_pw_3_sa_9DataArray_19read_bitext(PyObject *__pyx_v_self,
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_3_sa_9DataArray_18read_bitext(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), __pyx_v_filename, __pyx_v_side);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 static PyObject *__pyx_gb_3_sa_9DataArray_11read_bitext_2generator6(__pyx_GeneratorObject *__pyx_generator, PyObject *__pyx_sent_value); /* proto */
 
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":74
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)             # <<<<<<<<<<<<<<
  *             self.read_text_data(data)
@@ -8344,7 +8799,7 @@ static PyObject *__pyx_gb_3_sa_9DataArray_11read_bitext_2generator6(__pyx_Genera
     __pyx_t_4 = 0;
     __pyx_t_4 = PyObject_GetAttr(__pyx_cur_scope->__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_19), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_18), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_5, __pyx_cur_scope->__pyx_outer_scope->__pyx_v_side, sizeof(int), PyInt_FromLong); if (!__pyx_t_4) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -8388,12 +8843,12 @@ static PyObject *__pyx_gb_3_sa_9DataArray_11read_bitext_2generator6(__pyx_Genera
 /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":72
  *             self.read_text_data(fp)
  * 
- *     def read_bitext(self, char* filename, int side):             # <<<<<<<<<<<<<<
+ *     def read_bitext(self, bytes filename, int side):             # <<<<<<<<<<<<<<
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename, int __pyx_v_side) {
+static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename, int __pyx_v_side) {
   struct __pyx_obj_3_sa___pyx_scope_struct_1_read_bitext *__pyx_cur_scope;
   PyObject *__pyx_v_data = NULL;
   PyObject *__pyx_r = NULL;
@@ -8423,7 +8878,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":73
  * 
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             data = (line.split(' ||| ')[side] for line in fp)
  *             self.read_text_data(data)
@@ -8431,25 +8886,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
   /*with:*/ {
     __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-    __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
+    __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -8463,7 +8916,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
           /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":74
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)             # <<<<<<<<<<<<<<
  *             self.read_text_data(data)
@@ -8483,16 +8936,16 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
  */
           __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text_data); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_v_data);
-          PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_data);
+          PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_data);
           __Pyx_GIVEREF(__pyx_v_data);
-          __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_3);
+          __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -8500,30 +8953,30 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
 
         /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":73
  * 
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             data = (line.split(' ||| ')[side] for line in fp)
  *             self.read_text_data(data)
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.DataArray.read_bitext", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_2, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_3);
+          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_3, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_GOTREF(__pyx_t_1);
           __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
-          __Pyx_GIVEREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2);
           __Pyx_GIVEREF(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_t_1);
           PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
@@ -8536,18 +8989,18 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
           if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_11 = (!__pyx_t_9);
           if (__pyx_t_11) {
-            __Pyx_GIVEREF(__pyx_t_3);
             __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_GIVEREF(__pyx_t_3);
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_3, __pyx_t_2, __pyx_t_1);
-            __pyx_t_3 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; 
+            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_3, __pyx_t_1);
+            __pyx_t_2 = 0; __pyx_t_3 = 0; __pyx_t_1 = 0; 
             {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L18;
           }
           __pyx_L18:;
           __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
-          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           goto __pyx_L8_exception_handled;
         }
@@ -8567,7 +9020,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_18read_bitext(struct __pyx_obj_3_sa_Da
     }
     /*finally:*/ {
       if (__pyx_t_4) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_20, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_19, NULL);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
         if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
@@ -8889,7 +9342,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_20read_text_data(struct __pyx_obj_3_sa
  *         self.data.append(0)
  *         self.sent_index.append(word_count)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def read_binary(self, bytes filename):
  */
   __pyx_t_1 = PyInt_FromLong(__pyx_v_word_count); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
@@ -8919,50 +9372,50 @@ static PyObject *__pyx_pf_3_sa_9DataArray_20read_text_data(struct __pyx_obj_3_sa
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_23read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_23read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9DataArray_23read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_23read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.DataArray.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray_22read_binary(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9DataArray_22read_binary(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":94
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":93
+ *         self.sent_index.append(word_count)
  * 
- *     def read_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_22read_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9DataArray_22read_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":96
- *     def read_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":95
+ *     def read_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
  *         self.read_handle(f)
  *         fclose(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__r);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":97
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":96
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  *         self.read_handle(f)             # <<<<<<<<<<<<<<
@@ -8971,416 +9424,287 @@ static PyObject *__pyx_pf_3_sa_9DataArray_22read_binary(struct __pyx_obj_3_sa_Da
  */
   ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->__pyx_vtab)->read_handle(__pyx_v_self, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":98
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":97
  *         f = fopen(filename, "r")
  *         self.read_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- *     cdef void read_handle(self, FILE* f):
+ *     cdef void read_mmaped(self, MemoryMap buf):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.DataArray.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":100
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":99
  *         fclose(f)
  * 
+ *     cdef void read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         self.data.read_mmaped(buf)
+ *         self.sent_index.read_mmaped(buf)
+ */
+
+static void __pyx_f_3_sa_9DataArray_read_mmaped(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":100
+ * 
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         self.data.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.sent_index.read_mmaped(buf)
+ *         self.sent_id.read_mmaped(buf)
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->data->__pyx_vtab)->read_mmaped(__pyx_v_self->data, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":101
+ *     cdef void read_mmaped(self, MemoryMap buf):
+ *         self.data.read_mmaped(buf)
+ *         self.sent_index.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.sent_id.read_mmaped(buf)
+ *         self.voc.read_mmaped(buf)
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->read_mmaped(__pyx_v_self->sent_index, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":102
+ *         self.data.read_mmaped(buf)
+ *         self.sent_index.read_mmaped(buf)
+ *         self.sent_id.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.voc.read_mmaped(buf)
+ *         self.use_sent_id = (len(self.sent_id) > 0)
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_id->__pyx_vtab)->read_mmaped(__pyx_v_self->sent_id, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":103
+ *         self.sent_index.read_mmaped(buf)
+ *         self.sent_id.read_mmaped(buf)
+ *         self.voc.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.use_sent_id = (len(self.sent_id) > 0)
+ * 
+ */
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->voc->__pyx_vtab)->read_mmaped(__pyx_v_self->voc, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":104
+ *         self.sent_id.read_mmaped(buf)
+ *         self.voc.read_mmaped(buf)
+ *         self.use_sent_id = (len(self.sent_id) > 0)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef void read_handle(self, FILE* f):
+ */
+  __pyx_t_1 = ((PyObject *)__pyx_v_self->sent_id);
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_self->use_sent_id = (__pyx_t_2 > 0);
+
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_WriteUnraisable("_sa.DataArray.read_mmaped", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":106
+ *         self.use_sent_id = (len(self.sent_id) > 0)
+ * 
  *     cdef void read_handle(self, FILE* f):             # <<<<<<<<<<<<<<
- *         cdef int num_words, word_len
- *         cdef unsigned i
+ *         self.data.read_handle(f)
+ *         self.sent_index.read_handle(f)
  */
 
 static void __pyx_f_3_sa_9DataArray_read_handle(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, FILE *__pyx_v_f) {
-  int __pyx_v_num_words;
-  int __pyx_v_word_len;
-  CYTHON_UNUSED unsigned int __pyx_v_i;
-  char *__pyx_v_word;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  unsigned int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  Py_ssize_t __pyx_t_4;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_t_6;
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":105
- *         cdef char* word
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":107
  * 
+ *     cdef void read_handle(self, FILE* f):
  *         self.data.read_handle(f)             # <<<<<<<<<<<<<<
  *         self.sent_index.read_handle(f)
  *         self.sent_id.read_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->data->__pyx_vtab)->read_handle(__pyx_v_self->data, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":106
- * 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":108
+ *     cdef void read_handle(self, FILE* f):
  *         self.data.read_handle(f)
  *         self.sent_index.read_handle(f)             # <<<<<<<<<<<<<<
  *         self.sent_id.read_handle(f)
- *         fread(&(num_words), sizeof(int), 1, f)
+ *         self.voc.read_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->read_handle(__pyx_v_self->sent_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":107
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":109
  *         self.data.read_handle(f)
  *         self.sent_index.read_handle(f)
  *         self.sent_id.read_handle(f)             # <<<<<<<<<<<<<<
- *         fread(&(num_words), sizeof(int), 1, f)
- *         for i in range(num_words):
+ *         self.voc.read_handle(f)
+ *         self.use_sent_id = (len(self.sent_id) > 0)
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_id->__pyx_vtab)->read_handle(__pyx_v_self->sent_id, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":108
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":110
  *         self.sent_index.read_handle(f)
  *         self.sent_id.read_handle(f)
- *         fread(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *         for i in range(num_words):
- *             fread(&(word_len), sizeof(int), 1, f)
+ *         self.voc.read_handle(f)             # <<<<<<<<<<<<<<
+ *         self.use_sent_id = (len(self.sent_id) > 0)
+ * 
  */
-  fread((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->voc->__pyx_vtab)->read_handle(__pyx_v_self->voc, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":109
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":111
  *         self.sent_id.read_handle(f)
- *         fread(&(num_words), sizeof(int), 1, f)
- *         for i in range(num_words):             # <<<<<<<<<<<<<<
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))
- */
-  __pyx_t_1 = __pyx_v_num_words;
-  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
-    __pyx_v_i = __pyx_t_2;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":110
- *         fread(&(num_words), sizeof(int), 1, f)
- *         for i in range(num_words):
- *             fread(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)
- */
-    fread((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":111
- *         for i in range(num_words):
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))             # <<<<<<<<<<<<<<
- *             fread(word, sizeof(char), word_len, f)
- *             self.word2id[word] = len(self.id2word)
- */
-    __pyx_v_word = ((char *)malloc((__pyx_v_word_len * (sizeof(char)))));
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":112
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)
- */
-    fread(__pyx_v_word, (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":113
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)
- *             self.word2id[word] = len(self.id2word)             # <<<<<<<<<<<<<<
- *             self.id2word.append(word)
- *             free(word)
- */
-    __pyx_t_3 = __pyx_v_self->id2word;
-    __Pyx_INCREF(__pyx_t_3);
-    __pyx_t_4 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_4); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_5 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-    if (PyObject_SetItem(__pyx_v_self->word2id, ((PyObject *)__pyx_t_5), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":114
- *             fread(word, sizeof(char), word_len, f)
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)             # <<<<<<<<<<<<<<
- *             free(word)
- *         if len(self.sent_id) == 0:
- */
-    __pyx_t_3 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_5 = __Pyx_PyObject_Append(__pyx_v_self->id2word, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":115
- *             self.word2id[word] = len(self.id2word)
- *             self.id2word.append(word)
- *             free(word)             # <<<<<<<<<<<<<<
- *         if len(self.sent_id) == 0:
- *             self.use_sent_id = False
- */
-    free(__pyx_v_word);
-  }
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":116
- *             self.id2word.append(word)
- *             free(word)
- *         if len(self.sent_id) == 0:             # <<<<<<<<<<<<<<
- *             self.use_sent_id = False
- *         else:
- */
-  __pyx_t_5 = ((PyObject *)__pyx_v_self->sent_id);
-  __Pyx_INCREF(__pyx_t_5);
-  __pyx_t_4 = PyObject_Length(__pyx_t_5); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_6 = (__pyx_t_4 == 0);
-  if (__pyx_t_6) {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":117
- *             free(word)
- *         if len(self.sent_id) == 0:
- *             self.use_sent_id = False             # <<<<<<<<<<<<<<
- *         else:
- *             self.use_sent_id = True
- */
-    __pyx_v_self->use_sent_id = 0;
-    goto __pyx_L5;
-  }
-  /*else*/ {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":119
- *             self.use_sent_id = False
- *         else:
- *             self.use_sent_id = True             # <<<<<<<<<<<<<<
+ *         self.voc.read_handle(f)
+ *         self.use_sent_id = (len(self.sent_id) > 0)             # <<<<<<<<<<<<<<
  * 
  *     cdef void write_handle(self, FILE* f):
  */
-    __pyx_v_self->use_sent_id = 1;
-  }
-  __pyx_L5:;
+  __pyx_t_1 = ((PyObject *)__pyx_v_self->sent_id);
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_self->use_sent_id = (__pyx_t_2 > 0);
 
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_WriteUnraisable("_sa.DataArray.read_handle", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":121
- *             self.use_sent_id = True
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":113
+ *         self.use_sent_id = (len(self.sent_id) > 0)
  * 
  *     cdef void write_handle(self, FILE* f):             # <<<<<<<<<<<<<<
- *         cdef int word_len
- *         cdef int num_words
+ *         self.data.write_handle(f)
+ *         self.sent_index.write_handle(f)
  */
 
 static void __pyx_f_3_sa_9DataArray_write_handle(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, FILE *__pyx_v_f) {
-  int __pyx_v_word_len;
-  int __pyx_v_num_words;
-  PyObject *__pyx_v_word = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   Py_ssize_t __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *(*__pyx_t_4)(PyObject *);
-  Py_ssize_t __pyx_t_5;
-  char *__pyx_t_6;
+  struct __pyx_opt_args_3_sa_10Vocabulary_write_handle __pyx_t_3;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":125
- *         cdef int num_words
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":114
  * 
+ *     cdef void write_handle(self, FILE* f):
  *         self.data.write_handle(f)             # <<<<<<<<<<<<<<
  *         self.sent_index.write_handle(f)
  *         self.sent_id.write_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->data->__pyx_vtab)->write_handle(__pyx_v_self->data, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":126
- * 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":115
+ *     cdef void write_handle(self, FILE* f):
  *         self.data.write_handle(f)
  *         self.sent_index.write_handle(f)             # <<<<<<<<<<<<<<
  *         self.sent_id.write_handle(f)
- *         num_words = len(self.id2word) - 2
+ *         self.voc.write_handle(f, len(INIT_VOCABULARY))
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->write_handle(__pyx_v_self->sent_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":127
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":116
  *         self.data.write_handle(f)
  *         self.sent_index.write_handle(f)
  *         self.sent_id.write_handle(f)             # <<<<<<<<<<<<<<
- *         num_words = len(self.id2word) - 2
- *         fwrite(&(num_words), sizeof(int), 1, f)
+ *         self.voc.write_handle(f, len(INIT_VOCABULARY))
+ * 
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_id->__pyx_vtab)->write_handle(__pyx_v_self->sent_id, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":128
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":117
  *         self.sent_index.write_handle(f)
  *         self.sent_id.write_handle(f)
- *         num_words = len(self.id2word) - 2             # <<<<<<<<<<<<<<
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in self.id2word[2:]:
- */
-  __pyx_t_1 = __pyx_v_self->id2word;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_num_words = (__pyx_t_2 - 2);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":129
- *         self.sent_id.write_handle(f)
- *         num_words = len(self.id2word) - 2
- *         fwrite(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *         for word in self.id2word[2:]:
- *             word_len = len(word) + 1
- */
-  fwrite((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":130
- *         num_words = len(self.id2word) - 2
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in self.id2word[2:]:             # <<<<<<<<<<<<<<
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)
+ *         self.voc.write_handle(f, len(INIT_VOCABULARY))             # <<<<<<<<<<<<<<
+ * 
+ *     def write_binary(self, bytes filename):
  */
-  __pyx_t_1 = __Pyx_PySequence_GetSlice(__pyx_v_self->id2word, 2, PY_SSIZE_T_MAX); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__INIT_VOCABULARY); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyList_CheckExact(__pyx_t_1) || PyTuple_CheckExact(__pyx_t_1)) {
-    __pyx_t_3 = __pyx_t_1; __Pyx_INCREF(__pyx_t_3); __pyx_t_2 = 0;
-    __pyx_t_4 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = Py_TYPE(__pyx_t_3)->tp_iternext;
-  }
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  for (;;) {
-    if (!__pyx_t_4 && PyList_CheckExact(__pyx_t_3)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_3)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_1 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_4 && PyTuple_CheckExact(__pyx_t_3)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_1 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_1 = __pyx_t_4(__pyx_t_3);
-      if (unlikely(!__pyx_t_1)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_1);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_1;
-    __pyx_t_1 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":131
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in self.id2word[2:]:
- *             word_len = len(word) + 1             # <<<<<<<<<<<<<<
- *             fwrite(&(word_len), sizeof(int), 1, f)
- *             fwrite(<char *>word, sizeof(char), word_len, f)
- */
-    __pyx_t_5 = PyObject_Length(__pyx_v_word); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_v_word_len = (__pyx_t_5 + 1);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":132
- *         for word in self.id2word[2:]:
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *             fwrite(<char *>word, sizeof(char), word_len, f)
- * 
- */
-    fwrite((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":133
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)
- *             fwrite(<char *>word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
- * 
- *     def write_binary(self, char* filename):
- */
-    __pyx_t_6 = PyBytes_AsString(__pyx_v_word); if (unlikely((!__pyx_t_6) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    fwrite(((char *)__pyx_t_6), (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
-  }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_3.__pyx_n = 1;
+  __pyx_t_3.offset = __pyx_t_2;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->voc->__pyx_vtab)->write_handle(__pyx_v_self->voc, __pyx_v_f, &__pyx_t_3); 
 
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_WriteUnraisable("_sa.DataArray.write_handle", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_word);
   __Pyx_RefNannyFinishContext();
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_25write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_25write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9DataArray_25write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_25write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.DataArray.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray_24write_binary(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 119; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9DataArray_24write_binary(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":135
- *             fwrite(<char *>word, sizeof(char), word_len, f)
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":119
+ *         self.voc.write_handle(f, len(INIT_VOCABULARY))
  * 
- *     def write_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":137
- *     def write_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":121
+ *     def write_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
  *         self.write_handle(f)
  *         fclose(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 121; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__w);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":138
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":122
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  *         self.write_handle(f)             # <<<<<<<<<<<<<<
@@ -9389,7 +9713,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_D
  */
   ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->__pyx_vtab)->write_handle(__pyx_v_self, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":139
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":123
  *         f = fopen(filename, "w")
  *         self.write_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
@@ -9399,6 +9723,11 @@ static PyObject *__pyx_pf_3_sa_9DataArray_24write_binary(struct __pyx_obj_3_sa_D
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.DataArray.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
@@ -9415,7 +9744,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_27write_enhanced_handle(PyObject *__py
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":141
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":125
  *         fclose(f)
  * 
  *     def write_enhanced_handle(self, f):             # <<<<<<<<<<<<<<
@@ -9425,6 +9754,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_27write_enhanced_handle(PyObject *__py
 
 static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_f) {
   PyObject *__pyx_v_i = NULL;
+  PyObject *__pyx_v_w = NULL;
   PyObject *__pyx_v_word = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -9434,12 +9764,13 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_enhanced_handle", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":142
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":126
  * 
  *     def write_enhanced_handle(self, f):
  *         for i in self.data:             # <<<<<<<<<<<<<<
@@ -9450,7 +9781,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_t_1 = ((PyObject *)__pyx_v_self->data); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->data)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->data)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -9458,23 +9789,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 126; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -9484,23 +9815,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_v_i = __pyx_t_4;
     __pyx_t_4 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":143
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":127
  *     def write_enhanced_handle(self, f):
  *         for i in self.data:
  *             f.write("%d " %i)             # <<<<<<<<<<<<<<
  *         f.write("\n")
  *         for i in self.sent_index:
  */
-    __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_i); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_5));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_5));
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 127; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -9508,21 +9839,21 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":144
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":128
  *         for i in self.data:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
  *         for i in self.sent_index:
  *             f.write("%d " %i)
  */
-  __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_5 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_22), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_21), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":145
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":129
  *             f.write("%d " %i)
  *         f.write("\n")
  *         for i in self.sent_index:             # <<<<<<<<<<<<<<
@@ -9533,7 +9864,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_t_5 = ((PyObject *)__pyx_v_self->sent_index); __Pyx_INCREF(__pyx_t_5); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_5 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_index)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_5 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_index)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __pyx_t_3 = Py_TYPE(__pyx_t_5)->tp_iternext;
   }
@@ -9541,23 +9872,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_5)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_5)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_1 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyList_GET_ITEM(__pyx_t_5, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_5)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_5)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_5, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_1 = __pyx_t_3(__pyx_t_5);
       if (unlikely(!__pyx_t_1)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 145; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -9567,23 +9898,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_v_i = __pyx_t_1;
     __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":146
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":130
  *         f.write("\n")
  *         for i in self.sent_index:
  *             f.write("%d " %i)             # <<<<<<<<<<<<<<
  *         f.write("\n")
  *         for i in self.sent_id:
  */
-    __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_6 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_i); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_i); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_6));
-    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_6));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_6));
     __pyx_t_6 = 0;
-    __pyx_t_6 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 146; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 130; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
@@ -9591,21 +9922,21 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
   }
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":147
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":131
  *         for i in self.sent_index:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
  *         for i in self.sent_id:
  *             f.write("%d " %i)
  */
-  __pyx_t_5 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_k_tuple_23), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_k_tuple_22), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":148
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":132
  *             f.write("%d " %i)
  *         f.write("\n")
  *         for i in self.sent_id:             # <<<<<<<<<<<<<<
@@ -9616,7 +9947,7 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_t_6 = ((PyObject *)__pyx_v_self->sent_id); __Pyx_INCREF(__pyx_t_6); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_6 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_id)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_6 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_id)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_3 = Py_TYPE(__pyx_t_6)->tp_iternext;
   }
@@ -9624,23 +9955,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_6)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_6)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_6)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_6)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_5 = __pyx_t_3(__pyx_t_6);
       if (unlikely(!__pyx_t_5)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 148; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -9650,23 +9981,23 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
     __pyx_v_i = __pyx_t_5;
     __pyx_t_5 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":149
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":133
  *         f.write("\n")
  *         for i in self.sent_id:
  *             f.write("%d " %i)             # <<<<<<<<<<<<<<
  *         f.write("\n")
- *         for word in self.id2word:
+ *         for w, word in enumerate(self.voc.id2word):
  */
-    __pyx_t_5 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_t_4));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 133; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
@@ -9674,113 +10005,122 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
   }
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":150
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":134
  *         for i in self.sent_id:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
- *         for word in self.id2word:
- *             f.write("%s %d " % (word, self.word2id[word]))
+ *         for w, word in enumerate(self.voc.id2word):
+ *             f.write("%s %d " % (word, w))
  */
-  __pyx_t_6 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_4 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_k_tuple_24), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_k_tuple_23), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":151
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":135
  *             f.write("%d " %i)
  *         f.write("\n")
- *         for word in self.id2word:             # <<<<<<<<<<<<<<
- *             f.write("%s %d " % (word, self.word2id[word]))
+ *         for w, word in enumerate(self.voc.id2word):             # <<<<<<<<<<<<<<
+ *             f.write("%s %d " % (word, w))
  *         f.write("\n")
  */
-  if (PyList_CheckExact(__pyx_v_self->id2word) || PyTuple_CheckExact(__pyx_v_self->id2word)) {
-    __pyx_t_4 = __pyx_v_self->id2word; __Pyx_INCREF(__pyx_t_4); __pyx_t_2 = 0;
+  __Pyx_INCREF(__pyx_int_0);
+  __pyx_t_4 = __pyx_int_0;
+  if (PyList_CheckExact(__pyx_v_self->voc->id2word) || PyTuple_CheckExact(__pyx_v_self->voc->id2word)) {
+    __pyx_t_6 = __pyx_v_self->voc->id2word; __Pyx_INCREF(__pyx_t_6); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_self->id2word); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = Py_TYPE(__pyx_t_4)->tp_iternext;
+    __pyx_t_2 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_v_self->voc->id2word); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_3 = Py_TYPE(__pyx_t_6)->tp_iternext;
   }
   for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_4)) break;
+    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_6)) {
+      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_6)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_6 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_6); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
+    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_6)) {
+      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_6)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_6); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_2); __Pyx_INCREF(__pyx_t_1); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PySequence_ITEM(__pyx_t_6, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
-      __pyx_t_6 = __pyx_t_3(__pyx_t_4);
-      if (unlikely(!__pyx_t_6)) {
+      __pyx_t_1 = __pyx_t_3(__pyx_t_6);
+      if (unlikely(!__pyx_t_1)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 151; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
-      __Pyx_GOTREF(__pyx_t_6);
+      __Pyx_GOTREF(__pyx_t_1);
     }
     __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_6;
-    __pyx_t_6 = 0;
+    __pyx_v_word = __pyx_t_1;
+    __pyx_t_1 = 0;
+    __Pyx_INCREF(__pyx_t_4);
+    __Pyx_XDECREF(__pyx_v_w);
+    __pyx_v_w = __pyx_t_4;
+    __pyx_t_1 = PyNumber_Add(__pyx_t_4, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 135; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_4);
+    __pyx_t_4 = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":152
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":136
  *         f.write("\n")
- *         for word in self.id2word:
- *             f.write("%s %d " % (word, self.word2id[word]))             # <<<<<<<<<<<<<<
+ *         for w, word in enumerate(self.voc.id2word):
+ *             f.write("%s %d " % (word, w))             # <<<<<<<<<<<<<<
  *         f.write("\n")
  * 
  */
-    __pyx_t_6 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_1 = PyObject_GetItem(__pyx_v_self->word2id, __pyx_v_word); if (!__pyx_t_1) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_INCREF(__pyx_v_word);
     PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_word);
     __Pyx_GIVEREF(__pyx_v_word);
-    PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1);
-    __Pyx_GIVEREF(__pyx_t_1);
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_25), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+    __Pyx_INCREF(__pyx_v_w);
+    PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_v_w);
+    __Pyx_GIVEREF(__pyx_v_w);
+    __pyx_t_7 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_24), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_7));
     __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_7));
+    __Pyx_GIVEREF(((PyObject *)__pyx_t_7));
+    __pyx_t_7 = 0;
+    __pyx_t_7 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":153
- *         for word in self.id2word:
- *             f.write("%s %d " % (word, self.word2id[word]))
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":137
+ *         for w, word in enumerate(self.voc.id2word):
+ *             f.write("%s %d " % (word, w))
  *         f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  */
-  __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_26), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_6 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_25), NULL); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
@@ -9789,10 +10129,12 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("_sa.DataArray.write_enhanced_handle", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_v_i);
+  __Pyx_XDECREF(__pyx_v_w);
   __Pyx_XDECREF(__pyx_v_word);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
@@ -9800,35 +10142,30 @@ static PyObject *__pyx_pf_3_sa_9DataArray_26write_enhanced_handle(struct __pyx_o
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_29write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_29write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9DataArray_29write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_29write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_enhanced (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 155; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.DataArray.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9DataArray_28write_enhanced(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 139; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9DataArray_28write_enhanced(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":155
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":139
  *         f.write("\n")
  * 
- *     def write_enhanced(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_enhanced(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             self.write_enhanced_handle(self, f)
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
@@ -9848,34 +10185,32 @@ static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_enhanced", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":156
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":140
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.write_enhanced_handle(self, f)
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -9887,26 +10222,26 @@ static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":157
- *     def write_enhanced(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":141
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:
  *             self.write_enhanced_handle(self, f)             # <<<<<<<<<<<<<<
  */
-          __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s_27); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s_26); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_INCREF(((PyObject *)__pyx_v_self));
-          PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self));
+          PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_self));
           __Pyx_GIVEREF(((PyObject *)__pyx_v_self));
           __Pyx_INCREF(__pyx_v_f);
-          PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_f);
+          PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_f);
           __Pyx_GIVEREF(__pyx_v_f);
-          __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 157; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -9914,53 +10249,53 @@ static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
         __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":156
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":140
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.write_enhanced_handle(self, f)
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.DataArray.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_1, &__pyx_t_4) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_2, &__pyx_t_4) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_1);
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1);
+          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_4);
           PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_t_4);
           __Pyx_GIVEREF(__pyx_t_4);
           __pyx_t_10 = PyObject_Call(__pyx_t_3, __pyx_t_8, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_10);
           __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_10);
           __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-          if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_9 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_11 = (!__pyx_t_9);
           if (__pyx_t_11) {
-            __Pyx_GIVEREF(__pyx_t_2);
             __Pyx_GIVEREF(__pyx_t_1);
+            __Pyx_GIVEREF(__pyx_t_2);
             __Pyx_GIVEREF(__pyx_t_4);
-            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_1, __pyx_t_4);
-            __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_4 = 0; 
-            {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_2, __pyx_t_4);
+            __pyx_t_1 = 0; __pyx_t_2 = 0; __pyx_t_4 = 0; 
+            {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L18;
           }
           __pyx_L18:;
           __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           goto __pyx_L8_exception_handled;
         }
@@ -9980,13 +10315,13 @@ static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_28, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_27, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L19;
@@ -10013,31 +10348,31 @@ static PyObject *__pyx_pf_3_sa_9DataArray_28write_enhanced(struct __pyx_obj_3_sa
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_7word2id_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_7word2id_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_3_sa_9DataArray_3voc_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_3_sa_9DataArray_3voc_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7word2id___get__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
+  __pyx_r = __pyx_pf_3_sa_9DataArray_3voc___get__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":10
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":13
  * 
  * cdef class DataArray:
- *     cdef public word2id             # <<<<<<<<<<<<<<
- *     cdef public id2word
+ *     cdef public Vocabulary voc             # <<<<<<<<<<<<<<
  *     cdef public IntList data
+ *     cdef public IntList sent_id
  */
 
-static PyObject *__pyx_pf_3_sa_9DataArray_7word2id___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
+static PyObject *__pyx_pf_3_sa_9DataArray_3voc___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__", 0);
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->word2id);
-  __pyx_r = __pyx_v_self->word2id;
+  __Pyx_INCREF(((PyObject *)__pyx_v_self->voc));
+  __pyx_r = ((PyObject *)__pyx_v_self->voc);
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
@@ -10048,138 +10383,60 @@ static PyObject *__pyx_pf_3_sa_9DataArray_7word2id___get__(struct __pyx_obj_3_sa
 }
 
 /* Python wrapper */
-static int __pyx_pw_3_sa_9DataArray_7word2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_3_sa_9DataArray_7word2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pw_3_sa_9DataArray_3voc_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_3_sa_9DataArray_3voc_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7word2id_2__set__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __pyx_r = __pyx_pf_3_sa_9DataArray_3voc_2__set__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject *)__pyx_v_value));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_9DataArray_7word2id_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pf_3_sa_9DataArray_3voc_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__set__", 0);
+  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_Vocabulary))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->word2id);
-  __Pyx_DECREF(__pyx_v_self->word2id);
-  __pyx_v_self->word2id = __pyx_v_value;
-
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_3_sa_9DataArray_7word2id_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_3_sa_9DataArray_7word2id_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7word2id_4__del__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_3_sa_9DataArray_7word2id_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->word2id);
-  __Pyx_DECREF(__pyx_v_self->word2id);
-  __pyx_v_self->word2id = Py_None;
+  __Pyx_GOTREF(__pyx_v_self->voc);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->voc));
+  __pyx_v_self->voc = ((struct __pyx_obj_3_sa_Vocabulary *)__pyx_v_value);
 
   __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9DataArray_7id2word_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_3_sa_9DataArray_7id2word_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7id2word___get__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":11
- * cdef class DataArray:
- *     cdef public word2id
- *     cdef public id2word             # <<<<<<<<<<<<<<
- *     cdef public IntList data
- *     cdef public IntList sent_id
- */
-
-static PyObject *__pyx_pf_3_sa_9DataArray_7id2word___get__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->id2word);
-  __pyx_r = __pyx_v_self->id2word;
   goto __pyx_L0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.DataArray.voc.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_3_sa_9DataArray_7id2word_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_3_sa_9DataArray_7id2word_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7id2word_2__set__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self), ((PyObject *)__pyx_v_value));
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_3_sa_9DataArray_7id2word_2__set__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->id2word);
-  __Pyx_DECREF(__pyx_v_self->id2word);
-  __pyx_v_self->id2word = __pyx_v_value;
-
-  __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static int __pyx_pw_3_sa_9DataArray_7id2word_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_3_sa_9DataArray_7id2word_5__del__(PyObject *__pyx_v_self) {
+static int __pyx_pw_3_sa_9DataArray_3voc_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_3_sa_9DataArray_3voc_5__del__(PyObject *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9DataArray_7id2word_4__del__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
+  __pyx_r = __pyx_pf_3_sa_9DataArray_3voc_4__del__(((struct __pyx_obj_3_sa_DataArray *)__pyx_v_self));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_9DataArray_7id2word_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
+static int __pyx_pf_3_sa_9DataArray_3voc_4__del__(struct __pyx_obj_3_sa_DataArray *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__", 0);
   __Pyx_INCREF(Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->id2word);
-  __Pyx_DECREF(__pyx_v_self->id2word);
-  __pyx_v_self->id2word = Py_None;
+  __Pyx_GOTREF(__pyx_v_self->voc);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->voc));
+  __pyx_v_self->voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None);
 
   __pyx_r = 0;
   __Pyx_RefNannyFinishContext();
@@ -10197,9 +10454,9 @@ static PyObject *__pyx_pw_3_sa_9DataArray_4data_1__get__(PyObject *__pyx_v_self)
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":12
- *     cdef public word2id
- *     cdef public id2word
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":14
+ * cdef class DataArray:
+ *     cdef public Vocabulary voc
  *     cdef public IntList data             # <<<<<<<<<<<<<<
  *     cdef public IntList sent_id
  *     cdef public IntList sent_index
@@ -10239,7 +10496,7 @@ static int __pyx_pf_3_sa_9DataArray_4data_2__set__(struct __pyx_obj_3_sa_DataArr
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__set__", 0);
-  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
   __Pyx_GOTREF(__pyx_v_self->data);
@@ -10293,8 +10550,8 @@ static PyObject *__pyx_pw_3_sa_9DataArray_7sent_id_1__get__(PyObject *__pyx_v_se
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":13
- *     cdef public id2word
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":15
+ *     cdef public Vocabulary voc
  *     cdef public IntList data
  *     cdef public IntList sent_id             # <<<<<<<<<<<<<<
  *     cdef public IntList sent_index
@@ -10335,7 +10592,7 @@ static int __pyx_pf_3_sa_9DataArray_7sent_id_2__set__(struct __pyx_obj_3_sa_Data
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__set__", 0);
-  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
   __Pyx_GOTREF(__pyx_v_self->sent_id);
@@ -10389,7 +10646,7 @@ static PyObject *__pyx_pw_3_sa_9DataArray_10sent_index_1__get__(PyObject *__pyx_
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":14
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":16
  *     cdef public IntList data
  *     cdef public IntList sent_id
  *     cdef public IntList sent_index             # <<<<<<<<<<<<<<
@@ -10431,7 +10688,7 @@ static int __pyx_pf_3_sa_9DataArray_10sent_index_2__set__(struct __pyx_obj_3_sa_
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__set__", 0);
-  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (!(likely(((__pyx_v_value) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_value, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
   __Pyx_GOTREF(__pyx_v_self->sent_index);
@@ -10799,7 +11056,7 @@ static int *__pyx_f_3_sa_9Alignment__get_sent_links(struct __pyx_obj_3_sa_Alignm
  *             self._unlink(self.links.arr[start + i], sent_links + (2*i), sent_links + (2*i) + 1)
  *         return sent_links             # <<<<<<<<<<<<<<
  * 
- *     def __cinit__(self, from_binary=None, from_text=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
  */
   __pyx_r = __pyx_v_sent_links;
   goto __pyx_L0;
@@ -10820,26 +11077,29 @@ static int __pyx_pw_3_sa_9Alignment_5__cinit__(PyObject *__pyx_v_self, PyObject
 static int __pyx_pw_3_sa_9Alignment_5__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_from_binary = 0;
   PyObject *__pyx_v_from_text = 0;
+  PyObject *__pyx_v_mmaped = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,0};
-    PyObject* values[2] = {0,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,&__pyx_n_s__mmaped,0};
+    PyObject* values[3] = {0,0,0};
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":45
  *         return sent_links
  * 
- *     def __cinit__(self, from_binary=None, from_text=None):             # <<<<<<<<<<<<<<
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):             # <<<<<<<<<<<<<<
  *         self.links = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)
  */
     values[0] = ((PyObject *)Py_None);
     values[1] = ((PyObject *)Py_None);
+    values[2] = __pyx_k_28;
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
@@ -10857,12 +11117,18 @@ static int __pyx_pw_3_sa_9Alignment_5__cinit__(PyObject *__pyx_v_self, PyObject
           PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__from_text);
           if (value) { values[1] = value; kw_args--; }
         }
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__mmaped);
+          if (value) { values[2] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
         if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         case  0: break;
@@ -10871,21 +11137,22 @@ static int __pyx_pw_3_sa_9Alignment_5__cinit__(PyObject *__pyx_v_self, PyObject
     }
     __pyx_v_from_binary = values[0];
     __pyx_v_from_text = values[1];
+    __pyx_v_mmaped = values[2];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[4]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.Alignment.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_4__cinit__(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text);
+  __pyx_r = __pyx_pf_3_sa_9Alignment_4__cinit__(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text, __pyx_v_mmaped);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text) {
+static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_mmaped) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -10899,7 +11166,7 @@ static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":46
  * 
- *     def __cinit__(self, from_binary=None, from_text=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
  *         self.links = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_index = IntList(1000,1000)
  *         if from_binary:
@@ -10913,11 +11180,11 @@ static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *
   __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":47
- *     def __cinit__(self, from_binary=None, from_text=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
  *         self.links = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
   __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_k_tuple_30), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
@@ -10931,8 +11198,8 @@ static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *
  *         self.links = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)
  *         if from_binary:             # <<<<<<<<<<<<<<
- *             self.read_binary(from_binary)
- *         elif from_text:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))
  */
   __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
@@ -10940,54 +11207,97 @@ static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":49
  *         self.sent_index = IntList(1000,1000)
  *         if from_binary:
- *             self.read_binary(from_binary)             # <<<<<<<<<<<<<<
+ *             if mmaped:             # <<<<<<<<<<<<<<
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ */
+    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_mmaped); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_2) {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":50
+ *         if from_binary:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.read_binary(from_binary)
+ */
+      __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_mmaped); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_4 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_MemoryMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);
+      __Pyx_GIVEREF(__pyx_t_4);
+      __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":52
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ *                 self.read_binary(from_binary)             # <<<<<<<<<<<<<<
  *         elif from_text:
  *             self.read_text(from_text)
  */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_from_binary);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
-    __Pyx_GIVEREF(__pyx_v_from_binary);
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 49; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
+    __pyx_L4:;
     goto __pyx_L3;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":50
- *         if from_binary:
- *             self.read_binary(from_binary)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":53
+ *             else:
+ *                 self.read_binary(from_binary)
  *         elif from_text:             # <<<<<<<<<<<<<<
  *             self.read_text(from_text)
  * 
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":51
- *             self.read_binary(from_binary)
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":54
+ *                 self.read_binary(from_binary)
  *         elif from_text:
  *             self.read_text(from_text)             # <<<<<<<<<<<<<<
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_INCREF(__pyx_v_from_text);
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_text);
     __Pyx_GIVEREF(__pyx_v_from_text);
-    __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 51; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     goto __pyx_L3;
   }
   __pyx_L3:;
@@ -11006,35 +11316,30 @@ static int __pyx_pf_3_sa_9Alignment_4__cinit__(struct __pyx_obj_3_sa_Alignment *
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_7read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9Alignment_7read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9Alignment_7read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_7read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Alignment.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_6read_text(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_6read_text(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":53
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":56
  *             self.read_text(from_text)
  * 
- *     def read_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with gzip_or_text(filename) as f:
  *             for line in f:
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_v_line = NULL;
   PyObject *__pyx_v_pairs = NULL;
@@ -11068,35 +11373,33 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":54
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":57
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
  *             for line in f:
  *                 self.sent_index.append(len(self.links))
  */
   /*with:*/ {
-    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-    __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
+    __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -11108,8 +11411,8 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
           __pyx_v_f = __pyx_t_1;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":55
- *     def read_text(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":58
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as f:
  *             for line in f:             # <<<<<<<<<<<<<<
  *                 self.sent_index.append(len(self.links))
@@ -11119,7 +11422,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
             __pyx_t_1 = __pyx_v_f; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
             __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
@@ -11127,67 +11430,67 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_2 = __pyx_t_9(__pyx_t_1);
-              if (unlikely(!__pyx_t_2)) {
+              __pyx_t_3 = __pyx_t_9(__pyx_t_1);
+              if (unlikely(!__pyx_t_3)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_2);
+              __Pyx_GOTREF(__pyx_t_3);
             }
             __Pyx_XDECREF(__pyx_v_line);
-            __pyx_v_line = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_line = __pyx_t_3;
+            __pyx_t_3 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":56
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":59
  *         with gzip_or_text(filename) as f:
  *             for line in f:
  *                 self.sent_index.append(len(self.links))             # <<<<<<<<<<<<<<
  *                 pairs = line.split()
  *                 for pair in pairs:
  */
-            __pyx_t_2 = ((PyObject *)__pyx_v_self->links);
-            __Pyx_INCREF(__pyx_t_2);
-            __pyx_t_10 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-            __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_10); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_3 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->sent_index), __pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_3 = ((PyObject *)__pyx_v_self->links);
+            __Pyx_INCREF(__pyx_t_3);
+            __pyx_t_10 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_10 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_10); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_3);
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __pyx_t_2 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->sent_index), __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":57
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":60
  *             for line in f:
  *                 self.sent_index.append(len(self.links))
  *                 pairs = line.split()             # <<<<<<<<<<<<<<
  *                 for pair in pairs:
  *                     (i, j) = map(int, pair.split('-'))
  */
-            __pyx_t_3 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
-            __pyx_t_2 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_2);
-            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __pyx_t_3 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             __Pyx_XDECREF(__pyx_v_pairs);
-            __pyx_v_pairs = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_pairs = __pyx_t_3;
+            __pyx_t_3 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":58
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":61
  *                 self.sent_index.append(len(self.links))
  *                 pairs = line.split()
  *                 for pair in pairs:             # <<<<<<<<<<<<<<
@@ -11195,66 +11498,66 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
  *                     self.links.append(self.link(i, j))
  */
             if (PyList_CheckExact(__pyx_v_pairs) || PyTuple_CheckExact(__pyx_v_pairs)) {
-              __pyx_t_2 = __pyx_v_pairs; __Pyx_INCREF(__pyx_t_2); __pyx_t_10 = 0;
+              __pyx_t_3 = __pyx_v_pairs; __Pyx_INCREF(__pyx_t_3); __pyx_t_10 = 0;
               __pyx_t_11 = NULL;
             } else {
-              __pyx_t_10 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_pairs); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_2);
-              __pyx_t_11 = Py_TYPE(__pyx_t_2)->tp_iternext;
+              __pyx_t_10 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_pairs); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_3);
+              __pyx_t_11 = Py_TYPE(__pyx_t_3)->tp_iternext;
             }
             for (;;) {
-              if (!__pyx_t_11 && PyList_CheckExact(__pyx_t_2)) {
-                if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_2)) break;
+              if (!__pyx_t_11 && PyList_CheckExact(__pyx_t_3)) {
+                if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_3)) break;
                 #if CYTHON_COMPILING_IN_CPYTHON
-                __pyx_t_3 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_10); __Pyx_INCREF(__pyx_t_3); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_2 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_10); __Pyx_INCREF(__pyx_t_2); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 #else
-                __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_2 = PySequence_ITEM(__pyx_t_3, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 #endif
-              } else if (!__pyx_t_11 && PyTuple_CheckExact(__pyx_t_2)) {
-                if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+              } else if (!__pyx_t_11 && PyTuple_CheckExact(__pyx_t_3)) {
+                if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
                 #if CYTHON_COMPILING_IN_CPYTHON
-                __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_10); __Pyx_INCREF(__pyx_t_3); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_10); __Pyx_INCREF(__pyx_t_2); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 #else
-                __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_2 = PySequence_ITEM(__pyx_t_3, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 #endif
               } else {
-                __pyx_t_3 = __pyx_t_11(__pyx_t_2);
-                if (unlikely(!__pyx_t_3)) {
+                __pyx_t_2 = __pyx_t_11(__pyx_t_3);
+                if (unlikely(!__pyx_t_2)) {
                   if (PyErr_Occurred()) {
                     if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                    else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                    else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                   }
                   break;
                 }
-                __Pyx_GOTREF(__pyx_t_3);
+                __Pyx_GOTREF(__pyx_t_2);
               }
               __Pyx_XDECREF(__pyx_v_pair);
-              __pyx_v_pair = __pyx_t_3;
-              __pyx_t_3 = 0;
+              __pyx_v_pair = __pyx_t_2;
+              __pyx_t_2 = 0;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":59
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":62
  *                 pairs = line.split()
  *                 for pair in pairs:
  *                     (i, j) = map(int, pair.split('-'))             # <<<<<<<<<<<<<<
  *                     self.links.append(self.link(i, j))
  *             self.sent_index.append(len(self.links))
  */
-              __pyx_t_3 = PyObject_GetAttr(__pyx_v_pair, __pyx_n_s__split); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_3);
-              __pyx_t_12 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_k_tuple_32), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyObject_GetAttr(__pyx_v_pair, __pyx_n_s__split); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_2);
+              __pyx_t_12 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_32), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-              __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_3);
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+              __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_2);
               __Pyx_INCREF(((PyObject *)((PyObject*)(&PyInt_Type))));
-              PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)((PyObject*)(&PyInt_Type))));
+              PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)((PyObject*)(&PyInt_Type))));
               __Pyx_GIVEREF(((PyObject *)((PyObject*)(&PyInt_Type))));
-              PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_12);
+              PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_12);
               __Pyx_GIVEREF(__pyx_t_12);
               __pyx_t_12 = 0;
-              __pyx_t_12 = PyObject_Call(__pyx_builtin_map, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyObject_Call(__pyx_builtin_map, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
-              __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+              __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
               if ((likely(PyTuple_CheckExact(__pyx_t_12))) || (PyList_CheckExact(__pyx_t_12))) {
                 PyObject* sequence = __pyx_t_12;
                 #if CYTHON_COMPILING_IN_CPYTHON
@@ -11265,35 +11568,35 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
                 if (unlikely(size != 2)) {
                   if (size > 2) __Pyx_RaiseTooManyValuesError(2);
                   else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-                  {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 #if CYTHON_COMPILING_IN_CPYTHON
                 if (likely(PyTuple_CheckExact(sequence))) {
-                  __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+                  __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
                   __pyx_t_13 = PyTuple_GET_ITEM(sequence, 1); 
                 } else {
-                  __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+                  __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
                   __pyx_t_13 = PyList_GET_ITEM(sequence, 1); 
                 }
-                __Pyx_INCREF(__pyx_t_3);
+                __Pyx_INCREF(__pyx_t_2);
                 __Pyx_INCREF(__pyx_t_13);
                 #else
-                __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-                __pyx_t_13 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_13 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 #endif
                 __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               } else
               {
                 Py_ssize_t index = -1;
-                __pyx_t_14 = PyObject_GetIter(__pyx_t_12); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                __pyx_t_14 = PyObject_GetIter(__pyx_t_12); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 __Pyx_GOTREF(__pyx_t_14);
                 __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
                 __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
-                index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_14); if (unlikely(!__pyx_t_3)) goto __pyx_L20_unpacking_failed;
-                __Pyx_GOTREF(__pyx_t_3);
+                index = 0; __pyx_t_2 = __pyx_t_15(__pyx_t_14); if (unlikely(!__pyx_t_2)) goto __pyx_L20_unpacking_failed;
+                __Pyx_GOTREF(__pyx_t_2);
                 index = 1; __pyx_t_13 = __pyx_t_15(__pyx_t_14); if (unlikely(!__pyx_t_13)) goto __pyx_L20_unpacking_failed;
                 __Pyx_GOTREF(__pyx_t_13);
-                if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 2) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 2) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 __pyx_t_15 = NULL;
                 __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
                 goto __pyx_L21_unpacking_done;
@@ -11301,53 +11604,53 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
                 __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
                 __pyx_t_15 = NULL;
                 if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-                {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 __pyx_L21_unpacking_done:;
               }
               __Pyx_XDECREF(__pyx_v_i);
-              __pyx_v_i = __pyx_t_3;
-              __pyx_t_3 = 0;
+              __pyx_v_i = __pyx_t_2;
+              __pyx_t_2 = 0;
               __Pyx_XDECREF(__pyx_v_j);
               __pyx_v_j = __pyx_t_13;
               __pyx_t_13 = 0;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":60
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":63
  *                 for pair in pairs:
  *                     (i, j) = map(int, pair.split('-'))
  *                     self.links.append(self.link(i, j))             # <<<<<<<<<<<<<<
  *             self.sent_index.append(len(self.links))
  * 
  */
-              __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __pyx_t_17 = __Pyx_PyInt_AsInt(__pyx_v_j); if (unlikely((__pyx_t_17 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __pyx_t_12 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_Alignment *)__pyx_v_self->__pyx_vtab)->link(__pyx_v_self, __pyx_t_16, __pyx_t_17)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_17 = __Pyx_PyInt_AsInt(__pyx_v_j); if (unlikely((__pyx_t_17 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_Alignment *)__pyx_v_self->__pyx_vtab)->link(__pyx_v_self, __pyx_t_16, __pyx_t_17)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
-              __pyx_t_13 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->links), __pyx_t_12); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_13 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->links), __pyx_t_12); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_13);
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
             }
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           }
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":61
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":64
  *                     (i, j) = map(int, pair.split('-'))
  *                     self.links.append(self.link(i, j))
  *             self.sent_index.append(len(self.links))             # <<<<<<<<<<<<<<
  * 
- *     def read_binary(self, char* filename):
+ *     def read_binary(self, bytes filename):
  */
           __pyx_t_1 = ((PyObject *)__pyx_v_self->links);
           __Pyx_INCREF(__pyx_t_1);
-          __pyx_t_8 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_8 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_2 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->sent_index), __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_3 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->sent_index), __pyx_t_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -11355,30 +11658,30 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
         __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":54
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":57
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
  *             for line in f:
  *                 self.sent_index.append(len(self.links))
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.Alignment.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_1, &__pyx_t_13) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          if (__Pyx_GetException(&__pyx_t_3, &__pyx_t_1, &__pyx_t_13) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_3);
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_GOTREF(__pyx_t_13);
-          __pyx_t_12 = PyTuple_New(3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __pyx_t_12 = PyTuple_New(3); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_12);
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_3);
+          __Pyx_GIVEREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_t_1);
           PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
@@ -11387,24 +11690,24 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
           __Pyx_GIVEREF(__pyx_t_13);
           __pyx_t_19 = PyObject_Call(__pyx_t_4, __pyx_t_12, NULL);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_19)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_19);
           __pyx_t_18 = __Pyx_PyObject_IsTrue(__pyx_t_19);
           __Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
-          if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_18 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_20 = (!__pyx_t_18);
           if (__pyx_t_20) {
-            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_GIVEREF(__pyx_t_3);
             __Pyx_GIVEREF(__pyx_t_1);
             __Pyx_GIVEREF(__pyx_t_13);
-            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_1, __pyx_t_13);
-            __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_13 = 0; 
-            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_ErrRestore(__pyx_t_3, __pyx_t_1, __pyx_t_13);
+            __pyx_t_3 = 0; __pyx_t_1 = 0; __pyx_t_13 = 0; 
+            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L24;
           }
           __pyx_L24:;
           __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
           goto __pyx_L8_exception_handled;
@@ -11427,11 +11730,11 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
       if (__pyx_t_4) {
         __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_33, NULL);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_20 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_20 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L25;
@@ -11465,50 +11768,50 @@ static PyObject *__pyx_pf_3_sa_9Alignment_6read_text(struct __pyx_obj_3_sa_Align
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_9read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9Alignment_9read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9Alignment_9read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_9read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Alignment.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_8read_binary(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_8read_binary(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":63
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":66
  *             self.sent_index.append(len(self.links))
  * 
- *     def read_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":65
- *     def read_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":68
+ *     def read_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
  *         self.links.read_handle(f)
  *         self.sent_index.read_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__r);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":66
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":69
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  *         self.links.read_handle(f)             # <<<<<<<<<<<<<<
@@ -11517,7 +11820,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Ali
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->links->__pyx_vtab)->read_handle(__pyx_v_self->links, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":67
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":70
  *         f = fopen(filename, "r")
  *         self.links.read_handle(f)
  *         self.sent_index.read_handle(f)             # <<<<<<<<<<<<<<
@@ -11526,51 +11829,104 @@ static PyObject *__pyx_pf_3_sa_9Alignment_8read_binary(struct __pyx_obj_3_sa_Ali
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->read_handle(__pyx_v_self->sent_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":68
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":71
  *         self.links.read_handle(f)
  *         self.sent_index.read_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- *     def write_text(self, char* filename):
+ *     def read_mmaped(self, MemoryMap buf):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.Alignment.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_11write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9Alignment_11write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9Alignment_11read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_11read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Alignment.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_10write_text(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((char *)__pyx_v_filename));
+  __Pyx_RefNannySetupContext("read_mmaped (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_buf), __pyx_ptype_3_sa_MemoryMap, 1, "buf", 0))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_10read_mmaped(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_buf));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":70
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":73
  *         fclose(f)
  * 
- *     def write_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         self.links.read_mmaped(buf)
+ *         self.sent_index.read_mmaped(buf)
+ */
+
+static PyObject *__pyx_pf_3_sa_9Alignment_10read_mmaped(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":74
+ * 
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.links.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.sent_index.read_mmaped(buf)
+ * 
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->links->__pyx_vtab)->read_mmaped(__pyx_v_self->links, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":75
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.links.read_mmaped(buf)
+ *         self.sent_index.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ * 
+ *     def write_text(self, bytes filename):
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->read_mmaped(__pyx_v_self->sent_index, __pyx_v_buf);
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_9Alignment_13write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_13write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_12write_text(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":77
+ *         self.sent_index.read_mmaped(buf)
+ * 
+ *     def write_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             sent_num = 0
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9Alignment_12write_text(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_v_sent_num = NULL;
   PyObject *__pyx_v_i = NULL;
@@ -11597,35 +11953,33 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":71
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":78
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 0
  *             for i, link in enumerate(self.links):
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -11637,8 +11991,8 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":72
- *     def write_text(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":79
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:
  *             sent_num = 0             # <<<<<<<<<<<<<<
  *             for i, link in enumerate(self.links):
@@ -11647,7 +12001,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
           __Pyx_INCREF(__pyx_int_0);
           __pyx_v_sent_num = __pyx_int_0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":73
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":80
  *         with open(filename, "w") as f:
  *             sent_num = 0
  *             for i, link in enumerate(self.links):             # <<<<<<<<<<<<<<
@@ -11657,52 +12011,52 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
           __Pyx_INCREF(__pyx_int_0);
           __pyx_t_4 = __pyx_int_0;
           if (PyList_CheckExact(((PyObject *)__pyx_v_self->links)) || PyTuple_CheckExact(((PyObject *)__pyx_v_self->links))) {
-            __pyx_t_1 = ((PyObject *)__pyx_v_self->links); __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
+            __pyx_t_2 = ((PyObject *)__pyx_v_self->links); __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->links)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(((PyObject *)__pyx_v_self->links)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
           }
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_2 = __pyx_t_9(__pyx_t_1);
-              if (unlikely(!__pyx_t_2)) {
+              __pyx_t_1 = __pyx_t_9(__pyx_t_2);
+              if (unlikely(!__pyx_t_1)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_2);
+              __Pyx_GOTREF(__pyx_t_1);
             }
             __Pyx_XDECREF(__pyx_v_link);
-            __pyx_v_link = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_link = __pyx_t_1;
+            __pyx_t_1 = 0;
             __Pyx_INCREF(__pyx_t_4);
             __Pyx_XDECREF(__pyx_v_i);
             __pyx_v_i = __pyx_t_4;
-            __pyx_t_2 = PyNumber_Add(__pyx_t_4, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_1 = PyNumber_Add(__pyx_t_4, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
             __Pyx_DECREF(__pyx_t_4);
-            __pyx_t_4 = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_t_4 = __pyx_t_1;
+            __pyx_t_1 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":74
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":81
  *             sent_num = 0
  *             for i, link in enumerate(self.links):
  *                 while i >= self.sent_index[sent_num]:             # <<<<<<<<<<<<<<
@@ -11710,92 +12064,92 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
  *                     sent_num = sent_num + 1
  */
             while (1) {
-              __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_self->sent_index), __pyx_v_sent_num); if (!__pyx_t_2) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_2);
-              __pyx_t_10 = PyObject_RichCompare(__pyx_v_i, __pyx_t_2, Py_GE); __Pyx_XGOTREF(__pyx_t_10); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-              __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_self->sent_index), __pyx_v_sent_num); if (!__pyx_t_1) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_1);
+              __pyx_t_10 = PyObject_RichCompare(__pyx_v_i, __pyx_t_1, Py_GE); __Pyx_XGOTREF(__pyx_t_10); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+              __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_10); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
               if (!__pyx_t_11) break;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":75
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":82
  *             for i, link in enumerate(self.links):
  *                 while i >= self.sent_index[sent_num]:
  *                     f.write("\n")             # <<<<<<<<<<<<<<
  *                     sent_num = sent_num + 1
  *                 f.write("%d-%d " % self.unlink(link))
  */
-              __pyx_t_10 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_10);
-              __pyx_t_2 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_k_tuple_34), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_2);
+              __pyx_t_1 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_k_tuple_34), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_1);
               __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":76
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":83
  *                 while i >= self.sent_index[sent_num]:
  *                     f.write("\n")
  *                     sent_num = sent_num + 1             # <<<<<<<<<<<<<<
  *                 f.write("%d-%d " % self.unlink(link))
  *             f.write("\n")
  */
-              __pyx_t_2 = PyNumber_Add(__pyx_v_sent_num, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_2);
+              __pyx_t_1 = PyNumber_Add(__pyx_v_sent_num, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_1);
               __Pyx_DECREF(__pyx_v_sent_num);
-              __pyx_v_sent_num = __pyx_t_2;
-              __pyx_t_2 = 0;
+              __pyx_v_sent_num = __pyx_t_1;
+              __pyx_t_1 = 0;
             }
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":77
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":84
  *                     f.write("\n")
  *                     sent_num = sent_num + 1
  *                 f.write("%d-%d " % self.unlink(link))             # <<<<<<<<<<<<<<
  *             f.write("\n")
  * 
  */
-            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_10 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__unlink); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_10 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__unlink); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
             __Pyx_INCREF(__pyx_v_link);
             PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_v_link);
             __Pyx_GIVEREF(__pyx_v_link);
-            __pyx_t_13 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_13 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_13);
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
-            __pyx_t_12 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_35), __pyx_t_13); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_35), __pyx_t_13); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_12));
             __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-            __pyx_t_13 = PyTuple_New(1); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_13 = PyTuple_New(1); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_13);
             PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)__pyx_t_12));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_12));
             __pyx_t_12 = 0;
-            __pyx_t_12 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_13), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_13), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
             __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
           }
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":78
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":85
  *                     sent_num = sent_num + 1
  *                 f.write("%d-%d " % self.unlink(link))
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def write_binary(self, char* filename):
+ *     def write_binary(self, bytes filename):
  */
-          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_36), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_36), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -11803,30 +12157,30 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
         __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
         __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":71
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":78
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 0
  *             for i, link in enumerate(self.links):
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.Alignment.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_4, &__pyx_t_12) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_4, &__pyx_t_12) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_GOTREF(__pyx_t_4);
           __Pyx_GOTREF(__pyx_t_12);
-          __pyx_t_13 = PyTuple_New(3); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __pyx_t_13 = PyTuple_New(3); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_13);
-          __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_t_1);
-          __Pyx_GIVEREF(__pyx_t_1);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_4);
           PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_t_4);
           __Pyx_GIVEREF(__pyx_t_4);
@@ -11835,24 +12189,24 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
           __Pyx_GIVEREF(__pyx_t_12);
           __pyx_t_14 = PyObject_Call(__pyx_t_3, __pyx_t_13, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_14);
           __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_14);
           __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_15 = (!__pyx_t_11);
           if (__pyx_t_15) {
-            __Pyx_GIVEREF(__pyx_t_1);
+            __Pyx_GIVEREF(__pyx_t_2);
             __Pyx_GIVEREF(__pyx_t_4);
             __Pyx_GIVEREF(__pyx_t_12);
-            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_4, __pyx_t_12);
-            __pyx_t_1 = 0; __pyx_t_4 = 0; __pyx_t_12 = 0; 
-            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_4, __pyx_t_12);
+            __pyx_t_2 = 0; __pyx_t_4 = 0; __pyx_t_12 = 0; 
+            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L22;
           }
           __pyx_L22:;
           __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
           goto __pyx_L8_exception_handled;
@@ -11875,11 +12229,11 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
       if (__pyx_t_3) {
         __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_37, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_15 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_15 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L23;
@@ -11911,50 +12265,50 @@ static PyObject *__pyx_pf_3_sa_9Alignment_10write_text(struct __pyx_obj_3_sa_Ali
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_13write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9Alignment_13write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9Alignment_15write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_15write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Alignment.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_12write_binary(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_14write_binary(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":80
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":87
  *             f.write("\n")
  * 
- *     def write_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_12write_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9Alignment_14write_binary(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":82
- *     def write_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":89
+ *     def write_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
  *         self.links.write_handle(f)
  *         self.sent_index.write_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__w);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":83
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":90
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  *         self.links.write_handle(f)             # <<<<<<<<<<<<<<
@@ -11963,7 +12317,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_12write_binary(struct __pyx_obj_3_sa_A
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->links->__pyx_vtab)->write_handle(__pyx_v_self->links, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":84
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":91
  *         f = fopen(filename, "w")
  *         self.links.write_handle(f)
  *         self.sent_index.write_handle(f)             # <<<<<<<<<<<<<<
@@ -11972,51 +12326,51 @@ static PyObject *__pyx_pf_3_sa_9Alignment_12write_binary(struct __pyx_obj_3_sa_A
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sent_index->__pyx_vtab)->write_handle(__pyx_v_self->sent_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":85
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":92
  *         self.links.write_handle(f)
  *         self.sent_index.write_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.Alignment.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_9Alignment_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_9Alignment_17write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_9Alignment_17write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_enhanced (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Alignment.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_9Alignment_14write_enhanced(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_9Alignment_16write_enhanced(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":87
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":94
  *         fclose(f)
  * 
- *     def write_enhanced(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_enhanced(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             sent_num = 1
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_9Alignment_16write_enhanced(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   CYTHON_UNUSED long __pyx_v_sent_num;
   PyObject *__pyx_v_link = NULL;
@@ -12041,35 +12395,33 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_enhanced", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":88
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":95
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 1
  *             for link in self.links:
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -12081,8 +12433,8 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":89
- *     def write_enhanced(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":96
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:
  *             sent_num = 1             # <<<<<<<<<<<<<<
  *             for link in self.links:
@@ -12090,7 +12442,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
  */
           __pyx_v_sent_num = 1;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":90
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":97
  *         with open(filename, "w") as f:
  *             sent_num = 1
  *             for link in self.links:             # <<<<<<<<<<<<<<
@@ -12101,7 +12453,7 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
             __pyx_t_4 = ((PyObject *)__pyx_v_self->links); __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->links)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->links)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext;
           }
@@ -12109,71 +12461,71 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_1 = __pyx_t_9(__pyx_t_4);
-              if (unlikely(!__pyx_t_1)) {
+              __pyx_t_2 = __pyx_t_9(__pyx_t_4);
+              if (unlikely(!__pyx_t_2)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_1);
+              __Pyx_GOTREF(__pyx_t_2);
             }
             __Pyx_XDECREF(__pyx_v_link);
-            __pyx_v_link = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_link = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":91
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":98
  *             sent_num = 1
  *             for link in self.links:
  *                 f.write("%d " % link)             # <<<<<<<<<<<<<<
  *             f.write("\n")
  *             for i in self.sent_index:
  */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_link); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_10);
-            PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_2));
-            __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-            __pyx_t_2 = 0;
-            __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_2);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
+            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_link); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_10);
+            PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_1));
+            __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+            __pyx_t_1 = 0;
+            __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
             __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           }
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":92
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":99
  *             for link in self.links:
  *                 f.write("%d " % link)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for i in self.sent_index:
  *                 f.write("%d " % i)
  */
-          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_38), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_38), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":93
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":100
  *                 f.write("%d " % link)
  *             f.write("\n")
  *             for i in self.sent_index:             # <<<<<<<<<<<<<<
@@ -12181,34 +12533,34 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
  *             f.write("\n")
  */
           if (PyList_CheckExact(((PyObject *)__pyx_v_self->sent_index)) || PyTuple_CheckExact(((PyObject *)__pyx_v_self->sent_index))) {
-            __pyx_t_2 = ((PyObject *)__pyx_v_self->sent_index); __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
+            __pyx_t_1 = ((PyObject *)__pyx_v_self->sent_index); __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_index)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->sent_index)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_4 = __pyx_t_9(__pyx_t_2);
+              __pyx_t_4 = __pyx_t_9(__pyx_t_1);
               if (unlikely(!__pyx_t_4)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
@@ -12218,42 +12570,42 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
             __pyx_v_i = __pyx_t_4;
             __pyx_t_4 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":94
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":101
  *             f.write("\n")
  *             for i in self.sent_index:
  *                 f.write("%d " % i)             # <<<<<<<<<<<<<<
  *             f.write("\n")
  * 
  */
-            __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
-            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_i); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_i); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_10));
-            __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_t_10));
+            __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_10));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_10));
             __pyx_t_10 = 0;
-            __pyx_t_10 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
             __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
           }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":95
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":102
  *             for i in self.sent_index:
  *                 f.write("%d " % i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  *     def alignment(self, i):
  */
-          __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_39), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_10 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_39), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_10);
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
@@ -12262,56 +12614,56 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
         __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":88
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":95
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 1
  *             for link in self.links:
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.Alignment.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_10, &__pyx_t_2, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (__Pyx_GetException(&__pyx_t_10, &__pyx_t_1, &__pyx_t_2) < 0) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_10);
-          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_4);
           __Pyx_INCREF(__pyx_t_10);
           PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_10);
           __Pyx_GIVEREF(__pyx_t_10);
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_1);
+          PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __pyx_t_12 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_12);
           __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_12);
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_13 = (!__pyx_t_11);
           if (__pyx_t_13) {
             __Pyx_GIVEREF(__pyx_t_10);
-            __Pyx_GIVEREF(__pyx_t_2);
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_10, __pyx_t_2, __pyx_t_1);
-            __pyx_t_10 = 0; __pyx_t_2 = 0; __pyx_t_1 = 0; 
-            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_ErrRestore(__pyx_t_10, __pyx_t_1, __pyx_t_2);
+            __pyx_t_10 = 0; __pyx_t_1 = 0; __pyx_t_2 = 0; 
+            {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L22;
           }
           __pyx_L22:;
           __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
           __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           goto __pyx_L8_exception_handled;
         }
         __pyx_L9_except_error:;
@@ -12332,11 +12684,11 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
       if (__pyx_t_3) {
         __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_40, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_13 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_13 < 0)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L23;
@@ -12365,18 +12717,18 @@ static PyObject *__pyx_pf_3_sa_9Alignment_14write_enhanced(struct __pyx_obj_3_sa
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_9Alignment_17alignment(PyObject *__pyx_v_self, PyObject *__pyx_v_i); /*proto*/
-static char __pyx_doc_3_sa_9Alignment_16alignment[] = "Return all (e,f) pairs for sentence i";
-static PyObject *__pyx_pw_3_sa_9Alignment_17alignment(PyObject *__pyx_v_self, PyObject *__pyx_v_i) {
+static PyObject *__pyx_pw_3_sa_9Alignment_19alignment(PyObject *__pyx_v_self, PyObject *__pyx_v_i); /*proto*/
+static char __pyx_doc_3_sa_9Alignment_18alignment[] = "Return all (e,f) pairs for sentence i";
+static PyObject *__pyx_pw_3_sa_9Alignment_19alignment(PyObject *__pyx_v_self, PyObject *__pyx_v_i) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("alignment (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_9Alignment_16alignment(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject *)__pyx_v_i));
+  __pyx_r = __pyx_pf_3_sa_9Alignment_18alignment(((struct __pyx_obj_3_sa_Alignment *)__pyx_v_self), ((PyObject *)__pyx_v_i));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":97
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":104
  *             f.write("\n")
  * 
  *     def alignment(self, i):             # <<<<<<<<<<<<<<
@@ -12384,7 +12736,7 @@ static PyObject *__pyx_pw_3_sa_9Alignment_17alignment(PyObject *__pyx_v_self, Py
  *         cdef int j, start, end
  */
 
-static PyObject *__pyx_pf_3_sa_9Alignment_16alignment(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_i) {
+static PyObject *__pyx_pf_3_sa_9Alignment_18alignment(struct __pyx_obj_3_sa_Alignment *__pyx_v_self, PyObject *__pyx_v_i) {
   int __pyx_v_j;
   int __pyx_v_start;
   int __pyx_v_end;
@@ -12402,42 +12754,42 @@ static PyObject *__pyx_pf_3_sa_9Alignment_16alignment(struct __pyx_obj_3_sa_Alig
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("alignment", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":100
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":107
  *         """Return all (e,f) pairs for sentence i"""
  *         cdef int j, start, end
  *         result = []             # <<<<<<<<<<<<<<
  *         start = self.sent_index.arr[i]
  *         end = self.sent_index.arr[i+1]
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_result = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":101
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":108
  *         cdef int j, start, end
  *         result = []
  *         start = self.sent_index.arr[i]             # <<<<<<<<<<<<<<
  *         end = self.sent_index.arr[i+1]
  *         for j from start <= j < end:
  */
-  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_start = (__pyx_v_self->sent_index->arr[__pyx_t_2]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":102
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":109
  *         result = []
  *         start = self.sent_index.arr[i]
  *         end = self.sent_index.arr[i+1]             # <<<<<<<<<<<<<<
  *         for j from start <= j < end:
  *             result.append(self.unlink(self.links.arr[j]))
  */
-  __pyx_t_1 = PyNumber_Add(__pyx_v_i, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyNumber_Add(__pyx_v_i, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_v_end = (__pyx_v_self->sent_index->arr[__pyx_t_2]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":103
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":110
  *         start = self.sent_index.arr[i]
  *         end = self.sent_index.arr[i+1]
  *         for j from start <= j < end:             # <<<<<<<<<<<<<<
@@ -12447,30 +12799,30 @@ static PyObject *__pyx_pf_3_sa_9Alignment_16alignment(struct __pyx_obj_3_sa_Alig
   __pyx_t_3 = __pyx_v_end;
   for (__pyx_v_j = __pyx_v_start; __pyx_v_j < __pyx_t_3; __pyx_v_j++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":104
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":111
  *         end = self.sent_index.arr[i+1]
  *         for j from start <= j < end:
  *             result.append(self.unlink(self.links.arr[j]))             # <<<<<<<<<<<<<<
  *         return result
  */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__unlink); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__unlink); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = PyInt_FromLong((__pyx_v_self->links->arr[__pyx_v_j])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong((__pyx_v_self->links->arr[__pyx_v_j])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
-    __pyx_t_6 = PyList_Append(__pyx_v_result, __pyx_t_4); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyList_Append(__pyx_v_result, __pyx_t_4); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":105
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":112
  *         for j from start <= j < end:
  *             result.append(self.unlink(self.links.arr[j]))
  *         return result             # <<<<<<<<<<<<<<
@@ -12785,7 +13137,7 @@ static int *__pyx_f_3_sa_get_val(struct __pyx_t_3_sa__node *__pyx_v_n, int __pyx
  *             return &(n.bigger.val)
  *         return get_val(n.bigger, key)             # <<<<<<<<<<<<<<
  * 
- * 
+ * cdef int NULL_WORD = 0
  */
     __pyx_r = __pyx_f_3_sa_get_val(__pyx_v_n->bigger, __pyx_v_key);
     goto __pyx_L0;
@@ -12807,38 +13159,41 @@ static int __pyx_pw_3_sa_5BiLex_1__cinit__(PyObject *__pyx_v_self, PyObject *__p
   PyObject *__pyx_v_earray = 0;
   PyObject *__pyx_v_fsarray = 0;
   PyObject *__pyx_v_alignment = 0;
+  PyObject *__pyx_v_mmaped = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_text,&__pyx_n_s__from_data,&__pyx_n_s__from_binary,&__pyx_n_s__earray,&__pyx_n_s__fsarray,&__pyx_n_s__alignment,0};
-    PyObject* values[6] = {0,0,0,0,0,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_text,&__pyx_n_s__from_data,&__pyx_n_s__from_binary,&__pyx_n_s__earray,&__pyx_n_s__fsarray,&__pyx_n_s__alignment,&__pyx_n_s__mmaped,0};
+    PyObject* values[7] = {0,0,0,0,0,0,0};
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":54
- *     cdef id2eword, id2fword, eword2id, fword2id
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":53
+ *     cdef Vocabulary f_voc, e_voc
  * 
  *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,             # <<<<<<<<<<<<<<
- *             earray=None, fsarray=None, alignment=None):
- *         self.id2eword = []
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):
+ *         self.f_voc = Vocabulary()
  */
     values[0] = ((PyObject *)Py_None);
     values[1] = __pyx_k_41;
     values[2] = ((PyObject *)Py_None);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":55
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":54
  * 
  *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,
- *             earray=None, fsarray=None, alignment=None):             # <<<<<<<<<<<<<<
- *         self.id2eword = []
- *         self.id2fword = []
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):             # <<<<<<<<<<<<<<
+ *         self.f_voc = Vocabulary()
+ *         self.e_voc = Vocabulary()
  */
     values[3] = ((PyObject *)Py_None);
     values[4] = ((PyObject *)Py_None);
     values[5] = ((PyObject *)Py_None);
+    values[6] = __pyx_k_42;
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
         case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
         case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
         case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
@@ -12880,12 +13235,18 @@ static int __pyx_pw_3_sa_5BiLex_1__cinit__(PyObject *__pyx_v_self, PyObject *__p
           PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__alignment);
           if (value) { values[5] = value; kw_args--; }
         }
+        case  6:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__mmaped);
+          if (value) { values[6] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
         case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
         case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
         case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
@@ -12902,29 +13263,30 @@ static int __pyx_pw_3_sa_5BiLex_1__cinit__(PyObject *__pyx_v_self, PyObject *__p
     __pyx_v_earray = values[3];
     __pyx_v_fsarray = values[4];
     __pyx_v_alignment = values[5];
+    __pyx_v_mmaped = values[6];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 7, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.BiLex.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex___cinit__(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), __pyx_v_from_text, __pyx_v_from_data, __pyx_v_from_binary, __pyx_v_earray, __pyx_v_fsarray, __pyx_v_alignment);
+  __pyx_r = __pyx_pf_3_sa_5BiLex___cinit__(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), __pyx_v_from_text, __pyx_v_from_data, __pyx_v_from_binary, __pyx_v_earray, __pyx_v_fsarray, __pyx_v_alignment, __pyx_v_mmaped);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":54
- *     cdef id2eword, id2fword, eword2id, fword2id
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":53
+ *     cdef Vocabulary f_voc, e_voc
  * 
  *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,             # <<<<<<<<<<<<<<
- *             earray=None, fsarray=None, alignment=None):
- *         self.id2eword = []
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):
+ *         self.f_voc = Vocabulary()
  */
 
-static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_from_text, PyObject *__pyx_v_from_data, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_earray, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_alignment) {
+static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_from_text, PyObject *__pyx_v_from_data, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_earray, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_alignment, PyObject *__pyx_v_mmaped) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -12937,74 +13299,44 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":56
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":55
  *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,
- *             earray=None, fsarray=None, alignment=None):
- *         self.id2eword = []             # <<<<<<<<<<<<<<
- *         self.id2fword = []
- *         self.eword2id = {}
- */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->id2eword);
-  __Pyx_DECREF(__pyx_v_self->id2eword);
-  __pyx_v_self->id2eword = ((PyObject *)__pyx_t_1);
-  __pyx_t_1 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":57
- *             earray=None, fsarray=None, alignment=None):
- *         self.id2eword = []
- *         self.id2fword = []             # <<<<<<<<<<<<<<
- *         self.eword2id = {}
- *         self.fword2id = {}
- */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->id2fword);
-  __Pyx_DECREF(__pyx_v_self->id2fword);
-  __pyx_v_self->id2fword = ((PyObject *)__pyx_t_1);
-  __pyx_t_1 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":58
- *         self.id2eword = []
- *         self.id2fword = []
- *         self.eword2id = {}             # <<<<<<<<<<<<<<
- *         self.fword2id = {}
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):
+ *         self.f_voc = Vocabulary()             # <<<<<<<<<<<<<<
+ *         self.e_voc = Vocabulary()
  *         self.e_index = IntList()
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->eword2id);
-  __Pyx_DECREF(__pyx_v_self->eword2id);
-  __pyx_v_self->eword2id = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_Vocabulary)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->f_voc);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->f_voc));
+  __pyx_v_self->f_voc = ((struct __pyx_obj_3_sa_Vocabulary *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":59
- *         self.id2fword = []
- *         self.eword2id = {}
- *         self.fword2id = {}             # <<<<<<<<<<<<<<
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":56
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):
+ *         self.f_voc = Vocabulary()
+ *         self.e_voc = Vocabulary()             # <<<<<<<<<<<<<<
  *         self.e_index = IntList()
  *         self.f_index = IntList()
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-  __Pyx_GOTREF(__pyx_v_self->fword2id);
-  __Pyx_DECREF(__pyx_v_self->fword2id);
-  __pyx_v_self->fword2id = ((PyObject *)__pyx_t_1);
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_Vocabulary)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 56; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->e_voc);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->e_voc));
+  __pyx_v_self->e_voc = ((struct __pyx_obj_3_sa_Vocabulary *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":60
- *         self.eword2id = {}
- *         self.fword2id = {}
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":57
+ *         self.f_voc = Vocabulary()
+ *         self.e_voc = Vocabulary()
  *         self.e_index = IntList()             # <<<<<<<<<<<<<<
  *         self.f_index = IntList()
  *         self.col1 = FloatList()
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->e_index);
@@ -13012,14 +13344,14 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   __pyx_v_self->e_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":61
- *         self.fword2id = {}
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":58
+ *         self.e_voc = Vocabulary()
  *         self.e_index = IntList()
  *         self.f_index = IntList()             # <<<<<<<<<<<<<<
  *         self.col1 = FloatList()
  *         self.col2 = FloatList()
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->f_index);
@@ -13027,14 +13359,14 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   __pyx_v_self->f_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":62
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":59
  *         self.e_index = IntList()
  *         self.f_index = IntList()
  *         self.col1 = FloatList()             # <<<<<<<<<<<<<<
  *         self.col2 = FloatList()
  *         if from_binary:
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->col1);
@@ -13042,14 +13374,14 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   __pyx_v_self->col1 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":63
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":60
  *         self.f_index = IntList()
  *         self.col1 = FloatList()
  *         self.col2 = FloatList()             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->col2);
@@ -13057,41 +13389,84 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   __pyx_v_self->col2 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":64
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":61
  *         self.col1 = FloatList()
  *         self.col2 = FloatList()
  *         if from_binary:             # <<<<<<<<<<<<<<
- *             self.read_binary(from_binary)
- *         elif from_data:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":65
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":62
  *         self.col2 = FloatList()
  *         if from_binary:
- *             self.read_binary(from_binary)             # <<<<<<<<<<<<<<
+ *             if mmaped:             # <<<<<<<<<<<<<<
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ */
+    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_mmaped); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_2) {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":63
+ *         if from_binary:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.read_binary(from_binary)
+ */
+      __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_mmaped); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_4 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_MemoryMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);
+      __Pyx_GIVEREF(__pyx_t_4);
+      __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":65
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ *                 self.read_binary(from_binary)             # <<<<<<<<<<<<<<
  *         elif from_data:
  *             self.compute_from_data(fsarray, earray, alignment)
  */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_from_binary);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
-    __Pyx_GIVEREF(__pyx_v_from_binary);
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 65; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
+    __pyx_L4:;
     goto __pyx_L3;
   }
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":66
- *         if from_binary:
- *             self.read_binary(from_binary)
+ *             else:
+ *                 self.read_binary(from_binary)
  *         elif from_data:             # <<<<<<<<<<<<<<
  *             self.compute_from_data(fsarray, earray, alignment)
  *         else:
@@ -13100,26 +13475,26 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   if (__pyx_t_2) {
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":67
- *             self.read_binary(from_binary)
+ *                 self.read_binary(from_binary)
  *         elif from_data:
  *             self.compute_from_data(fsarray, earray, alignment)             # <<<<<<<<<<<<<<
  *         else:
  *             self.read_text(from_text)
  */
     if (!(likely(((__pyx_v_fsarray) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_fsarray, __pyx_ptype_3_sa_SuffixArray))))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_4 = __pyx_v_fsarray;
-    __Pyx_INCREF(__pyx_t_4);
+    __pyx_t_1 = __pyx_v_fsarray;
+    __Pyx_INCREF(__pyx_t_1);
     if (!(likely(((__pyx_v_earray) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_earray, __pyx_ptype_3_sa_DataArray))))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_3 = __pyx_v_earray;
     __Pyx_INCREF(__pyx_t_3);
     if (!(likely(((__pyx_v_alignment) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_alignment, __pyx_ptype_3_sa_Alignment))))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __pyx_v_alignment;
-    __Pyx_INCREF(__pyx_t_1);
-    __pyx_t_5 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->compute_from_data(__pyx_v_self, ((struct __pyx_obj_3_sa_SuffixArray *)__pyx_t_4), ((struct __pyx_obj_3_sa_DataArray *)__pyx_t_3), ((struct __pyx_obj_3_sa_Alignment *)__pyx_t_1)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __pyx_v_alignment;
+    __Pyx_INCREF(__pyx_t_4);
+    __pyx_t_5 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->compute_from_data(__pyx_v_self, ((struct __pyx_obj_3_sa_SuffixArray *)__pyx_t_1), ((struct __pyx_obj_3_sa_DataArray *)__pyx_t_3), ((struct __pyx_obj_3_sa_Alignment *)__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     goto __pyx_L3;
   }
@@ -13134,15 +13509,15 @@ static int __pyx_pf_3_sa_5BiLex___cinit__(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
     __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_INCREF(__pyx_v_from_text);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_from_text);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_from_text);
     __Pyx_GIVEREF(__pyx_v_from_text);
-    __pyx_t_3 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   }
   __pyx_L3:;
@@ -13191,353 +13566,142 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
   int *__pyx_v_fmargin;
   int *__pyx_v_emargin;
   int *__pyx_v_count;
-  int __pyx_v_null_word;
-  PyObject *__pyx_v_word = NULL;
-  PyObject *__pyx_v_id = NULL;
   PyObject *__pyx_v_num_sents = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  Py_ssize_t __pyx_t_2;
-  PyObject *(*__pyx_t_3)(PyObject *);
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_t_6;
+  int __pyx_t_5;
+  Py_ssize_t __pyx_t_6;
   int __pyx_t_7;
   int __pyx_t_8;
   int __pyx_t_9;
   int __pyx_t_10;
   PyObject *__pyx_t_11 = NULL;
   PyObject *__pyx_t_12 = NULL;
-  PyObject *__pyx_t_13 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("compute_from_data", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":79
- *         cdef int null_word
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":78
+ *         cdef int *fmargin, *emargin, *count
  * 
- *         null_word = 0             # <<<<<<<<<<<<<<
- *         for word in fsa.darray.id2word: # I miss list comprehensions
- *             self.id2fword.append(word)
- */
-  __pyx_v_null_word = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":80
- * 
- *         null_word = 0
- *         for word in fsa.darray.id2word: # I miss list comprehensions             # <<<<<<<<<<<<<<
- *             self.id2fword.append(word)
- *         self.id2fword[null_word] = "NULL"
- */
-  if (PyList_CheckExact(__pyx_v_fsa->darray->id2word) || PyTuple_CheckExact(__pyx_v_fsa->darray->id2word)) {
-    __pyx_t_1 = __pyx_v_fsa->darray->id2word; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_fsa->darray->id2word); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
-  }
-  for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_4 = __pyx_t_3(__pyx_t_1);
-      if (unlikely(!__pyx_t_4)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_4);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_4;
-    __pyx_t_4 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":81
- *         null_word = 0
- *         for word in fsa.darray.id2word: # I miss list comprehensions
- *             self.id2fword.append(word)             # <<<<<<<<<<<<<<
- *         self.id2fword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2fword):
+ *         self.f_voc.extend(fsa.darray.voc)             # <<<<<<<<<<<<<<
+ *         self.e_voc.extend(eda.voc)
+ *         assert(self.f_voc['NULL'] == self.e_voc['NULL'] == NULL_WORD)
  */
-    __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_self->id2fword, __pyx_v_word); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  }
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self->f_voc), __pyx_n_s__extend); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_fsa->darray->voc));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_fsa->darray->voc));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_fsa->darray->voc));
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":82
- *         for word in fsa.darray.id2word: # I miss list comprehensions
- *             self.id2fword.append(word)
- *         self.id2fword[null_word] = "NULL"             # <<<<<<<<<<<<<<
- *         for id, word in enumerate(self.id2fword):
- *             self.fword2id[word] = id
- */
-  if (__Pyx_SetItemInt(__pyx_v_self->id2fword, __pyx_v_null_word, ((PyObject *)__pyx_n_s__NULL), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":83
- *             self.id2fword.append(word)
- *         self.id2fword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2fword):             # <<<<<<<<<<<<<<
- *             self.fword2id[word] = id
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":79
  * 
- */
-  __Pyx_INCREF(__pyx_int_0);
-  __pyx_t_1 = __pyx_int_0;
-  if (PyList_CheckExact(__pyx_v_self->id2fword) || PyTuple_CheckExact(__pyx_v_self->id2fword)) {
-    __pyx_t_4 = __pyx_v_self->id2fword; __Pyx_INCREF(__pyx_t_4); __pyx_t_2 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_self->id2fword); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = Py_TYPE(__pyx_t_4)->tp_iternext;
-  }
-  for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_4)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_5 = __pyx_t_3(__pyx_t_4);
-      if (unlikely(!__pyx_t_5)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_5);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_5;
-    __pyx_t_5 = 0;
-    __Pyx_INCREF(__pyx_t_1);
-    __Pyx_XDECREF(__pyx_v_id);
-    __pyx_v_id = __pyx_t_1;
-    __pyx_t_5 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 83; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_1);
-    __pyx_t_1 = __pyx_t_5;
-    __pyx_t_5 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":84
- *         self.id2fword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2fword):
- *             self.fword2id[word] = id             # <<<<<<<<<<<<<<
+ *         self.f_voc.extend(fsa.darray.voc)
+ *         self.e_voc.extend(eda.voc)             # <<<<<<<<<<<<<<
+ *         assert(self.f_voc['NULL'] == self.e_voc['NULL'] == NULL_WORD)
  * 
- *         for word in eda.id2word:
  */
-    if (PyObject_SetItem(__pyx_v_self->fword2id, __pyx_v_word, __pyx_v_id) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self->e_voc), __pyx_n_s__extend); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_eda->voc));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_eda->voc));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_eda->voc));
+  __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":86
- *             self.fword2id[word] = id
- * 
- *         for word in eda.id2word:             # <<<<<<<<<<<<<<
- *             self.id2eword.append(word)
- *         self.id2eword[null_word] = "NULL"
- */
-  if (PyList_CheckExact(__pyx_v_eda->id2word) || PyTuple_CheckExact(__pyx_v_eda->id2word)) {
-    __pyx_t_1 = __pyx_v_eda->id2word; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_eda->id2word); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
-  }
-  for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_4 = __pyx_t_3(__pyx_t_1);
-      if (unlikely(!__pyx_t_4)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_4);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_4;
-    __pyx_t_4 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":87
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":80
+ *         self.f_voc.extend(fsa.darray.voc)
+ *         self.e_voc.extend(eda.voc)
+ *         assert(self.f_voc['NULL'] == self.e_voc['NULL'] == NULL_WORD)             # <<<<<<<<<<<<<<
  * 
- *         for word in eda.id2word:
- *             self.id2eword.append(word)             # <<<<<<<<<<<<<<
- *         self.id2eword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2eword):
+ *         num_pairs = 0
  */
-    __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_self->id2eword, __pyx_v_word); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_self->f_voc), ((PyObject *)__pyx_n_s__NULL)); if (!__pyx_t_1) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_self->e_voc), ((PyObject *)__pyx_n_s__NULL)); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_RichCompare(__pyx_t_1, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_PyObject_IsTrue(__pyx_t_3)) {
+    __Pyx_DECREF(__pyx_t_3);
+    __pyx_t_4 = PyInt_FromLong(__pyx_v_3_sa_NULL_WORD); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":88
- *         for word in eda.id2word:
- *             self.id2eword.append(word)
- *         self.id2eword[null_word] = "NULL"             # <<<<<<<<<<<<<<
- *         for id, word in enumerate(self.id2eword):
- *             self.eword2id[word] = id
- */
-  if (__Pyx_SetItemInt(__pyx_v_self->id2eword, __pyx_v_null_word, ((PyObject *)__pyx_n_s__NULL), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":89
- *             self.id2eword.append(word)
- *         self.id2eword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2eword):             # <<<<<<<<<<<<<<
- *             self.eword2id[word] = id
- * 
- */
-  __Pyx_INCREF(__pyx_int_0);
-  __pyx_t_1 = __pyx_int_0;
-  if (PyList_CheckExact(__pyx_v_self->id2eword) || PyTuple_CheckExact(__pyx_v_self->id2eword)) {
-    __pyx_t_4 = __pyx_v_self->id2eword; __Pyx_INCREF(__pyx_t_4); __pyx_t_2 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_2 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_self->id2eword); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = Py_TYPE(__pyx_t_4)->tp_iternext;
-  }
-  for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_4)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_4)) {
-      if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_4, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_5 = __pyx_t_3(__pyx_t_4);
-      if (unlikely(!__pyx_t_5)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_5);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_5;
-    __pyx_t_5 = 0;
-    __Pyx_INCREF(__pyx_t_1);
-    __Pyx_XDECREF(__pyx_v_id);
-    __pyx_v_id = __pyx_t_1;
-    __pyx_t_5 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_1);
-    __pyx_t_1 = __pyx_t_5;
-    __pyx_t_5 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":90
- *         self.id2eword[null_word] = "NULL"
- *         for id, word in enumerate(self.id2eword):
- *             self.eword2id[word] = id             # <<<<<<<<<<<<<<
- * 
- *         num_pairs = 0
- */
-    if (PyObject_SetItem(__pyx_v_self->eword2id, __pyx_v_word, __pyx_v_id) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 90; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_5 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_5)) {
+    PyErr_SetNone(PyExc_AssertionError);
+    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 80; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  #endif
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":92
- *             self.eword2id[word] = id
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":82
+ *         assert(self.f_voc['NULL'] == self.e_voc['NULL'] == NULL_WORD)
  * 
  *         num_pairs = 0             # <<<<<<<<<<<<<<
  * 
- *         V_E = len(eda.id2word)
+ *         V_E = len(eda.voc)
  */
   __pyx_v_num_pairs = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":94
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":84
  *         num_pairs = 0
  * 
- *         V_E = len(eda.id2word)             # <<<<<<<<<<<<<<
- *         V_F = len(fsa.darray.id2word)
+ *         V_E = len(eda.voc)             # <<<<<<<<<<<<<<
+ *         V_F = len(fsa.darray.voc)
  *         fmargin = <int*> malloc(V_F*sizeof(int))
  */
-  __pyx_t_1 = __pyx_v_eda->id2word;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_V_E = __pyx_t_2;
+  __pyx_t_3 = ((PyObject *)__pyx_v_eda->voc);
+  __Pyx_INCREF(__pyx_t_3);
+  __pyx_t_6 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 84; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_V_E = __pyx_t_6;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":95
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":85
  * 
- *         V_E = len(eda.id2word)
- *         V_F = len(fsa.darray.id2word)             # <<<<<<<<<<<<<<
+ *         V_E = len(eda.voc)
+ *         V_F = len(fsa.darray.voc)             # <<<<<<<<<<<<<<
  *         fmargin = <int*> malloc(V_F*sizeof(int))
  *         emargin = <int*> malloc(V_E*sizeof(int))
  */
-  __pyx_t_1 = __pyx_v_fsa->darray->id2word;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_V_F = __pyx_t_2;
+  __pyx_t_3 = ((PyObject *)__pyx_v_fsa->darray->voc);
+  __Pyx_INCREF(__pyx_t_3);
+  __pyx_t_6 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_V_F = __pyx_t_6;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":96
- *         V_E = len(eda.id2word)
- *         V_F = len(fsa.darray.id2word)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":86
+ *         V_E = len(eda.voc)
+ *         V_F = len(fsa.darray.voc)
  *         fmargin = <int*> malloc(V_F*sizeof(int))             # <<<<<<<<<<<<<<
  *         emargin = <int*> malloc(V_E*sizeof(int))
  *         memset(fmargin, 0, V_F*sizeof(int))
  */
   __pyx_v_fmargin = ((int *)malloc((__pyx_v_V_F * (sizeof(int)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":97
- *         V_F = len(fsa.darray.id2word)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":87
+ *         V_F = len(fsa.darray.voc)
  *         fmargin = <int*> malloc(V_F*sizeof(int))
  *         emargin = <int*> malloc(V_E*sizeof(int))             # <<<<<<<<<<<<<<
  *         memset(fmargin, 0, V_F*sizeof(int))
@@ -13545,7 +13709,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   __pyx_v_emargin = ((int *)malloc((__pyx_v_V_E * (sizeof(int)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":98
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":88
  *         fmargin = <int*> malloc(V_F*sizeof(int))
  *         emargin = <int*> malloc(V_E*sizeof(int))
  *         memset(fmargin, 0, V_F*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13554,7 +13718,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   memset(__pyx_v_fmargin, 0, (__pyx_v_V_F * (sizeof(int))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":99
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":89
  *         emargin = <int*> malloc(V_E*sizeof(int))
  *         memset(fmargin, 0, V_F*sizeof(int))
  *         memset(emargin, 0, V_E*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13563,7 +13727,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   memset(__pyx_v_emargin, 0, (__pyx_v_V_E * (sizeof(int))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":101
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":91
  *         memset(emargin, 0, V_E*sizeof(int))
  * 
  *         dict = <_node**> malloc(V_F*sizeof(_node*))             # <<<<<<<<<<<<<<
@@ -13572,7 +13736,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   __pyx_v_dict = ((struct __pyx_t_3_sa__node **)malloc((__pyx_v_V_F * (sizeof(struct __pyx_t_3_sa__node *)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":102
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":92
  * 
  *         dict = <_node**> malloc(V_F*sizeof(_node*))
  *         memset(dict, 0, V_F*sizeof(_node*))             # <<<<<<<<<<<<<<
@@ -13581,36 +13745,36 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   memset(__pyx_v_dict, 0, (__pyx_v_V_F * (sizeof(struct __pyx_t_3_sa__node *))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":104
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":94
  *         memset(dict, 0, V_F*sizeof(_node*))
  * 
  *         num_sents = len(fsa.darray.sent_index)             # <<<<<<<<<<<<<<
  *         for sent_id from 0 <= sent_id < num_sents-1:
  * 
  */
-  __pyx_t_1 = ((PyObject *)__pyx_v_fsa->darray->sent_index);
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_num_sents = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __pyx_t_3 = ((PyObject *)__pyx_v_fsa->darray->sent_index);
+  __Pyx_INCREF(__pyx_t_3);
+  __pyx_t_6 = PyObject_Length(__pyx_t_3); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_6); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_v_num_sents = __pyx_t_3;
+  __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":105
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":95
  * 
  *         num_sents = len(fsa.darray.sent_index)
  *         for sent_id from 0 <= sent_id < num_sents-1:             # <<<<<<<<<<<<<<
  * 
  *             fsent = fsa.darray.data.arr + fsa.darray.sent_index.arr[sent_id]
  */
-  __pyx_t_1 = PyNumber_Subtract(__pyx_v_num_sents, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_t_1); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  for (__pyx_v_sent_id = 0; __pyx_v_sent_id < __pyx_t_6; __pyx_v_sent_id++) {
+  __pyx_t_3 = PyNumber_Subtract(__pyx_v_num_sents, __pyx_int_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_7 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  for (__pyx_v_sent_id = 0; __pyx_v_sent_id < __pyx_t_7; __pyx_v_sent_id++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":107
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":97
  *         for sent_id from 0 <= sent_id < num_sents-1:
  * 
  *             fsent = fsa.darray.data.arr + fsa.darray.sent_index.arr[sent_id]             # <<<<<<<<<<<<<<
@@ -13619,7 +13783,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_fsent = (__pyx_v_fsa->darray->data->arr + (__pyx_v_fsa->darray->sent_index->arr[__pyx_v_sent_id]));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":108
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":98
  * 
  *             fsent = fsa.darray.data.arr + fsa.darray.sent_index.arr[sent_id]
  *             I = fsa.darray.sent_index.arr[sent_id+1] - fsa.darray.sent_index.arr[sent_id] - 1             # <<<<<<<<<<<<<<
@@ -13628,7 +13792,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_I = (((__pyx_v_fsa->darray->sent_index->arr[(__pyx_v_sent_id + 1)]) - (__pyx_v_fsa->darray->sent_index->arr[__pyx_v_sent_id])) - 1);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":109
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":99
  *             fsent = fsa.darray.data.arr + fsa.darray.sent_index.arr[sent_id]
  *             I = fsa.darray.sent_index.arr[sent_id+1] - fsa.darray.sent_index.arr[sent_id] - 1
  *             faligned = <int*> malloc(I*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13637,7 +13801,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_faligned = ((int *)malloc((__pyx_v_I * (sizeof(int)))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":110
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":100
  *             I = fsa.darray.sent_index.arr[sent_id+1] - fsa.darray.sent_index.arr[sent_id] - 1
  *             faligned = <int*> malloc(I*sizeof(int))
  *             memset(faligned, 0, I*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13646,7 +13810,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     memset(__pyx_v_faligned, 0, (__pyx_v_I * (sizeof(int))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":112
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":102
  *             memset(faligned, 0, I*sizeof(int))
  * 
  *             esent = eda.data.arr + eda.sent_index.arr[sent_id]             # <<<<<<<<<<<<<<
@@ -13655,7 +13819,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_esent = (__pyx_v_eda->data->arr + (__pyx_v_eda->sent_index->arr[__pyx_v_sent_id]));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":113
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":103
  * 
  *             esent = eda.data.arr + eda.sent_index.arr[sent_id]
  *             J = eda.sent_index.arr[sent_id+1] - eda.sent_index.arr[sent_id] - 1             # <<<<<<<<<<<<<<
@@ -13664,7 +13828,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_J = (((__pyx_v_eda->sent_index->arr[(__pyx_v_sent_id + 1)]) - (__pyx_v_eda->sent_index->arr[__pyx_v_sent_id])) - 1);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":114
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":104
  *             esent = eda.data.arr + eda.sent_index.arr[sent_id]
  *             J = eda.sent_index.arr[sent_id+1] - eda.sent_index.arr[sent_id] - 1
  *             ealigned = <int*> malloc(J*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13673,7 +13837,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_ealigned = ((int *)malloc((__pyx_v_J * (sizeof(int)))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":115
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":105
  *             J = eda.sent_index.arr[sent_id+1] - eda.sent_index.arr[sent_id] - 1
  *             ealigned = <int*> malloc(J*sizeof(int))
  *             memset(ealigned, 0, J*sizeof(int))             # <<<<<<<<<<<<<<
@@ -13682,7 +13846,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     memset(__pyx_v_ealigned, 0, (__pyx_v_J * (sizeof(int))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":117
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":107
  *             memset(ealigned, 0, J*sizeof(int))
  * 
  *             links = aa._get_sent_links(sent_id, &num_links)             # <<<<<<<<<<<<<<
@@ -13691,17 +13855,17 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     __pyx_v_links = ((struct __pyx_vtabstruct_3_sa_Alignment *)__pyx_v_aa->__pyx_vtab)->_get_sent_links(__pyx_v_aa, __pyx_v_sent_id, (&__pyx_v_num_links));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":119
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":109
  *             links = aa._get_sent_links(sent_id, &num_links)
  * 
  *             for l from 0 <= l < num_links:             # <<<<<<<<<<<<<<
  *                 i = links[l*2]
  *                 j = links[l*2+1]
  */
-    __pyx_t_7 = __pyx_v_num_links;
-    for (__pyx_v_l = 0; __pyx_v_l < __pyx_t_7; __pyx_v_l++) {
+    __pyx_t_8 = __pyx_v_num_links;
+    for (__pyx_v_l = 0; __pyx_v_l < __pyx_t_8; __pyx_v_l++) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":120
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":110
  * 
  *             for l from 0 <= l < num_links:
  *                 i = links[l*2]             # <<<<<<<<<<<<<<
@@ -13710,7 +13874,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       __pyx_v_i = (__pyx_v_links[(__pyx_v_l * 2)]);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":121
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":111
  *             for l from 0 <= l < num_links:
  *                 i = links[l*2]
  *                 j = links[l*2+1]             # <<<<<<<<<<<<<<
@@ -13719,75 +13883,75 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       __pyx_v_j = (__pyx_v_links[((__pyx_v_l * 2) + 1)]);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":122
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":112
  *                 i = links[l*2]
  *                 j = links[l*2+1]
  *                 if i >= I or j >= J:             # <<<<<<<<<<<<<<
  *                     raise Exception("%d-%d out of bounds (I=%d,J=%d) in line %d\n" % (i,j,I,J,sent_id+1))
  *                 f_i = fsent[i]
  */
-      __pyx_t_8 = (__pyx_v_i >= __pyx_v_I);
-      if (!__pyx_t_8) {
+      __pyx_t_5 = (__pyx_v_i >= __pyx_v_I);
+      if (!__pyx_t_5) {
         __pyx_t_9 = (__pyx_v_j >= __pyx_v_J);
         __pyx_t_10 = __pyx_t_9;
       } else {
-        __pyx_t_10 = __pyx_t_8;
+        __pyx_t_10 = __pyx_t_5;
       }
       if (__pyx_t_10) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":123
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":113
  *                 j = links[l*2+1]
  *                 if i >= I or j >= J:
  *                     raise Exception("%d-%d out of bounds (I=%d,J=%d) in line %d\n" % (i,j,I,J,sent_id+1))             # <<<<<<<<<<<<<<
  *                 f_i = fsent[i]
  *                 e_j = esent[j]
  */
-        __pyx_t_1 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_2 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_2);
+        __pyx_t_1 = PyInt_FromLong(__pyx_v_I); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_4 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_4 = PyInt_FromLong(__pyx_v_J); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_4);
-        __pyx_t_5 = PyInt_FromLong(__pyx_v_I); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_5);
-        __pyx_t_11 = PyInt_FromLong(__pyx_v_J); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_11 = PyInt_FromLong((__pyx_v_sent_id + 1)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_11);
-        __pyx_t_12 = PyInt_FromLong((__pyx_v_sent_id + 1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_12 = PyTuple_New(5); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_12);
-        __pyx_t_13 = PyTuple_New(5); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_13);
-        PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_t_1);
+        PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_3);
+        __Pyx_GIVEREF(__pyx_t_3);
+        PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_2);
+        __Pyx_GIVEREF(__pyx_t_2);
+        PyTuple_SET_ITEM(__pyx_t_12, 2, __pyx_t_1);
         __Pyx_GIVEREF(__pyx_t_1);
-        PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_t_4);
+        PyTuple_SET_ITEM(__pyx_t_12, 3, __pyx_t_4);
         __Pyx_GIVEREF(__pyx_t_4);
-        PyTuple_SET_ITEM(__pyx_t_13, 2, __pyx_t_5);
-        __Pyx_GIVEREF(__pyx_t_5);
-        PyTuple_SET_ITEM(__pyx_t_13, 3, __pyx_t_11);
+        PyTuple_SET_ITEM(__pyx_t_12, 4, __pyx_t_11);
         __Pyx_GIVEREF(__pyx_t_11);
-        PyTuple_SET_ITEM(__pyx_t_13, 4, __pyx_t_12);
-        __Pyx_GIVEREF(__pyx_t_12);
+        __pyx_t_3 = 0;
+        __pyx_t_2 = 0;
         __pyx_t_1 = 0;
         __pyx_t_4 = 0;
-        __pyx_t_5 = 0;
         __pyx_t_11 = 0;
-        __pyx_t_12 = 0;
-        __pyx_t_12 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_42), ((PyObject *)__pyx_t_13)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(((PyObject *)__pyx_t_12));
-        __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
-        __pyx_t_13 = PyTuple_New(1); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_13);
-        PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)__pyx_t_12));
-        __Pyx_GIVEREF(((PyObject *)__pyx_t_12));
-        __pyx_t_12 = 0;
-        __pyx_t_12 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_t_13), NULL); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_11 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_43), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(((PyObject *)__pyx_t_11));
+        __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+        __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_12);
-        __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
-        __Pyx_Raise(__pyx_t_12, 0, 0, 0);
-        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-        {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        goto __pyx_L15;
+        PyTuple_SET_ITEM(__pyx_t_12, 0, ((PyObject *)__pyx_t_11));
+        __Pyx_GIVEREF(((PyObject *)__pyx_t_11));
+        __pyx_t_11 = 0;
+        __pyx_t_11 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_11);
+        __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+        __Pyx_Raise(__pyx_t_11, 0, 0, 0);
+        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+        {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        goto __pyx_L7;
       }
-      __pyx_L15:;
+      __pyx_L7:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":124
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":114
  *                 if i >= I or j >= J:
  *                     raise Exception("%d-%d out of bounds (I=%d,J=%d) in line %d\n" % (i,j,I,J,sent_id+1))
  *                 f_i = fsent[i]             # <<<<<<<<<<<<<<
@@ -13796,7 +13960,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       __pyx_v_f_i = (__pyx_v_fsent[__pyx_v_i]);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":125
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":115
  *                     raise Exception("%d-%d out of bounds (I=%d,J=%d) in line %d\n" % (i,j,I,J,sent_id+1))
  *                 f_i = fsent[i]
  *                 e_j = esent[j]             # <<<<<<<<<<<<<<
@@ -13805,7 +13969,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       __pyx_v_e_j = (__pyx_v_esent[__pyx_v_j]);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":126
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":116
  *                 f_i = fsent[i]
  *                 e_j = esent[j]
  *                 fmargin[f_i] = fmargin[f_i]+1             # <<<<<<<<<<<<<<
@@ -13814,7 +13978,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       (__pyx_v_fmargin[__pyx_v_f_i]) = ((__pyx_v_fmargin[__pyx_v_f_i]) + 1);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":127
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":117
  *                 e_j = esent[j]
  *                 fmargin[f_i] = fmargin[f_i]+1
  *                 emargin[e_j] = emargin[e_j]+1             # <<<<<<<<<<<<<<
@@ -13823,7 +13987,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       (__pyx_v_emargin[__pyx_v_e_j]) = ((__pyx_v_emargin[__pyx_v_e_j]) + 1);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":128
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":118
  *                 fmargin[f_i] = fmargin[f_i]+1
  *                 emargin[e_j] = emargin[e_j]+1
  *                 if dict[f_i] == NULL:             # <<<<<<<<<<<<<<
@@ -13833,7 +13997,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
       __pyx_t_10 = ((__pyx_v_dict[__pyx_v_f_i]) == NULL);
       if (__pyx_t_10) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":129
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":119
  *                 emargin[e_j] = emargin[e_j]+1
  *                 if dict[f_i] == NULL:
  *                     dict[f_i] = new_node(e_j)             # <<<<<<<<<<<<<<
@@ -13842,7 +14006,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
         (__pyx_v_dict[__pyx_v_f_i]) = __pyx_f_3_sa_new_node(__pyx_v_e_j);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":130
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":120
  *                 if dict[f_i] == NULL:
  *                     dict[f_i] = new_node(e_j)
  *                     dict[f_i].val = 1             # <<<<<<<<<<<<<<
@@ -13851,7 +14015,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
         (__pyx_v_dict[__pyx_v_f_i])->val = 1;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":131
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":121
  *                     dict[f_i] = new_node(e_j)
  *                     dict[f_i].val = 1
  *                     num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
@@ -13859,11 +14023,11 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  *                     count = get_val(dict[f_i], e_j)
  */
         __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-        goto __pyx_L16;
+        goto __pyx_L8;
       }
       /*else*/ {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":133
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":123
  *                     num_pairs = num_pairs + 1
  *                 else:
  *                     count = get_val(dict[f_i], e_j)             # <<<<<<<<<<<<<<
@@ -13872,7 +14036,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
         __pyx_v_count = __pyx_f_3_sa_get_val((__pyx_v_dict[__pyx_v_f_i]), __pyx_v_e_j);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":134
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":124
  *                 else:
  *                     count = get_val(dict[f_i], e_j)
  *                     if count[0] == 0:             # <<<<<<<<<<<<<<
@@ -13882,7 +14046,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
         __pyx_t_10 = ((__pyx_v_count[0]) == 0);
         if (__pyx_t_10) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":135
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":125
  *                     count = get_val(dict[f_i], e_j)
  *                     if count[0] == 0:
  *                         num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
@@ -13890,11 +14054,11 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  *                 # add count
  */
           __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-          goto __pyx_L17;
+          goto __pyx_L9;
         }
-        __pyx_L17:;
+        __pyx_L9:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":136
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":126
  *                     if count[0] == 0:
  *                         num_pairs = num_pairs + 1
  *                     count[0] = count[0] + 1             # <<<<<<<<<<<<<<
@@ -13903,9 +14067,9 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
         (__pyx_v_count[0]) = ((__pyx_v_count[0]) + 1);
       }
-      __pyx_L16:;
+      __pyx_L8:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":138
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":128
  *                     count[0] = count[0] + 1
  *                 # add count
  *                 faligned[i] = 1             # <<<<<<<<<<<<<<
@@ -13914,7 +14078,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
       (__pyx_v_faligned[__pyx_v_i]) = 1;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":139
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":129
  *                 # add count
  *                 faligned[i] = 1
  *                 ealigned[j] = 1             # <<<<<<<<<<<<<<
@@ -13924,17 +14088,17 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
       (__pyx_v_ealigned[__pyx_v_j]) = 1;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":140
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":130
  *                 faligned[i] = 1
  *                 ealigned[j] = 1
  *             for i from 0 <= i < I:             # <<<<<<<<<<<<<<
  *                 if faligned[i] == 0:
  *                     f_i = fsent[i]
  */
-    __pyx_t_7 = __pyx_v_I;
-    for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_7; __pyx_v_i++) {
+    __pyx_t_8 = __pyx_v_I;
+    for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_8; __pyx_v_i++) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":141
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":131
  *                 ealigned[j] = 1
  *             for i from 0 <= i < I:
  *                 if faligned[i] == 0:             # <<<<<<<<<<<<<<
@@ -13944,85 +14108,85 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
       __pyx_t_10 = ((__pyx_v_faligned[__pyx_v_i]) == 0);
       if (__pyx_t_10) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":142
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":132
  *             for i from 0 <= i < I:
  *                 if faligned[i] == 0:
  *                     f_i = fsent[i]             # <<<<<<<<<<<<<<
  *                     fmargin[f_i] = fmargin[f_i] + 1
- *                     emargin[null_word] = emargin[null_word] + 1
+ *                     emargin[NULL_WORD] = emargin[NULL_WORD] + 1
  */
         __pyx_v_f_i = (__pyx_v_fsent[__pyx_v_i]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":143
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":133
  *                 if faligned[i] == 0:
  *                     f_i = fsent[i]
  *                     fmargin[f_i] = fmargin[f_i] + 1             # <<<<<<<<<<<<<<
- *                     emargin[null_word] = emargin[null_word] + 1
+ *                     emargin[NULL_WORD] = emargin[NULL_WORD] + 1
  *                     if dict[f_i] == NULL:
  */
         (__pyx_v_fmargin[__pyx_v_f_i]) = ((__pyx_v_fmargin[__pyx_v_f_i]) + 1);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":144
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":134
  *                     f_i = fsent[i]
  *                     fmargin[f_i] = fmargin[f_i] + 1
- *                     emargin[null_word] = emargin[null_word] + 1             # <<<<<<<<<<<<<<
+ *                     emargin[NULL_WORD] = emargin[NULL_WORD] + 1             # <<<<<<<<<<<<<<
  *                     if dict[f_i] == NULL:
- *                         dict[f_i] = new_node(null_word)
+ *                         dict[f_i] = new_node(NULL_WORD)
  */
-        (__pyx_v_emargin[__pyx_v_null_word]) = ((__pyx_v_emargin[__pyx_v_null_word]) + 1);
+        (__pyx_v_emargin[__pyx_v_3_sa_NULL_WORD]) = ((__pyx_v_emargin[__pyx_v_3_sa_NULL_WORD]) + 1);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":145
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":135
  *                     fmargin[f_i] = fmargin[f_i] + 1
- *                     emargin[null_word] = emargin[null_word] + 1
+ *                     emargin[NULL_WORD] = emargin[NULL_WORD] + 1
  *                     if dict[f_i] == NULL:             # <<<<<<<<<<<<<<
- *                         dict[f_i] = new_node(null_word)
+ *                         dict[f_i] = new_node(NULL_WORD)
  *                         dict[f_i].val = 1
  */
         __pyx_t_10 = ((__pyx_v_dict[__pyx_v_f_i]) == NULL);
         if (__pyx_t_10) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":146
- *                     emargin[null_word] = emargin[null_word] + 1
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":136
+ *                     emargin[NULL_WORD] = emargin[NULL_WORD] + 1
  *                     if dict[f_i] == NULL:
- *                         dict[f_i] = new_node(null_word)             # <<<<<<<<<<<<<<
+ *                         dict[f_i] = new_node(NULL_WORD)             # <<<<<<<<<<<<<<
  *                         dict[f_i].val = 1
  *                         num_pairs = num_pairs + 1
  */
-          (__pyx_v_dict[__pyx_v_f_i]) = __pyx_f_3_sa_new_node(__pyx_v_null_word);
+          (__pyx_v_dict[__pyx_v_f_i]) = __pyx_f_3_sa_new_node(__pyx_v_3_sa_NULL_WORD);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":147
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":137
  *                     if dict[f_i] == NULL:
- *                         dict[f_i] = new_node(null_word)
+ *                         dict[f_i] = new_node(NULL_WORD)
  *                         dict[f_i].val = 1             # <<<<<<<<<<<<<<
  *                         num_pairs = num_pairs + 1
  *                     else:
  */
           (__pyx_v_dict[__pyx_v_f_i])->val = 1;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":148
- *                         dict[f_i] = new_node(null_word)
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":138
+ *                         dict[f_i] = new_node(NULL_WORD)
  *                         dict[f_i].val = 1
  *                         num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
  *                     else:
- *                         count = get_val(dict[f_i], null_word)
+ *                         count = get_val(dict[f_i], NULL_WORD)
  */
           __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-          goto __pyx_L21;
+          goto __pyx_L13;
         }
         /*else*/ {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":150
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":140
  *                         num_pairs = num_pairs + 1
  *                     else:
- *                         count = get_val(dict[f_i], null_word)             # <<<<<<<<<<<<<<
+ *                         count = get_val(dict[f_i], NULL_WORD)             # <<<<<<<<<<<<<<
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1
  */
-          __pyx_v_count = __pyx_f_3_sa_get_val((__pyx_v_dict[__pyx_v_f_i]), __pyx_v_null_word);
+          __pyx_v_count = __pyx_f_3_sa_get_val((__pyx_v_dict[__pyx_v_f_i]), __pyx_v_3_sa_NULL_WORD);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":151
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":141
  *                     else:
- *                         count = get_val(dict[f_i], null_word)
+ *                         count = get_val(dict[f_i], NULL_WORD)
  *                         if count[0] == 0:             # <<<<<<<<<<<<<<
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1
@@ -14030,19 +14194,19 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
           __pyx_t_10 = ((__pyx_v_count[0]) == 0);
           if (__pyx_t_10) {
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":152
- *                         count = get_val(dict[f_i], null_word)
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":142
+ *                         count = get_val(dict[f_i], NULL_WORD)
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
  *                         count[0] = count[0] + 1
  *             for j from 0 <= j < J:
  */
             __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-            goto __pyx_L22;
+            goto __pyx_L14;
           }
-          __pyx_L22:;
+          __pyx_L14:;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":153
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":143
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1             # <<<<<<<<<<<<<<
@@ -14051,111 +14215,111 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
           (__pyx_v_count[0]) = ((__pyx_v_count[0]) + 1);
         }
-        __pyx_L21:;
-        goto __pyx_L20;
+        __pyx_L13:;
+        goto __pyx_L12;
       }
-      __pyx_L20:;
+      __pyx_L12:;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":154
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":144
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1
  *             for j from 0 <= j < J:             # <<<<<<<<<<<<<<
  *                 if ealigned[j] == 0:
  *                     e_j = esent[j]
  */
-    __pyx_t_7 = __pyx_v_J;
-    for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_7; __pyx_v_j++) {
+    __pyx_t_8 = __pyx_v_J;
+    for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_8; __pyx_v_j++) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":155
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":145
  *                         count[0] = count[0] + 1
  *             for j from 0 <= j < J:
  *                 if ealigned[j] == 0:             # <<<<<<<<<<<<<<
  *                     e_j = esent[j]
- *                     fmargin[null_word] = fmargin[null_word] + 1
+ *                     fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1
  */
       __pyx_t_10 = ((__pyx_v_ealigned[__pyx_v_j]) == 0);
       if (__pyx_t_10) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":156
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":146
  *             for j from 0 <= j < J:
  *                 if ealigned[j] == 0:
  *                     e_j = esent[j]             # <<<<<<<<<<<<<<
- *                     fmargin[null_word] = fmargin[null_word] + 1
+ *                     fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1
  *                     emargin[e_j] = emargin[e_j] + 1
  */
         __pyx_v_e_j = (__pyx_v_esent[__pyx_v_j]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":157
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":147
  *                 if ealigned[j] == 0:
  *                     e_j = esent[j]
- *                     fmargin[null_word] = fmargin[null_word] + 1             # <<<<<<<<<<<<<<
+ *                     fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1             # <<<<<<<<<<<<<<
  *                     emargin[e_j] = emargin[e_j] + 1
- *                     if dict[null_word] == NULL:
+ *                     if dict[NULL_WORD] == NULL:
  */
-        (__pyx_v_fmargin[__pyx_v_null_word]) = ((__pyx_v_fmargin[__pyx_v_null_word]) + 1);
+        (__pyx_v_fmargin[__pyx_v_3_sa_NULL_WORD]) = ((__pyx_v_fmargin[__pyx_v_3_sa_NULL_WORD]) + 1);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":158
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":148
  *                     e_j = esent[j]
- *                     fmargin[null_word] = fmargin[null_word] + 1
+ *                     fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1
  *                     emargin[e_j] = emargin[e_j] + 1             # <<<<<<<<<<<<<<
- *                     if dict[null_word] == NULL:
- *                         dict[null_word] = new_node(e_j)
+ *                     if dict[NULL_WORD] == NULL:
+ *                         dict[NULL_WORD] = new_node(e_j)
  */
         (__pyx_v_emargin[__pyx_v_e_j]) = ((__pyx_v_emargin[__pyx_v_e_j]) + 1);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":159
- *                     fmargin[null_word] = fmargin[null_word] + 1
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":149
+ *                     fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1
  *                     emargin[e_j] = emargin[e_j] + 1
- *                     if dict[null_word] == NULL:             # <<<<<<<<<<<<<<
- *                         dict[null_word] = new_node(e_j)
- *                         dict[null_word].val = 1
+ *                     if dict[NULL_WORD] == NULL:             # <<<<<<<<<<<<<<
+ *                         dict[NULL_WORD] = new_node(e_j)
+ *                         dict[NULL_WORD].val = 1
  */
-        __pyx_t_10 = ((__pyx_v_dict[__pyx_v_null_word]) == NULL);
+        __pyx_t_10 = ((__pyx_v_dict[__pyx_v_3_sa_NULL_WORD]) == NULL);
         if (__pyx_t_10) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":160
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":150
  *                     emargin[e_j] = emargin[e_j] + 1
- *                     if dict[null_word] == NULL:
- *                         dict[null_word] = new_node(e_j)             # <<<<<<<<<<<<<<
- *                         dict[null_word].val = 1
+ *                     if dict[NULL_WORD] == NULL:
+ *                         dict[NULL_WORD] = new_node(e_j)             # <<<<<<<<<<<<<<
+ *                         dict[NULL_WORD].val = 1
  *                         num_pairs = num_pairs + 1
  */
-          (__pyx_v_dict[__pyx_v_null_word]) = __pyx_f_3_sa_new_node(__pyx_v_e_j);
+          (__pyx_v_dict[__pyx_v_3_sa_NULL_WORD]) = __pyx_f_3_sa_new_node(__pyx_v_e_j);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":161
- *                     if dict[null_word] == NULL:
- *                         dict[null_word] = new_node(e_j)
- *                         dict[null_word].val = 1             # <<<<<<<<<<<<<<
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":151
+ *                     if dict[NULL_WORD] == NULL:
+ *                         dict[NULL_WORD] = new_node(e_j)
+ *                         dict[NULL_WORD].val = 1             # <<<<<<<<<<<<<<
  *                         num_pairs = num_pairs + 1
  *                     else:
  */
-          (__pyx_v_dict[__pyx_v_null_word])->val = 1;
+          (__pyx_v_dict[__pyx_v_3_sa_NULL_WORD])->val = 1;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":162
- *                         dict[null_word] = new_node(e_j)
- *                         dict[null_word].val = 1
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":152
+ *                         dict[NULL_WORD] = new_node(e_j)
+ *                         dict[NULL_WORD].val = 1
  *                         num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
  *                     else:
- *                         count = get_val(dict[null_word], e_j)
+ *                         count = get_val(dict[NULL_WORD], e_j)
  */
           __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-          goto __pyx_L26;
+          goto __pyx_L18;
         }
         /*else*/ {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":164
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":154
  *                         num_pairs = num_pairs + 1
  *                     else:
- *                         count = get_val(dict[null_word], e_j)             # <<<<<<<<<<<<<<
+ *                         count = get_val(dict[NULL_WORD], e_j)             # <<<<<<<<<<<<<<
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1
  */
-          __pyx_v_count = __pyx_f_3_sa_get_val((__pyx_v_dict[__pyx_v_null_word]), __pyx_v_e_j);
+          __pyx_v_count = __pyx_f_3_sa_get_val((__pyx_v_dict[__pyx_v_3_sa_NULL_WORD]), __pyx_v_e_j);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":165
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":155
  *                     else:
- *                         count = get_val(dict[null_word], e_j)
+ *                         count = get_val(dict[NULL_WORD], e_j)
  *                         if count[0] == 0:             # <<<<<<<<<<<<<<
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1
@@ -14163,19 +14327,19 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
           __pyx_t_10 = ((__pyx_v_count[0]) == 0);
           if (__pyx_t_10) {
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":166
- *                         count = get_val(dict[null_word], e_j)
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":156
+ *                         count = get_val(dict[NULL_WORD], e_j)
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1             # <<<<<<<<<<<<<<
  *                         count[0] = count[0] + 1
  *             free(links)
  */
             __pyx_v_num_pairs = (__pyx_v_num_pairs + 1);
-            goto __pyx_L27;
+            goto __pyx_L19;
           }
-          __pyx_L27:;
+          __pyx_L19:;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":167
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":157
  *                         if count[0] == 0:
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1             # <<<<<<<<<<<<<<
@@ -14184,13 +14348,13 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
           (__pyx_v_count[0]) = ((__pyx_v_count[0]) + 1);
         }
-        __pyx_L26:;
-        goto __pyx_L25;
+        __pyx_L18:;
+        goto __pyx_L17;
       }
-      __pyx_L25:;
+      __pyx_L17:;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":168
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":158
  *                             num_pairs = num_pairs + 1
  *                         count[0] = count[0] + 1
  *             free(links)             # <<<<<<<<<<<<<<
@@ -14199,7 +14363,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     free(__pyx_v_links);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":169
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":159
  *                         count[0] = count[0] + 1
  *             free(links)
  *             free(faligned)             # <<<<<<<<<<<<<<
@@ -14208,7 +14372,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     free(__pyx_v_faligned);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":170
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":160
  *             free(links)
  *             free(faligned)
  *             free(ealigned)             # <<<<<<<<<<<<<<
@@ -14218,95 +14382,95 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
     free(__pyx_v_ealigned);
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":171
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":161
  *             free(faligned)
  *             free(ealigned)
  *         self.f_index = IntList(initial_len=V_F)             # <<<<<<<<<<<<<<
  *         self.e_index = IntList(initial_len=num_pairs)
  *         self.col1 = FloatList(initial_len=num_pairs)
  */
-  __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_12));
-  __pyx_t_13 = PyInt_FromLong(__pyx_v_V_F); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_13);
-  if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_13) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-  __pyx_t_13 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
-  __Pyx_GIVEREF(__pyx_t_13);
+  __pyx_t_11 = PyDict_New(); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_11));
+  __pyx_t_12 = PyInt_FromLong(__pyx_v_V_F); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_12);
+  if (PyDict_SetItem(__pyx_t_11, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+  __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_11)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 161; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_12);
+  __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
+  __Pyx_GIVEREF(__pyx_t_12);
   __Pyx_GOTREF(__pyx_v_self->f_index);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->f_index));
-  __pyx_v_self->f_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_13);
-  __pyx_t_13 = 0;
+  __pyx_v_self->f_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_12);
+  __pyx_t_12 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":172
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":162
  *             free(ealigned)
  *         self.f_index = IntList(initial_len=V_F)
  *         self.e_index = IntList(initial_len=num_pairs)             # <<<<<<<<<<<<<<
  *         self.col1 = FloatList(initial_len=num_pairs)
  *         self.col2 = FloatList(initial_len=num_pairs)
  */
-  __pyx_t_13 = PyDict_New(); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_13));
-  __pyx_t_12 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_12);
-  if (PyDict_SetItem(__pyx_t_13, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-  __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_13)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_12);
-  __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
-  __Pyx_GIVEREF(__pyx_t_12);
+  __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_12));
+  __pyx_t_11 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_11);
+  if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_11) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+  __pyx_t_11 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_11);
+  __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+  __Pyx_GIVEREF(__pyx_t_11);
   __Pyx_GOTREF(__pyx_v_self->e_index);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->e_index));
-  __pyx_v_self->e_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_12);
-  __pyx_t_12 = 0;
+  __pyx_v_self->e_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_11);
+  __pyx_t_11 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":173
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":163
  *         self.f_index = IntList(initial_len=V_F)
  *         self.e_index = IntList(initial_len=num_pairs)
  *         self.col1 = FloatList(initial_len=num_pairs)             # <<<<<<<<<<<<<<
  *         self.col2 = FloatList(initial_len=num_pairs)
  * 
  */
-  __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_12));
-  __pyx_t_13 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_13);
-  if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_13) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-  __pyx_t_13 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
-  __Pyx_GIVEREF(__pyx_t_13);
+  __pyx_t_11 = PyDict_New(); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_11));
+  __pyx_t_12 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_12);
+  if (PyDict_SetItem(__pyx_t_11, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+  __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_11)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 163; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_12);
+  __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
+  __Pyx_GIVEREF(__pyx_t_12);
   __Pyx_GOTREF(__pyx_v_self->col1);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->col1));
-  __pyx_v_self->col1 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_13);
-  __pyx_t_13 = 0;
+  __pyx_v_self->col1 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_12);
+  __pyx_t_12 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":174
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":164
  *         self.e_index = IntList(initial_len=num_pairs)
  *         self.col1 = FloatList(initial_len=num_pairs)
  *         self.col2 = FloatList(initial_len=num_pairs)             # <<<<<<<<<<<<<<
  * 
  *         num_pairs = 0
  */
-  __pyx_t_13 = PyDict_New(); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_13));
-  __pyx_t_12 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_12);
-  if (PyDict_SetItem(__pyx_t_13, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-  __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_13)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 174; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_12);
-  __Pyx_DECREF(((PyObject *)__pyx_t_13)); __pyx_t_13 = 0;
-  __Pyx_GIVEREF(__pyx_t_12);
+  __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_12));
+  __pyx_t_11 = PyInt_FromLong(__pyx_v_num_pairs); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_11);
+  if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_11) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+  __pyx_t_11 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 164; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_11);
+  __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+  __Pyx_GIVEREF(__pyx_t_11);
   __Pyx_GOTREF(__pyx_v_self->col2);
   __Pyx_DECREF(((PyObject *)__pyx_v_self->col2));
-  __pyx_v_self->col2 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_12);
-  __pyx_t_12 = 0;
+  __pyx_v_self->col2 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_11);
+  __pyx_t_11 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":176
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":166
  *         self.col2 = FloatList(initial_len=num_pairs)
  * 
  *         num_pairs = 0             # <<<<<<<<<<<<<<
@@ -14315,17 +14479,17 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   __pyx_v_num_pairs = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":177
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":167
  * 
  *         num_pairs = 0
  *         for i from 0 <= i < V_F:             # <<<<<<<<<<<<<<
  *             #self.f_index[i] = num_pairs
  *             self.f_index.set(i, num_pairs)
  */
-  __pyx_t_6 = __pyx_v_V_F;
-  for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_6; __pyx_v_i++) {
+  __pyx_t_7 = __pyx_v_V_F;
+  for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_7; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":179
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":169
  *         for i from 0 <= i < V_F:
  *             #self.f_index[i] = num_pairs
  *             self.f_index.set(i, num_pairs)             # <<<<<<<<<<<<<<
@@ -14334,7 +14498,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
     ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->f_index->__pyx_vtab)->set(__pyx_v_self->f_index, __pyx_v_i, __pyx_v_num_pairs);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":180
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":170
  *             #self.f_index[i] = num_pairs
  *             self.f_index.set(i, num_pairs)
  *             if dict[i] != NULL:             # <<<<<<<<<<<<<<
@@ -14344,33 +14508,33 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
     __pyx_t_10 = ((__pyx_v_dict[__pyx_v_i]) != NULL);
     if (__pyx_t_10) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":181
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":171
  *             self.f_index.set(i, num_pairs)
  *             if dict[i] != NULL:
  *                 self._add_node(dict[i], &num_pairs, float(fmargin[i]), emargin)             # <<<<<<<<<<<<<<
  *                 del_node(dict[i])
  *         free(fmargin)
  */
-      __pyx_t_12 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, (__pyx_v_dict[__pyx_v_i]), (&__pyx_v_num_pairs), ((double)(__pyx_v_fmargin[__pyx_v_i])), __pyx_v_emargin); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 181; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_12);
-      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+      __pyx_t_11 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, (__pyx_v_dict[__pyx_v_i]), (&__pyx_v_num_pairs), ((double)(__pyx_v_fmargin[__pyx_v_i])), __pyx_v_emargin); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 171; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_11);
+      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":182
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":172
  *             if dict[i] != NULL:
  *                 self._add_node(dict[i], &num_pairs, float(fmargin[i]), emargin)
  *                 del_node(dict[i])             # <<<<<<<<<<<<<<
  *         free(fmargin)
  *         free(emargin)
  */
-      __pyx_t_12 = __pyx_f_3_sa_del_node((__pyx_v_dict[__pyx_v_i])); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_12);
-      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-      goto __pyx_L30;
+      __pyx_t_11 = __pyx_f_3_sa_del_node((__pyx_v_dict[__pyx_v_i])); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_11);
+      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+      goto __pyx_L22;
     }
-    __pyx_L30:;
+    __pyx_L22:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":183
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":173
  *                 self._add_node(dict[i], &num_pairs, float(fmargin[i]), emargin)
  *                 del_node(dict[i])
  *         free(fmargin)             # <<<<<<<<<<<<<<
@@ -14379,7 +14543,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   free(__pyx_v_fmargin);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":184
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":174
  *                 del_node(dict[i])
  *         free(fmargin)
  *         free(emargin)             # <<<<<<<<<<<<<<
@@ -14388,7 +14552,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   free(__pyx_v_emargin);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":185
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":175
  *         free(fmargin)
  *         free(emargin)
  *         free(dict)             # <<<<<<<<<<<<<<
@@ -14397,7 +14561,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
  */
   free(__pyx_v_dict);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":186
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":176
  *         free(emargin)
  *         free(dict)
  *         return             # <<<<<<<<<<<<<<
@@ -14412,23 +14576,21 @@ static PyObject *__pyx_f_3_sa_5BiLex_compute_from_data(struct __pyx_obj_3_sa_BiL
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_11);
   __Pyx_XDECREF(__pyx_t_12);
-  __Pyx_XDECREF(__pyx_t_13);
   __Pyx_AddTraceback("_sa.BiLex.compute_from_data", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_word);
-  __Pyx_XDECREF(__pyx_v_id);
   __Pyx_XDECREF(__pyx_v_num_sents);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":189
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":179
  * 
  * 
  *     cdef _add_node(self, _node* n, int* num_pairs, float fmargin, int* emargin):             # <<<<<<<<<<<<<<
@@ -14447,7 +14609,7 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("_add_node", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":191
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":181
  *     cdef _add_node(self, _node* n, int* num_pairs, float fmargin, int* emargin):
  *         cdef int loc
  *         if n.smaller != NULL:             # <<<<<<<<<<<<<<
@@ -14457,21 +14619,21 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
   __pyx_t_1 = (__pyx_v_n->smaller != NULL);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":192
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":182
  *         cdef int loc
  *         if n.smaller != NULL:
  *             self._add_node(n.smaller, num_pairs, fmargin, emargin)             # <<<<<<<<<<<<<<
  *         loc = num_pairs[0]
  *         self.e_index.set(loc, n.key)
  */
-    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, __pyx_v_n->smaller, __pyx_v_num_pairs, __pyx_v_fmargin, __pyx_v_emargin); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, __pyx_v_n->smaller, __pyx_v_num_pairs, __pyx_v_fmargin, __pyx_v_emargin); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 182; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     goto __pyx_L3;
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":193
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":183
  *         if n.smaller != NULL:
  *             self._add_node(n.smaller, num_pairs, fmargin, emargin)
  *         loc = num_pairs[0]             # <<<<<<<<<<<<<<
@@ -14480,7 +14642,7 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
  */
   __pyx_v_loc = (__pyx_v_num_pairs[0]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":194
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":184
  *             self._add_node(n.smaller, num_pairs, fmargin, emargin)
  *         loc = num_pairs[0]
  *         self.e_index.set(loc, n.key)             # <<<<<<<<<<<<<<
@@ -14489,7 +14651,7 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->e_index->__pyx_vtab)->set(__pyx_v_self->e_index, __pyx_v_loc, __pyx_v_n->key);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":195
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":185
  *         loc = num_pairs[0]
  *         self.e_index.set(loc, n.key)
  *         self.col1.set(loc, float(n.val)/fmargin)             # <<<<<<<<<<<<<<
@@ -14498,11 +14660,11 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
  */
   if (unlikely(__pyx_v_fmargin == 0)) {
     PyErr_Format(PyExc_ZeroDivisionError, "float division");
-    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 185; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col1->__pyx_vtab)->set(__pyx_v_self->col1, __pyx_v_loc, (((double)__pyx_v_n->val) / __pyx_v_fmargin));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":196
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":186
  *         self.e_index.set(loc, n.key)
  *         self.col1.set(loc, float(n.val)/fmargin)
  *         self.col2.set(loc, float(n.val)/float(emargin[n.key]))             # <<<<<<<<<<<<<<
@@ -14511,11 +14673,11 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
  */
   if (unlikely(((double)(__pyx_v_emargin[__pyx_v_n->key])) == 0)) {
     PyErr_Format(PyExc_ZeroDivisionError, "float division");
-    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 186; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col2->__pyx_vtab)->set(__pyx_v_self->col2, __pyx_v_loc, (((double)__pyx_v_n->val) / ((double)(__pyx_v_emargin[__pyx_v_n->key]))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":197
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":187
  *         self.col1.set(loc, float(n.val)/fmargin)
  *         self.col2.set(loc, float(n.val)/float(emargin[n.key]))
  *         num_pairs[0] = loc + 1             # <<<<<<<<<<<<<<
@@ -14524,7 +14686,7 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
  */
   (__pyx_v_num_pairs[0]) = (__pyx_v_loc + 1);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":198
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":188
  *         self.col2.set(loc, float(n.val)/float(emargin[n.key]))
  *         num_pairs[0] = loc + 1
  *         if n.bigger != NULL:             # <<<<<<<<<<<<<<
@@ -14534,14 +14696,14 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
   __pyx_t_1 = (__pyx_v_n->bigger != NULL);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":199
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":189
  *         num_pairs[0] = loc + 1
  *         if n.bigger != NULL:
  *             self._add_node(n.bigger, num_pairs, fmargin, emargin)             # <<<<<<<<<<<<<<
  * 
  * 
  */
-    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, __pyx_v_n->bigger, __pyx_v_num_pairs, __pyx_v_fmargin, __pyx_v_emargin); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->_add_node(__pyx_v_self, __pyx_v_n->bigger, __pyx_v_num_pairs, __pyx_v_fmargin, __pyx_v_emargin); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     goto __pyx_L4;
@@ -14561,55 +14723,50 @@ static PyObject *__pyx_f_3_sa_5BiLex__add_node(struct __pyx_obj_3_sa_BiLex *__py
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_3write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_3write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_5BiLex_3write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_3write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.BiLex.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_2write_binary(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_2write_binary(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":202
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":192
  * 
  * 
- *     def write_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
+  const char *__pyx_t_1;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":204
- *     def write_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":194
+ *     def write_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
  *         self.f_index.write_handle(f)
  *         self.e_index.write_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__w);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":205
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":195
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  *         self.f_index.write_handle(f)             # <<<<<<<<<<<<<<
@@ -14618,7 +14775,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->f_index->__pyx_vtab)->write_handle(__pyx_v_self->f_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":206
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":196
  *         f = fopen(filename, "w")
  *         self.f_index.write_handle(f)
  *         self.e_index.write_handle(f)             # <<<<<<<<<<<<<<
@@ -14627,66 +14784,54 @@ static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->e_index->__pyx_vtab)->write_handle(__pyx_v_self->e_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":207
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":197
  *         self.f_index.write_handle(f)
  *         self.e_index.write_handle(f)
  *         self.col1.write_handle(f)             # <<<<<<<<<<<<<<
  *         self.col2.write_handle(f)
- *         self.write_wordlist(self.id2fword, f)
+ *         self.f_voc.write_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col1->__pyx_vtab)->write_handle(__pyx_v_self->col1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":208
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":198
  *         self.e_index.write_handle(f)
  *         self.col1.write_handle(f)
  *         self.col2.write_handle(f)             # <<<<<<<<<<<<<<
- *         self.write_wordlist(self.id2fword, f)
- *         self.write_wordlist(self.id2eword, f)
+ *         self.f_voc.write_handle(f)
+ *         self.e_voc.write_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col2->__pyx_vtab)->write_handle(__pyx_v_self->col2, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":209
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":199
  *         self.col1.write_handle(f)
  *         self.col2.write_handle(f)
- *         self.write_wordlist(self.id2fword, f)             # <<<<<<<<<<<<<<
- *         self.write_wordlist(self.id2eword, f)
+ *         self.f_voc.write_handle(f)             # <<<<<<<<<<<<<<
+ *         self.e_voc.write_handle(f)
  *         fclose(f)
  */
-  __pyx_t_1 = __pyx_v_self->id2fword;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->write_wordlist(__pyx_v_self, __pyx_t_1, __pyx_v_f); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->f_voc->__pyx_vtab)->write_handle(__pyx_v_self->f_voc, __pyx_v_f, NULL);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":210
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":200
  *         self.col2.write_handle(f)
- *         self.write_wordlist(self.id2fword, f)
- *         self.write_wordlist(self.id2eword, f)             # <<<<<<<<<<<<<<
+ *         self.f_voc.write_handle(f)
+ *         self.e_voc.write_handle(f)             # <<<<<<<<<<<<<<
  *         fclose(f)
  * 
  */
-  __pyx_t_2 = __pyx_v_self->id2eword;
-  __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->write_wordlist(__pyx_v_self, __pyx_t_2, __pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->e_voc->__pyx_vtab)->write_handle(__pyx_v_self->e_voc, __pyx_v_f, NULL);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":211
- *         self.write_wordlist(self.id2fword, f)
- *         self.write_wordlist(self.id2eword, f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":201
+ *         self.f_voc.write_handle(f)
+ *         self.e_voc.write_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def read_binary(self, bytes filename):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_AddTraceback("_sa.BiLex.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -14695,314 +14840,51 @@ static PyObject *__pyx_pf_3_sa_5BiLex_2write_binary(struct __pyx_obj_3_sa_BiLex
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":214
- * 
- * 
- *     cdef write_wordlist(self, wordlist, FILE* f):             # <<<<<<<<<<<<<<
- *         cdef int word_len
- *         cdef int num_words
- */
-
-static PyObject *__pyx_f_3_sa_5BiLex_write_wordlist(CYTHON_UNUSED struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_wordlist, FILE *__pyx_v_f) {
-  int __pyx_v_word_len;
-  int __pyx_v_num_words;
-  PyObject *__pyx_v_word = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  Py_ssize_t __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *(*__pyx_t_3)(PyObject *);
-  PyObject *__pyx_t_4 = NULL;
-  Py_ssize_t __pyx_t_5;
-  char *__pyx_t_6;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("write_wordlist", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":218
- *         cdef int num_words
- * 
- *         num_words = len(wordlist)             # <<<<<<<<<<<<<<
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in wordlist:
- */
-  __pyx_t_1 = PyObject_Length(__pyx_v_wordlist); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 218; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_v_num_words = __pyx_t_1;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":219
- * 
- *         num_words = len(wordlist)
- *         fwrite(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *         for word in wordlist:
- *             word_len = len(word) + 1
- */
-  fwrite((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":220
- *         num_words = len(wordlist)
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in wordlist:             # <<<<<<<<<<<<<<
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)
- */
-  if (PyList_CheckExact(__pyx_v_wordlist) || PyTuple_CheckExact(__pyx_v_wordlist)) {
-    __pyx_t_2 = __pyx_v_wordlist; __Pyx_INCREF(__pyx_t_2); __pyx_t_1 = 0;
-    __pyx_t_3 = NULL;
-  } else {
-    __pyx_t_1 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_wordlist); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = Py_TYPE(__pyx_t_2)->tp_iternext;
-  }
-  for (;;) {
-    if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_2)) {
-      if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_2)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_1); __Pyx_INCREF(__pyx_t_4); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_2)) {
-      if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
-      #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_1); __Pyx_INCREF(__pyx_t_4); __pyx_t_1++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      #endif
-    } else {
-      __pyx_t_4 = __pyx_t_3(__pyx_t_2);
-      if (unlikely(!__pyx_t_4)) {
-        if (PyErr_Occurred()) {
-          if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_4);
-    }
-    __Pyx_XDECREF(__pyx_v_word);
-    __pyx_v_word = __pyx_t_4;
-    __pyx_t_4 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":221
- *         fwrite(&(num_words), sizeof(int), 1, f)
- *         for word in wordlist:
- *             word_len = len(word) + 1             # <<<<<<<<<<<<<<
- *             fwrite(&(word_len), sizeof(int), 1, f)
- *             fwrite(<char *>word, sizeof(char), word_len, f)
- */
-    __pyx_t_5 = PyObject_Length(__pyx_v_word); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_v_word_len = (__pyx_t_5 + 1);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":222
- *         for word in wordlist:
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *             fwrite(<char *>word, sizeof(char), word_len, f)
- * 
- */
-    fwrite((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":223
- *             word_len = len(word) + 1
- *             fwrite(&(word_len), sizeof(int), 1, f)
- *             fwrite(<char *>word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
- * 
- * 
- */
-    __pyx_t_6 = PyBytes_AsString(__pyx_v_word); if (unlikely((!__pyx_t_6) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    fwrite(((char *)__pyx_t_6), (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
-  }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("_sa.BiLex.write_wordlist", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_word);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":226
- * 
- * 
- *     cdef read_wordlist(self, word2id, id2word, FILE* f):             # <<<<<<<<<<<<<<
- *         cdef int num_words
- *         cdef int word_len
- */
-
-static PyObject *__pyx_f_3_sa_5BiLex_read_wordlist(CYTHON_UNUSED struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_word2id, PyObject *__pyx_v_id2word, FILE *__pyx_v_f) {
-  int __pyx_v_num_words;
-  int __pyx_v_word_len;
-  char *__pyx_v_word;
-  CYTHON_UNUSED long __pyx_v_i;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  Py_ssize_t __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("read_wordlist", 0);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":231
- *         cdef char* word
- * 
- *         fread(&(num_words), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *         for i from 0 <= i < num_words:
- *             fread(&(word_len), sizeof(int), 1, f)
- */
-  fread((&__pyx_v_num_words), (sizeof(int)), 1, __pyx_v_f);
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":232
- * 
- *         fread(&(num_words), sizeof(int), 1, f)
- *         for i from 0 <= i < num_words:             # <<<<<<<<<<<<<<
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))
- */
-  __pyx_t_1 = __pyx_v_num_words;
-  for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_1; __pyx_v_i++) {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":233
- *         fread(&(num_words), sizeof(int), 1, f)
- *         for i from 0 <= i < num_words:
- *             fread(&(word_len), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)
- */
-    fread((&__pyx_v_word_len), (sizeof(int)), 1, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":234
- *         for i from 0 <= i < num_words:
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))             # <<<<<<<<<<<<<<
- *             fread(word, sizeof(char), word_len, f)
- *             word2id[word] = len(id2word)
- */
-    __pyx_v_word = ((char *)malloc((__pyx_v_word_len * (sizeof(char)))));
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":235
- *             fread(&(word_len), sizeof(int), 1, f)
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)             # <<<<<<<<<<<<<<
- *             word2id[word] = len(id2word)
- *             id2word.append(word)
- */
-    fread(__pyx_v_word, (sizeof(char)), __pyx_v_word_len, __pyx_v_f);
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":236
- *             word = <char*> malloc (word_len * sizeof(char))
- *             fread(word, sizeof(char), word_len, f)
- *             word2id[word] = len(id2word)             # <<<<<<<<<<<<<<
- *             id2word.append(word)
- *             free(word)
- */
-    __pyx_t_2 = PyObject_Length(__pyx_v_id2word); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-    if (PyObject_SetItem(__pyx_v_word2id, ((PyObject *)__pyx_t_4), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":237
- *             fread(word, sizeof(char), word_len, f)
- *             word2id[word] = len(id2word)
- *             id2word.append(word)             # <<<<<<<<<<<<<<
- *             free(word)
- * 
- */
-    __pyx_t_3 = PyBytes_FromString(__pyx_v_word); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_id2word, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":238
- *             word2id[word] = len(id2word)
- *             id2word.append(word)
- *             free(word)             # <<<<<<<<<<<<<<
- * 
- *     def read_binary(self, char* filename):
- */
-    free(__pyx_v_word);
-  }
-
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("_sa.BiLex.read_wordlist", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_5read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_5read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_5BiLex_5read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_5read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.BiLex.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_4read_binary(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_4read_binary(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":240
- *             free(word)
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":203
+ *         fclose(f)
  * 
- *     def read_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
+  const char *__pyx_t_1;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":242
- *     def read_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":205
+ *     def read_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
  *         self.f_index.read_handle(f)
  *         self.e_index.read_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__r);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":243
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":206
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  *         self.f_index.read_handle(f)             # <<<<<<<<<<<<<<
@@ -15011,7 +14893,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->f_index->__pyx_vtab)->read_handle(__pyx_v_self->f_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":244
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":207
  *         f = fopen(filename, "r")
  *         self.f_index.read_handle(f)
  *         self.e_index.read_handle(f)             # <<<<<<<<<<<<<<
@@ -15020,73 +14902,54 @@ static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->e_index->__pyx_vtab)->read_handle(__pyx_v_self->e_index, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":245
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":208
  *         self.f_index.read_handle(f)
  *         self.e_index.read_handle(f)
  *         self.col1.read_handle(f)             # <<<<<<<<<<<<<<
  *         self.col2.read_handle(f)
- *         self.read_wordlist(self.fword2id, self.id2fword, f)
+ *         self.f_voc.read_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col1->__pyx_vtab)->read_handle(__pyx_v_self->col1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":246
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":209
  *         self.e_index.read_handle(f)
  *         self.col1.read_handle(f)
  *         self.col2.read_handle(f)             # <<<<<<<<<<<<<<
- *         self.read_wordlist(self.fword2id, self.id2fword, f)
- *         self.read_wordlist(self.eword2id, self.id2eword, f)
+ *         self.f_voc.read_handle(f)
+ *         self.e_voc.read_handle(f)
  */
   ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col2->__pyx_vtab)->read_handle(__pyx_v_self->col2, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":247
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":210
  *         self.col1.read_handle(f)
  *         self.col2.read_handle(f)
- *         self.read_wordlist(self.fword2id, self.id2fword, f)             # <<<<<<<<<<<<<<
- *         self.read_wordlist(self.eword2id, self.id2eword, f)
+ *         self.f_voc.read_handle(f)             # <<<<<<<<<<<<<<
+ *         self.e_voc.read_handle(f)
  *         fclose(f)
  */
-  __pyx_t_1 = __pyx_v_self->fword2id;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_v_self->id2fword;
-  __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_3 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->read_wordlist(__pyx_v_self, __pyx_t_1, __pyx_t_2, __pyx_v_f); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->f_voc->__pyx_vtab)->read_handle(__pyx_v_self->f_voc, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":248
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":211
  *         self.col2.read_handle(f)
- *         self.read_wordlist(self.fword2id, self.id2fword, f)
- *         self.read_wordlist(self.eword2id, self.id2eword, f)             # <<<<<<<<<<<<<<
+ *         self.f_voc.read_handle(f)
+ *         self.e_voc.read_handle(f)             # <<<<<<<<<<<<<<
  *         fclose(f)
  * 
  */
-  __pyx_t_3 = __pyx_v_self->eword2id;
-  __Pyx_INCREF(__pyx_t_3);
-  __pyx_t_2 = __pyx_v_self->id2eword;
-  __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->read_wordlist(__pyx_v_self, __pyx_t_3, __pyx_t_2, __pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->e_voc->__pyx_vtab)->read_handle(__pyx_v_self->e_voc, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":249
- *         self.read_wordlist(self.fword2id, self.id2fword, f)
- *         self.read_wordlist(self.eword2id, self.id2eword, f)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":212
+ *         self.f_voc.read_handle(f)
+ *         self.e_voc.read_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def read_mmaped(self, MemoryMap buf):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_AddTraceback("_sa.BiLex.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -15096,249 +14959,227 @@ static PyObject *__pyx_pf_3_sa_5BiLex_4read_binary(struct __pyx_obj_3_sa_BiLex *
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_7get_e_id(PyObject *__pyx_v_self, PyObject *__pyx_v_eword); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_7get_e_id(PyObject *__pyx_v_self, PyObject *__pyx_v_eword) {
+static PyObject *__pyx_pw_3_sa_5BiLex_7read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_7read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("get_e_id (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_5BiLex_6get_e_id(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject *)__pyx_v_eword));
+  __Pyx_RefNannySetupContext("read_mmaped (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_buf), __pyx_ptype_3_sa_MemoryMap, 1, "buf", 0))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 214; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_6read_mmaped(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_buf));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":252
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":214
+ *         fclose(f)
  * 
- *     def get_e_id(self, eword):             # <<<<<<<<<<<<<<
- *         if eword not in self.eword2id:
- *             e_id = len(self.id2eword)
+ *     def read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         self.f_index.read_mmaped(buf)
+ *         self.e_index.read_mmaped(buf)
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_6get_e_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_eword) {
-  PyObject *__pyx_v_e_id = NULL;
+static PyObject *__pyx_pf_3_sa_5BiLex_6read_mmaped(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  Py_ssize_t __pyx_t_3;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("get_e_id", 0);
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":253
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":215
  * 
- *     def get_e_id(self, eword):
- *         if eword not in self.eword2id:             # <<<<<<<<<<<<<<
- *             e_id = len(self.id2eword)
- *             self.id2eword.append(eword)
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.f_index.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.e_index.read_mmaped(buf)
+ *         self.col1.read_mmaped(buf)
  */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_eword, __pyx_v_self->eword2id, Py_NE)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_1) {
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->f_index->__pyx_vtab)->read_mmaped(__pyx_v_self->f_index, __pyx_v_buf);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":254
- *     def get_e_id(self, eword):
- *         if eword not in self.eword2id:
- *             e_id = len(self.id2eword)             # <<<<<<<<<<<<<<
- *             self.id2eword.append(eword)
- *             self.eword2id[eword] = e_id
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":216
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.f_index.read_mmaped(buf)
+ *         self.e_index.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.col1.read_mmaped(buf)
+ *         self.col2.read_mmaped(buf)
  */
-    __pyx_t_2 = __pyx_v_self->id2eword;
-    __Pyx_INCREF(__pyx_t_2);
-    __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_v_e_id = __pyx_t_2;
-    __pyx_t_2 = 0;
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->e_index->__pyx_vtab)->read_mmaped(__pyx_v_self->e_index, __pyx_v_buf);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":255
- *         if eword not in self.eword2id:
- *             e_id = len(self.id2eword)
- *             self.id2eword.append(eword)             # <<<<<<<<<<<<<<
- *             self.eword2id[eword] = e_id
- *         return self.eword2id[eword]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":217
+ *         self.f_index.read_mmaped(buf)
+ *         self.e_index.read_mmaped(buf)
+ *         self.col1.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.col2.read_mmaped(buf)
+ *         self.f_voc.read_mmaped(buf)
  */
-    __pyx_t_2 = __Pyx_PyObject_Append(__pyx_v_self->id2eword, __pyx_v_eword); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col1->__pyx_vtab)->read_mmaped(__pyx_v_self->col1, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":218
+ *         self.e_index.read_mmaped(buf)
+ *         self.col1.read_mmaped(buf)
+ *         self.col2.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.f_voc.read_mmaped(buf)
+ *         self.e_voc.read_mmaped(buf)
+ */
+  ((struct __pyx_vtabstruct_3_sa_FloatList *)__pyx_v_self->col2->__pyx_vtab)->read_mmaped(__pyx_v_self->col2, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":219
+ *         self.col1.read_mmaped(buf)
+ *         self.col2.read_mmaped(buf)
+ *         self.f_voc.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.e_voc.read_mmaped(buf)
+ * 
+ */
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->f_voc->__pyx_vtab)->read_mmaped(__pyx_v_self->f_voc, __pyx_v_buf);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":256
- *             e_id = len(self.id2eword)
- *             self.id2eword.append(eword)
- *             self.eword2id[eword] = e_id             # <<<<<<<<<<<<<<
- *         return self.eword2id[eword]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":220
+ *         self.col2.read_mmaped(buf)
+ *         self.f_voc.read_mmaped(buf)
+ *         self.e_voc.read_mmaped(buf)             # <<<<<<<<<<<<<<
  * 
+ *     def get_e_id(self, eword):
  */
-    if (PyObject_SetItem(__pyx_v_self->eword2id, __pyx_v_eword, __pyx_v_e_id) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
-  }
-  __pyx_L3:;
+  ((struct __pyx_vtabstruct_3_sa_Vocabulary *)__pyx_v_self->e_voc->__pyx_vtab)->read_mmaped(__pyx_v_self->e_voc, __pyx_v_buf);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":257
- *             self.id2eword.append(eword)
- *             self.eword2id[eword] = e_id
- *         return self.eword2id[eword]             # <<<<<<<<<<<<<<
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_5BiLex_9get_e_id(PyObject *__pyx_v_self, PyObject *__pyx_v_eword); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_9get_e_id(PyObject *__pyx_v_self, PyObject *__pyx_v_eword) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("get_e_id (wrapper)", 0);
+  __pyx_r = __pyx_pf_3_sa_5BiLex_8get_e_id(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject *)__pyx_v_eword));
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":222
+ *         self.e_voc.read_mmaped(buf)
+ * 
+ *     def get_e_id(self, eword):             # <<<<<<<<<<<<<<
+ *         return self.e_voc[eword]
+ * 
+ */
+
+static PyObject *__pyx_pf_3_sa_5BiLex_8get_e_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_eword) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("get_e_id", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":223
  * 
+ *     def get_e_id(self, eword):
+ *         return self.e_voc[eword]             # <<<<<<<<<<<<<<
  * 
+ *     def get_f_id(self, fword):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = PyObject_GetItem(__pyx_v_self->eword2id, __pyx_v_eword); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = __pyx_t_2;
-  __pyx_t_2 = 0;
+  __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_self->e_voc), __pyx_v_eword); if (!__pyx_t_1) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 223; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_AddTraceback("_sa.BiLex.get_e_id", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_e_id);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_9get_f_id(PyObject *__pyx_v_self, PyObject *__pyx_v_fword); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_9get_f_id(PyObject *__pyx_v_self, PyObject *__pyx_v_fword) {
+static PyObject *__pyx_pw_3_sa_5BiLex_11get_f_id(PyObject *__pyx_v_self, PyObject *__pyx_v_fword); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_11get_f_id(PyObject *__pyx_v_self, PyObject *__pyx_v_fword) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("get_f_id (wrapper)", 0);
-  __pyx_r = __pyx_pf_3_sa_5BiLex_8get_f_id(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject *)__pyx_v_fword));
+  __pyx_r = __pyx_pf_3_sa_5BiLex_10get_f_id(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject *)__pyx_v_fword));
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":260
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":225
+ *         return self.e_voc[eword]
  * 
  *     def get_f_id(self, fword):             # <<<<<<<<<<<<<<
- *         if fword not in self.fword2id:
- *             f_id = len(self.id2fword)
+ *         return self.f_voc[fword]
+ * 
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_8get_f_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword) {
-  PyObject *__pyx_v_f_id = NULL;
+static PyObject *__pyx_pf_3_sa_5BiLex_10get_f_id(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  Py_ssize_t __pyx_t_3;
+  PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_f_id", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":261
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":226
  * 
  *     def get_f_id(self, fword):
- *         if fword not in self.fword2id:             # <<<<<<<<<<<<<<
- *             f_id = len(self.id2fword)
- *             self.id2fword.append(fword)
- */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_fword, __pyx_v_self->fword2id, Py_NE)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_1) {
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":262
- *     def get_f_id(self, fword):
- *         if fword not in self.fword2id:
- *             f_id = len(self.id2fword)             # <<<<<<<<<<<<<<
- *             self.id2fword.append(fword)
- *             self.fword2id[fword] = f_id
- */
-    __pyx_t_2 = __pyx_v_self->id2fword;
-    __Pyx_INCREF(__pyx_t_2);
-    __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_v_f_id = __pyx_t_2;
-    __pyx_t_2 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":263
- *         if fword not in self.fword2id:
- *             f_id = len(self.id2fword)
- *             self.id2fword.append(fword)             # <<<<<<<<<<<<<<
- *             self.fword2id[fword] = f_id
- *         return self.fword2id[fword]
- */
-    __pyx_t_2 = __Pyx_PyObject_Append(__pyx_v_self->id2fword, __pyx_v_fword); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":264
- *             f_id = len(self.id2fword)
- *             self.id2fword.append(fword)
- *             self.fword2id[fword] = f_id             # <<<<<<<<<<<<<<
- *         return self.fword2id[fword]
- * 
- */
-    if (PyObject_SetItem(__pyx_v_self->fword2id, __pyx_v_fword, __pyx_v_f_id) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    goto __pyx_L3;
-  }
-  __pyx_L3:;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":265
- *             self.id2fword.append(fword)
- *             self.fword2id[fword] = f_id
- *         return self.fword2id[fword]             # <<<<<<<<<<<<<<
- * 
+ *         return self.f_voc[fword]             # <<<<<<<<<<<<<<
  * 
+ *     def read_text(self, bytes filename):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = PyObject_GetItem(__pyx_v_self->fword2id, __pyx_v_fword); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = __pyx_t_2;
-  __pyx_t_2 = 0;
+  __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_self->f_voc), __pyx_v_fword); if (!__pyx_t_1) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_AddTraceback("_sa.BiLex.get_f_id", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_f_id);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_11read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_11read_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_5BiLex_13read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_13read_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 268; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.BiLex.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_10read_text(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_12read_text(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":268
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":228
+ *         return self.f_voc[fword]
  * 
- *     def read_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef i, j, w, e_id, f_id, n_f, n_e, N
  *         cdef IntList fcount
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_5BiLex_12read_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_i = 0;
   PyObject *__pyx_v_j = 0;
   PyObject *__pyx_v_e_id = 0;
@@ -15385,19 +15226,19 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":272
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":232
  *         cdef IntList fcount
  * 
  *         fcount = IntList()             # <<<<<<<<<<<<<<
  *         with gzip_or_text(filename) as f:
  *             # first loop merely establishes size of array objects
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_fcount = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":273
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":233
  * 
  *         fcount = IntList()
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
@@ -15405,27 +15246,25 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
  *             for line in f:
  */
   /*with:*/ {
-    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__gzip_or_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-    __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
+    __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+    __pyx_t_4 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____exit__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -15437,7 +15276,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __pyx_v_f = __pyx_t_1;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":275
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":235
  *         with gzip_or_text(filename) as f:
  *             # first loop merely establishes size of array objects
  *             for line in f:             # <<<<<<<<<<<<<<
@@ -15448,7 +15287,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             __pyx_t_1 = __pyx_v_f; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
             __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
@@ -15456,46 +15295,46 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_3 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_2 = __pyx_t_9(__pyx_t_1);
-              if (unlikely(!__pyx_t_2)) {
+              __pyx_t_3 = __pyx_t_9(__pyx_t_1);
+              if (unlikely(!__pyx_t_3)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 275; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 235; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_2);
+              __Pyx_GOTREF(__pyx_t_3);
             }
             __Pyx_XDECREF(__pyx_v_line);
-            __pyx_v_line = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_line = __pyx_t_3;
+            __pyx_t_3 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":276
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":236
  *             # first loop merely establishes size of array objects
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()             # <<<<<<<<<<<<<<
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)
  */
-            __pyx_t_2 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_3 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_3 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_3);
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-            if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-              PyObject* sequence = __pyx_t_3;
+            __pyx_t_2 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
+              PyObject* sequence = __pyx_t_2;
               #if CYTHON_COMPILING_IN_CPYTHON
               Py_ssize_t size = Py_SIZE(sequence);
               #else
@@ -15504,47 +15343,47 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
               if (unlikely(size != 4)) {
                 if (size > 4) __Pyx_RaiseTooManyValuesError(4);
                 else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               }
               #if CYTHON_COMPILING_IN_CPYTHON
               if (likely(PyTuple_CheckExact(sequence))) {
-                __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
+                __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
                 __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1); 
                 __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); 
                 __pyx_t_12 = PyTuple_GET_ITEM(sequence, 3); 
               } else {
-                __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
+                __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
                 __pyx_t_10 = PyList_GET_ITEM(sequence, 1); 
                 __pyx_t_11 = PyList_GET_ITEM(sequence, 2); 
                 __pyx_t_12 = PyList_GET_ITEM(sequence, 3); 
               }
-              __Pyx_INCREF(__pyx_t_2);
+              __Pyx_INCREF(__pyx_t_3);
               __Pyx_INCREF(__pyx_t_10);
               __Pyx_INCREF(__pyx_t_11);
               __Pyx_INCREF(__pyx_t_12);
               #else
               Py_ssize_t i;
-              PyObject** temps[4] = {&__pyx_t_2,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
+              PyObject** temps[4] = {&__pyx_t_3,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
               for (i=0; i < 4; i++) {
-                PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 *(temps[i]) = item;
               }
               #endif
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             } else
             {
               Py_ssize_t index = -1;
-              PyObject** temps[4] = {&__pyx_t_2,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
-              __pyx_t_13 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              PyObject** temps[4] = {&__pyx_t_3,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
+              __pyx_t_13 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_13);
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
               __pyx_t_14 = Py_TYPE(__pyx_t_13)->tp_iternext;
               for (index=0; index < 4; index++) {
                 PyObject* item = __pyx_t_14(__pyx_t_13); if (unlikely(!item)) goto __pyx_L18_unpacking_failed;
                 __Pyx_GOTREF(item);
                 *(temps[index]) = item;
               }
-              if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_13), 4) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_13), 4) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_t_14 = NULL;
               __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
               goto __pyx_L19_unpacking_done;
@@ -15552,12 +15391,12 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
               __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
               __pyx_t_14 = NULL;
               if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_L19_unpacking_done:;
             }
             __Pyx_XDECREF(__pyx_v_fword);
-            __pyx_v_fword = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_fword = __pyx_t_3;
+            __pyx_t_3 = 0;
             __Pyx_XDECREF(__pyx_v_eword);
             __pyx_v_eword = __pyx_t_10;
             __pyx_t_10 = 0;
@@ -15568,51 +15407,51 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             __pyx_v_score2 = __pyx_t_12;
             __pyx_t_12 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":277
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":237
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()
  *                 f_id = self.get_f_id(fword)             # <<<<<<<<<<<<<<
  *                 e_id = self.get_e_id(eword)
  *                 while f_id >= len(fcount):
  */
-            __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_f_id); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
-            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_f_id); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
             __Pyx_INCREF(__pyx_v_fword);
             PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_v_fword);
             __Pyx_GIVEREF(__pyx_v_fword);
-            __pyx_t_11 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 277; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 237; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
-            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
             __Pyx_XDECREF(__pyx_v_f_id);
             __pyx_v_f_id = __pyx_t_11;
             __pyx_t_11 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":278
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":238
  *                 (fword, eword, score1, score2) = line.split()
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)             # <<<<<<<<<<<<<<
  *                 while f_id >= len(fcount):
  *                     fcount.append(0)
  */
-            __pyx_t_11 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_e_id); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_e_id); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
-            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
             __Pyx_INCREF(__pyx_v_eword);
             PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_v_eword);
             __Pyx_GIVEREF(__pyx_v_eword);
-            __pyx_t_3 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_2 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
             __Pyx_XDECREF(__pyx_v_e_id);
-            __pyx_v_e_id = __pyx_t_3;
-            __pyx_t_3 = 0;
+            __pyx_v_e_id = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":279
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":239
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)
  *                 while f_id >= len(fcount):             # <<<<<<<<<<<<<<
@@ -15620,41 +15459,41 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  */
             while (1) {
-              __pyx_t_15 = PyObject_Length(((PyObject *)__pyx_v_fcount)); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __pyx_t_3 = PyInt_FromSsize_t(__pyx_t_15); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_3);
-              __pyx_t_12 = PyObject_RichCompare(__pyx_v_f_id, __pyx_t_3, Py_GE); __Pyx_XGOTREF(__pyx_t_12); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-              __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_12); if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 279; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_15 = PyObject_Length(((PyObject *)__pyx_v_fcount)); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 239; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyInt_FromSsize_t(__pyx_t_15); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 239; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_2);
+              __pyx_t_12 = PyObject_RichCompare(__pyx_v_f_id, __pyx_t_2, Py_GE); __Pyx_XGOTREF(__pyx_t_12); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 239; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+              __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_12); if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 239; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               if (!__pyx_t_16) break;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":280
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":240
  *                 e_id = self.get_e_id(eword)
  *                 while f_id >= len(fcount):
  *                     fcount.append(0)             # <<<<<<<<<<<<<<
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  * 
  */
-              __pyx_t_12 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_fcount), __pyx_int_0); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 280; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_fcount), __pyx_int_0); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
             }
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":281
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":241
  *                 while f_id >= len(fcount):
  *                     fcount.append(0)
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1             # <<<<<<<<<<<<<<
  * 
  *             # Allocate space for dictionary in arrays
  */
-            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 281; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 241; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 241; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             (__pyx_v_fcount->arr[__pyx_t_17]) = ((__pyx_v_fcount->arr[__pyx_t_15]) + 1);
           }
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":284
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":244
  * 
  *             # Allocate space for dictionary in arrays
  *             N = 0             # <<<<<<<<<<<<<<
@@ -15664,33 +15503,33 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __Pyx_INCREF(__pyx_int_0);
           __pyx_v_N = __pyx_int_0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":285
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":245
  *             # Allocate space for dictionary in arrays
  *             N = 0
  *             n_f = len(fcount)             # <<<<<<<<<<<<<<
  *             self.f_index = IntList(initial_len=n_f+1)
  *             for i from 0 <= i < n_f:
  */
-          __pyx_t_8 = PyObject_Length(((PyObject *)__pyx_v_fcount)); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 285; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_8 = PyObject_Length(((PyObject *)__pyx_v_fcount)); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __pyx_v_n_f = __pyx_t_1;
           __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":286
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":246
  *             N = 0
  *             n_f = len(fcount)
  *             self.f_index = IntList(initial_len=n_f+1)             # <<<<<<<<<<<<<<
  *             for i from 0 <= i < n_f:
  *                 self.f_index.arr[i] = N
  */
-          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-          __pyx_t_12 = PyNumber_Add(__pyx_v_n_f, __pyx_int_1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyNumber_Add(__pyx_v_n_f, __pyx_int_1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_12);
-          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_12) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 286; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_12);
           __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           __Pyx_GIVEREF(__pyx_t_12);
@@ -15699,96 +15538,96 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __pyx_v_self->f_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_12);
           __pyx_t_12 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":287
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":247
  *             n_f = len(fcount)
  *             self.f_index = IntList(initial_len=n_f+1)
  *             for i from 0 <= i < n_f:             # <<<<<<<<<<<<<<
  *                 self.f_index.arr[i] = N
  *                 N = N + fcount.arr[i]
  */
-          __pyx_t_18 = __Pyx_PyInt_AsLong(__pyx_v_n_f); if (unlikely((__pyx_t_18 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_18 = __Pyx_PyInt_AsLong(__pyx_v_n_f); if (unlikely((__pyx_t_18 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19++) {
-            __pyx_t_12 = PyInt_FromLong(__pyx_t_19); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyInt_FromLong(__pyx_t_19); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
             __Pyx_XDECREF(__pyx_v_i);
             __pyx_v_i = __pyx_t_12;
             __pyx_t_12 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":288
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":248
  *             self.f_index = IntList(initial_len=n_f+1)
  *             for i from 0 <= i < n_f:
  *                 self.f_index.arr[i] = N             # <<<<<<<<<<<<<<
  *                 N = N + fcount.arr[i]
  *                 fcount.arr[i] = 0
  */
-            __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_N); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_N); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             (__pyx_v_self->f_index->arr[__pyx_t_8]) = __pyx_t_20;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":289
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":249
  *             for i from 0 <= i < n_f:
  *                 self.f_index.arr[i] = N
  *                 N = N + fcount.arr[i]             # <<<<<<<<<<<<<<
  *                 fcount.arr[i] = 0
  *             self.f_index.arr[n_f] = N
  */
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_12 = PyInt_FromLong((__pyx_v_fcount->arr[__pyx_t_8])); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyInt_FromLong((__pyx_v_fcount->arr[__pyx_t_8])); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
-            __pyx_t_1 = PyNumber_Add(__pyx_v_N, __pyx_t_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_1 = PyNumber_Add(__pyx_v_N, __pyx_t_12); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 249; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
             __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
             __Pyx_DECREF(__pyx_v_N);
             __pyx_v_N = __pyx_t_1;
             __pyx_t_1 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":290
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":250
  *                 self.f_index.arr[i] = N
  *                 N = N + fcount.arr[i]
  *                 fcount.arr[i] = 0             # <<<<<<<<<<<<<<
  *             self.f_index.arr[n_f] = N
  *             self.e_index = IntList(initial_len=N)
  */
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 290; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             (__pyx_v_fcount->arr[__pyx_t_8]) = 0;
-            __pyx_t_19 = __Pyx_PyInt_AsLong(__pyx_v_i); if (unlikely((__pyx_t_19 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_19 = __Pyx_PyInt_AsLong(__pyx_v_i); if (unlikely((__pyx_t_19 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           }
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":287
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":247
  *             n_f = len(fcount)
  *             self.f_index = IntList(initial_len=n_f+1)
  *             for i from 0 <= i < n_f:             # <<<<<<<<<<<<<<
  *                 self.f_index.arr[i] = N
  *                 N = N + fcount.arr[i]
  */
-          __pyx_t_1 = PyInt_FromLong(__pyx_t_19); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyInt_FromLong(__pyx_t_19); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_XDECREF(__pyx_v_i);
           __pyx_v_i = __pyx_t_1;
           __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":291
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":251
  *                 N = N + fcount.arr[i]
  *                 fcount.arr[i] = 0
  *             self.f_index.arr[n_f] = N             # <<<<<<<<<<<<<<
  *             self.e_index = IntList(initial_len=N)
  *             self.col1 = FloatList(initial_len=N)
  */
-          __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_N); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 291; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_n_f); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 291; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_N); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 251; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_n_f); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 251; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           (__pyx_v_self->f_index->arr[__pyx_t_8]) = __pyx_t_20;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":292
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":252
  *                 fcount.arr[i] = 0
  *             self.f_index.arr[n_f] = N
  *             self.e_index = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *             self.col1 = FloatList(initial_len=N)
  *             self.col2 = FloatList(initial_len=N)
  */
-          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 252; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_12);
           __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           __Pyx_GIVEREF(__pyx_t_12);
@@ -15797,17 +15636,17 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __pyx_v_self->e_index = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_12);
           __pyx_t_12 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":293
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":253
  *             self.f_index.arr[n_f] = N
  *             self.e_index = IntList(initial_len=N)
  *             self.col1 = FloatList(initial_len=N)             # <<<<<<<<<<<<<<
  *             self.col2 = FloatList(initial_len=N)
  * 
  */
-          __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyDict_New(); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_12));
-          if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          if (PyDict_SetItem(__pyx_t_12, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
           __Pyx_GIVEREF(__pyx_t_1);
@@ -15816,17 +15655,17 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __pyx_v_self->col1 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_1);
           __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":294
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":254
  *             self.e_index = IntList(initial_len=N)
  *             self.col1 = FloatList(initial_len=N)
  *             self.col2 = FloatList(initial_len=N)             # <<<<<<<<<<<<<<
  * 
  *             # Re-read file, placing words into buckets
  */
-          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_v_N) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_12);
           __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           __Pyx_GIVEREF(__pyx_t_12);
@@ -15835,21 +15674,21 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
           __pyx_v_self->col2 = ((struct __pyx_obj_3_sa_FloatList *)__pyx_t_12);
           __pyx_t_12 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":297
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":257
  * 
  *             # Re-read file, placing words into buckets
  *             f.seek(0)             # <<<<<<<<<<<<<<
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()
  */
-          __pyx_t_12 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__seek); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_12 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__seek); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_12);
-          __pyx_t_1 = PyObject_Call(__pyx_t_12, ((PyObject *)__pyx_k_tuple_43), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_Call(__pyx_t_12, ((PyObject *)__pyx_k_tuple_44), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":298
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":258
  *             # Re-read file, placing words into buckets
  *             f.seek(0)
  *             for line in f:             # <<<<<<<<<<<<<<
@@ -15860,7 +15699,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             __pyx_t_1 = __pyx_v_f; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
             __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
@@ -15868,23 +15707,23 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_12 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_12); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_12); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_12 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_12 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_12); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_12); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_12 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
               __pyx_t_12 = __pyx_t_9(__pyx_t_1);
               if (unlikely(!__pyx_t_12)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 298; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 258; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
@@ -15894,20 +15733,20 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             __pyx_v_line = __pyx_t_12;
             __pyx_t_12 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":299
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":259
  *             f.seek(0)
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()             # <<<<<<<<<<<<<<
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)
  */
-            __pyx_t_12 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyObject_GetAttr(__pyx_v_line, __pyx_n_s__split); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
-            __pyx_t_3 = PyObject_Call(__pyx_t_12, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_2 = PyObject_Call(__pyx_t_12, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-            if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-              PyObject* sequence = __pyx_t_3;
+            if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
+              PyObject* sequence = __pyx_t_2;
               #if CYTHON_COMPILING_IN_CPYTHON
               Py_ssize_t size = Py_SIZE(sequence);
               #else
@@ -15916,47 +15755,47 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
               if (unlikely(size != 4)) {
                 if (size > 4) __Pyx_RaiseTooManyValuesError(4);
                 else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               }
               #if CYTHON_COMPILING_IN_CPYTHON
               if (likely(PyTuple_CheckExact(sequence))) {
                 __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0); 
                 __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); 
                 __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); 
-                __pyx_t_2 = PyTuple_GET_ITEM(sequence, 3); 
+                __pyx_t_3 = PyTuple_GET_ITEM(sequence, 3); 
               } else {
                 __pyx_t_12 = PyList_GET_ITEM(sequence, 0); 
                 __pyx_t_11 = PyList_GET_ITEM(sequence, 1); 
                 __pyx_t_10 = PyList_GET_ITEM(sequence, 2); 
-                __pyx_t_2 = PyList_GET_ITEM(sequence, 3); 
+                __pyx_t_3 = PyList_GET_ITEM(sequence, 3); 
               }
               __Pyx_INCREF(__pyx_t_12);
               __Pyx_INCREF(__pyx_t_11);
               __Pyx_INCREF(__pyx_t_10);
-              __Pyx_INCREF(__pyx_t_2);
+              __Pyx_INCREF(__pyx_t_3);
               #else
               Py_ssize_t i;
-              PyObject** temps[4] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_2};
+              PyObject** temps[4] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_3};
               for (i=0; i < 4; i++) {
-                PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 *(temps[i]) = item;
               }
               #endif
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             } else
             {
               Py_ssize_t index = -1;
-              PyObject** temps[4] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_2};
-              __pyx_t_13 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              PyObject** temps[4] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_3};
+              __pyx_t_13 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_13);
-              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
               __pyx_t_14 = Py_TYPE(__pyx_t_13)->tp_iternext;
               for (index=0; index < 4; index++) {
                 PyObject* item = __pyx_t_14(__pyx_t_13); if (unlikely(!item)) goto __pyx_L26_unpacking_failed;
                 __Pyx_GOTREF(item);
                 *(temps[index]) = item;
               }
-              if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_13), 4) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_13), 4) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_t_14 = NULL;
               __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
               goto __pyx_L27_unpacking_done;
@@ -15964,7 +15803,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
               __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
               __pyx_t_14 = NULL;
               if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_L27_unpacking_done:;
             }
             __Pyx_XDECREF(__pyx_v_fword);
@@ -15977,124 +15816,124 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
             __pyx_v_score1 = __pyx_t_10;
             __pyx_t_10 = 0;
             __Pyx_XDECREF(__pyx_v_score2);
-            __pyx_v_score2 = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_score2 = __pyx_t_3;
+            __pyx_t_3 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":300
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":260
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()
  *                 f_id = self.get_f_id(fword)             # <<<<<<<<<<<<<<
  *                 e_id = self.get_e_id(eword)
  *                 index = self.f_index.arr[f_id] + fcount.arr[f_id]
  */
-            __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_f_id); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 300; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
-            __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 300; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_f_id); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
             __Pyx_INCREF(__pyx_v_fword);
-            PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_fword);
+            PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_fword);
             __Pyx_GIVEREF(__pyx_v_fword);
-            __pyx_t_10 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 300; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 260; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
             __Pyx_XDECREF(__pyx_v_f_id);
             __pyx_v_f_id = __pyx_t_10;
             __pyx_t_10 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":301
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":261
  *                 (fword, eword, score1, score2) = line.split()
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)             # <<<<<<<<<<<<<<
  *                 index = self.f_index.arr[f_id] + fcount.arr[f_id]
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  */
-            __pyx_t_10 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_e_id); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__get_e_id); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
             __Pyx_INCREF(__pyx_v_eword);
-            PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_eword);
+            PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_eword);
             __Pyx_GIVEREF(__pyx_v_eword);
-            __pyx_t_3 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_2 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 261; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
             __Pyx_XDECREF(__pyx_v_e_id);
-            __pyx_v_e_id = __pyx_t_3;
-            __pyx_t_3 = 0;
+            __pyx_v_e_id = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":302
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":262
  *                 f_id = self.get_f_id(fword)
  *                 e_id = self.get_e_id(eword)
  *                 index = self.f_index.arr[f_id] + fcount.arr[f_id]             # <<<<<<<<<<<<<<
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  *                 self.e_index.arr[index] = int(e_id)
  */
-            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_3 = PyInt_FromLong(((__pyx_v_self->f_index->arr[__pyx_t_15]) + (__pyx_v_fcount->arr[__pyx_t_17]))); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyInt_FromLong(((__pyx_v_self->f_index->arr[__pyx_t_15]) + (__pyx_v_fcount->arr[__pyx_t_17]))); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 262; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_XDECREF(__pyx_v_index);
-            __pyx_v_index = __pyx_t_3;
-            __pyx_t_3 = 0;
+            __pyx_v_index = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":303
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":263
  *                 e_id = self.get_e_id(eword)
  *                 index = self.f_index.arr[f_id] + fcount.arr[f_id]
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1             # <<<<<<<<<<<<<<
  *                 self.e_index.arr[index] = int(e_id)
  *                 self.col1[index] = float(score1)
  */
-            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 303; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 303; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_15 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_15 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 263; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             (__pyx_v_fcount->arr[__pyx_t_15]) = ((__pyx_v_fcount->arr[__pyx_t_17]) + 1);
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":304
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":264
  *                 index = self.f_index.arr[f_id] + fcount.arr[f_id]
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  *                 self.e_index.arr[index] = int(e_id)             # <<<<<<<<<<<<<<
  *                 self.col1[index] = float(score1)
  *                 self.col2[index] = float(score2)
  */
-            __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_INCREF(__pyx_v_e_id);
-            PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_e_id);
+            PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_e_id);
             __Pyx_GIVEREF(__pyx_v_e_id);
-            __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-            __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_t_2); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)(&PyInt_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
+            __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+            __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __pyx_t_17 = __Pyx_PyIndex_AsSsize_t(__pyx_v_index); if (unlikely((__pyx_t_17 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             (__pyx_v_self->e_index->arr[__pyx_t_17]) = __pyx_t_20;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":305
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":265
  *                 fcount.arr[f_id] = fcount.arr[f_id] + 1
  *                 self.e_index.arr[index] = int(e_id)
  *                 self.col1[index] = float(score1)             # <<<<<<<<<<<<<<
  *                 self.col2[index] = float(score2)
  * 
  */
-            __pyx_t_21 = __Pyx_PyObject_AsDouble(__pyx_v_score1); if (unlikely(__pyx_t_21 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_2 = PyFloat_FromDouble(__pyx_t_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            if (PyObject_SetItem(((PyObject *)__pyx_v_self->col1), __pyx_v_index, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __pyx_t_21 = __Pyx_PyObject_AsDouble(__pyx_v_score1); if (unlikely(__pyx_t_21 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_3 = PyFloat_FromDouble(__pyx_t_21); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
+            if (PyObject_SetItem(((PyObject *)__pyx_v_self->col1), __pyx_v_index, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 265; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":306
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":266
  *                 self.e_index.arr[index] = int(e_id)
  *                 self.col1[index] = float(score1)
  *                 self.col2[index] = float(score2)             # <<<<<<<<<<<<<<
  * 
  *         # Sort buckets by eword
  */
-            __pyx_t_21 = __Pyx_PyObject_AsDouble(__pyx_v_score2); if (unlikely(__pyx_t_21 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_2 = PyFloat_FromDouble(__pyx_t_21); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            if (PyObject_SetItem(((PyObject *)__pyx_v_self->col2), __pyx_v_index, __pyx_t_2) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __pyx_t_21 = __Pyx_PyObject_AsDouble(__pyx_v_score2); if (unlikely(__pyx_t_21 == ((double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_3 = PyFloat_FromDouble(__pyx_t_21); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_3);
+            if (PyObject_SetItem(((PyObject *)__pyx_v_self->col2), __pyx_v_index, __pyx_t_3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           }
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
         }
@@ -16107,11 +15946,11 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
         __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
         __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
-        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
         __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":273
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":233
  * 
  *         fcount = IntList()
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
@@ -16120,43 +15959,43 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.BiLex.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_3, &__pyx_t_2) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_GOTREF(__pyx_t_3);
-          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_10);
           __Pyx_INCREF(__pyx_t_1);
           PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_1);
           __Pyx_GIVEREF(__pyx_t_1);
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_t_3);
-          PyTuple_SET_ITEM(__pyx_t_10, 2, __pyx_t_3);
+          PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_3);
           __Pyx_GIVEREF(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_10, 2, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __pyx_t_22 = PyObject_Call(__pyx_t_4, __pyx_t_10, NULL);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          if (unlikely(!__pyx_t_22)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_22)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_22);
           __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_22);
           __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
-          if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_23 = (!__pyx_t_16);
           if (__pyx_t_23) {
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_GIVEREF(__pyx_t_2);
             __Pyx_GIVEREF(__pyx_t_3);
-            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-            __pyx_t_1 = 0; __pyx_t_2 = 0; __pyx_t_3 = 0; 
-            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_3, __pyx_t_2);
+            __pyx_t_1 = 0; __pyx_t_3 = 0; __pyx_t_2 = 0; 
+            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L30;
           }
           __pyx_L30:;
           __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           goto __pyx_L8_exception_handled;
         }
         __pyx_L9_except_error:;
@@ -16175,13 +16014,13 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
     }
     /*finally:*/ {
       if (__pyx_t_4) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_44, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_4, __pyx_k_tuple_45, NULL);
         __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_23 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_23 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_23 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L31;
@@ -16191,79 +16030,76 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
     __pyx_L31:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":309
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":269
  * 
  *         # Sort buckets by eword
  *         for b from 0 <= b < n_f:             # <<<<<<<<<<<<<<
  *             i = self.f_index.arr[b]
  *             j = self.f_index.arr[b+1]
  */
-  if (unlikely(!__pyx_v_n_f)) { __Pyx_RaiseUnboundLocalError("n_f"); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
-  __pyx_t_19 = __Pyx_PyInt_AsLong(__pyx_v_n_f); if (unlikely((__pyx_t_19 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_v_n_f)) { __Pyx_RaiseUnboundLocalError("n_f"); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  __pyx_t_19 = __Pyx_PyInt_AsLong(__pyx_v_n_f); if (unlikely((__pyx_t_19 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_19; __pyx_t_18++) {
-    __pyx_t_3 = PyInt_FromLong(__pyx_t_18); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = PyInt_FromLong(__pyx_t_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_XDECREF(__pyx_v_b);
-    __pyx_v_b = __pyx_t_3;
-    __pyx_t_3 = 0;
+    __pyx_v_b = __pyx_t_2;
+    __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":310
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":270
  *         # Sort buckets by eword
  *         for b from 0 <= b < n_f:
  *             i = self.f_index.arr[b]             # <<<<<<<<<<<<<<
  *             j = self.f_index.arr[b+1]
- *             self.qsort(i,j, "")
+ *             self.qsort(i, j)
  */
-    __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_b); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_b); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 270; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_XDECREF(__pyx_v_i);
-    __pyx_v_i = __pyx_t_3;
-    __pyx_t_3 = 0;
+    __pyx_v_i = __pyx_t_2;
+    __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":311
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":271
  *         for b from 0 <= b < n_f:
  *             i = self.f_index.arr[b]
  *             j = self.f_index.arr[b+1]             # <<<<<<<<<<<<<<
- *             self.qsort(i,j, "")
+ *             self.qsort(i, j)
  * 
  */
-    __pyx_t_3 = PyNumber_Add(__pyx_v_b, __pyx_int_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_t_3); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = PyNumber_Add(__pyx_v_b, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_t_2); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_2 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_2);
     __Pyx_XDECREF(__pyx_v_j);
-    __pyx_v_j = __pyx_t_3;
-    __pyx_t_3 = 0;
+    __pyx_v_j = __pyx_t_2;
+    __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":312
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":272
  *             i = self.f_index.arr[b]
  *             j = self.f_index.arr[b+1]
- *             self.qsort(i,j, "")             # <<<<<<<<<<<<<<
+ *             self.qsort(i, j)             # <<<<<<<<<<<<<<
  * 
  * 
  */
-    __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_24 = __Pyx_PyInt_AsInt(__pyx_v_j); if (unlikely((__pyx_t_24 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_3 = ((PyObject *)__pyx_kp_s_45);
-    __Pyx_INCREF(__pyx_t_3);
-    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, __pyx_t_20, __pyx_t_24, __pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_20 = __Pyx_PyInt_AsInt(__pyx_v_i); if (unlikely((__pyx_t_20 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_24 = __Pyx_PyInt_AsInt(__pyx_v_j); if (unlikely((__pyx_t_24 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, __pyx_t_20, __pyx_t_24); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_18 = __Pyx_PyInt_AsLong(__pyx_v_b); if (unlikely((__pyx_t_18 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_18 = __Pyx_PyInt_AsLong(__pyx_v_b); if (unlikely((__pyx_t_18 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":309
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":269
  * 
  *         # Sort buckets by eword
  *         for b from 0 <= b < n_f:             # <<<<<<<<<<<<<<
  *             i = self.f_index.arr[b]
  *             j = self.f_index.arr[b+1]
  */
-  __pyx_t_2 = PyInt_FromLong(__pyx_t_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong(__pyx_t_18); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 269; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_v_b);
   __pyx_v_b = __pyx_t_2;
@@ -16302,7 +16138,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_10read_text(struct __pyx_obj_3_sa_BiLex *_
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":315
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":275
  * 
  * 
  *     cdef swap(self, int i, int j):             # <<<<<<<<<<<<<<
@@ -16318,7 +16154,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("swap", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":319
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":279
  *         cdef float ftmp
  * 
  *         if i == j:             # <<<<<<<<<<<<<<
@@ -16328,7 +16164,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   __pyx_t_1 = (__pyx_v_i == __pyx_v_j);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":320
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":280
  * 
  *         if i == j:
  *             return             # <<<<<<<<<<<<<<
@@ -16342,7 +16178,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":322
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":282
  *             return
  * 
  *         itmp = self.e_index.arr[i]             # <<<<<<<<<<<<<<
@@ -16351,7 +16187,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   __pyx_v_itmp = (__pyx_v_self->e_index->arr[__pyx_v_i]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":323
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":283
  * 
  *         itmp = self.e_index.arr[i]
  *         self.e_index.arr[i] = self.e_index.arr[j]             # <<<<<<<<<<<<<<
@@ -16360,7 +16196,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   (__pyx_v_self->e_index->arr[__pyx_v_i]) = (__pyx_v_self->e_index->arr[__pyx_v_j]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":324
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":284
  *         itmp = self.e_index.arr[i]
  *         self.e_index.arr[i] = self.e_index.arr[j]
  *         self.e_index.arr[j] = itmp             # <<<<<<<<<<<<<<
@@ -16369,7 +16205,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   (__pyx_v_self->e_index->arr[__pyx_v_j]) = __pyx_v_itmp;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":326
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":286
  *         self.e_index.arr[j] = itmp
  * 
  *         ftmp = self.col1.arr[i]             # <<<<<<<<<<<<<<
@@ -16378,7 +16214,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   __pyx_v_ftmp = (__pyx_v_self->col1->arr[__pyx_v_i]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":327
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":287
  * 
  *         ftmp = self.col1.arr[i]
  *         self.col1.arr[i] = self.col1.arr[j]             # <<<<<<<<<<<<<<
@@ -16387,7 +16223,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   (__pyx_v_self->col1->arr[__pyx_v_i]) = (__pyx_v_self->col1->arr[__pyx_v_j]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":328
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":288
  *         ftmp = self.col1.arr[i]
  *         self.col1.arr[i] = self.col1.arr[j]
  *         self.col1.arr[j] = ftmp             # <<<<<<<<<<<<<<
@@ -16396,7 +16232,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   (__pyx_v_self->col1->arr[__pyx_v_j]) = __pyx_v_ftmp;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":330
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":290
  *         self.col1.arr[j] = ftmp
  * 
  *         ftmp = self.col2.arr[i]             # <<<<<<<<<<<<<<
@@ -16405,7 +16241,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   __pyx_v_ftmp = (__pyx_v_self->col2->arr[__pyx_v_i]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":331
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":291
  * 
  *         ftmp = self.col2.arr[i]
  *         self.col2.arr[i] = self.col2.arr[j]             # <<<<<<<<<<<<<<
@@ -16414,7 +16250,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
  */
   (__pyx_v_self->col2->arr[__pyx_v_i]) = (__pyx_v_self->col2->arr[__pyx_v_j]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":332
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":292
  *         ftmp = self.col2.arr[i]
  *         self.col2.arr[i] = self.col2.arr[j]
  *         self.col2.arr[j] = ftmp             # <<<<<<<<<<<<<<
@@ -16430,15 +16266,15 @@ static PyObject *__pyx_f_3_sa_5BiLex_swap(struct __pyx_obj_3_sa_BiLex *__pyx_v_s
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":335
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":295
  * 
  * 
- *     cdef qsort(self, int i, int j, pad):             # <<<<<<<<<<<<<<
+ *     cdef qsort(self, int i, int j):             # <<<<<<<<<<<<<<
  *         cdef int pval, p
  * 
  */
 
-static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, int __pyx_v_i, int __pyx_v_j, PyObject *__pyx_v_pad) {
+static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, int __pyx_v_i, int __pyx_v_j) {
   int __pyx_v_pval;
   int __pyx_v_p;
   long __pyx_v_k;
@@ -16447,13 +16283,12 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("qsort", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":338
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":298
  *         cdef int pval, p
  * 
  *         if i > j:             # <<<<<<<<<<<<<<
@@ -16463,23 +16298,23 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   __pyx_t_1 = (__pyx_v_i > __pyx_v_j);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":339
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":299
  * 
  *         if i > j:
  *             raise Exception("Sort error in CLex")             # <<<<<<<<<<<<<<
  *         if i == j: #empty interval
  *             return
  */
-    __pyx_t_2 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_47), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_47), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L3;
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":340
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":300
  *         if i > j:
  *             raise Exception("Sort error in CLex")
  *         if i == j: #empty interval             # <<<<<<<<<<<<<<
@@ -16489,7 +16324,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   __pyx_t_1 = (__pyx_v_i == __pyx_v_j);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":341
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":301
  *             raise Exception("Sort error in CLex")
  *         if i == j: #empty interval
  *             return             # <<<<<<<<<<<<<<
@@ -16503,7 +16338,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":342
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":302
  *         if i == j: #empty interval
  *             return
  *         if i == j-1: # singleton interval             # <<<<<<<<<<<<<<
@@ -16513,7 +16348,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   __pyx_t_1 = (__pyx_v_i == (__pyx_v_j - 1));
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":343
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":303
  *             return
  *         if i == j-1: # singleton interval
  *             return             # <<<<<<<<<<<<<<
@@ -16527,7 +16362,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   }
   __pyx_L5:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":345
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":305
  *             return
  * 
  *         p = (i+j)/2             # <<<<<<<<<<<<<<
@@ -16536,7 +16371,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
  */
   __pyx_v_p = __Pyx_div_long((__pyx_v_i + __pyx_v_j), 2);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":346
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":306
  * 
  *         p = (i+j)/2
  *         pval = self.e_index.arr[p]             # <<<<<<<<<<<<<<
@@ -16545,18 +16380,18 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
  */
   __pyx_v_pval = (__pyx_v_self->e_index->arr[__pyx_v_p]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":347
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":307
  *         p = (i+j)/2
  *         pval = self.e_index.arr[p]
  *         self.swap(i, p)             # <<<<<<<<<<<<<<
  *         p = i
  *         for k from i+1 <= k < j:
  */
-  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, __pyx_v_i, __pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, __pyx_v_i, __pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 307; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":348
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":308
  *         pval = self.e_index.arr[p]
  *         self.swap(i, p)
  *         p = i             # <<<<<<<<<<<<<<
@@ -16565,7 +16400,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
  */
   __pyx_v_p = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":349
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":309
  *         self.swap(i, p)
  *         p = i
  *         for k from i+1 <= k < j:             # <<<<<<<<<<<<<<
@@ -16575,7 +16410,7 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
   __pyx_t_3 = __pyx_v_j;
   for (__pyx_v_k = (__pyx_v_i + 1); __pyx_v_k < __pyx_t_3; __pyx_v_k++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":350
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":310
  *         p = i
  *         for k from i+1 <= k < j:
  *             if pval >= self.e_index.arr[k]:             # <<<<<<<<<<<<<<
@@ -16585,34 +16420,34 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
     __pyx_t_1 = (__pyx_v_pval >= (__pyx_v_self->e_index->arr[__pyx_v_k]));
     if (__pyx_t_1) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":351
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":311
  *         for k from i+1 <= k < j:
  *             if pval >= self.e_index.arr[k]:
  *                 self.swap(p+1, k)             # <<<<<<<<<<<<<<
  *                 self.swap(p, p+1)
  *                 p = p + 1
  */
-      __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, (__pyx_v_p + 1), __pyx_v_k); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, (__pyx_v_p + 1), __pyx_v_k); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":352
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":312
  *             if pval >= self.e_index.arr[k]:
  *                 self.swap(p+1, k)
  *                 self.swap(p, p+1)             # <<<<<<<<<<<<<<
  *                 p = p + 1
- *         self.qsort(i,p, pad+"    ")
+ *         self.qsort(i, p)
  */
-      __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, __pyx_v_p, (__pyx_v_p + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 352; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->swap(__pyx_v_self, __pyx_v_p, (__pyx_v_p + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":353
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":313
  *                 self.swap(p+1, k)
  *                 self.swap(p, p+1)
  *                 p = p + 1             # <<<<<<<<<<<<<<
- *         self.qsort(i,p, pad+"    ")
- *         self.qsort(p+1,j, pad+"    ")
+ *         self.qsort(i, p)
+ *         self.qsort(p+1, j)
  */
       __pyx_v_p = (__pyx_v_p + 1);
       goto __pyx_L8;
@@ -16620,39 +16455,32 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
     __pyx_L8:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":354
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":314
  *                 self.swap(p, p+1)
  *                 p = p + 1
- *         self.qsort(i,p, pad+"    ")             # <<<<<<<<<<<<<<
- *         self.qsort(p+1,j, pad+"    ")
+ *         self.qsort(i, p)             # <<<<<<<<<<<<<<
+ *         self.qsort(p+1, j)
  * 
  */
-  __pyx_t_2 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_48)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, __pyx_v_i, __pyx_v_p); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, __pyx_v_i, __pyx_v_p, __pyx_t_2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":355
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":315
  *                 p = p + 1
- *         self.qsort(i,p, pad+"    ")
- *         self.qsort(p+1,j, pad+"    ")             # <<<<<<<<<<<<<<
+ *         self.qsort(i, p)
+ *         self.qsort(p+1, j)             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_4 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_48)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 355; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, (__pyx_v_p + 1), __pyx_v_j, __pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 355; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_BiLex *)__pyx_v_self->__pyx_vtab)->qsort(__pyx_v_self, (__pyx_v_p + 1), __pyx_v_j); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_AddTraceback("_sa.BiLex.qsort", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
@@ -16662,35 +16490,30 @@ static PyObject *__pyx_f_3_sa_5BiLex_qsort(struct __pyx_obj_3_sa_BiLex *__pyx_v_
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_13write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_13write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_5BiLex_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_enhanced (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 358; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.BiLex.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_12write_enhanced(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_14write_enhanced(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":358
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":318
  * 
  * 
- *     def write_enhanced(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_enhanced(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             for i in self.f_index:
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_5BiLex_14write_enhanced(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_v_i = NULL;
   PyObject *__pyx_v_s1 = NULL;
@@ -16719,35 +16542,33 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_enhanced", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":359
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":319
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for i in self.f_index:
  *                 f.write("%d " % i)
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -16759,8 +16580,8 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":360
- *     def write_enhanced(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":320
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:
  *             for i in self.f_index:             # <<<<<<<<<<<<<<
  *                 f.write("%d " % i)
@@ -16770,7 +16591,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __pyx_t_4 = ((PyObject *)__pyx_v_self->f_index); __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->f_index)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->f_index)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext;
           }
@@ -16778,121 +16599,121 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_1 = __pyx_t_9(__pyx_t_4);
-              if (unlikely(!__pyx_t_1)) {
+              __pyx_t_2 = __pyx_t_9(__pyx_t_4);
+              if (unlikely(!__pyx_t_2)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 360; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 320; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_1);
+              __Pyx_GOTREF(__pyx_t_2);
             }
             __Pyx_XDECREF(__pyx_v_i);
-            __pyx_v_i = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_i = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":361
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":321
  *         with open(filename, "w") as f:
  *             for i in self.f_index:
  *                 f.write("%d " % i)             # <<<<<<<<<<<<<<
  *             f.write("\n")
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_10);
-            PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_2));
-            __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-            __pyx_t_2 = 0;
-            __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 361; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_2);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
+            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_10);
+            PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_1));
+            __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+            __pyx_t_1 = 0;
+            __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
             __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           }
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":362
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":322
  *             for i in self.f_index:
  *                 f.write("%d " % i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  *                 f.write("%d %f %f " % (i, s1, s2))
  */
-          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_49), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_48), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":363
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":323
  *                 f.write("%d " % i)
  *             f.write("\n")
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):             # <<<<<<<<<<<<<<
  *                 f.write("%d %f %f " % (i, s1, s2))
  *             f.write("\n")
  */
-          __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_INCREF(((PyObject *)__pyx_v_self->e_index));
-          PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_self->e_index));
+          PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_self->e_index));
           __Pyx_GIVEREF(((PyObject *)__pyx_v_self->e_index));
           __Pyx_INCREF(((PyObject *)__pyx_v_self->col1));
-          PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_v_self->col1));
+          PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_self->col1));
           __Pyx_GIVEREF(((PyObject *)__pyx_v_self->col1));
           __Pyx_INCREF(((PyObject *)__pyx_v_self->col2));
-          PyTuple_SET_ITEM(__pyx_t_2, 2, ((PyObject *)__pyx_v_self->col2));
+          PyTuple_SET_ITEM(__pyx_t_1, 2, ((PyObject *)__pyx_v_self->col2));
           __Pyx_GIVEREF(((PyObject *)__pyx_v_self->col2));
-          __pyx_t_4 = PyObject_Call(__pyx_builtin_zip, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_Call(__pyx_builtin_zip, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           if (PyList_CheckExact(__pyx_t_4) || PyTuple_CheckExact(__pyx_t_4)) {
-            __pyx_t_2 = __pyx_t_4; __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
+            __pyx_t_1 = __pyx_t_4; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_4 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_4 = __pyx_t_9(__pyx_t_2);
+              __pyx_t_4 = __pyx_t_9(__pyx_t_1);
               if (unlikely(!__pyx_t_4)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
@@ -16908,41 +16729,41 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
               if (unlikely(size != 3)) {
                 if (size > 3) __Pyx_RaiseTooManyValuesError(3);
                 else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               }
               #if CYTHON_COMPILING_IN_CPYTHON
               if (likely(PyTuple_CheckExact(sequence))) {
                 __pyx_t_10 = PyTuple_GET_ITEM(sequence, 0); 
-                __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); 
+                __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); 
                 __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); 
               } else {
                 __pyx_t_10 = PyList_GET_ITEM(sequence, 0); 
-                __pyx_t_1 = PyList_GET_ITEM(sequence, 1); 
+                __pyx_t_2 = PyList_GET_ITEM(sequence, 1); 
                 __pyx_t_11 = PyList_GET_ITEM(sequence, 2); 
               }
               __Pyx_INCREF(__pyx_t_10);
-              __Pyx_INCREF(__pyx_t_1);
+              __Pyx_INCREF(__pyx_t_2);
               __Pyx_INCREF(__pyx_t_11);
               #else
-              __pyx_t_10 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __pyx_t_1 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __pyx_t_11 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
               __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
             } else
             {
               Py_ssize_t index = -1;
-              __pyx_t_12 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_12 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_12);
               __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
               __pyx_t_13 = Py_TYPE(__pyx_t_12)->tp_iternext;
               index = 0; __pyx_t_10 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_10)) goto __pyx_L20_unpacking_failed;
               __Pyx_GOTREF(__pyx_t_10);
-              index = 1; __pyx_t_1 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_1)) goto __pyx_L20_unpacking_failed;
-              __Pyx_GOTREF(__pyx_t_1);
+              index = 1; __pyx_t_2 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_2)) goto __pyx_L20_unpacking_failed;
+              __Pyx_GOTREF(__pyx_t_2);
               index = 2; __pyx_t_11 = __pyx_t_13(__pyx_t_12); if (unlikely(!__pyx_t_11)) goto __pyx_L20_unpacking_failed;
               __Pyx_GOTREF(__pyx_t_11);
-              if (__Pyx_IternextUnpackEndCheck(__pyx_t_13(__pyx_t_12), 3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              if (__Pyx_IternextUnpackEndCheck(__pyx_t_13(__pyx_t_12), 3) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_t_13 = NULL;
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               goto __pyx_L21_unpacking_done;
@@ -16950,29 +16771,29 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
               __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
               __pyx_t_13 = NULL;
               if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __pyx_L21_unpacking_done:;
             }
             __Pyx_XDECREF(__pyx_v_i);
             __pyx_v_i = __pyx_t_10;
             __pyx_t_10 = 0;
             __Pyx_XDECREF(__pyx_v_s1);
-            __pyx_v_s1 = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_s1 = __pyx_t_2;
+            __pyx_t_2 = 0;
             __Pyx_XDECREF(__pyx_v_s2);
             __pyx_v_s2 = __pyx_t_11;
             __pyx_t_11 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":364
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":324
  *             f.write("\n")
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  *                 f.write("%d %f %f " % (i, s1, s2))             # <<<<<<<<<<<<<<
  *             f.write("\n")
- *             for i, w in enumerate(self.id2fword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  */
-            __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
-            __pyx_t_11 = PyTuple_New(3); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyTuple_New(3); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
             __Pyx_INCREF(__pyx_v_i);
             PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_v_i);
@@ -16983,74 +16804,74 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __Pyx_INCREF(__pyx_v_s2);
             PyTuple_SET_ITEM(__pyx_t_11, 2, __pyx_v_s2);
             __Pyx_GIVEREF(__pyx_v_s2);
-            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_50), ((PyObject *)__pyx_t_11)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+            __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_49), ((PyObject *)__pyx_t_11)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(((PyObject *)__pyx_t_2));
             __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
-            __pyx_t_11 = PyTuple_New(1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyTuple_New(1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
-            PyTuple_SET_ITEM(__pyx_t_11, 0, ((PyObject *)__pyx_t_1));
-            __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
-            __pyx_t_1 = 0;
-            __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 364; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
+            PyTuple_SET_ITEM(__pyx_t_11, 0, ((PyObject *)__pyx_t_2));
+            __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
+            __pyx_t_2 = 0;
+            __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":365
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":325
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  *                 f.write("%d %f %f " % (i, s1, s2))
  *             f.write("\n")             # <<<<<<<<<<<<<<
- *             for i, w in enumerate(self.id2fword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  */
-          __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_51), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_50), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":366
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":326
  *                 f.write("%d %f %f " % (i, s1, s2))
  *             f.write("\n")
- *             for i, w in enumerate(self.id2fword):             # <<<<<<<<<<<<<<
+ *             for i, w in enumerate(self.f_voc.id2word):             # <<<<<<<<<<<<<<
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")
  */
           __Pyx_INCREF(__pyx_int_0);
-          __pyx_t_1 = __pyx_int_0;
-          if (PyList_CheckExact(__pyx_v_self->id2fword) || PyTuple_CheckExact(__pyx_v_self->id2fword)) {
-            __pyx_t_2 = __pyx_v_self->id2fword; __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
+          __pyx_t_2 = __pyx_int_0;
+          if (PyList_CheckExact(__pyx_v_self->f_voc->id2word) || PyTuple_CheckExact(__pyx_v_self->f_voc->id2word)) {
+            __pyx_t_1 = __pyx_v_self->f_voc->id2word; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_self->id2fword); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_self->f_voc->id2word); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_11 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_11); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_11); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_11 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_11 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_11); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_11); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_11 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_11 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_11 = __pyx_t_9(__pyx_t_2);
+              __pyx_t_11 = __pyx_t_9(__pyx_t_1);
               if (unlikely(!__pyx_t_11)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
@@ -17059,25 +16880,25 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __Pyx_XDECREF(__pyx_v_w);
             __pyx_v_w = __pyx_t_11;
             __pyx_t_11 = 0;
-            __Pyx_INCREF(__pyx_t_1);
+            __Pyx_INCREF(__pyx_t_2);
             __Pyx_XDECREF(__pyx_v_i);
-            __pyx_v_i = __pyx_t_1;
-            __pyx_t_11 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_v_i = __pyx_t_2;
+            __pyx_t_11 = PyNumber_Add(__pyx_t_2, __pyx_int_1); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
-            __Pyx_DECREF(__pyx_t_1);
-            __pyx_t_1 = __pyx_t_11;
+            __Pyx_DECREF(__pyx_t_2);
+            __pyx_t_2 = __pyx_t_11;
             __pyx_t_11 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":367
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":327
  *             f.write("\n")
- *             for i, w in enumerate(self.id2fword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))             # <<<<<<<<<<<<<<
  *             f.write("\n")
- *             for i, w in enumerate(self.id2eword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  */
-            __pyx_t_11 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
-            __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __Pyx_INCREF(__pyx_v_i);
             PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_i);
@@ -17085,75 +16906,75 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __Pyx_INCREF(__pyx_v_w);
             PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_w);
             __Pyx_GIVEREF(__pyx_v_w);
-            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_52), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_51), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_10));
             __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-            __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_10));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_10));
             __pyx_t_10 = 0;
-            __pyx_t_10 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
             __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
           }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":368
- *             for i, w in enumerate(self.id2fword):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":328
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")             # <<<<<<<<<<<<<<
- *             for i, w in enumerate(self.id2eword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  */
-          __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_53), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_52), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":369
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":329
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")
- *             for i, w in enumerate(self.id2eword):             # <<<<<<<<<<<<<<
+ *             for i, w in enumerate(self.f_voc.id2word):             # <<<<<<<<<<<<<<
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")
  */
           __Pyx_INCREF(__pyx_int_0);
-          __pyx_t_2 = __pyx_int_0;
-          if (PyList_CheckExact(__pyx_v_self->id2eword) || PyTuple_CheckExact(__pyx_v_self->id2eword)) {
-            __pyx_t_1 = __pyx_v_self->id2eword; __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
+          __pyx_t_1 = __pyx_int_0;
+          if (PyList_CheckExact(__pyx_v_self->f_voc->id2word) || PyTuple_CheckExact(__pyx_v_self->f_voc->id2word)) {
+            __pyx_t_2 = __pyx_v_self->f_voc->id2word; __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_self->id2eword); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_self->f_voc->id2word); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
           }
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_10 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_10); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_10); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_10 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_10 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_10); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_10); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_10 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_10 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_10 = __pyx_t_9(__pyx_t_1);
+              __pyx_t_10 = __pyx_t_9(__pyx_t_2);
               if (unlikely(!__pyx_t_10)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
@@ -17162,25 +16983,25 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __Pyx_XDECREF(__pyx_v_w);
             __pyx_v_w = __pyx_t_10;
             __pyx_t_10 = 0;
-            __Pyx_INCREF(__pyx_t_2);
+            __Pyx_INCREF(__pyx_t_1);
             __Pyx_XDECREF(__pyx_v_i);
-            __pyx_v_i = __pyx_t_2;
-            __pyx_t_10 = PyNumber_Add(__pyx_t_2, __pyx_int_1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_v_i = __pyx_t_1;
+            __pyx_t_10 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __Pyx_DECREF(__pyx_t_2);
-            __pyx_t_2 = __pyx_t_10;
+            __Pyx_DECREF(__pyx_t_1);
+            __pyx_t_1 = __pyx_t_10;
             __pyx_t_10 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":370
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":330
  *             f.write("\n")
- *             for i, w in enumerate(self.id2eword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))             # <<<<<<<<<<<<<<
  *             f.write("\n")
  * 
  */
-            __pyx_t_10 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __Pyx_INCREF(__pyx_v_i);
             PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_i);
@@ -17188,36 +17009,36 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
             __Pyx_INCREF(__pyx_v_w);
             PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_w);
             __Pyx_GIVEREF(__pyx_v_w);
-            __pyx_t_11 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_52), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_51), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_11));
             __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-            __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_11));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_11));
             __pyx_t_11 = 0;
-            __pyx_t_11 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_11 = PyObject_Call(__pyx_t_10, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_11);
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
             __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
           }
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":371
- *             for i, w in enumerate(self.id2eword):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":331
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  * 
  */
-          __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_54), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_53), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -17228,54 +17049,54 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
         __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":359
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":319
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for i in self.f_index:
  *                 f.write("%d " % i)
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.BiLex.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_2, &__pyx_t_11) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_1, &__pyx_t_11) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_2);
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_GOTREF(__pyx_t_11);
-          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
-          __Pyx_GIVEREF(__pyx_t_1);
           __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
           __Pyx_GIVEREF(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_1);
+          PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
+          __Pyx_GIVEREF(__pyx_t_1);
           __Pyx_INCREF(__pyx_t_11);
           PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_11);
           __Pyx_GIVEREF(__pyx_t_11);
           __pyx_t_15 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_15)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_15)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_15);
           __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_15);
           __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-          if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_16 = (!__pyx_t_14);
           if (__pyx_t_16) {
-            __Pyx_GIVEREF(__pyx_t_1);
             __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_GIVEREF(__pyx_t_1);
             __Pyx_GIVEREF(__pyx_t_11);
-            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_2, __pyx_t_11);
-            __pyx_t_1 = 0; __pyx_t_2 = 0; __pyx_t_11 = 0; 
-            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_1, __pyx_t_11);
+            __pyx_t_2 = 0; __pyx_t_1 = 0; __pyx_t_11 = 0; 
+            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L28;
           }
           __pyx_L28:;
           __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
           goto __pyx_L8_exception_handled;
         }
@@ -17295,13 +17116,13 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_55, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_54, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_16 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_16 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L29;
@@ -17334,8 +17155,8 @@ static PyObject *__pyx_pf_3_sa_5BiLex_12write_enhanced(struct __pyx_obj_3_sa_BiL
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_15get_score(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_3_sa_5BiLex_15get_score(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_3_sa_5BiLex_17get_score(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_3_sa_5BiLex_17get_score(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_fword = 0;
   PyObject *__pyx_v_eword = 0;
   PyObject *__pyx_v_col = 0;
@@ -17363,16 +17184,16 @@ static PyObject *__pyx_pw_3_sa_5BiLex_15get_score(PyObject *__pyx_v_self, PyObje
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__eword)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, 1); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, 1); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__col)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, 2); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, 2); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_score") < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_score") < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
       goto __pyx_L5_argtuple_error;
@@ -17387,18 +17208,18 @@ static PyObject *__pyx_pw_3_sa_5BiLex_15get_score(PyObject *__pyx_v_self, PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("get_score", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[5]; __pyx_lineno = 334; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.BiLex.get_score", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_14get_score(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), __pyx_v_fword, __pyx_v_eword, __pyx_v_col);
+  __pyx_r = __pyx_pf_3_sa_5BiLex_16get_score(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), __pyx_v_fword, __pyx_v_eword, __pyx_v_col);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":374
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":334
  * 
  * 
  *     def get_score(self, fword, eword, col):             # <<<<<<<<<<<<<<
@@ -17406,7 +17227,7 @@ static PyObject *__pyx_pw_3_sa_5BiLex_15get_score(PyObject *__pyx_v_self, PyObje
  * 
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword, PyObject *__pyx_v_eword, PyObject *__pyx_v_col) {
+static PyObject *__pyx_pf_3_sa_5BiLex_16get_score(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_fword, PyObject *__pyx_v_eword, PyObject *__pyx_v_col) {
   PyObject *__pyx_v_e_id = 0;
   PyObject *__pyx_v_f_id = 0;
   PyObject *__pyx_v_low = 0;
@@ -17415,119 +17236,119 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
   PyObject *__pyx_v_val = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
+  PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  Py_ssize_t __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  Py_ssize_t __pyx_t_7;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("get_score", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":377
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":337
  *         cdef e_id, f_id, low, high, midpoint, val
  * 
- *         if eword not in self.eword2id:             # <<<<<<<<<<<<<<
- *             return None
- *         if fword not in self.fword2id:
+ *         f_id = self.f_voc.get(fword, None)             # <<<<<<<<<<<<<<
+ *         e_id = self.e_voc.get(eword, None)
+ *         if f_id is None or e_id is None: return None
  */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_eword, __pyx_v_self->eword2id, Py_NE)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 377; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_1) {
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self->f_voc), __pyx_n_s__get); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 337; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 337; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_fword);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_fword);
+  __Pyx_GIVEREF(__pyx_v_fword);
+  __Pyx_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 337; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __pyx_v_f_id = __pyx_t_3;
+  __pyx_t_3 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":378
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":338
+ * 
+ *         f_id = self.f_voc.get(fword, None)
+ *         e_id = self.e_voc.get(eword, None)             # <<<<<<<<<<<<<<
+ *         if f_id is None or e_id is None: return None
  * 
- *         if eword not in self.eword2id:
- *             return None             # <<<<<<<<<<<<<<
- *         if fword not in self.fword2id:
- *             return None
- */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_INCREF(Py_None);
-    __pyx_r = Py_None;
-    goto __pyx_L0;
-    goto __pyx_L3;
-  }
-  __pyx_L3:;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":379
- *         if eword not in self.eword2id:
- *             return None
- *         if fword not in self.fword2id:             # <<<<<<<<<<<<<<
- *             return None
- *         f_id = self.fword2id[fword]
  */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_fword, __pyx_v_self->fword2id, Py_NE)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 379; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_1) {
+  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self->e_voc), __pyx_n_s__get); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(__pyx_v_eword);
+  PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_eword);
+  __Pyx_GIVEREF(__pyx_v_eword);
+  __Pyx_INCREF(Py_None);
+  PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 338; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __pyx_v_e_id = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":380
- *             return None
- *         if fword not in self.fword2id:
- *             return None             # <<<<<<<<<<<<<<
- *         f_id = self.fword2id[fword]
- *         e_id = self.eword2id[eword]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":339
+ *         f_id = self.f_voc.get(fword, None)
+ *         e_id = self.e_voc.get(eword, None)
+ *         if f_id is None or e_id is None: return None             # <<<<<<<<<<<<<<
+ * 
+ *         low = self.f_index.arr[f_id]
  */
+  __pyx_t_4 = (__pyx_v_f_id == Py_None);
+  if (!__pyx_t_4) {
+    __pyx_t_5 = (__pyx_v_e_id == Py_None);
+    __pyx_t_6 = __pyx_t_5;
+  } else {
+    __pyx_t_6 = __pyx_t_4;
+  }
+  if (__pyx_t_6) {
     __Pyx_XDECREF(__pyx_r);
     __Pyx_INCREF(Py_None);
     __pyx_r = Py_None;
     goto __pyx_L0;
-    goto __pyx_L4;
+    goto __pyx_L3;
   }
-  __pyx_L4:;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":381
- *         if fword not in self.fword2id:
- *             return None
- *         f_id = self.fword2id[fword]             # <<<<<<<<<<<<<<
- *         e_id = self.eword2id[eword]
- *         low = self.f_index.arr[f_id]
- */
-  __pyx_t_2 = PyObject_GetItem(__pyx_v_self->fword2id, __pyx_v_fword); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 381; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_f_id = __pyx_t_2;
-  __pyx_t_2 = 0;
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":382
- *             return None
- *         f_id = self.fword2id[fword]
- *         e_id = self.eword2id[eword]             # <<<<<<<<<<<<<<
- *         low = self.f_index.arr[f_id]
- *         high = self.f_index.arr[f_id+1]
- */
-  __pyx_t_2 = PyObject_GetItem(__pyx_v_self->eword2id, __pyx_v_eword); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 382; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_e_id = __pyx_t_2;
-  __pyx_t_2 = 0;
+  __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":383
- *         f_id = self.fword2id[fword]
- *         e_id = self.eword2id[eword]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":341
+ *         if f_id is None or e_id is None: return None
+ * 
  *         low = self.f_index.arr[f_id]             # <<<<<<<<<<<<<<
  *         high = self.f_index.arr[f_id+1]
  *         while high - low > 0:
  */
-  __pyx_t_3 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_3 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_3])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_low = __pyx_t_2;
-  __pyx_t_2 = 0;
+  __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_f_id); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_7])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 341; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_low = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":384
- *         e_id = self.eword2id[eword]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":342
+ * 
  *         low = self.f_index.arr[f_id]
  *         high = self.f_index.arr[f_id+1]             # <<<<<<<<<<<<<<
  *         while high - low > 0:
  *             midpoint = (low+high)/2
  */
-  __pyx_t_2 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyIndex_AsSsize_t(__pyx_t_2); if (unlikely((__pyx_t_3 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_3])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 384; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_high = __pyx_t_2;
-  __pyx_t_2 = 0;
+  __pyx_t_1 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 342; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 342; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_7])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 342; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_high = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":385
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":343
  *         low = self.f_index.arr[f_id]
  *         high = self.f_index.arr[f_id+1]
  *         while high - low > 0:             # <<<<<<<<<<<<<<
@@ -17535,69 +17356,69 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
  *             val = self.e_index.arr[midpoint]
  */
   while (1) {
-    __pyx_t_2 = PyNumber_Subtract(__pyx_v_high, __pyx_v_low); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_RichCompare(__pyx_t_2, __pyx_int_0, Py_GT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyNumber_Subtract(__pyx_v_high, __pyx_v_low); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_int_0, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 343; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 385; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (!__pyx_t_1) break;
+    if (!__pyx_t_6) break;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":386
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":344
  *         high = self.f_index.arr[f_id+1]
  *         while high - low > 0:
  *             midpoint = (low+high)/2             # <<<<<<<<<<<<<<
  *             val = self.e_index.arr[midpoint]
  *             if val == e_id:
  */
-    __pyx_t_4 = PyNumber_Add(__pyx_v_low, __pyx_v_high); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_2 = __Pyx_PyNumber_Divide(__pyx_t_4, __pyx_int_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyNumber_Add(__pyx_v_low, __pyx_v_high); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __pyx_t_1 = __Pyx_PyNumber_Divide(__pyx_t_2, __pyx_int_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_XDECREF(__pyx_v_midpoint);
-    __pyx_v_midpoint = __pyx_t_2;
-    __pyx_t_2 = 0;
+    __pyx_v_midpoint = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":387
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":345
  *         while high - low > 0:
  *             midpoint = (low+high)/2
  *             val = self.e_index.arr[midpoint]             # <<<<<<<<<<<<<<
  *             if val == e_id:
  *                 if col == 0:
  */
-    __pyx_t_3 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_3 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_2 = PyInt_FromLong((__pyx_v_self->e_index->arr[__pyx_t_3])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong((__pyx_v_self->e_index->arr[__pyx_t_7])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 345; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
     __Pyx_XDECREF(__pyx_v_val);
-    __pyx_v_val = __pyx_t_2;
-    __pyx_t_2 = 0;
+    __pyx_v_val = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":388
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":346
  *             midpoint = (low+high)/2
  *             val = self.e_index.arr[midpoint]
  *             if val == e_id:             # <<<<<<<<<<<<<<
  *                 if col == 0:
  *                     return self.col1.arr[midpoint]
  */
-    __pyx_t_2 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 388; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 388; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (__pyx_t_1) {
+    __pyx_t_1 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    if (__pyx_t_6) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":389
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":347
  *             val = self.e_index.arr[midpoint]
  *             if val == e_id:
  *                 if col == 0:             # <<<<<<<<<<<<<<
  *                     return self.col1.arr[midpoint]
  *                 if col == 1:
  */
-      __pyx_t_2 = PyObject_RichCompare(__pyx_v_col, __pyx_int_0, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 389; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 389; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__pyx_t_1) {
+      __pyx_t_1 = PyObject_RichCompare(__pyx_v_col, __pyx_int_0, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      if (__pyx_t_6) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":390
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":348
  *             if val == e_id:
  *                 if col == 0:
  *                     return self.col1.arr[midpoint]             # <<<<<<<<<<<<<<
@@ -17605,29 +17426,29 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
  *                     return self.col2.arr[midpoint]
  */
         __Pyx_XDECREF(__pyx_r);
-        __pyx_t_3 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_3 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->col1->arr[__pyx_t_3])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_2);
-        __pyx_r = __pyx_t_2;
-        __pyx_t_2 = 0;
+        __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->col1->arr[__pyx_t_7])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 348; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_1);
+        __pyx_r = __pyx_t_1;
+        __pyx_t_1 = 0;
         goto __pyx_L0;
-        goto __pyx_L8;
+        goto __pyx_L7;
       }
-      __pyx_L8:;
+      __pyx_L7:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":391
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":349
  *                 if col == 0:
  *                     return self.col1.arr[midpoint]
  *                 if col == 1:             # <<<<<<<<<<<<<<
  *                     return self.col2.arr[midpoint]
  *             if val > e_id:
  */
-      __pyx_t_2 = PyObject_RichCompare(__pyx_v_col, __pyx_int_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 391; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 391; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (__pyx_t_1) {
+      __pyx_t_1 = PyObject_RichCompare(__pyx_v_col, __pyx_int_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 349; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 349; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      if (__pyx_t_6) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":392
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":350
  *                     return self.col1.arr[midpoint]
  *                 if col == 1:
  *                     return self.col2.arr[midpoint]             # <<<<<<<<<<<<<<
@@ -17635,32 +17456,32 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
  *                 high = midpoint
  */
         __Pyx_XDECREF(__pyx_r);
-        __pyx_t_3 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_3 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->col2->arr[__pyx_t_3])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __Pyx_GOTREF(__pyx_t_2);
-        __pyx_r = __pyx_t_2;
-        __pyx_t_2 = 0;
+        __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_midpoint); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->col2->arr[__pyx_t_7])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __Pyx_GOTREF(__pyx_t_1);
+        __pyx_r = __pyx_t_1;
+        __pyx_t_1 = 0;
         goto __pyx_L0;
-        goto __pyx_L9;
+        goto __pyx_L8;
       }
-      __pyx_L9:;
-      goto __pyx_L7;
+      __pyx_L8:;
+      goto __pyx_L6;
     }
-    __pyx_L7:;
+    __pyx_L6:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":393
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":351
  *                 if col == 1:
  *                     return self.col2.arr[midpoint]
  *             if val > e_id:             # <<<<<<<<<<<<<<
  *                 high = midpoint
  *             if val < e_id:
  */
-    __pyx_t_2 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (__pyx_t_1) {
+    __pyx_t_1 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    if (__pyx_t_6) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":394
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":352
  *                     return self.col2.arr[midpoint]
  *             if val > e_id:
  *                 high = midpoint             # <<<<<<<<<<<<<<
@@ -17670,40 +17491,40 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
       __Pyx_INCREF(__pyx_v_midpoint);
       __Pyx_DECREF(__pyx_v_high);
       __pyx_v_high = __pyx_v_midpoint;
-      goto __pyx_L10;
+      goto __pyx_L9;
     }
-    __pyx_L10:;
+    __pyx_L9:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":395
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":353
  *             if val > e_id:
  *                 high = midpoint
  *             if val < e_id:             # <<<<<<<<<<<<<<
  *                 low = midpoint + 1
  *         return None
  */
-    __pyx_t_2 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (__pyx_t_1) {
+    __pyx_t_1 = PyObject_RichCompare(__pyx_v_val, __pyx_v_e_id, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 353; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 353; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    if (__pyx_t_6) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":396
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":354
  *                 high = midpoint
  *             if val < e_id:
  *                 low = midpoint + 1             # <<<<<<<<<<<<<<
  *         return None
  * 
  */
-      __pyx_t_2 = PyNumber_Add(__pyx_v_midpoint, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 396; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_1 = PyNumber_Add(__pyx_v_midpoint, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_v_low);
-      __pyx_v_low = __pyx_t_2;
-      __pyx_t_2 = 0;
-      goto __pyx_L11;
+      __pyx_v_low = __pyx_t_1;
+      __pyx_t_1 = 0;
+      goto __pyx_L10;
     }
-    __pyx_L11:;
+    __pyx_L10:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":397
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":355
  *             if val < e_id:
  *                 low = midpoint + 1
  *         return None             # <<<<<<<<<<<<<<
@@ -17718,8 +17539,9 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_AddTraceback("_sa.BiLex.get_score", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -17735,36 +17557,31 @@ static PyObject *__pyx_pf_3_sa_5BiLex_14get_score(struct __pyx_obj_3_sa_BiLex *_
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_5BiLex_17write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static char __pyx_doc_3_sa_5BiLex_16write_text[] = "Note: does not guarantee writing the dictionary in the original order";
-static PyObject *__pyx_pw_3_sa_5BiLex_17write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_5BiLex_19write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static char __pyx_doc_3_sa_5BiLex_18write_text[] = "Note: does not guarantee writing the dictionary in the original order";
+static PyObject *__pyx_pw_3_sa_5BiLex_19write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.BiLex.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_5BiLex_16write_text(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 358; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_5BiLex_18write_text(((struct __pyx_obj_3_sa_BiLex *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":400
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":358
  * 
  * 
- *     def write_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         """Note: does not guarantee writing the dictionary in the original order"""
  *         cdef i, N, e_id, f_id
  */
 
-static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_5BiLex_18write_text(struct __pyx_obj_3_sa_BiLex *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_i = 0;
   PyObject *__pyx_v_N = 0;
   PyObject *__pyx_v_e_id = 0;
@@ -17793,7 +17610,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":404
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":362
  *         cdef i, N, e_id, f_id
  * 
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
@@ -17801,27 +17618,25 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
  *             f_id = 0
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -17833,7 +17648,7 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":405
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":363
  * 
  *         with open(filename, "w") as f:
  *             N = len(self.e_index)             # <<<<<<<<<<<<<<
@@ -17842,14 +17657,14 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
  */
           __pyx_t_4 = ((PyObject *)__pyx_v_self->e_index);
           __Pyx_INCREF(__pyx_t_4);
-          __pyx_t_8 = PyObject_Length(__pyx_t_4); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 405; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_8 = PyObject_Length(__pyx_t_4); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __pyx_t_4 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 405; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
           __pyx_v_N = __pyx_t_4;
           __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":406
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":364
  *         with open(filename, "w") as f:
  *             N = len(self.e_index)
  *             f_id = 0             # <<<<<<<<<<<<<<
@@ -17859,22 +17674,22 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
           __Pyx_INCREF(__pyx_int_0);
           __pyx_v_f_id = __pyx_int_0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":407
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":365
  *             N = len(self.e_index)
  *             f_id = 0
  *             for i from 0 <= i < N:             # <<<<<<<<<<<<<<
  *                 while self.f_index.arr[f_id+1] == i:
  *                     f_id = f_id + 1
  */
-          __pyx_t_9 = __Pyx_PyInt_AsLong(__pyx_v_N); if (unlikely((__pyx_t_9 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_9 = __Pyx_PyInt_AsLong(__pyx_v_N); if (unlikely((__pyx_t_9 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10++) {
-            __pyx_t_4 = PyInt_FromLong(__pyx_t_10); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyInt_FromLong(__pyx_t_10); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __Pyx_XDECREF(__pyx_v_i);
             __pyx_v_i = __pyx_t_4;
             __pyx_t_4 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":408
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":366
  *             f_id = 0
  *             for i from 0 <= i < N:
  *                 while self.f_index.arr[f_id+1] == i:             # <<<<<<<<<<<<<<
@@ -17882,90 +17697,90 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
  *                 e_id = self.e_index.arr[i]
  */
             while (1) {
-              __pyx_t_4 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_4);
-              __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_t_4); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-              __pyx_t_4 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_4 = PyInt_FromLong((__pyx_v_self->f_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_GOTREF(__pyx_t_4);
-              __pyx_t_1 = PyObject_RichCompare(__pyx_t_4, __pyx_v_i, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyObject_RichCompare(__pyx_t_4, __pyx_v_i, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-              __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+              __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 366; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
               if (!__pyx_t_11) break;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":409
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":367
  *             for i from 0 <= i < N:
  *                 while self.f_index.arr[f_id+1] == i:
  *                     f_id = f_id + 1             # <<<<<<<<<<<<<<
  *                 e_id = self.e_index.arr[i]
  *                 score1 = self.col1.arr[i]
  */
-              __pyx_t_1 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-              __Pyx_GOTREF(__pyx_t_1);
+              __pyx_t_2 = PyNumber_Add(__pyx_v_f_id, __pyx_int_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __Pyx_GOTREF(__pyx_t_2);
               __Pyx_DECREF(__pyx_v_f_id);
-              __pyx_v_f_id = __pyx_t_1;
-              __pyx_t_1 = 0;
+              __pyx_v_f_id = __pyx_t_2;
+              __pyx_t_2 = 0;
             }
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":410
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":368
  *                 while self.f_index.arr[f_id+1] == i:
  *                     f_id = f_id + 1
  *                 e_id = self.e_index.arr[i]             # <<<<<<<<<<<<<<
  *                 score1 = self.col1.arr[i]
  *                 score2 = self.col2.arr[i]
  */
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_1 = PyInt_FromLong((__pyx_v_self->e_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyInt_FromLong((__pyx_v_self->e_index->arr[__pyx_t_8])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_XDECREF(__pyx_v_e_id);
-            __pyx_v_e_id = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_e_id = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":411
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":369
  *                     f_id = f_id + 1
  *                 e_id = self.e_index.arr[i]
  *                 score1 = self.col1.arr[i]             # <<<<<<<<<<<<<<
  *                 score2 = self.col2.arr[i]
- *                 f.write("%s %s %.6f %.6f\n" % (self.id2fword[f_id], self.id2eword[e_id], score1, score2))
+ *                 f.write("%s %s %.6f %.6f\n" % (self.f_voc.id2word[f_id], self.e_voc.id2word[e_id], score1, score2))
  */
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 411; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->col1->arr[__pyx_t_8])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 411; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->col1->arr[__pyx_t_8])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 369; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_XDECREF(__pyx_v_score1);
-            __pyx_v_score1 = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_score1 = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":412
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":370
  *                 e_id = self.e_index.arr[i]
  *                 score1 = self.col1.arr[i]
  *                 score2 = self.col2.arr[i]             # <<<<<<<<<<<<<<
- *                 f.write("%s %s %.6f %.6f\n" % (self.id2fword[f_id], self.id2eword[e_id], score1, score2))
+ *                 f.write("%s %s %.6f %.6f\n" % (self.f_voc.id2word[f_id], self.e_voc.id2word[e_id], score1, score2))
  */
-            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->col2->arr[__pyx_t_8])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_8 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_8 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->col2->arr[__pyx_t_8])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 370; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
             __Pyx_XDECREF(__pyx_v_score2);
-            __pyx_v_score2 = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_score2 = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":413
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":371
  *                 score1 = self.col1.arr[i]
  *                 score2 = self.col2.arr[i]
- *                 f.write("%s %s %.6f %.6f\n" % (self.id2fword[f_id], self.id2eword[e_id], score1, score2))             # <<<<<<<<<<<<<<
+ *                 f.write("%s %s %.6f %.6f\n" % (self.f_voc.id2word[f_id], self.e_voc.id2word[e_id], score1, score2))             # <<<<<<<<<<<<<<
  */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_4 = PyObject_GetItem(__pyx_v_self->id2fword, __pyx_v_f_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_4);
-            __pyx_t_2 = PyObject_GetItem(__pyx_v_self->id2eword, __pyx_v_e_id); if (!__pyx_t_2) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_12 = PyTuple_New(4); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyObject_GetItem(__pyx_v_self->f_voc->id2word, __pyx_v_f_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_4);
+            __pyx_t_1 = PyObject_GetItem(__pyx_v_self->e_voc->id2word, __pyx_v_e_id); if (!__pyx_t_1) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_12 = PyTuple_New(4); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
             PyTuple_SET_ITEM(__pyx_t_12, 0, __pyx_t_4);
             __Pyx_GIVEREF(__pyx_t_4);
-            PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_2);
-            __Pyx_GIVEREF(__pyx_t_2);
+            PyTuple_SET_ITEM(__pyx_t_12, 1, __pyx_t_1);
+            __Pyx_GIVEREF(__pyx_t_1);
             __Pyx_INCREF(__pyx_v_score1);
             PyTuple_SET_ITEM(__pyx_t_12, 2, __pyx_v_score1);
             __Pyx_GIVEREF(__pyx_v_score1);
@@ -17973,35 +17788,35 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
             PyTuple_SET_ITEM(__pyx_t_12, 3, __pyx_v_score2);
             __Pyx_GIVEREF(__pyx_v_score2);
             __pyx_t_4 = 0;
-            __pyx_t_2 = 0;
-            __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_56), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(((PyObject *)__pyx_t_2));
+            __pyx_t_1 = 0;
+            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_55), ((PyObject *)__pyx_t_12)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(((PyObject *)__pyx_t_1));
             __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
-            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_12 = PyTuple_New(1); if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_12);
-            PyTuple_SET_ITEM(__pyx_t_12, 0, ((PyObject *)__pyx_t_2));
-            __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-            __pyx_t_2 = 0;
-            __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+            PyTuple_SET_ITEM(__pyx_t_12, 0, ((PyObject *)__pyx_t_1));
+            __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+            __pyx_t_1 = 0;
+            __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_12), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
             __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-            __pyx_t_10 = __Pyx_PyInt_AsLong(__pyx_v_i); if (unlikely((__pyx_t_10 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_DECREF(((PyObject *)__pyx_t_12)); __pyx_t_12 = 0;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __pyx_t_10 = __Pyx_PyInt_AsLong(__pyx_v_i); if (unlikely((__pyx_t_10 == (long)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           }
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":407
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":365
  *             N = len(self.e_index)
  *             f_id = 0
  *             for i from 0 <= i < N:             # <<<<<<<<<<<<<<
  *                 while self.f_index.arr[f_id+1] == i:
  *                     f_id = f_id + 1
  */
-          __pyx_t_2 = PyInt_FromLong(__pyx_t_10); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyInt_FromLong(__pyx_t_10); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_XDECREF(__pyx_v_i);
-          __pyx_v_i = __pyx_t_2;
-          __pyx_t_2 = 0;
+          __pyx_v_i = __pyx_t_1;
+          __pyx_t_1 = 0;
         }
         __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
         __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
@@ -18009,11 +17824,11 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
         __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+        __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":404
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":362
  *         cdef i, N, e_id, f_id
  * 
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
@@ -18022,43 +17837,43 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.BiLex.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_2, &__pyx_t_12, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __Pyx_GOTREF(__pyx_t_12);
+          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_12, &__pyx_t_2) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_12);
+          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_2);
-          PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
-          __Pyx_GIVEREF(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_1);
+          PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
+          __Pyx_GIVEREF(__pyx_t_1);
           __Pyx_INCREF(__pyx_t_12);
           PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_12);
           __Pyx_GIVEREF(__pyx_t_12);
-          __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_1);
-          __Pyx_GIVEREF(__pyx_t_1);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
           __pyx_t_13 = PyObject_Call(__pyx_t_3, __pyx_t_4, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_13);
           __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_13);
           __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_14 = (!__pyx_t_11);
           if (__pyx_t_14) {
-            __Pyx_GIVEREF(__pyx_t_2);
-            __Pyx_GIVEREF(__pyx_t_12);
             __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_2, __pyx_t_12, __pyx_t_1);
-            __pyx_t_2 = 0; __pyx_t_12 = 0; __pyx_t_1 = 0; 
-            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_GIVEREF(__pyx_t_12);
+            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_ErrRestore(__pyx_t_1, __pyx_t_12, __pyx_t_2);
+            __pyx_t_1 = 0; __pyx_t_12 = 0; __pyx_t_2 = 0; 
+            {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L22;
           }
           __pyx_L22:;
           __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
           __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           goto __pyx_L8_exception_handled;
         }
         __pyx_L9_except_error:;
@@ -18077,13 +17892,13 @@ static PyObject *__pyx_pf_3_sa_5BiLex_16write_text(struct __pyx_obj_3_sa_BiLex *
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_57, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_56, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_14 < 0)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L23;
@@ -19069,7 +18884,7 @@ static PyObject *__pyx_pf_3_sa_6BitSet_10__str__(struct __pyx_obj_3_sa_BitSet *_
   __Pyx_XDECREF(__pyx_r);
   __pyx_t_1 = ((PyObject *)__pyx_f_3_sa_dec2bin(__pyx_v_self->b->bitset)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyNumber_Add(__pyx_t_1, ((PyObject *)__pyx_kp_s_58)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyNumber_Add(__pyx_t_1, ((PyObject *)__pyx_kp_s_57)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __pyx_t_1 = PyInt_FromLong(__pyx_v_self->b->size); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -19086,7 +18901,7 @@ static PyObject *__pyx_pf_3_sa_6BitSet_10__str__(struct __pyx_obj_3_sa_BitSet *_
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyNumber_Add(__pyx_t_3, ((PyObject *)__pyx_kp_s_4)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyNumber_Add(__pyx_t_3, ((PyObject *)__pyx_kp_s_58)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __pyx_t_3 = PyInt_FromLong(__pyx_v_self->b->min_val); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -19103,7 +18918,7 @@ static PyObject *__pyx_pf_3_sa_6BitSet_10__str__(struct __pyx_obj_3_sa_BitSet *_
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyNumber_Add(__pyx_t_2, ((PyObject *)__pyx_kp_s_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyNumber_Add(__pyx_t_2, ((PyObject *)__pyx_kp_s_58)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_t_2 = PyInt_FromLong(__pyx_v_self->b->max_val); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 142; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -19374,8 +19189,8 @@ static PyObject *__pyx_f_3_sa_dec2bin(long __pyx_v_i) {
  *     cdef unsigned d
  *     for d in range(MIN_BOTTOM_SIZE):
  */
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_45));
-  __pyx_v_result = __pyx_kp_s_45;
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_60));
+  __pyx_v_result = __pyx_kp_s_60;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/veb.pxi":160
  *     cdef str result = ""
@@ -21366,7 +21181,7 @@ static int __pyx_pw_3_sa_3LCP_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
@@ -21377,13 +21192,13 @@ static int __pyx_pw_3_sa_3LCP_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[9]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[11]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.LCP.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sa), __pyx_ptype_3_sa_SuffixArray, 1, "sa", 0))) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sa), __pyx_ptype_3_sa_SuffixArray, 1, "sa", 0))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_3_sa_3LCP___cinit__(((struct __pyx_obj_3_sa_LCP *)__pyx_v_self), __pyx_v_sa);
   goto __pyx_L0;
   __pyx_L1_error:;
@@ -21429,12 +21244,12 @@ static int __pyx_pf_3_sa_3LCP___cinit__(struct __pyx_obj_3_sa_LCP *__pyx_v_self,
  *         self.sa = sa
  *         n = self.sa.sa.len
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_61), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_62), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -21468,13 +21283,13 @@ static int __pyx_pf_3_sa_3LCP___cinit__(struct __pyx_obj_3_sa_LCP *__pyx_v_self,
  * 
  *         rank = IntList(initial_len=n)
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __pyx_t_2 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
@@ -21490,13 +21305,13 @@ static int __pyx_pf_3_sa_3LCP___cinit__(struct __pyx_obj_3_sa_LCP *__pyx_v_self,
  *         for i from 0 <= i < n:
  *             rank.arr[sa.sa.arr[i]] = i
  */
-  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __pyx_v_rank = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
@@ -21655,12 +21470,12 @@ static int __pyx_pf_3_sa_3LCP___cinit__(struct __pyx_obj_3_sa_LCP *__pyx_v_self,
  * 
  *     def compute_stats(self, int max_n):
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_63), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_64), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -21688,7 +21503,7 @@ static PyObject *__pyx_pw_3_sa_3LCP_3compute_stats(PyObject *__pyx_v_self, PyObj
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("compute_stats (wrapper)", 0);
   assert(__pyx_arg_max_n); {
-    __pyx_v_max_n = __Pyx_PyInt_AsInt(__pyx_arg_max_n); if (unlikely((__pyx_v_max_n == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_max_n = __Pyx_PyInt_AsInt(__pyx_arg_max_n); if (unlikely((__pyx_v_max_n == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L3_error:;
@@ -21728,7 +21543,7 @@ static PyObject *__pyx_pf_3_sa_3LCP_2compute_stats(struct __pyx_obj_3_sa_LCP *__
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __pyx_cur_scope->__pyx_v_max_n = __pyx_v_max_n;
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_3LCP_4generator1, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_3LCP_4generator1, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -21770,7 +21585,7 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/lcp.pxi":48
  *         cdef VEB veb
@@ -21788,7 +21603,7 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *         for n from 0 <= n < max_n:
  *             ngram_starts.append(IntList(initial_len=N))
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 50; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
   __pyx_cur_scope->__pyx_v_ngram_starts = __pyx_t_1;
@@ -21811,16 +21626,16 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  * 
  *         run_start = IntList(initial_len=max_n)
  */
-    __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_3 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_N); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_N); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-    __pyx_t_4 = PyList_Append(__pyx_cur_scope->__pyx_v_ngram_starts, __pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyList_Append(__pyx_cur_scope->__pyx_v_ngram_starts, __pyx_t_3); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 52; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   }
 
@@ -21831,13 +21646,13 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *         veb = VEB(N)
  * 
  */
-  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-  __pyx_t_1 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_max_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_max_n); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __Pyx_GIVEREF(__pyx_t_1);
@@ -21851,14 +21666,14 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  * 
  *         for i from 0 <= i < N:
  */
-  __pyx_t_1 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_VEB)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_VEB)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __Pyx_GIVEREF(__pyx_t_1);
@@ -21969,9 +21784,9 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *                     while ngram_start.arr[freq] > 0:
  *                         freq = freq + 1 # cheating a bit, should be ok for sparse histogram
  */
-        __pyx_t_1 = __Pyx_GetItemInt_List(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_starts), __pyx_cur_scope->__pyx_v_n, sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = __Pyx_GetItemInt_List(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_starts), __pyx_cur_scope->__pyx_v_n, sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 67; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_start));
         __Pyx_XDECREF(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_start));
         __Pyx_GIVEREF(__pyx_t_1);
@@ -22059,9 +21874,9 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *                 iii = i
  *                 rs = ngram_start.arr[iii]
  */
-      __pyx_t_1 = __Pyx_GetItemInt_List(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_starts), __pyx_cur_scope->__pyx_v_n, sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = __Pyx_GetItemInt_List(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_starts), __pyx_cur_scope->__pyx_v_n, sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
-      if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_start));
       __Pyx_XDECREF(((PyObject *)__pyx_cur_scope->__pyx_v_ngram_start));
       __Pyx_GIVEREF(__pyx_t_1);
@@ -22176,17 +21991,17 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *                         yield i, n+1, ngram
  *                     iii = iii + 1
  */
-          __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
           __pyx_t_9 = (__pyx_cur_scope->__pyx_v_n + 1);
           for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_9; __pyx_t_6+=1) {
             __pyx_cur_scope->__pyx_v_k = __pyx_t_6;
-            __pyx_t_3 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_self->sa->darray->data->arr[(__pyx_cur_scope->__pyx_v_j + __pyx_cur_scope->__pyx_v_k)])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_3 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_self->sa->darray->data->arr[(__pyx_cur_scope->__pyx_v_j + __pyx_cur_scope->__pyx_v_k)])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(__pyx_t_3);
-            if (unlikely(__Pyx_PyList_Append(__pyx_t_1, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            if (unlikely(__Pyx_PyList_Append(__pyx_t_1, (PyObject*)__pyx_t_3))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           }
-          __pyx_t_3 = ((PyObject *)PyList_AsTuple(__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = ((PyObject *)PyList_AsTuple(__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_3));
           __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           __Pyx_XGOTREF(((PyObject *)__pyx_cur_scope->__pyx_v_ngram));
@@ -22202,11 +22017,11 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
  *                     iii = iii + 1
  *                     rs = ngram_start.arr[iii]
  */
-          __pyx_t_3 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
-          __pyx_t_1 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_n + 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_1 = PyInt_FromLong((__pyx_cur_scope->__pyx_v_n + 1)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_10 = PyTuple_New(3); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_10);
           PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_3);
           __Pyx_GIVEREF(__pyx_t_3);
@@ -22227,7 +22042,7 @@ static PyObject *__pyx_gb_3_sa_3LCP_4generator1(__pyx_GeneratorObject *__pyx_gen
           return __pyx_r;
           __pyx_L26_resume_from_yield:;
           __pyx_t_2 = __pyx_cur_scope->__pyx_t_0;
-          if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           goto __pyx_L23;
         }
         __pyx_L23:;
@@ -22311,7 +22126,7 @@ static int __pyx_pf_3_sa_8Alphabet___cinit__(struct __pyx_obj_3_sa_Alphabet *__p
  *         self.nonterminals = StringMap()
  *         self.id2sym = {}
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->terminals);
@@ -22326,7 +22141,7 @@ static int __pyx_pf_3_sa_8Alphabet___cinit__(struct __pyx_obj_3_sa_Alphabet *__p
  *         self.id2sym = {}
  *         self.first_nonterminal = -1
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->nonterminals);
@@ -22341,7 +22156,7 @@ static int __pyx_pf_3_sa_8Alphabet___cinit__(struct __pyx_obj_3_sa_Alphabet *__p
  *         self.first_nonterminal = -1
  * 
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
   __Pyx_GOTREF(__pyx_v_self->id2sym);
@@ -22720,13 +22535,13 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
  *                 return self.id2sym[sym]
  *             ind = self.getindex(sym)
  */
-    __pyx_t_2 = PyInt_FromLong(__pyx_v_sym); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong(__pyx_v_sym); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     if (unlikely(((PyObject *)__pyx_v_self->id2sym) == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-      {__pyx_filename = __pyx_f[10]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[12]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_3 = (__Pyx_PyDict_Contains(__pyx_t_2, ((PyObject *)__pyx_v_self->id2sym), Py_EQ)); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = (__Pyx_PyDict_Contains(__pyx_t_2, ((PyObject *)__pyx_v_self->id2sym), Py_EQ)); if (unlikely(__pyx_t_3 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     if (__pyx_t_3) {
 
@@ -22739,11 +22554,11 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
  */
       if (unlikely(((PyObject *)__pyx_v_self->id2sym) == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      __pyx_t_2 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = PyBytes_AsString(__pyx_t_2); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyBytes_AsString(__pyx_t_2); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 55; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
       __pyx_r = __pyx_t_4;
       goto __pyx_L0;
@@ -22777,11 +22592,11 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
  *             else:
  *                 self.id2sym[sym] = "[%s]" % self.tocat(sym)
  */
-      __pyx_t_2 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_Alphabet *)__pyx_v_self->__pyx_vtab)->tocat(__pyx_v_self, __pyx_v_sym)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_Alphabet *)__pyx_v_self->__pyx_vtab)->tocat(__pyx_v_self, __pyx_v_sym)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-      __pyx_t_5 = PyInt_FromLong(__pyx_v_ind); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyInt_FromLong(__pyx_v_ind); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_2));
       __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
@@ -22789,14 +22604,14 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
       __Pyx_GIVEREF(__pyx_t_5);
       __pyx_t_2 = 0;
       __pyx_t_5 = 0;
-      __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_64), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_65), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_5));
       __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
       if (unlikely(((PyObject *)__pyx_v_self->id2sym) == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      if (__Pyx_SetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, ((PyObject *)__pyx_t_5), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_SetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, ((PyObject *)__pyx_t_5), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 58; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
       goto __pyx_L5;
     }
@@ -22809,16 +22624,16 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
  *             return self.id2sym[sym]
  *         else:
  */
-      __pyx_t_5 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_Alphabet *)__pyx_v_self->__pyx_vtab)->tocat(__pyx_v_self, __pyx_v_sym)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_Alphabet *)__pyx_v_self->__pyx_vtab)->tocat(__pyx_v_self, __pyx_v_sym)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_5));
-      __pyx_t_6 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_65), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_66), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_6));
       __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
       if (unlikely(((PyObject *)__pyx_v_self->id2sym) == Py_None)) {
         PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
-      if (__Pyx_SetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, ((PyObject *)__pyx_t_6), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_SetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, ((PyObject *)__pyx_t_6), sizeof(int), PyInt_FromLong) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 60; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
     }
     __pyx_L5:;
@@ -22832,11 +22647,11 @@ static char *__pyx_f_3_sa_8Alphabet_tostring(struct __pyx_obj_3_sa_Alphabet *__p
  */
     if (unlikely(((PyObject *)__pyx_v_self->id2sym) == Py_None)) {
       PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      {__pyx_filename = __pyx_f[10]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[12]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
-    __pyx_t_6 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, sizeof(int), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = __Pyx_GetItemInt(((PyObject *)__pyx_v_self->id2sym), __pyx_v_sym, sizeof(int), PyInt_FromLong); if (!__pyx_t_6) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_4 = PyBytes_AsString(__pyx_t_6); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyBytes_AsString(__pyx_t_6); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __pyx_r = __pyx_t_4;
     goto __pyx_L0;
@@ -22959,9 +22774,9 @@ static int __pyx_f_3_sa_8Alphabet_fromstring(struct __pyx_obj_3_sa_Alphabet *__p
  *                 return self.terminals.index(s1)
  *             s[n-1] = c'\0'
  */
-      __pyx_t_6 = PyBytes_FromString(__pyx_v_s); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyBytes_FromString(__pyx_v_s); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_6));
-      __pyx_t_7 = PyNumber_Add(((PyObject *)__pyx_kp_s_66), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyNumber_Add(((PyObject *)__pyx_kp_s_67), ((PyObject *)__pyx_t_6)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
       __pyx_v_s1 = __pyx_t_7;
@@ -22974,7 +22789,7 @@ static int __pyx_f_3_sa_8Alphabet_fromstring(struct __pyx_obj_3_sa_Alphabet *__p
  *             s[n-1] = c'\0'
  *             s = s + 1
  */
-      __pyx_t_8 = PyBytes_AsString(__pyx_v_s1); if (unlikely((!__pyx_t_8) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyBytes_AsString(__pyx_v_s1); if (unlikely((!__pyx_t_8) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_r = ((struct __pyx_vtabstruct_3_sa_StringMap *)__pyx_v_self->terminals->__pyx_vtab)->index(__pyx_v_self->terminals, __pyx_t_8);
       goto __pyx_L0;
       goto __pyx_L4;
@@ -23355,7 +23170,7 @@ static PyObject *__pyx_pf_3_sa_12make_lattice_genexpr(PyObject *__pyx_self) {
   __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_12make_lattice_2generator7, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_12make_lattice_2generator7, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -23392,13 +23207,13 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_2generator7(__pyx_GeneratorObject
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words)) { __Pyx_RaiseClosureNameError("words"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words)) { __Pyx_RaiseClosureNameError("words"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
   if (PyList_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words)) {
     __pyx_t_1 = __pyx_cur_scope->__pyx_outer_scope->__pyx_v_words; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_words); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -23406,23 +23221,23 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_2generator7(__pyx_GeneratorObject
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -23433,8 +23248,8 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_2generator7(__pyx_GeneratorObject
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_cur_scope->__pyx_v_word = __pyx_t_4;
     __pyx_t_4 = 0;
-    __pyx_t_5 = PyBytes_AsString(__pyx_cur_scope->__pyx_v_word); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_4 = PyInt_FromLong(__pyx_f_3_sa_sym_fromstring(__pyx_t_5, 1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyBytes_AsString(__pyx_cur_scope->__pyx_v_word); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong(__pyx_f_3_sa_sym_fromstring(__pyx_t_5, 1)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_r = __pyx_t_4;
     __pyx_t_4 = 0;
@@ -23453,7 +23268,7 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_2generator7(__pyx_GeneratorObject
     __Pyx_XGOTREF(__pyx_t_1);
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
     __pyx_t_3 = __pyx_cur_scope->__pyx_t_2;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyErr_SetNone(PyExc_StopIteration);
@@ -23497,7 +23312,7 @@ static PyObject *__pyx_pf_3_sa_12make_lattice_3genexpr(PyObject *__pyx_self) {
   __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_12make_lattice_5generator8, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_12make_lattice_5generator8, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -23534,13 +23349,13 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_5generator8(__pyx_GeneratorObject
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids)) { __Pyx_RaiseClosureNameError("word_ids"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids)) { __Pyx_RaiseClosureNameError("word_ids"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
   if (PyList_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids)) {
     __pyx_t_1 = __pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_word_ids); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -23548,23 +23363,23 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_5generator8(__pyx_GeneratorObject
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -23575,7 +23390,7 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_5generator8(__pyx_GeneratorObject
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_cur_scope->__pyx_v_word = __pyx_t_4;
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_INCREF(__pyx_cur_scope->__pyx_v_word);
     PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_cur_scope->__pyx_v_word);
@@ -23586,7 +23401,7 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_5generator8(__pyx_GeneratorObject
     __Pyx_INCREF(__pyx_int_1);
     PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_int_1);
     __Pyx_GIVEREF(__pyx_int_1);
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_4));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
@@ -23608,7 +23423,7 @@ static PyObject *__pyx_gb_3_sa_12make_lattice_5generator8(__pyx_GeneratorObject
     __Pyx_XGOTREF(__pyx_t_1);
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
     __pyx_t_3 = __pyx_cur_scope->__pyx_t_2;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyErr_SetNone(PyExc_StopIteration);
@@ -23661,7 +23476,7 @@ static PyObject *__pyx_pf_3_sa_2make_lattice(CYTHON_UNUSED PyObject *__pyx_self,
  *     return tuple(((word, None, 1), ) for word in word_ids)
  * 
  */
-  __pyx_t_1 = __pyx_pf_3_sa_12make_lattice_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __pyx_pf_3_sa_12make_lattice_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_cur_scope->__pyx_v_word_ids = __pyx_t_1;
@@ -23675,14 +23490,14 @@ static PyObject *__pyx_pf_3_sa_2make_lattice(CYTHON_UNUSED PyObject *__pyx_self,
  * def decode_lattice(lattice):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_pf_3_sa_12make_lattice_3genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __pyx_pf_3_sa_12make_lattice_3genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
@@ -23742,7 +23557,7 @@ static PyObject *__pyx_pf_3_sa_14decode_lattice_genexpr(PyObject *__pyx_self) {
   __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_14decode_lattice_2generator9, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_14decode_lattice_2generator9, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -23788,7 +23603,7 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":113
  * def decode_lattice(lattice):
@@ -23797,12 +23612,12 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
  * 
  * def decode_sentence(lattice):
  */
-  if (unlikely(!__pyx_cur_scope->__pyx_v_arc)) { __Pyx_RaiseUnboundLocalError("arc"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  if (unlikely(!__pyx_cur_scope->__pyx_v_arc)) { __Pyx_RaiseUnboundLocalError("arc"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
   if (PyList_CheckExact(__pyx_cur_scope->__pyx_v_arc) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_v_arc)) {
     __pyx_t_1 = __pyx_cur_scope->__pyx_v_arc; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_v_arc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_v_arc); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -23818,23 +23633,23 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -23850,7 +23665,7 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       if (unlikely(size != 3)) {
         if (size > 3) __Pyx_RaiseTooManyValuesError(3);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -23866,15 +23681,15 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       __Pyx_INCREF(__pyx_t_6);
       __Pyx_INCREF(__pyx_t_7);
       #else
-      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     } else
     {
       Py_ssize_t index = -1;
-      __pyx_t_8 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
@@ -23884,7 +23699,7 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       __Pyx_GOTREF(__pyx_t_6);
       index = 2; __pyx_t_7 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_7)) goto __pyx_L6_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_7);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 3) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 3) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_9 = NULL;
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       goto __pyx_L7_unpacking_done;
@@ -23892,7 +23707,7 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       __pyx_t_9 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_L7_unpacking_done:;
     }
     __Pyx_XGOTREF(__pyx_cur_scope->__pyx_v_sym);
@@ -23918,12 +23733,12 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
  * 
  * def decode_sentence(lattice):
  */
-    if (unlikely(!__pyx_cur_scope->__pyx_v_node)) { __Pyx_RaiseUnboundLocalError("node"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+    if (unlikely(!__pyx_cur_scope->__pyx_v_node)) { __Pyx_RaiseUnboundLocalError("node"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
     if (PyList_CheckExact(__pyx_cur_scope->__pyx_v_node) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_v_node)) {
       __pyx_t_4 = __pyx_cur_scope->__pyx_v_node; __Pyx_INCREF(__pyx_t_4); __pyx_t_10 = 0;
       __pyx_t_11 = NULL;
     } else {
-      __pyx_t_10 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_cur_scope->__pyx_v_node); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_cur_scope->__pyx_v_node); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __pyx_t_11 = Py_TYPE(__pyx_t_4)->tp_iternext;
     }
@@ -23931,23 +23746,23 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       if (!__pyx_t_11 && PyList_CheckExact(__pyx_t_4)) {
         if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_4)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_7); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_7); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #endif
       } else if (!__pyx_t_11 && PyTuple_CheckExact(__pyx_t_4)) {
         if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_7); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_10); __Pyx_INCREF(__pyx_t_7); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #endif
       } else {
         __pyx_t_7 = __pyx_t_11(__pyx_t_4);
         if (unlikely(!__pyx_t_7)) {
           if (PyErr_Occurred()) {
             if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-            else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           break;
         }
@@ -23958,12 +23773,12 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
       __Pyx_GIVEREF(__pyx_t_7);
       __pyx_cur_scope->__pyx_v_arc = __pyx_t_7;
       __pyx_t_7 = 0;
-      if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) { __Pyx_RaiseClosureNameError("lattice"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+      if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) { __Pyx_RaiseClosureNameError("lattice"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
       if (PyList_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) {
         __pyx_t_7 = __pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice; __Pyx_INCREF(__pyx_t_7); __pyx_t_12 = 0;
         __pyx_t_13 = NULL;
       } else {
-        __pyx_t_12 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_12 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_13 = Py_TYPE(__pyx_t_7)->tp_iternext;
       }
@@ -23971,23 +23786,23 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
         if (!__pyx_t_13 && PyList_CheckExact(__pyx_t_7)) {
           if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_7)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_6); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_6 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_6); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else if (!__pyx_t_13 && PyTuple_CheckExact(__pyx_t_7)) {
           if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_6); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_6); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_6 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else {
           __pyx_t_6 = __pyx_t_13(__pyx_t_7);
           if (unlikely(!__pyx_t_6)) {
             if (PyErr_Occurred()) {
               if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-              else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+              else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             }
             break;
           }
@@ -24006,10 +23821,10 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
  *             for arc in node for node in lattice)
  * 
  */
-        __pyx_t_14 = __Pyx_PyInt_AsInt(__pyx_cur_scope->__pyx_v_sym); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_6 = PyBytes_FromString(__pyx_f_3_sa_sym_tostring(__pyx_t_14)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_14 = __Pyx_PyInt_AsInt(__pyx_cur_scope->__pyx_v_sym); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_6 = PyBytes_FromString(__pyx_f_3_sa_sym_tostring(__pyx_t_14)); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(((PyObject *)__pyx_t_6));
-        __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_5);
         PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_t_6));
         __Pyx_GIVEREF(((PyObject *)__pyx_t_6));
@@ -24055,7 +23870,7 @@ static PyObject *__pyx_gb_3_sa_14decode_lattice_2generator9(__pyx_GeneratorObjec
         __pyx_t_11 = __pyx_cur_scope->__pyx_t_6;
         __pyx_t_12 = __pyx_cur_scope->__pyx_t_7;
         __pyx_t_13 = __pyx_cur_scope->__pyx_t_8;
-        if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
     }
@@ -24116,14 +23931,14 @@ static PyObject *__pyx_pf_3_sa_4decode_lattice(CYTHON_UNUSED PyObject *__pyx_sel
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_pf_3_sa_14decode_lattice_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __pyx_pf_3_sa_14decode_lattice_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
@@ -24181,7 +23996,7 @@ static PyObject *__pyx_pf_3_sa_15decode_sentence_genexpr(PyObject *__pyx_self) {
   __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_15decode_sentence_2generator10, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_15decode_sentence_2generator10, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -24224,13 +24039,13 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) { __Pyx_RaiseClosureNameError("lattice"); {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) { __Pyx_RaiseClosureNameError("lattice"); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
   if (PyList_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice) || PyTuple_CheckExact(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice)) {
     __pyx_t_1 = __pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_cur_scope->__pyx_outer_scope->__pyx_v_lattice); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -24238,23 +24053,23 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -24270,7 +24085,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       if (unlikely(size != 1)) {
         if (size > 1) __Pyx_RaiseTooManyValuesError(1);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -24280,19 +24095,19 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       }
       __Pyx_INCREF(__pyx_t_5);
       #else
-      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     } else
     {
       Py_ssize_t index = -1;
-      __pyx_t_6 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __pyx_t_7 = Py_TYPE(__pyx_t_6)->tp_iternext;
       index = 0; __pyx_t_5 = __pyx_t_7(__pyx_t_6); if (unlikely(!__pyx_t_5)) goto __pyx_L6_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_5);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 1) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_7 = NULL;
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       goto __pyx_L7_unpacking_done;
@@ -24300,7 +24115,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       __pyx_t_7 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_L7_unpacking_done:;
     }
     if ((likely(PyTuple_CheckExact(__pyx_t_5))) || (PyList_CheckExact(__pyx_t_5))) {
@@ -24313,7 +24128,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       if (unlikely(size != 3)) {
         if (size > 3) __Pyx_RaiseTooManyValuesError(3);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -24329,15 +24144,15 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       __Pyx_INCREF(__pyx_t_8);
       __Pyx_INCREF(__pyx_t_9);
       #else
-      __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_9 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     } else
     {
       Py_ssize_t index = -1;
-      __pyx_t_10 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_10 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_10);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __pyx_t_7 = Py_TYPE(__pyx_t_10)->tp_iternext;
@@ -24347,7 +24162,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       __Pyx_GOTREF(__pyx_t_8);
       index = 2; __pyx_t_9 = __pyx_t_7(__pyx_t_10); if (unlikely(!__pyx_t_9)) goto __pyx_L8_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_9);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_10), 3) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_10), 3) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_7 = NULL;
       __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
       goto __pyx_L9_unpacking_done;
@@ -24355,7 +24170,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
       __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
       __pyx_t_7 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_L9_unpacking_done:;
     }
     __Pyx_XGOTREF(__pyx_cur_scope->__pyx_v_sym);
@@ -24373,8 +24188,8 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
     __Pyx_GIVEREF(__pyx_t_9);
     __pyx_cur_scope->__pyx_v__ = __pyx_t_9;
     __pyx_t_9 = 0;
-    __pyx_t_11 = __Pyx_PyInt_AsInt(__pyx_cur_scope->__pyx_v_sym); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_4 = PyBytes_FromString(__pyx_f_3_sa_sym_tostring(__pyx_t_11)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_11 = __Pyx_PyInt_AsInt(__pyx_cur_scope->__pyx_v_sym); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyBytes_FromString(__pyx_f_3_sa_sym_tostring(__pyx_t_11)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
     __pyx_r = ((PyObject *)__pyx_t_4);
     __pyx_t_4 = 0;
@@ -24393,7 +24208,7 @@ static PyObject *__pyx_gb_3_sa_15decode_sentence_2generator10(__pyx_GeneratorObj
     __Pyx_XGOTREF(__pyx_t_1);
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
     __pyx_t_3 = __pyx_cur_scope->__pyx_t_2;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyErr_SetNone(PyExc_StopIteration);
@@ -24448,14 +24263,14 @@ static PyObject *__pyx_pf_3_sa_6decode_sentence(CYTHON_UNUSED PyObject *__pyx_se
  *     return tuple(sym_tostring(sym) for ((sym, _, _),) in lattice)             # <<<<<<<<<<<<<<
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_pf_3_sa_15decode_sentence_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __pyx_pf_3_sa_15decode_sentence_genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)(&PyTuple_Type))), ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __pyx_r = __pyx_t_1;
@@ -24839,7 +24654,7 @@ static PyObject *__pyx_pf_3_sa_6Phrase_4__str__(struct __pyx_obj_3_sa_Phrase *__
  *     def handle(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_67), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_68), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
@@ -25176,7 +24991,7 @@ static PyObject *__pyx_pf_3_sa_6Phrase_8strhandle(struct __pyx_obj_3_sa_Phrase *
  *     def arity(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_67), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_68), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 63; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
@@ -26669,7 +26484,7 @@ static int __pyx_pf_3_sa_4Rule___cinit__(struct __pyx_obj_3_sa_Rule *__pyx_v_sel
   if (__pyx_t_1) {
     __pyx_t_2 = PyInt_FromLong(__pyx_v_lhs); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_68), __pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_69), __pyx_t_2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -27199,7 +27014,7 @@ static PyObject *__pyx_gb_3_sa_4Rule_7__str___2generator11(__pyx_GeneratorObject
     __Pyx_GIVEREF(__pyx_t_2);
     __pyx_cur_scope->__pyx_v_a = __pyx_t_2;
     __pyx_t_2 = 0;
-    __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_69), __pyx_cur_scope->__pyx_v_a); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_70), __pyx_cur_scope->__pyx_v_a); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_2));
     __pyx_r = ((PyObject *)__pyx_t_2);
     __pyx_t_2 = 0;
@@ -27336,7 +27151,7 @@ static PyObject *__pyx_pf_3_sa_4Rule_10__str__(struct __pyx_obj_3_sa_Rule *__pyx
  *         return ' ||| '.join(fields)
  * 
  */
-    __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_67), __pyx_n_s__join); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_68), __pyx_n_s__join); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __pyx_t_5 = __pyx_pf_3_sa_4Rule_7__str___genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 187; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
@@ -27363,7 +27178,7 @@ static PyObject *__pyx_pf_3_sa_4Rule_10__str__(struct __pyx_obj_3_sa_Rule *__pyx
  *     def alignments(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_18), __pyx_n_s__join); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_17), __pyx_n_s__join); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
@@ -27584,7 +27399,7 @@ static PyObject *__pyx_pw_3_sa_4Rule_1f_1__get__(PyObject *__pyx_v_self) {
   return __pyx_r;
 }
 
-/* "_sa.pxd":37
+/* "_sa.pxd":51
  * cdef class Rule:
  *     cdef int lhs
  *     cdef readonly Phrase f, e             # <<<<<<<<<<<<<<
@@ -27811,7 +27626,7 @@ static PyObject *__pyx_f_3_sa_free_trie_node(struct __pyx_t_3_sa__Trie_Node *__p
  *         free(node.arr)
  * 
  */
-    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_node->root); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_node->root); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
@@ -27874,7 +27689,7 @@ static PyObject *__pyx_f_3_sa_free_trie_edge(struct __pyx_t_3_sa__Trie_Edge *__p
  *         free_trie_edge(edge.bigger)
  *         free_trie_edge(edge.smaller)
  */
-    __pyx_t_2 = __pyx_f_3_sa_free_trie_node(__pyx_v_edge->node); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_free_trie_node(__pyx_v_edge->node); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
@@ -27885,7 +27700,7 @@ static PyObject *__pyx_f_3_sa_free_trie_edge(struct __pyx_t_3_sa__Trie_Edge *__p
  *         free_trie_edge(edge.smaller)
  * 
  */
-    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_edge->bigger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_edge->bigger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 46; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
@@ -27896,7 +27711,7 @@ static PyObject *__pyx_f_3_sa_free_trie_edge(struct __pyx_t_3_sa__Trie_Edge *__p
  * 
  * cdef _Trie_Node* trie_find(_Trie_Node* node, int val):
  */
-    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_edge->smaller); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_free_trie_edge(__pyx_v_edge->smaller); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     goto __pyx_L3;
@@ -28145,7 +27960,7 @@ static PyObject *__pyx_f_3_sa_trie_node_data_extend(struct __pyx_t_3_sa__Trie_No
  *     memcpy(node.arr + node.arr_len, vals, num_vals*sizeof(int))
  *     node.arr_len = new_len             # <<<<<<<<<<<<<<
  * 
- * 
+ * cdef _Trie_Node* trie_insert(_Trie_Node* node, int val):
  */
   __pyx_v_node->arr_len = __pyx_v_new_len;
 
@@ -28155,8 +27970,8 @@ static PyObject *__pyx_f_3_sa_trie_node_data_extend(struct __pyx_t_3_sa__Trie_No
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":77
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":76
+ *     node.arr_len = new_len
  * 
  * cdef _Trie_Node* trie_insert(_Trie_Node* node, int val):             # <<<<<<<<<<<<<<
  *     cdef _Trie_Edge** cur
@@ -28172,7 +27987,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
   int __pyx_t_3;
   __Pyx_RefNannySetupContext("trie_insert", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":79
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":78
  * cdef _Trie_Node* trie_insert(_Trie_Node* node, int val):
  *     cdef _Trie_Edge** cur
  *     cur = &node.root             # <<<<<<<<<<<<<<
@@ -28181,7 +27996,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
  */
   __pyx_v_cur = (&__pyx_v_node->root);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":80
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":79
  *     cdef _Trie_Edge** cur
  *     cur = &node.root
  *     while cur[0] != NULL and cur[0].val != val:             # <<<<<<<<<<<<<<
@@ -28198,7 +28013,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
     }
     if (!__pyx_t_3) break;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":81
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":80
  *     cur = &node.root
  *     while cur[0] != NULL and cur[0].val != val:
  *         if val > cur[0].val:             # <<<<<<<<<<<<<<
@@ -28208,7 +28023,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
     __pyx_t_3 = (__pyx_v_val > (__pyx_v_cur[0])->val);
     if (__pyx_t_3) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":82
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":81
  *     while cur[0] != NULL and cur[0].val != val:
  *         if val > cur[0].val:
  *             cur = &cur[0].bigger             # <<<<<<<<<<<<<<
@@ -28219,7 +28034,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
       goto __pyx_L5;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":83
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":82
  *         if val > cur[0].val:
  *             cur = &cur[0].bigger
  *         elif val < cur[0].val:             # <<<<<<<<<<<<<<
@@ -28229,7 +28044,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
     __pyx_t_3 = (__pyx_v_val < (__pyx_v_cur[0])->val);
     if (__pyx_t_3) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":84
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":83
  *             cur = &cur[0].bigger
  *         elif val < cur[0].val:
  *             cur = &cur[0].smaller             # <<<<<<<<<<<<<<
@@ -28242,7 +28057,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
     __pyx_L5:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":85
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":84
  *         elif val < cur[0].val:
  *             cur = &cur[0].smaller
  *     if cur[0] == NULL:             # <<<<<<<<<<<<<<
@@ -28252,7 +28067,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
   __pyx_t_3 = ((__pyx_v_cur[0]) == NULL);
   if (__pyx_t_3) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":86
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":85
  *             cur = &cur[0].smaller
  *     if cur[0] == NULL:
  *         cur[0] = new_trie_edge(val)             # <<<<<<<<<<<<<<
@@ -28264,7 +28079,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
   }
   __pyx_L6:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":87
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":86
  *     if cur[0] == NULL:
  *         cur[0] = new_trie_edge(val)
  *     return cur[0].node             # <<<<<<<<<<<<<<
@@ -28280,7 +28095,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_trie_insert(struct __pyx_t_3
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":89
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":88
  *     return cur[0].node
  * 
  * cdef trie_node_to_map(_Trie_Node* node, result, prefix, int include_zeros):             # <<<<<<<<<<<<<<
@@ -28300,7 +28115,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("trie_node_to_map", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":92
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":91
  *     cdef IntList arr
  * 
  *     if include_zeros or node.arr_len > 0:             # <<<<<<<<<<<<<<
@@ -28315,19 +28130,19 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
   }
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":93
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":92
  * 
  *     if include_zeros or node.arr_len > 0:
  *         arr = IntList()             # <<<<<<<<<<<<<<
  *         free(arr.arr)
  *         arr.arr = <int*> malloc(node.arr_len * sizeof(int))
  */
-    __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_v_arr = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_3);
     __pyx_t_3 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":94
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":93
  *     if include_zeros or node.arr_len > 0:
  *         arr = IntList()
  *         free(arr.arr)             # <<<<<<<<<<<<<<
@@ -28336,7 +28151,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
  */
     free(__pyx_v_arr->arr);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":95
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":94
  *         arr = IntList()
  *         free(arr.arr)
  *         arr.arr = <int*> malloc(node.arr_len * sizeof(int))             # <<<<<<<<<<<<<<
@@ -28345,7 +28160,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
  */
     __pyx_v_arr->arr = ((int *)malloc((__pyx_v_node->arr_len * (sizeof(int)))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":96
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":95
  *         free(arr.arr)
  *         arr.arr = <int*> malloc(node.arr_len * sizeof(int))
  *         memcpy(arr.arr, node.arr, node.arr_len * sizeof(int))             # <<<<<<<<<<<<<<
@@ -28354,7 +28169,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
  */
     memcpy(__pyx_v_arr->arr, __pyx_v_node->arr, (__pyx_v_node->arr_len * (sizeof(int))));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":97
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":96
  *         arr.arr = <int*> malloc(node.arr_len * sizeof(int))
  *         memcpy(arr.arr, node.arr, node.arr_len * sizeof(int))
  *         arr.len = node.arr_len             # <<<<<<<<<<<<<<
@@ -28363,7 +28178,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
  */
     __pyx_v_arr->len = __pyx_v_node->arr_len;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":98
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":97
  *         memcpy(arr.arr, node.arr, node.arr_len * sizeof(int))
  *         arr.len = node.arr_len
  *         arr.size = node.arr_len             # <<<<<<<<<<<<<<
@@ -28372,26 +28187,26 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
  */
     __pyx_v_arr->size = __pyx_v_node->arr_len;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":99
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":98
  *         arr.len = node.arr_len
  *         arr.size = node.arr_len
  *         result[prefix] = arr             # <<<<<<<<<<<<<<
  *     trie_edge_to_map(node.root, result, prefix, include_zeros)
  * 
  */
-    if (PyObject_SetItem(__pyx_v_result, __pyx_v_prefix, ((PyObject *)__pyx_v_arr)) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyObject_SetItem(__pyx_v_result, __pyx_v_prefix, ((PyObject *)__pyx_v_arr)) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L3;
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":100
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":99
  *         arr.size = node.arr_len
  *         result[prefix] = arr
  *     trie_edge_to_map(node.root, result, prefix, include_zeros)             # <<<<<<<<<<<<<<
  * 
  * cdef trie_edge_to_map(_Trie_Edge* edge, result, prefix, int include_zeros):
  */
-  __pyx_t_3 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_node->root, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_node->root, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
@@ -28408,7 +28223,7 @@ static PyObject *__pyx_f_3_sa_trie_node_to_map(struct __pyx_t_3_sa__Trie_Node *_
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":102
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":101
  *     trie_edge_to_map(node.root, result, prefix, include_zeros)
  * 
  * cdef trie_edge_to_map(_Trie_Edge* edge, result, prefix, int include_zeros):             # <<<<<<<<<<<<<<
@@ -28428,7 +28243,7 @@ static PyObject *__pyx_f_3_sa_trie_edge_to_map(struct __pyx_t_3_sa__Trie_Edge *_
   __Pyx_RefNannySetupContext("trie_edge_to_map", 0);
   __Pyx_INCREF(__pyx_v_prefix);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":103
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":102
  * 
  * cdef trie_edge_to_map(_Trie_Edge* edge, result, prefix, int include_zeros):
  *     if edge != NULL:             # <<<<<<<<<<<<<<
@@ -28438,57 +28253,57 @@ static PyObject *__pyx_f_3_sa_trie_edge_to_map(struct __pyx_t_3_sa__Trie_Edge *_
   __pyx_t_1 = (__pyx_v_edge != NULL);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":104
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":103
  * cdef trie_edge_to_map(_Trie_Edge* edge, result, prefix, int include_zeros):
  *     if edge != NULL:
  *         trie_edge_to_map(edge.smaller, result, prefix, include_zeros)             # <<<<<<<<<<<<<<
  *         trie_edge_to_map(edge.bigger, result, prefix, include_zeros)
  *         prefix = prefix + (edge.val,)
  */
-    __pyx_t_2 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_edge->smaller, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_edge->smaller, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":105
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":104
  *     if edge != NULL:
  *         trie_edge_to_map(edge.smaller, result, prefix, include_zeros)
  *         trie_edge_to_map(edge.bigger, result, prefix, include_zeros)             # <<<<<<<<<<<<<<
  *         prefix = prefix + (edge.val,)
  *         trie_node_to_map(edge.node, result, prefix, include_zeros)
  */
-    __pyx_t_2 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_edge->bigger, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_trie_edge_to_map(__pyx_v_edge->bigger, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 104; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":106
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":105
  *         trie_edge_to_map(edge.smaller, result, prefix, include_zeros)
  *         trie_edge_to_map(edge.bigger, result, prefix, include_zeros)
  *         prefix = prefix + (edge.val,)             # <<<<<<<<<<<<<<
  *         trie_node_to_map(edge.node, result, prefix, include_zeros)
  * 
  */
-    __pyx_t_2 = PyInt_FromLong(__pyx_v_edge->val); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong(__pyx_v_edge->val); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
     __Pyx_GIVEREF(__pyx_t_2);
     __pyx_t_2 = 0;
-    __pyx_t_2 = PyNumber_Add(__pyx_v_prefix, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyNumber_Add(__pyx_v_prefix, ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 105; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
     __Pyx_DECREF(__pyx_v_prefix);
     __pyx_v_prefix = __pyx_t_2;
     __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":107
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":106
  *         trie_edge_to_map(edge.bigger, result, prefix, include_zeros)
  *         prefix = prefix + (edge.val,)
  *         trie_node_to_map(edge.node, result, prefix, include_zeros)             # <<<<<<<<<<<<<<
  * 
  * cdef class TrieMap:
  */
-    __pyx_t_2 = __pyx_f_3_sa_trie_node_to_map(__pyx_v_edge->node, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __pyx_f_3_sa_trie_node_to_map(__pyx_v_edge->node, __pyx_v_result, __pyx_v_prefix, __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 106; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     goto __pyx_L3;
@@ -28534,18 +28349,18 @@ static int __pyx_pw_3_sa_7TrieMap_1__cinit__(PyObject *__pyx_v_self, PyObject *_
         else goto __pyx_L5_argtuple_error;
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 1) {
       goto __pyx_L5_argtuple_error;
     } else {
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
     }
-    __pyx_v_alphabet_size = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_alphabet_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_alphabet_size = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_alphabet_size == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[11]; __pyx_lineno = 114; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.TrieMap.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -28556,7 +28371,7 @@ static int __pyx_pw_3_sa_7TrieMap_1__cinit__(PyObject *__pyx_v_self, PyObject *_
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":114
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":113
  *     cdef int V
  * 
  *     def __cinit__(self, int alphabet_size):             # <<<<<<<<<<<<<<
@@ -28569,7 +28384,7 @@ static int __pyx_pf_3_sa_7TrieMap___cinit__(struct __pyx_obj_3_sa_TrieMap *__pyx
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":115
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":114
  * 
  *     def __cinit__(self, int alphabet_size):
  *         self.V = alphabet_size             # <<<<<<<<<<<<<<
@@ -28578,7 +28393,7 @@ static int __pyx_pf_3_sa_7TrieMap___cinit__(struct __pyx_obj_3_sa_TrieMap *__pyx
  */
   __pyx_v_self->V = __pyx_v_alphabet_size;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":116
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":115
  *     def __cinit__(self, int alphabet_size):
  *         self.V = alphabet_size
  *         self.root = <_Trie_Node**> malloc(self.V * sizeof(_Trie_Node*))             # <<<<<<<<<<<<<<
@@ -28587,12 +28402,12 @@ static int __pyx_pf_3_sa_7TrieMap___cinit__(struct __pyx_obj_3_sa_TrieMap *__pyx
  */
   __pyx_v_self->root = ((struct __pyx_t_3_sa__Trie_Node **)malloc((__pyx_v_self->V * (sizeof(struct __pyx_t_3_sa__Trie_Node *)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":117
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":116
  *         self.V = alphabet_size
  *         self.root = <_Trie_Node**> malloc(self.V * sizeof(_Trie_Node*))
  *         memset(self.root, 0, self.V * sizeof(_Trie_Node*))             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def __dealloc__(self):
  */
   memset(__pyx_v_self->root, 0, (__pyx_v_self->V * (sizeof(struct __pyx_t_3_sa__Trie_Node *))));
 
@@ -28610,8 +28425,8 @@ static void __pyx_pw_3_sa_7TrieMap_3__dealloc__(PyObject *__pyx_v_self) {
   __Pyx_RefNannyFinishContext();
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":120
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":118
+ *         memset(self.root, 0, self.V * sizeof(_Trie_Node*))
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
  *         cdef int i
@@ -28629,7 +28444,7 @@ static void __pyx_pf_3_sa_7TrieMap_2__dealloc__(struct __pyx_obj_3_sa_TrieMap *_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":122
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":120
  *     def __dealloc__(self):
  *         cdef int i
  *         for i from 0 <= i < self.V:             # <<<<<<<<<<<<<<
@@ -28639,7 +28454,7 @@ static void __pyx_pf_3_sa_7TrieMap_2__dealloc__(struct __pyx_obj_3_sa_TrieMap *_
   __pyx_t_1 = __pyx_v_self->V;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_1; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":123
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":121
  *         cdef int i
  *         for i from 0 <= i < self.V:
  *             if self.root[i] != NULL:             # <<<<<<<<<<<<<<
@@ -28649,14 +28464,14 @@ static void __pyx_pf_3_sa_7TrieMap_2__dealloc__(struct __pyx_obj_3_sa_TrieMap *_
     __pyx_t_2 = ((__pyx_v_self->root[__pyx_v_i]) != NULL);
     if (__pyx_t_2) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":124
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":122
  *         for i from 0 <= i < self.V:
  *             if self.root[i] != NULL:
  *                 free_trie_node(self.root[i])             # <<<<<<<<<<<<<<
  *         free(self.root)
  * 
  */
-      __pyx_t_3 = __pyx_f_3_sa_free_trie_node((__pyx_v_self->root[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 124; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __pyx_f_3_sa_free_trie_node((__pyx_v_self->root[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 122; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       goto __pyx_L5;
@@ -28664,12 +28479,12 @@ static void __pyx_pf_3_sa_7TrieMap_2__dealloc__(struct __pyx_obj_3_sa_TrieMap *_
     __pyx_L5:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":125
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":123
  *             if self.root[i] != NULL:
  *                 free_trie_node(self.root[i])
  *         free(self.root)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def insert(self, pattern):
  */
   free(__pyx_v_self->root);
 
@@ -28692,8 +28507,8 @@ static PyObject *__pyx_pw_3_sa_7TrieMap_5insert(PyObject *__pyx_v_self, PyObject
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":128
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":125
+ *         free(self.root)
  * 
  *     def insert(self, pattern):             # <<<<<<<<<<<<<<
  *         cdef int* p
@@ -28715,17 +28530,17 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("insert", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":131
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":128
  *         cdef int* p
  *         cdef int i, l
  *         l = len(pattern)             # <<<<<<<<<<<<<<
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:
  */
-  __pyx_t_1 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_l = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":132
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":129
  *         cdef int i, l
  *         l = len(pattern)
  *         p = <int*> malloc(l*sizeof(int))             # <<<<<<<<<<<<<<
@@ -28734,7 +28549,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *_
  */
   __pyx_v_p = ((int *)malloc((__pyx_v_l * (sizeof(int)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":133
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":130
  *         l = len(pattern)
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:             # <<<<<<<<<<<<<<
@@ -28744,21 +28559,21 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *_
   __pyx_t_2 = __pyx_v_l;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_2; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":134
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":131
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:
  *             p[i] = pattern[i]             # <<<<<<<<<<<<<<
  *         self._insert(p,l)
  *         free(p)
  */
-    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_pattern, __pyx_v_i, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_pattern, __pyx_v_i, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     (__pyx_v_p[__pyx_v_i]) = __pyx_t_4;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":135
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":132
  *         for i from 0 <= i < l:
  *             p[i] = pattern[i]
  *         self._insert(p,l)             # <<<<<<<<<<<<<<
@@ -28767,12 +28582,12 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *_
  */
   ((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_self->__pyx_vtab)->_insert(__pyx_v_self, __pyx_v_p, __pyx_v_l);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":136
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":133
  *             p[i] = pattern[i]
  *         self._insert(p,l)
  *         free(p)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     cdef _Trie_Node* _insert(self, int* pattern, int pattern_len):
  */
   free(__pyx_v_p);
 
@@ -28788,8 +28603,8 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_4insert(struct __pyx_obj_3_sa_TrieMap *_
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":139
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":135
+ *         free(p)
  * 
  *     cdef _Trie_Node* _insert(self, int* pattern, int pattern_len):             # <<<<<<<<<<<<<<
  *         cdef int i
@@ -28805,7 +28620,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
   int __pyx_t_2;
   __Pyx_RefNannySetupContext("_insert", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":142
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":138
  *         cdef int i
  *         cdef _Trie_Node* node
  *         if self.root[pattern[0]] == NULL:             # <<<<<<<<<<<<<<
@@ -28815,7 +28630,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
   __pyx_t_1 = ((__pyx_v_self->root[(__pyx_v_pattern[0])]) == NULL);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":143
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":139
  *         cdef _Trie_Node* node
  *         if self.root[pattern[0]] == NULL:
  *             self.root[pattern[0]] = new_trie_node()             # <<<<<<<<<<<<<<
@@ -28827,7 +28642,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":144
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":140
  *         if self.root[pattern[0]] == NULL:
  *             self.root[pattern[0]] = new_trie_node()
  *         node = self.root[pattern[0]]             # <<<<<<<<<<<<<<
@@ -28836,7 +28651,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
  */
   __pyx_v_node = (__pyx_v_self->root[(__pyx_v_pattern[0])]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":145
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":141
  *             self.root[pattern[0]] = new_trie_node()
  *         node = self.root[pattern[0]]
  *         for i from 1 <= i < pattern_len:             # <<<<<<<<<<<<<<
@@ -28846,7 +28661,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
   __pyx_t_2 = __pyx_v_pattern_len;
   for (__pyx_v_i = 1; __pyx_v_i < __pyx_t_2; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":146
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":142
  *         node = self.root[pattern[0]]
  *         for i from 1 <= i < pattern_len:
  *             node = trie_insert(node, pattern[i])             # <<<<<<<<<<<<<<
@@ -28856,7 +28671,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__insert(struct __py
     __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, (__pyx_v_pattern[__pyx_v_i]));
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":147
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":143
  *         for i from 1 <= i < pattern_len:
  *             node = trie_insert(node, pattern[i])
  *         return node             # <<<<<<<<<<<<<<
@@ -28883,7 +28698,7 @@ static PyObject *__pyx_pw_3_sa_7TrieMap_7contains(PyObject *__pyx_v_self, PyObje
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":149
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":145
  *         return node
  * 
  *     def contains(self, pattern):             # <<<<<<<<<<<<<<
@@ -28908,17 +28723,17 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("contains", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":153
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":149
  *         cdef int i, l
  *         cdef _Trie_Node* node
  *         l = len(pattern)             # <<<<<<<<<<<<<<
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:
  */
-  __pyx_t_1 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 149; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_l = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":154
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":150
  *         cdef _Trie_Node* node
  *         l = len(pattern)
  *         p = <int*> malloc(l*sizeof(int))             # <<<<<<<<<<<<<<
@@ -28927,7 +28742,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
  */
   __pyx_v_p = ((int *)malloc((__pyx_v_l * (sizeof(int)))));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":155
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":151
  *         l = len(pattern)
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:             # <<<<<<<<<<<<<<
@@ -28937,21 +28752,21 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
   __pyx_t_2 = __pyx_v_l;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_2; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":156
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":152
  *         p = <int*> malloc(l*sizeof(int))
  *         for i from 0 <= i < l:
  *             p[i] = pattern[i]             # <<<<<<<<<<<<<<
  *         node = self._contains(p,l)
  *         free(p)
  */
-    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_pattern, __pyx_v_i, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_pattern, __pyx_v_i, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 152; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     (__pyx_v_p[__pyx_v_i]) = __pyx_t_4;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":157
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":153
  *         for i from 0 <= i < l:
  *             p[i] = pattern[i]
  *         node = self._contains(p,l)             # <<<<<<<<<<<<<<
@@ -28960,7 +28775,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
  */
   __pyx_v_node = ((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_self->__pyx_vtab)->_contains(__pyx_v_self, __pyx_v_p, __pyx_v_l);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":158
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":154
  *             p[i] = pattern[i]
  *         node = self._contains(p,l)
  *         free(p)             # <<<<<<<<<<<<<<
@@ -28969,7 +28784,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
  */
   free(__pyx_v_p);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":159
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":155
  *         node = self._contains(p,l)
  *         free(p)
  *         if node == NULL:             # <<<<<<<<<<<<<<
@@ -28979,7 +28794,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
   __pyx_t_5 = (__pyx_v_node == NULL);
   if (__pyx_t_5) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":160
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":156
  *         free(p)
  *         if node == NULL:
  *             return False             # <<<<<<<<<<<<<<
@@ -28987,7 +28802,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
  *             return True
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 160; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_r = __pyx_t_3;
     __pyx_t_3 = 0;
@@ -28996,7 +28811,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":162
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":158
  *             return False
  *         else:
  *             return True             # <<<<<<<<<<<<<<
@@ -29004,7 +28819,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
  *     cdef _Trie_Node* _contains(self, int* pattern, int pattern_len):
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 162; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 158; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_r = __pyx_t_3;
     __pyx_t_3 = 0;
@@ -29024,7 +28839,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_6contains(struct __pyx_obj_3_sa_TrieMap
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":164
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":160
  *             return True
  * 
  *     cdef _Trie_Node* _contains(self, int* pattern, int pattern_len):             # <<<<<<<<<<<<<<
@@ -29042,7 +28857,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
   int __pyx_t_3;
   __Pyx_RefNannySetupContext("_contains", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":167
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":163
  *         cdef int i
  *         cdef _Trie_Node* node
  *         node = self.root[pattern[0]]             # <<<<<<<<<<<<<<
@@ -29051,7 +28866,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
  */
   __pyx_v_node = (__pyx_v_self->root[(__pyx_v_pattern[0])]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":168
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":164
  *         cdef _Trie_Node* node
  *         node = self.root[pattern[0]]
  *         i = 1             # <<<<<<<<<<<<<<
@@ -29060,7 +28875,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
  */
   __pyx_v_i = 1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":169
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":165
  *         node = self.root[pattern[0]]
  *         i = 1
  *         while node != NULL and i < pattern_len:             # <<<<<<<<<<<<<<
@@ -29077,7 +28892,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
     }
     if (!__pyx_t_3) break;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":170
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":166
  *         i = 1
  *         while node != NULL and i < pattern_len:
  *             node = trie_find(node, pattern[i])             # <<<<<<<<<<<<<<
@@ -29086,7 +28901,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
  */
     __pyx_v_node = __pyx_f_3_sa_trie_find(__pyx_v_node, (__pyx_v_pattern[__pyx_v_i]));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":171
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":167
  *         while node != NULL and i < pattern_len:
  *             node = trie_find(node, pattern[i])
  *             i = i+1             # <<<<<<<<<<<<<<
@@ -29096,7 +28911,7 @@ static struct __pyx_t_3_sa__Trie_Node *__pyx_f_3_sa_7TrieMap__contains(struct __
     __pyx_v_i = (__pyx_v_i + 1);
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":172
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":168
  *             node = trie_find(node, pattern[i])
  *             i = i+1
  *         return node             # <<<<<<<<<<<<<<
@@ -29123,7 +28938,7 @@ static PyObject *__pyx_pw_3_sa_7TrieMap_9toMap(PyObject *__pyx_v_self, PyObject
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":174
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":170
  *         return node
  * 
  *     def toMap(self, flag):             # <<<<<<<<<<<<<<
@@ -29146,17 +28961,17 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("toMap", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":177
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":173
  *         cdef int i, include_zeros
  * 
  *         if flag:             # <<<<<<<<<<<<<<
  *             include_zeros=1
  *         else:
  */
-  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_flag); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_flag); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":178
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":174
  * 
  *         if flag:
  *             include_zeros=1             # <<<<<<<<<<<<<<
@@ -29168,7 +28983,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":180
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":176
  *             include_zeros=1
  *         else:
  *             include_zeros=0             # <<<<<<<<<<<<<<
@@ -29179,19 +28994,19 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":181
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":177
  *         else:
  *             include_zeros=0
  *         result = {}             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < self.V:
  *             if self.root[i] != NULL:
  */
-  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 181; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
   __pyx_v_result = __pyx_t_2;
   __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":182
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":178
  *             include_zeros=0
  *         result = {}
  *         for i from 0 <= i < self.V:             # <<<<<<<<<<<<<<
@@ -29201,7 +29016,7 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
   __pyx_t_3 = __pyx_v_self->V;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_3; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":183
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":179
  *         result = {}
  *         for i from 0 <= i < self.V:
  *             if self.root[i] != NULL:             # <<<<<<<<<<<<<<
@@ -29211,21 +29026,21 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
     __pyx_t_1 = ((__pyx_v_self->root[__pyx_v_i]) != NULL);
     if (__pyx_t_1) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":184
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":180
  *         for i from 0 <= i < self.V:
  *             if self.root[i] != NULL:
  *                 trie_node_to_map(self.root[i], result, (i,), include_zeros)             # <<<<<<<<<<<<<<
  *         return result
  * 
  */
-      __pyx_t_2 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
       __pyx_t_2 = 0;
-      __pyx_t_2 = __pyx_f_3_sa_trie_node_to_map((__pyx_v_self->root[__pyx_v_i]), ((PyObject *)__pyx_v_result), ((PyObject *)__pyx_t_4), __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 184; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __pyx_f_3_sa_trie_node_to_map((__pyx_v_self->root[__pyx_v_i]), ((PyObject *)__pyx_v_result), ((PyObject *)__pyx_t_4), __pyx_v_include_zeros); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -29234,12 +29049,12 @@ static PyObject *__pyx_pf_3_sa_7TrieMap_8toMap(struct __pyx_obj_3_sa_TrieMap *__
     __pyx_L6:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":185
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":181
  *             if self.root[i] != NULL:
  *                 trie_node_to_map(self.root[i], result, (i,), include_zeros)
  *         return result             # <<<<<<<<<<<<<<
  * 
- * 
+ * cdef class Precomputation:
  */
   __Pyx_XDECREF(__pyx_r);
   __Pyx_INCREF(((PyObject *)__pyx_v_result));
@@ -29266,6 +29081,7 @@ static int __pyx_pw_3_sa_14Precomputation_1__cinit__(PyObject *__pyx_v_self, PyO
   PyObject *__pyx_v_fsarray = 0;
   PyObject *__pyx_v_from_stats = 0;
   PyObject *__pyx_v_from_binary = 0;
+  PyObject *__pyx_v_mmaped = 0;
   PyObject *__pyx_v_precompute_rank = 0;
   PyObject *__pyx_v_precompute_secondary_rank = 0;
   PyObject *__pyx_v_max_length = 0;
@@ -29276,29 +29092,31 @@ static int __pyx_pw_3_sa_14Precomputation_1__cinit__(PyObject *__pyx_v_self, PyO
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__fsarray,&__pyx_n_s__from_stats,&__pyx_n_s__from_binary,&__pyx_n_s__precompute_rank,&__pyx_n_s_70,&__pyx_n_s__max_length,&__pyx_n_s__max_nonterminals,&__pyx_n_s_71,&__pyx_n_s__train_min_gap_size,0};
-    PyObject* values[9] = {0,0,0,0,0,0,0,0,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__fsarray,&__pyx_n_s__from_stats,&__pyx_n_s__from_binary,&__pyx_n_s__mmaped,&__pyx_n_s__precompute_rank,&__pyx_n_s_71,&__pyx_n_s__max_length,&__pyx_n_s__max_nonterminals,&__pyx_n_s_72,&__pyx_n_s__train_min_gap_size,0};
+    PyObject* values[10] = {0,0,0,0,0,0,0,0,0,0};
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":200
- *     cdef write_map(self, m, FILE* f)
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":193
+ *     cdef precomputed_collocations
  * 
- *     def __cinit__(self, fsarray=None, from_stats=None, from_binary=None,             # <<<<<<<<<<<<<<
+ *     def __cinit__(self, fsarray=None, from_stats=None, from_binary=None, mmaped=False,             # <<<<<<<<<<<<<<
  *             precompute_rank=1000, precompute_secondary_rank=20,
  *             max_length=5, max_nonterminals=2,
  */
     values[0] = ((PyObject *)Py_None);
     values[1] = ((PyObject *)Py_None);
     values[2] = ((PyObject *)Py_None);
-    values[3] = ((PyObject *)__pyx_int_1000);
-    values[4] = ((PyObject *)__pyx_int_20);
-    values[5] = ((PyObject *)__pyx_int_5);
-    values[6] = ((PyObject *)__pyx_int_2);
-    values[7] = ((PyObject *)__pyx_int_10);
-    values[8] = ((PyObject *)__pyx_int_2);
+    values[3] = __pyx_k_73;
+    values[4] = ((PyObject *)__pyx_int_1000);
+    values[5] = ((PyObject *)__pyx_int_20);
+    values[6] = ((PyObject *)__pyx_int_5);
+    values[7] = ((PyObject *)__pyx_int_2);
+    values[8] = ((PyObject *)__pyx_int_10);
+    values[9] = ((PyObject *)__pyx_int_2);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
         case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
         case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
         case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
@@ -29330,40 +29148,46 @@ static int __pyx_pw_3_sa_14Precomputation_1__cinit__(PyObject *__pyx_v_self, PyO
         }
         case  3:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__precompute_rank);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__mmaped);
           if (value) { values[3] = value; kw_args--; }
         }
         case  4:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_70);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__precompute_rank);
           if (value) { values[4] = value; kw_args--; }
         }
         case  5:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__max_length);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_71);
           if (value) { values[5] = value; kw_args--; }
         }
         case  6:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__max_nonterminals);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__max_length);
           if (value) { values[6] = value; kw_args--; }
         }
         case  7:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_71);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__max_nonterminals);
           if (value) { values[7] = value; kw_args--; }
         }
         case  8:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__train_min_gap_size);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_72);
           if (value) { values[8] = value; kw_args--; }
         }
+        case  9:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__train_min_gap_size);
+          if (value) { values[9] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case 10: values[9] = PyTuple_GET_ITEM(__pyx_args, 9);
         case  9: values[8] = PyTuple_GET_ITEM(__pyx_args, 8);
         case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
         case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
@@ -29380,27 +29204,28 @@ static int __pyx_pw_3_sa_14Precomputation_1__cinit__(PyObject *__pyx_v_self, PyO
     __pyx_v_fsarray = values[0];
     __pyx_v_from_stats = values[1];
     __pyx_v_from_binary = values[2];
-    __pyx_v_precompute_rank = values[3];
-    __pyx_v_precompute_secondary_rank = values[4];
-    __pyx_v_max_length = values[5];
-    __pyx_v_max_nonterminals = values[6];
-    __pyx_v_train_max_initial_size = values[7];
-    __pyx_v_train_min_gap_size = values[8];
+    __pyx_v_mmaped = values[3];
+    __pyx_v_precompute_rank = values[4];
+    __pyx_v_precompute_secondary_rank = values[5];
+    __pyx_v_max_length = values[6];
+    __pyx_v_max_nonterminals = values[7];
+    __pyx_v_train_max_initial_size = values[8];
+    __pyx_v_train_min_gap_size = values[9];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 9, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[11]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 10, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.Precomputation.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_14Precomputation___cinit__(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), __pyx_v_fsarray, __pyx_v_from_stats, __pyx_v_from_binary, __pyx_v_precompute_rank, __pyx_v_precompute_secondary_rank, __pyx_v_max_length, __pyx_v_max_nonterminals, __pyx_v_train_max_initial_size, __pyx_v_train_min_gap_size);
+  __pyx_r = __pyx_pf_3_sa_14Precomputation___cinit__(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), __pyx_v_fsarray, __pyx_v_from_stats, __pyx_v_from_binary, __pyx_v_mmaped, __pyx_v_precompute_rank, __pyx_v_precompute_secondary_rank, __pyx_v_max_length, __pyx_v_max_nonterminals, __pyx_v_train_max_initial_size, __pyx_v_train_min_gap_size);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_from_stats, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_precompute_rank, PyObject *__pyx_v_precompute_secondary_rank, PyObject *__pyx_v_max_length, PyObject *__pyx_v_max_nonterminals, PyObject *__pyx_v_train_max_initial_size, PyObject *__pyx_v_train_min_gap_size) {
+static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_fsarray, PyObject *__pyx_v_from_stats, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_mmaped, PyObject *__pyx_v_precompute_rank, PyObject *__pyx_v_precompute_secondary_rank, PyObject *__pyx_v_max_length, PyObject *__pyx_v_max_nonterminals, PyObject *__pyx_v_train_max_initial_size, PyObject *__pyx_v_train_min_gap_size) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
@@ -29413,118 +29238,161 @@ static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precom
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":204
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":197
  *             max_length=5, max_nonterminals=2,
  *             train_max_initial_size=10, train_min_gap_size=2):
  *         self.precompute_rank = precompute_rank             # <<<<<<<<<<<<<<
  *         self.precompute_secondary_rank = precompute_secondary_rank
  *         self.max_length = max_length
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_precompute_rank); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_precompute_rank); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->precompute_rank = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":205
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":198
  *             train_max_initial_size=10, train_min_gap_size=2):
  *         self.precompute_rank = precompute_rank
  *         self.precompute_secondary_rank = precompute_secondary_rank             # <<<<<<<<<<<<<<
  *         self.max_length = max_length
  *         self.max_nonterminals = max_nonterminals
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_precompute_secondary_rank); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_precompute_secondary_rank); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->precompute_secondary_rank = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":206
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":199
  *         self.precompute_rank = precompute_rank
  *         self.precompute_secondary_rank = precompute_secondary_rank
  *         self.max_length = max_length             # <<<<<<<<<<<<<<
  *         self.max_nonterminals = max_nonterminals
  *         self.train_max_initial_size = train_max_initial_size
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_max_length); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 206; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_max_length); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->max_length = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":207
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":200
  *         self.precompute_secondary_rank = precompute_secondary_rank
  *         self.max_length = max_length
  *         self.max_nonterminals = max_nonterminals             # <<<<<<<<<<<<<<
  *         self.train_max_initial_size = train_max_initial_size
  *         self.train_min_gap_size = train_min_gap_size
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_max_nonterminals); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_max_nonterminals); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->max_nonterminals = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":208
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":201
  *         self.max_length = max_length
  *         self.max_nonterminals = max_nonterminals
  *         self.train_max_initial_size = train_max_initial_size             # <<<<<<<<<<<<<<
  *         self.train_min_gap_size = train_min_gap_size
  *         if from_binary:
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_train_max_initial_size); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_train_max_initial_size); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->train_max_initial_size = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":209
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":202
  *         self.max_nonterminals = max_nonterminals
  *         self.train_max_initial_size = train_max_initial_size
  *         self.train_min_gap_size = train_min_gap_size             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
-  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_train_min_gap_size); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_AsInt(__pyx_v_train_min_gap_size); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_self->train_min_gap_size = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":210
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":203
  *         self.train_max_initial_size = train_max_initial_size
  *         self.train_min_gap_size = train_min_gap_size
  *         if from_binary:             # <<<<<<<<<<<<<<
- *             self.read_binary(from_binary)
- *         elif from_stats:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 210; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":211
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":204
  *         self.train_min_gap_size = train_min_gap_size
  *         if from_binary:
- *             self.read_binary(from_binary)             # <<<<<<<<<<<<<<
+ *             if mmaped:             # <<<<<<<<<<<<<<
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ */
+    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_mmaped); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_2) {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":205
+ *         if from_binary:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.read_binary(from_binary)
+ */
+      __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_mmaped); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_5 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_MemoryMap)), ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5);
+      __Pyx_GIVEREF(__pyx_t_5);
+      __pyx_t_5 = 0;
+      __pyx_t_5 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 205; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":207
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ *                 self.read_binary(from_binary)             # <<<<<<<<<<<<<<
  *         elif from_stats:
  *             self.precompute(from_stats, fsarray)
  */
-    __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_v_from_binary);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_from_binary);
-    __Pyx_GIVEREF(__pyx_v_from_binary);
-    __pyx_t_5 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_3 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 207; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    }
+    __pyx_L4:;
     goto __pyx_L3;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":212
- *         if from_binary:
- *             self.read_binary(from_binary)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":208
+ *             else:
+ *                 self.read_binary(from_binary)
  *         elif from_stats:             # <<<<<<<<<<<<<<
  *             self.precompute(from_stats, fsarray)
  * 
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_stats); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 212; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_stats); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 208; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":213
- *             self.read_binary(from_binary)
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":209
+ *                 self.read_binary(from_binary)
  *         elif from_stats:
  *             self.precompute(from_stats, fsarray)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def read_binary(self, bytes filename):
  */
-    __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__precompute); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__precompute); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_INCREF(__pyx_v_from_stats);
     PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_from_stats);
@@ -29532,11 +29400,11 @@ static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precom
     __Pyx_INCREF(__pyx_v_fsarray);
     PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_fsarray);
     __Pyx_GIVEREF(__pyx_v_fsarray);
-    __pyx_t_3 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __pyx_t_5 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 209; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     goto __pyx_L3;
   }
   __pyx_L3:;
@@ -29555,54 +29423,51 @@ static int __pyx_pf_3_sa_14Precomputation___cinit__(struct __pyx_obj_3_sa_Precom
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_14Precomputation_3read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_14Precomputation_3read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_14Precomputation_3read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_14Precomputation_3read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 216; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Precomputation.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_14Precomputation_2read_binary(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 211; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_14Precomputation_2read_binary(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":216
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":211
+ *             self.precompute(from_stats, fsarray)
  * 
- *     def read_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  */
 
-static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
+  const char *__pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":218
- *     def read_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":213
+ *     def read_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
  *         fread(&(self.precompute_rank), sizeof(int), 1, f)
  *         fread(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 213; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__r);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":219
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":214
  *         cdef FILE* f
  *         f = fopen(filename, "r")
  *         fread(&(self.precompute_rank), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29611,7 +29476,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->precompute_rank), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":220
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":215
  *         f = fopen(filename, "r")
  *         fread(&(self.precompute_rank), sizeof(int), 1, f)
  *         fread(&(self.precompute_secondary_rank), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29620,7 +29485,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->precompute_secondary_rank), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":221
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":216
  *         fread(&(self.precompute_rank), sizeof(int), 1, f)
  *         fread(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  *         fread(&(self.max_length), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29629,7 +29494,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->max_length), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":222
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":217
  *         fread(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  *         fread(&(self.max_length), sizeof(int), 1, f)
  *         fread(&(self.max_nonterminals), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29638,7 +29503,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->max_nonterminals), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":223
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":218
  *         fread(&(self.max_length), sizeof(int), 1, f)
  *         fread(&(self.max_nonterminals), sizeof(int), 1, f)
  *         fread(&(self.train_max_initial_size), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29647,7 +29512,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->train_max_initial_size), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":224
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":219
  *         fread(&(self.max_nonterminals), sizeof(int), 1, f)
  *         fread(&(self.train_max_initial_size), sizeof(int), 1, f)
  *         fread(&(self.train_min_gap_size), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29656,49 +29521,49 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
  */
   fread((&__pyx_v_self->train_min_gap_size), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":225
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":220
  *         fread(&(self.train_max_initial_size), sizeof(int), 1, f)
  *         fread(&(self.train_min_gap_size), sizeof(int), 1, f)
  *         self.precomputed_index = self.read_map(f)             # <<<<<<<<<<<<<<
  *         self.precomputed_collocations = self.read_map(f)
  *         fclose(f)
  */
-  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_map(__pyx_v_self, __pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 225; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_map(__pyx_v_self, __pyx_v_f); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 220; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
   __Pyx_GOTREF(__pyx_v_self->precomputed_index);
   __Pyx_DECREF(__pyx_v_self->precomputed_index);
-  __pyx_v_self->precomputed_index = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __pyx_v_self->precomputed_index = __pyx_t_2;
+  __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":226
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":221
  *         fread(&(self.train_min_gap_size), sizeof(int), 1, f)
  *         self.precomputed_index = self.read_map(f)
  *         self.precomputed_collocations = self.read_map(f)             # <<<<<<<<<<<<<<
  *         fclose(f)
  * 
  */
-  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_map(__pyx_v_self, __pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 226; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_map(__pyx_v_self, __pyx_v_f); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_2);
   __Pyx_GOTREF(__pyx_v_self->precomputed_collocations);
   __Pyx_DECREF(__pyx_v_self->precomputed_collocations);
-  __pyx_v_self->precomputed_collocations = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __pyx_v_self->precomputed_collocations = __pyx_t_2;
+  __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":227
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":222
  *         self.precomputed_index = self.read_map(f)
  *         self.precomputed_collocations = self.read_map(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     def read_mmaped(self, MemoryMap buf):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_AddTraceback("_sa.Precomputation.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -29708,55 +29573,181 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_2read_binary(struct __pyx_obj_3_
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_14Precomputation_5write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_14Precomputation_5write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_14Precomputation_5read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf); /*proto*/
+static PyObject *__pyx_pw_3_sa_14Precomputation_5read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 230; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.Precomputation.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_14Precomputation_4write_binary(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), ((char *)__pyx_v_filename));
+  __Pyx_RefNannySetupContext("read_mmaped (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_buf), __pyx_ptype_3_sa_MemoryMap, 1, "buf", 0))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 224; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_14Precomputation_4read_mmaped(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), ((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_buf));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":230
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":224
+ *         fclose(f)
  * 
+ *     def read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         self.precompute_rank = buf.read_int()
+ *         self.precompute_secondary_rank = buf.read_int()
+ */
+
+static PyObject *__pyx_pf_3_sa_14Precomputation_4read_mmaped(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":225
  * 
- *     def write_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.precompute_rank = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.precompute_secondary_rank = buf.read_int()
+ *         self.max_length = buf.read_int()
+ */
+  __pyx_v_self->precompute_rank = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":226
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.precompute_rank = buf.read_int()
+ *         self.precompute_secondary_rank = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.max_length = buf.read_int()
+ *         self.max_nonterminals = buf.read_int()
+ */
+  __pyx_v_self->precompute_secondary_rank = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":227
+ *         self.precompute_rank = buf.read_int()
+ *         self.precompute_secondary_rank = buf.read_int()
+ *         self.max_length = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.max_nonterminals = buf.read_int()
+ *         self.train_max_initial_size = buf.read_int()
+ */
+  __pyx_v_self->max_length = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":228
+ *         self.precompute_secondary_rank = buf.read_int()
+ *         self.max_length = buf.read_int()
+ *         self.max_nonterminals = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.train_max_initial_size = buf.read_int()
+ *         self.train_min_gap_size = buf.read_int()
+ */
+  __pyx_v_self->max_nonterminals = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":229
+ *         self.max_length = buf.read_int()
+ *         self.max_nonterminals = buf.read_int()
+ *         self.train_max_initial_size = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.train_min_gap_size = buf.read_int()
+ *         self.precomputed_index = self.read_mmaped_map(buf)
+ */
+  __pyx_v_self->train_max_initial_size = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":230
+ *         self.max_nonterminals = buf.read_int()
+ *         self.train_max_initial_size = buf.read_int()
+ *         self.train_min_gap_size = buf.read_int()             # <<<<<<<<<<<<<<
+ *         self.precomputed_index = self.read_mmaped_map(buf)
+ *         self.precomputed_collocations = self.read_mmaped_map(buf)
+ */
+  __pyx_v_self->train_min_gap_size = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":231
+ *         self.train_max_initial_size = buf.read_int()
+ *         self.train_min_gap_size = buf.read_int()
+ *         self.precomputed_index = self.read_mmaped_map(buf)             # <<<<<<<<<<<<<<
+ *         self.precomputed_collocations = self.read_mmaped_map(buf)
+ * 
+ */
+  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_mmaped_map(__pyx_v_self, __pyx_v_buf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 231; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->precomputed_index);
+  __Pyx_DECREF(__pyx_v_self->precomputed_index);
+  __pyx_v_self->precomputed_index = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":232
+ *         self.train_min_gap_size = buf.read_int()
+ *         self.precomputed_index = self.read_mmaped_map(buf)
+ *         self.precomputed_collocations = self.read_mmaped_map(buf)             # <<<<<<<<<<<<<<
+ * 
+ *     def write_binary(self, bytes filename):
+ */
+  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->read_mmaped_map(__pyx_v_self, __pyx_v_buf); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 232; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->precomputed_collocations);
+  __Pyx_DECREF(__pyx_v_self->precomputed_collocations);
+  __pyx_v_self->precomputed_collocations = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("_sa.Precomputation.read_mmaped", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_14Precomputation_7write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_14Precomputation_7write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_14Precomputation_6write_binary(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":234
+ *         self.precomputed_collocations = self.read_mmaped_map(buf)
+ * 
+ *     def write_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  */
 
-static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_14Precomputation_6write_binary(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
+  const char *__pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":232
- *     def write_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":236
+ *     def write_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
  *         fwrite(&(self.precompute_rank), sizeof(int), 1, f)
  *         fwrite(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__w);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":233
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":237
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  *         fwrite(&(self.precompute_rank), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29765,7 +29756,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->precompute_rank), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":234
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":238
  *         f = fopen(filename, "w")
  *         fwrite(&(self.precompute_rank), sizeof(int), 1, f)
  *         fwrite(&(self.precompute_secondary_rank), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29774,7 +29765,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->precompute_secondary_rank), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":235
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":239
  *         fwrite(&(self.precompute_rank), sizeof(int), 1, f)
  *         fwrite(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  *         fwrite(&(self.max_length), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29783,7 +29774,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->max_length), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":236
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":240
  *         fwrite(&(self.precompute_secondary_rank), sizeof(int), 1, f)
  *         fwrite(&(self.max_length), sizeof(int), 1, f)
  *         fwrite(&(self.max_nonterminals), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29792,7 +29783,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->max_nonterminals), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":237
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":241
  *         fwrite(&(self.max_length), sizeof(int), 1, f)
  *         fwrite(&(self.max_nonterminals), sizeof(int), 1, f)
  *         fwrite(&(self.train_max_initial_size), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29801,7 +29792,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->train_max_initial_size), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":238
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":242
  *         fwrite(&(self.max_nonterminals), sizeof(int), 1, f)
  *         fwrite(&(self.train_max_initial_size), sizeof(int), 1, f)
  *         fwrite(&(self.train_min_gap_size), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29810,48 +29801,48 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
  */
   fwrite((&__pyx_v_self->train_min_gap_size), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":239
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":243
  *         fwrite(&(self.train_max_initial_size), sizeof(int), 1, f)
  *         fwrite(&(self.train_min_gap_size), sizeof(int), 1, f)
  *         self.write_map(self.precomputed_index, f)             # <<<<<<<<<<<<<<
  *         self.write_map(self.precomputed_collocations, f)
  *         fclose(f)
  */
-  __pyx_t_1 = __pyx_v_self->precomputed_index;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->write_map(__pyx_v_self, __pyx_t_1, __pyx_v_f); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 239; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_2 = __pyx_v_self->precomputed_index;
+  __Pyx_INCREF(__pyx_t_2);
+  __pyx_t_3 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->write_map(__pyx_v_self, __pyx_t_2, __pyx_v_f); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 243; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":240
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":244
  *         fwrite(&(self.train_min_gap_size), sizeof(int), 1, f)
  *         self.write_map(self.precomputed_index, f)
  *         self.write_map(self.precomputed_collocations, f)             # <<<<<<<<<<<<<<
  *         fclose(f)
  * 
  */
-  __pyx_t_2 = __pyx_v_self->precomputed_collocations;
-  __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_1 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->write_map(__pyx_v_self, __pyx_t_2, __pyx_v_f); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_3 = __pyx_v_self->precomputed_collocations;
+  __Pyx_INCREF(__pyx_t_3);
+  __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_Precomputation *)__pyx_v_self->__pyx_vtab)->write_map(__pyx_v_self, __pyx_t_3, __pyx_v_f); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 244; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":241
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":245
  *         self.write_map(self.precomputed_index, f)
  *         self.write_map(self.precomputed_collocations, f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     cdef write_map(self, m, FILE* f):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_AddTraceback("_sa.Precomputation.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -29860,8 +29851,8 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_4write_binary(struct __pyx_obj_3
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":244
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":247
+ *         fclose(f)
  * 
  *     cdef write_map(self, m, FILE* f):             # <<<<<<<<<<<<<<
  *         cdef int i, N
@@ -29891,17 +29882,17 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_map", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":248
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":251
  *         cdef IntList arr
  * 
  *         N = len(m)             # <<<<<<<<<<<<<<
  *         fwrite(&(N), sizeof(int), 1, f)
  *         for pattern, val in m.iteritems():
  */
-  __pyx_t_1 = PyObject_Length(__pyx_v_m); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Length(__pyx_v_m); if (unlikely(__pyx_t_1 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 251; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_N = __pyx_t_1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":249
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":252
  * 
  *         N = len(m)
  *         fwrite(&(N), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29910,7 +29901,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
  */
   fwrite((&__pyx_v_N), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":250
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":253
  *         N = len(m)
  *         fwrite(&(N), sizeof(int), 1, f)
  *         for pattern, val in m.iteritems():             # <<<<<<<<<<<<<<
@@ -29920,9 +29911,9 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
   __pyx_t_1 = 0;
   if (unlikely(__pyx_v_m == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "iteritems");
-    {__pyx_filename = __pyx_f[11]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[13]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_5 = __Pyx_dict_iterator(__pyx_v_m, 0, ((PyObject *)__pyx_n_s__iteritems), (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_5 = __Pyx_dict_iterator(__pyx_v_m, 0, ((PyObject *)__pyx_n_s__iteritems), (&__pyx_t_3), (&__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_2);
   __pyx_t_2 = __pyx_t_5;
@@ -29930,7 +29921,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
   while (1) {
     __pyx_t_7 = __Pyx_dict_iter_next(__pyx_t_2, __pyx_t_3, &__pyx_t_1, &__pyx_t_5, &__pyx_t_6, NULL, __pyx_t_4);
     if (unlikely(__pyx_t_7 == 0)) break;
-    if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 250; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__pyx_t_7 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_XDECREF(__pyx_v_pattern);
@@ -29940,17 +29931,17 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
     __pyx_v_val = __pyx_t_6;
     __pyx_t_6 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":251
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":254
  *         fwrite(&(N), sizeof(int), 1, f)
  *         for pattern, val in m.iteritems():
  *             N = len(pattern)             # <<<<<<<<<<<<<<
  *             fwrite(&(N), sizeof(int), 1, f)
  *             for word_id in pattern:
  */
-    __pyx_t_8 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 251; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyObject_Length(__pyx_v_pattern); if (unlikely(__pyx_t_8 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_v_N = __pyx_t_8;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":252
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":255
  *         for pattern, val in m.iteritems():
  *             N = len(pattern)
  *             fwrite(&(N), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -29959,7 +29950,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
  */
     fwrite((&__pyx_v_N), (sizeof(int)), 1, __pyx_v_f);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":253
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":256
  *             N = len(pattern)
  *             fwrite(&(N), sizeof(int), 1, f)
  *             for word_id in pattern:             # <<<<<<<<<<<<<<
@@ -29970,7 +29961,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
       __pyx_t_6 = __pyx_v_pattern; __Pyx_INCREF(__pyx_t_6); __pyx_t_8 = 0;
       __pyx_t_9 = NULL;
     } else {
-      __pyx_t_8 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       __pyx_t_9 = Py_TYPE(__pyx_t_6)->tp_iternext;
     }
@@ -29978,23 +29969,23 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
       if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_6)) {
         if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_6)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_8); __Pyx_INCREF(__pyx_t_5); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_6, __pyx_t_8); __Pyx_INCREF(__pyx_t_5); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #endif
       } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_6)) {
         if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_6)) break;
         #if CYTHON_COMPILING_IN_CPYTHON
-        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_8); __Pyx_INCREF(__pyx_t_5); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_8); __Pyx_INCREF(__pyx_t_5); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #else
-        __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_6, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         #endif
       } else {
         __pyx_t_5 = __pyx_t_9(__pyx_t_6);
         if (unlikely(!__pyx_t_5)) {
           if (PyErr_Occurred()) {
             if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-            else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           break;
         }
@@ -30004,17 +29995,17 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
       __pyx_v_word_id = __pyx_t_5;
       __pyx_t_5 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":254
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":257
  *             fwrite(&(N), sizeof(int), 1, f)
  *             for word_id in pattern:
  *                 i = word_id             # <<<<<<<<<<<<<<
  *                 fwrite(&(i), sizeof(int), 1, f)
  *             arr = val
  */
-      __pyx_t_7 = __Pyx_PyInt_AsInt(__pyx_v_word_id); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = __Pyx_PyInt_AsInt(__pyx_v_word_id); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_i = __pyx_t_7;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":255
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":258
  *             for word_id in pattern:
  *                 i = word_id
  *                 fwrite(&(i), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -30025,24 +30016,24 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
     }
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":256
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":259
  *                 i = word_id
  *                 fwrite(&(i), sizeof(int), 1, f)
  *             arr = val             # <<<<<<<<<<<<<<
  *             arr.write_handle(f)
  * 
  */
-    if (!(likely(((__pyx_v_val) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_val, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_v_val) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_val, __pyx_ptype_3_sa_IntList))))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 259; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_INCREF(__pyx_v_val);
     __Pyx_XDECREF(((PyObject *)__pyx_v_arr));
     __pyx_v_arr = ((struct __pyx_obj_3_sa_IntList *)__pyx_v_val);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":257
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":260
  *                 fwrite(&(i), sizeof(int), 1, f)
  *             arr = val
  *             arr.write_handle(f)             # <<<<<<<<<<<<<<
  * 
- * 
+ *     cdef read_map(self, FILE* f):
  */
     ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_arr->__pyx_vtab)->write_handle(__pyx_v_arr, __pyx_v_f);
   }
@@ -30066,8 +30057,8 @@ static PyObject *__pyx_f_3_sa_14Precomputation_write_map(CYTHON_UNUSED struct __
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":260
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":262
+ *             arr.write_handle(f)
  * 
  *     cdef read_map(self, FILE* f):             # <<<<<<<<<<<<<<
  *         cdef int i, j, k, word_id, N
@@ -30094,19 +30085,19 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_map", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":264
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":266
  *         cdef IntList arr
  * 
  *         m = {}             # <<<<<<<<<<<<<<
  *         fread(&(N), sizeof(int), 1, f)
  *         for j from 0 <= j < N:
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 264; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 266; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_m = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":265
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":267
  * 
  *         m = {}
  *         fread(&(N), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -30115,7 +30106,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
  */
   fread((&__pyx_v_N), (sizeof(int)), 1, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":266
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":268
  *         m = {}
  *         fread(&(N), sizeof(int), 1, f)
  *         for j from 0 <= j < N:             # <<<<<<<<<<<<<<
@@ -30125,7 +30116,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
   __pyx_t_2 = __pyx_v_N;
   for (__pyx_v_j = 0; __pyx_v_j < __pyx_t_2; __pyx_v_j++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":267
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":269
  *         fread(&(N), sizeof(int), 1, f)
  *         for j from 0 <= j < N:
  *             fread(&(i), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -30134,7 +30125,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
  */
     fread((&__pyx_v_i), (sizeof(int)), 1, __pyx_v_f);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":268
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":270
  *         for j from 0 <= j < N:
  *             fread(&(i), sizeof(int), 1, f)
  *             key = ()             # <<<<<<<<<<<<<<
@@ -30145,7 +30136,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
     __Pyx_XDECREF(((PyObject *)__pyx_v_key));
     __pyx_v_key = __pyx_empty_tuple;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":269
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":271
  *             fread(&(i), sizeof(int), 1, f)
  *             key = ()
  *             for k from 0 <= k < i:             # <<<<<<<<<<<<<<
@@ -30155,7 +30146,7 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
     __pyx_t_3 = __pyx_v_i;
     for (__pyx_v_k = 0; __pyx_v_k < __pyx_t_3; __pyx_v_k++) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":270
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":272
  *             key = ()
  *             for k from 0 <= k < i:
  *                 fread(&(word_id), sizeof(int), 1, f)             # <<<<<<<<<<<<<<
@@ -30164,21 +30155,21 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
  */
       fread((&__pyx_v_word_id), (sizeof(int)), 1, __pyx_v_f);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":271
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":273
  *             for k from 0 <= k < i:
  *                 fread(&(word_id), sizeof(int), 1, f)
  *                 key = key + (word_id,)             # <<<<<<<<<<<<<<
  *             arr = IntList()
  *             arr.read_handle(f)
  */
-      __pyx_t_1 = PyInt_FromLong(__pyx_v_word_id); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyInt_FromLong(__pyx_v_word_id); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyNumber_Add(((PyObject *)__pyx_v_key), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 271; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyNumber_Add(((PyObject *)__pyx_v_key), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_1));
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_v_key));
@@ -30186,20 +30177,20 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
       __pyx_t_1 = 0;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":272
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":274
  *                 fread(&(word_id), sizeof(int), 1, f)
  *                 key = key + (word_id,)
  *             arr = IntList()             # <<<<<<<<<<<<<<
  *             arr.read_handle(f)
  *             m[key] = arr
  */
-    __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 272; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_XDECREF(((PyObject *)__pyx_v_arr));
     __pyx_v_arr = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
     __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":273
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":275
  *                 key = key + (word_id,)
  *             arr = IntList()
  *             arr.read_handle(f)             # <<<<<<<<<<<<<<
@@ -30208,22 +30199,22 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
  */
     ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_arr->__pyx_vtab)->read_handle(__pyx_v_arr, __pyx_v_f);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":274
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":276
  *             arr = IntList()
  *             arr.read_handle(f)
  *             m[key] = arr             # <<<<<<<<<<<<<<
  *         return m
  * 
  */
-    if (PyDict_SetItem(((PyObject *)__pyx_v_m), ((PyObject *)__pyx_v_key), ((PyObject *)__pyx_v_arr)) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 274; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(((PyObject *)__pyx_v_m), ((PyObject *)__pyx_v_key), ((PyObject *)__pyx_v_arr)) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":275
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":277
  *             arr.read_handle(f)
  *             m[key] = arr
  *         return m             # <<<<<<<<<<<<<<
  * 
- * 
+ *     cdef read_mmaped_map(self, MemoryMap buf):
  */
   __Pyx_XDECREF(__pyx_r);
   __Pyx_INCREF(((PyObject *)__pyx_v_m));
@@ -30246,9 +30237,178 @@ static PyObject *__pyx_f_3_sa_14Precomputation_read_map(CYTHON_UNUSED struct __p
   return __pyx_r;
 }
 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":279
+ *         return m
+ * 
+ *     cdef read_mmaped_map(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         cdef int i, j, k, word_id, N
+ *         cdef IntList arr
+ */
+
+static PyObject *__pyx_f_3_sa_14Precomputation_read_mmaped_map(CYTHON_UNUSED struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  CYTHON_UNUSED int __pyx_v_j;
+  CYTHON_UNUSED int __pyx_v_k;
+  int __pyx_v_N;
+  struct __pyx_obj_3_sa_IntList *__pyx_v_arr = 0;
+  PyObject *__pyx_v_m = NULL;
+  int __pyx_v_key_size;
+  PyObject *__pyx_v_key = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  int __pyx_t_4;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("read_mmaped_map", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":283
+ *         cdef IntList arr
+ * 
+ *         m = {}             # <<<<<<<<<<<<<<
+ *         N = buf.read_int()
+ *         for j in range(N):
+ */
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 283; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+  __pyx_v_m = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":284
+ * 
+ *         m = {}
+ *         N = buf.read_int()             # <<<<<<<<<<<<<<
+ *         for j in range(N):
+ *             key_size = buf.read_int()
+ */
+  __pyx_v_N = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":285
+ *         m = {}
+ *         N = buf.read_int()
+ *         for j in range(N):             # <<<<<<<<<<<<<<
+ *             key_size = buf.read_int()
+ *             key = []
+ */
+  __pyx_t_2 = __pyx_v_N;
+  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
+    __pyx_v_j = __pyx_t_3;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":286
+ *         N = buf.read_int()
+ *         for j in range(N):
+ *             key_size = buf.read_int()             # <<<<<<<<<<<<<<
+ *             key = []
+ *             for k in range(key_size):
+ */
+    __pyx_v_key_size = ((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":287
+ *         for j in range(N):
+ *             key_size = buf.read_int()
+ *             key = []             # <<<<<<<<<<<<<<
+ *             for k in range(key_size):
+ *                 key.append(buf.read_int())
+ */
+    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_XDECREF(((PyObject *)__pyx_v_key));
+    __pyx_v_key = __pyx_t_1;
+    __pyx_t_1 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":288
+ *             key_size = buf.read_int()
+ *             key = []
+ *             for k in range(key_size):             # <<<<<<<<<<<<<<
+ *                 key.append(buf.read_int())
+ *             arr = IntList()
+ */
+    __pyx_t_4 = __pyx_v_key_size;
+    for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
+      __pyx_v_k = __pyx_t_5;
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":289
+ *             key = []
+ *             for k in range(key_size):
+ *                 key.append(buf.read_int())             # <<<<<<<<<<<<<<
+ *             arr = IntList()
+ *             arr.read_mmaped(buf)
+ */
+      __pyx_t_1 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_MemoryMap *)__pyx_v_buf->__pyx_vtab)->read_int(__pyx_v_buf)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_6 = PyList_Append(__pyx_v_key, __pyx_t_1); if (unlikely(__pyx_t_6 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":290
+ *             for k in range(key_size):
+ *                 key.append(buf.read_int())
+ *             arr = IntList()             # <<<<<<<<<<<<<<
+ *             arr.read_mmaped(buf)
+ *             m[tuple(key)] = arr
+ */
+    __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 290; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_XDECREF(((PyObject *)__pyx_v_arr));
+    __pyx_v_arr = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
+    __pyx_t_1 = 0;
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":291
+ *                 key.append(buf.read_int())
+ *             arr = IntList()
+ *             arr.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *             m[tuple(key)] = arr
+ *         return m
+ */
+    ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_arr->__pyx_vtab)->read_mmaped(__pyx_v_arr, __pyx_v_buf);
+
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":292
+ *             arr = IntList()
+ *             arr.read_mmaped(buf)
+ *             m[tuple(key)] = arr             # <<<<<<<<<<<<<<
+ *         return m
+ * 
+ */
+    __pyx_t_1 = ((PyObject *)PyList_AsTuple(__pyx_v_key)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
+    if (PyDict_SetItem(((PyObject *)__pyx_v_m), ((PyObject *)__pyx_t_1), ((PyObject *)__pyx_v_arr)) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+  }
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":293
+ *             arr.read_mmaped(buf)
+ *             m[tuple(key)] = arr
+ *         return m             # <<<<<<<<<<<<<<
+ * 
+ *     def precompute(self, stats, SuffixArray sarray):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_m));
+  __pyx_r = ((PyObject *)__pyx_v_m);
+  goto __pyx_L0;
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("_sa.Precomputation.read_mmaped_map", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF((PyObject *)__pyx_v_arr);
+  __Pyx_XDECREF(__pyx_v_m);
+  __Pyx_XDECREF(__pyx_v_key);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_14Precomputation_7precompute(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_3_sa_14Precomputation_7precompute(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_3_sa_14Precomputation_9precompute(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_3_sa_14Precomputation_9precompute(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_stats = 0;
   struct __pyx_obj_3_sa_SuffixArray *__pyx_v_sarray = 0;
   PyObject *__pyx_r = 0;
@@ -30274,11 +30434,11 @@ static PyObject *__pyx_pw_3_sa_14Precomputation_7precompute(PyObject *__pyx_v_se
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__sarray)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("precompute", 1, 2, 2, 1); {__pyx_filename = __pyx_f[11]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("precompute", 1, 2, 2, 1); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "precompute") < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "precompute") < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -30291,14 +30451,14 @@ static PyObject *__pyx_pw_3_sa_14Precomputation_7precompute(PyObject *__pyx_v_se
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("precompute", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[11]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("precompute", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.Precomputation.precompute", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sarray), __pyx_ptype_3_sa_SuffixArray, 1, "sarray", 0))) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 278; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_r = __pyx_pf_3_sa_14Precomputation_6precompute(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), __pyx_v_stats, __pyx_v_sarray);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_sarray), __pyx_ptype_3_sa_SuffixArray, 1, "sarray", 0))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_14Precomputation_8precompute(((struct __pyx_obj_3_sa_Precomputation *)__pyx_v_self), __pyx_v_stats, __pyx_v_sarray);
   goto __pyx_L0;
   __pyx_L1_error:;
   __pyx_r = NULL;
@@ -30307,15 +30467,15 @@ static PyObject *__pyx_pw_3_sa_14Precomputation_7precompute(PyObject *__pyx_v_se
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":278
- * 
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":295
+ *         return m
  * 
  *     def precompute(self, stats, SuffixArray sarray):             # <<<<<<<<<<<<<<
  *         cdef int i, l, N, max_pattern_len, i1, l1, i2, l2, i3, l3, ptr1, ptr2, ptr3, is_super, sent_count, max_rank
  *         cdef DataArray darray = sarray.darray
  */
 
-static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_stats, struct __pyx_obj_3_sa_SuffixArray *__pyx_v_sarray) {
+static PyObject *__pyx_pf_3_sa_14Precomputation_8precompute(struct __pyx_obj_3_sa_Precomputation *__pyx_v_self, PyObject *__pyx_v_stats, struct __pyx_obj_3_sa_SuffixArray *__pyx_v_sarray) {
   int __pyx_v_i;
   int __pyx_v_l;
   int __pyx_v_N;
@@ -30392,7 +30552,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("precompute", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":280
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":297
  *     def precompute(self, stats, SuffixArray sarray):
  *         cdef int i, l, N, max_pattern_len, i1, l1, i2, l2, i3, l3, ptr1, ptr2, ptr3, is_super, sent_count, max_rank
  *         cdef DataArray darray = sarray.darray             # <<<<<<<<<<<<<<
@@ -30402,166 +30562,166 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __Pyx_INCREF(((PyObject *)__pyx_v_sarray->darray));
   __pyx_v_darray = __pyx_v_sarray->darray;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":285
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":302
  *         cdef _Trie_Node* node
  * 
  *         data = darray.data             # <<<<<<<<<<<<<<
  * 
- *         frequent_patterns = TrieMap(len(darray.id2word))
+ *         frequent_patterns = TrieMap(len(darray.voc.id2word))
  */
   __Pyx_INCREF(((PyObject *)__pyx_v_darray->data));
   __pyx_v_data = __pyx_v_darray->data;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":287
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":304
  *         data = darray.data
  * 
- *         frequent_patterns = TrieMap(len(darray.id2word))             # <<<<<<<<<<<<<<
- *         super_frequent_patterns = TrieMap(len(darray.id2word))
- *         collocations = TrieMap(len(darray.id2word))
+ *         frequent_patterns = TrieMap(len(darray.voc.id2word))             # <<<<<<<<<<<<<<
+ *         super_frequent_patterns = TrieMap(len(darray.voc.id2word))
+ *         collocations = TrieMap(len(darray.voc.id2word))
  */
-  __pyx_t_1 = __pyx_v_darray->id2word;
+  __pyx_t_1 = __pyx_v_darray->voc->id2word;
   __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 287; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __pyx_v_frequent_patterns = ((struct __pyx_obj_3_sa_TrieMap *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":288
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":305
  * 
- *         frequent_patterns = TrieMap(len(darray.id2word))
- *         super_frequent_patterns = TrieMap(len(darray.id2word))             # <<<<<<<<<<<<<<
- *         collocations = TrieMap(len(darray.id2word))
+ *         frequent_patterns = TrieMap(len(darray.voc.id2word))
+ *         super_frequent_patterns = TrieMap(len(darray.voc.id2word))             # <<<<<<<<<<<<<<
+ *         collocations = TrieMap(len(darray.voc.id2word))
  * 
  */
-  __pyx_t_1 = __pyx_v_darray->id2word;
+  __pyx_t_1 = __pyx_v_darray->voc->id2word;
   __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 288; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __pyx_v_super_frequent_patterns = ((struct __pyx_obj_3_sa_TrieMap *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":289
- *         frequent_patterns = TrieMap(len(darray.id2word))
- *         super_frequent_patterns = TrieMap(len(darray.id2word))
- *         collocations = TrieMap(len(darray.id2word))             # <<<<<<<<<<<<<<
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":306
+ *         frequent_patterns = TrieMap(len(darray.voc.id2word))
+ *         super_frequent_patterns = TrieMap(len(darray.voc.id2word))
+ *         collocations = TrieMap(len(darray.voc.id2word))             # <<<<<<<<<<<<<<
  * 
  *         I_set = set()
  */
-  __pyx_t_1 = __pyx_v_darray->id2word;
+  __pyx_t_1 = __pyx_v_darray->voc->id2word;
   __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 289; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_TrieMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __pyx_v_collocations = ((struct __pyx_obj_3_sa_TrieMap *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":291
- *         collocations = TrieMap(len(darray.id2word))
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":308
+ *         collocations = TrieMap(len(darray.voc.id2word))
  * 
  *         I_set = set()             # <<<<<<<<<<<<<<
  *         J_set = set()
  *         J2_set = set()
  */
-  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 291; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_I_set = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":292
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":309
  * 
  *         I_set = set()
  *         J_set = set()             # <<<<<<<<<<<<<<
  *         J2_set = set()
  *         IJ_set = set()
  */
-  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 292; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_J_set = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":293
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":310
  *         I_set = set()
  *         J_set = set()
  *         J2_set = set()             # <<<<<<<<<<<<<<
  *         IJ_set = set()
  *         pattern_rank = {}
  */
-  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 293; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_J2_set = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":294
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":311
  *         J_set = set()
  *         J2_set = set()
  *         IJ_set = set()             # <<<<<<<<<<<<<<
  *         pattern_rank = {}
  * 
  */
-  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 294; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 311; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_IJ_set = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":295
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":312
  *         J2_set = set()
  *         IJ_set = set()
  *         pattern_rank = {}             # <<<<<<<<<<<<<<
  * 
  *         logger.info("Precomputing frequent intersections")
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 295; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
   __pyx_v_pattern_rank = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":297
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":314
  *         pattern_rank = {}
  * 
  *         logger.info("Precomputing frequent intersections")             # <<<<<<<<<<<<<<
  *         cdef float start_time = monitor_cpu()
  * 
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__info); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_k_tuple_73), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_k_tuple_75), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":298
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":315
  * 
  *         logger.info("Precomputing frequent intersections")
  *         cdef float start_time = monitor_cpu()             # <<<<<<<<<<<<<<
@@ -30570,7 +30730,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_v_start_time = __pyx_f_3_sa_monitor_cpu();
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":300
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":317
  *         cdef float start_time = monitor_cpu()
  * 
  *         max_pattern_len = 0             # <<<<<<<<<<<<<<
@@ -30579,7 +30739,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_v_max_pattern_len = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":301
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":318
  * 
  *         max_pattern_len = 0
  *         for rank, (_, _, phrase) in enumerate(stats):             # <<<<<<<<<<<<<<
@@ -30592,7 +30752,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_t_3 = __pyx_v_stats; __Pyx_INCREF(__pyx_t_3); __pyx_t_2 = 0;
     __pyx_t_4 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_stats); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_stats); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_t_4 = Py_TYPE(__pyx_t_3)->tp_iternext;
   }
@@ -30600,23 +30760,23 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     if (!__pyx_t_4 && PyList_CheckExact(__pyx_t_3)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_3)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_4 && PyTuple_CheckExact(__pyx_t_3)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_2); __Pyx_INCREF(__pyx_t_5); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(__pyx_t_3, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_5 = __pyx_t_4(__pyx_t_3);
       if (unlikely(!__pyx_t_5)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -30632,7 +30792,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       if (unlikely(size != 3)) {
         if (size > 3) __Pyx_RaiseTooManyValuesError(3);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -30648,15 +30808,15 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __Pyx_INCREF(__pyx_t_7);
       __Pyx_INCREF(__pyx_t_8);
       #else
-      __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     } else
     {
       Py_ssize_t index = -1;
-      __pyx_t_9 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_9 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_9);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __pyx_t_10 = Py_TYPE(__pyx_t_9)->tp_iternext;
@@ -30666,7 +30826,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __Pyx_GOTREF(__pyx_t_7);
       index = 2; __pyx_t_8 = __pyx_t_10(__pyx_t_9); if (unlikely(!__pyx_t_8)) goto __pyx_L5_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_8);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 3) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_10(__pyx_t_9), 3) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_10 = NULL;
       __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
       goto __pyx_L6_unpacking_done;
@@ -30674,7 +30834,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
       __pyx_t_10 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_L6_unpacking_done:;
     }
     __Pyx_XDECREF(__pyx_v__);
@@ -30689,28 +30849,28 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __Pyx_INCREF(__pyx_t_1);
     __Pyx_XDECREF(__pyx_v_rank);
     __pyx_v_rank = __pyx_t_1;
-    __pyx_t_5 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 301; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyNumber_Add(__pyx_t_1, __pyx_int_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_1);
     __pyx_t_1 = __pyx_t_5;
     __pyx_t_5 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":302
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":319
  *         max_pattern_len = 0
  *         for rank, (_, _, phrase) in enumerate(stats):
  *             if rank >= self.precompute_rank:             # <<<<<<<<<<<<<<
  *                 break
  *             max_pattern_len = max(max_pattern_len, len(phrase))
  */
-    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->precompute_rank); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyInt_FromLong(__pyx_v_self->precompute_rank); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_8 = PyObject_RichCompare(__pyx_v_rank, __pyx_t_5, Py_GE); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyObject_RichCompare(__pyx_v_rank, __pyx_t_5, Py_GE); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 302; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
     if (__pyx_t_11) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":303
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":320
  *         for rank, (_, _, phrase) in enumerate(stats):
  *             if rank >= self.precompute_rank:
  *                 break             # <<<<<<<<<<<<<<
@@ -30722,14 +30882,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     }
     __pyx_L7:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":304
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":321
  *             if rank >= self.precompute_rank:
  *                 break
  *             max_pattern_len = max(max_pattern_len, len(phrase))             # <<<<<<<<<<<<<<
  *             frequent_patterns.insert(phrase)
  *             I_set.add(phrase)
  */
-    __pyx_t_12 = PyObject_Length(__pyx_v_phrase); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 304; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_12 = PyObject_Length(__pyx_v_phrase); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 321; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_13 = __pyx_v_max_pattern_len;
     if ((__pyx_t_12 > __pyx_t_13)) {
       __pyx_t_14 = __pyx_t_12;
@@ -30738,87 +30898,87 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     }
     __pyx_v_max_pattern_len = __pyx_t_14;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":305
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":322
  *                 break
  *             max_pattern_len = max(max_pattern_len, len(phrase))
  *             frequent_patterns.insert(phrase)             # <<<<<<<<<<<<<<
  *             I_set.add(phrase)
  *             pattern_rank[phrase] = rank
  */
-    __pyx_t_8 = PyObject_GetAttr(((PyObject *)__pyx_v_frequent_patterns), __pyx_n_s__insert); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyObject_GetAttr(((PyObject *)__pyx_v_frequent_patterns), __pyx_n_s__insert); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_INCREF(__pyx_v_phrase);
     PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_phrase);
     __Pyx_GIVEREF(__pyx_v_phrase);
-    __pyx_t_7 = PyObject_Call(__pyx_t_8, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 305; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyObject_Call(__pyx_t_8, ((PyObject *)__pyx_t_5), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":306
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":323
  *             max_pattern_len = max(max_pattern_len, len(phrase))
  *             frequent_patterns.insert(phrase)
  *             I_set.add(phrase)             # <<<<<<<<<<<<<<
  *             pattern_rank[phrase] = rank
  *             if rank < self.precompute_secondary_rank:
  */
-    __pyx_t_15 = PySet_Add(__pyx_v_I_set, __pyx_v_phrase); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 306; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_15 = PySet_Add(__pyx_v_I_set, __pyx_v_phrase); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":307
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":324
  *             frequent_patterns.insert(phrase)
  *             I_set.add(phrase)
  *             pattern_rank[phrase] = rank             # <<<<<<<<<<<<<<
  *             if rank < self.precompute_secondary_rank:
  *                 super_frequent_patterns.insert(phrase)
  */
-    if (PyDict_SetItem(((PyObject *)__pyx_v_pattern_rank), __pyx_v_phrase, __pyx_v_rank) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 307; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (PyDict_SetItem(((PyObject *)__pyx_v_pattern_rank), __pyx_v_phrase, __pyx_v_rank) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 324; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":308
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":325
  *             I_set.add(phrase)
  *             pattern_rank[phrase] = rank
  *             if rank < self.precompute_secondary_rank:             # <<<<<<<<<<<<<<
  *                 super_frequent_patterns.insert(phrase)
  *                 J_set.add(phrase)
  */
-    __pyx_t_7 = PyInt_FromLong(__pyx_v_self->precompute_secondary_rank); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyInt_FromLong(__pyx_v_self->precompute_secondary_rank); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_5 = PyObject_RichCompare(__pyx_v_rank, __pyx_t_7, Py_LT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_RichCompare(__pyx_v_rank, __pyx_t_7, Py_LT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 308; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
     if (__pyx_t_11) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":309
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":326
  *             pattern_rank[phrase] = rank
  *             if rank < self.precompute_secondary_rank:
  *                 super_frequent_patterns.insert(phrase)             # <<<<<<<<<<<<<<
  *                 J_set.add(phrase)
  * 
  */
-      __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_super_frequent_patterns), __pyx_n_s__insert); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyObject_GetAttr(((PyObject *)__pyx_v_super_frequent_patterns), __pyx_n_s__insert); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_INCREF(__pyx_v_phrase);
       PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_phrase);
       __Pyx_GIVEREF(__pyx_v_phrase);
-      __pyx_t_8 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 309; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyObject_Call(__pyx_t_5, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 326; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":310
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":327
  *             if rank < self.precompute_secondary_rank:
  *                 super_frequent_patterns.insert(phrase)
  *                 J_set.add(phrase)             # <<<<<<<<<<<<<<
  * 
  *         queue = IntList(increment=1000)
  */
-      __pyx_t_15 = PySet_Add(__pyx_v_J_set, __pyx_v_phrase); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 310; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_15 = PySet_Add(__pyx_v_J_set, __pyx_v_phrase); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       goto __pyx_L8;
     }
     __pyx_L8:;
@@ -30827,50 +30987,50 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":312
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":329
  *                 J_set.add(phrase)
  * 
  *         queue = IntList(increment=1000)             # <<<<<<<<<<<<<<
  * 
  *         logger.info("    Computing inverted indexes...")
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__increment), __pyx_int_1000) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 312; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__increment), __pyx_int_1000) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __pyx_v_queue = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_3);
   __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":314
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":331
  *         queue = IntList(increment=1000)
  * 
  *         logger.info("    Computing inverted indexes...")             # <<<<<<<<<<<<<<
  *         N = len(data)
  *         for i from 0 <= i < N:
  */
-  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_75), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_77), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":315
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":332
  * 
  *         logger.info("    Computing inverted indexes...")
  *         N = len(data)             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < N:
  *             sa_word_id = data.arr[i]
  */
-  __pyx_t_2 = PyObject_Length(((PyObject *)__pyx_v_data)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 315; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(((PyObject *)__pyx_v_data)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 332; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_N = __pyx_t_2;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":316
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":333
  *         logger.info("    Computing inverted indexes...")
  *         N = len(data)
  *         for i from 0 <= i < N:             # <<<<<<<<<<<<<<
@@ -30880,7 +31040,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __pyx_t_13 = __pyx_v_N;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":317
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":334
  *         N = len(data)
  *         for i from 0 <= i < N:
  *             sa_word_id = data.arr[i]             # <<<<<<<<<<<<<<
@@ -30889,7 +31049,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
     __pyx_v_sa_word_id = (__pyx_v_data->arr[__pyx_v_i]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":318
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":335
  *         for i from 0 <= i < N:
  *             sa_word_id = data.arr[i]
  *             if sa_word_id == 1:             # <<<<<<<<<<<<<<
@@ -30899,7 +31059,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_t_11 = (__pyx_v_sa_word_id == 1);
     if (__pyx_t_11) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":319
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":336
  *             sa_word_id = data.arr[i]
  *             if sa_word_id == 1:
  *                 queue._append(-1)             # <<<<<<<<<<<<<<
@@ -30911,7 +31071,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":321
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":338
  *                 queue._append(-1)
  *             else:
  *                 for l from 1 <= l <= max_pattern_len:             # <<<<<<<<<<<<<<
@@ -30921,7 +31081,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __pyx_t_16 = __pyx_v_max_pattern_len;
       for (__pyx_v_l = 1; __pyx_v_l <= __pyx_t_16; __pyx_v_l++) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":322
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":339
  *             else:
  *                 for l from 1 <= l <= max_pattern_len:
  *                     node = frequent_patterns._contains(data.arr+i, l)             # <<<<<<<<<<<<<<
@@ -30930,7 +31090,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
         __pyx_v_node = ((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_frequent_patterns->__pyx_vtab)->_contains(__pyx_v_frequent_patterns, (__pyx_v_data->arr + __pyx_v_i), __pyx_v_l);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":323
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":340
  *                 for l from 1 <= l <= max_pattern_len:
  *                     node = frequent_patterns._contains(data.arr+i, l)
  *                     if node == NULL:             # <<<<<<<<<<<<<<
@@ -30940,7 +31100,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_t_11 = (__pyx_v_node == NULL);
         if (__pyx_t_11) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":324
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":341
  *                     node = frequent_patterns._contains(data.arr+i, l)
  *                     if node == NULL:
  *                         break             # <<<<<<<<<<<<<<
@@ -30952,7 +31112,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         __pyx_L14:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":325
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":342
  *                     if node == NULL:
  *                         break
  *                     queue._append(i)             # <<<<<<<<<<<<<<
@@ -30961,7 +31121,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
         ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_queue->__pyx_vtab)->_append(__pyx_v_queue, __pyx_v_i);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":326
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":343
  *                         break
  *                     queue._append(i)
  *                     queue._append(l)             # <<<<<<<<<<<<<<
@@ -30970,14 +31130,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
         ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_queue->__pyx_vtab)->_append(__pyx_v_queue, __pyx_v_l);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":327
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":344
  *                     queue._append(i)
  *                     queue._append(l)
  *                     trie_node_data_append(node, i)             # <<<<<<<<<<<<<<
  * 
  *         logger.info("    Computing collocations...")
  */
-        __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 327; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 344; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       }
@@ -30986,34 +31146,34 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_L11:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":329
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":346
  *                     trie_node_data_append(node, i)
  * 
  *         logger.info("    Computing collocations...")             # <<<<<<<<<<<<<<
  *         N = len(queue)
  *         ptr1 = 0
  */
-  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_77), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_79), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":330
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":347
  * 
  *         logger.info("    Computing collocations...")
  *         N = len(queue)             # <<<<<<<<<<<<<<
  *         ptr1 = 0
  *         sent_count = 0
  */
-  __pyx_t_2 = PyObject_Length(((PyObject *)__pyx_v_queue)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 330; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(((PyObject *)__pyx_v_queue)); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 347; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_N = __pyx_t_2;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":331
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":348
  *         logger.info("    Computing collocations...")
  *         N = len(queue)
  *         ptr1 = 0             # <<<<<<<<<<<<<<
@@ -31022,7 +31182,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_v_ptr1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":332
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":349
  *         N = len(queue)
  *         ptr1 = 0
  *         sent_count = 0             # <<<<<<<<<<<<<<
@@ -31031,7 +31191,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_v_sent_count = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":333
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":350
  *         ptr1 = 0
  *         sent_count = 0
  *         while ptr1 < N:    # main loop             # <<<<<<<<<<<<<<
@@ -31042,7 +31202,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_t_11 = (__pyx_v_ptr1 < __pyx_v_N);
     if (!__pyx_t_11) break;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":334
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":351
  *         sent_count = 0
  *         while ptr1 < N:    # main loop
  *             i1 = queue.arr[ptr1]             # <<<<<<<<<<<<<<
@@ -31051,7 +31211,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
     __pyx_v_i1 = (__pyx_v_queue->arr[__pyx_v_ptr1]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":335
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":352
  *         while ptr1 < N:    # main loop
  *             i1 = queue.arr[ptr1]
  *             if i1 > -1:             # <<<<<<<<<<<<<<
@@ -31061,7 +31221,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_t_11 = (__pyx_v_i1 > -1);
     if (__pyx_t_11) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":336
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":353
  *             i1 = queue.arr[ptr1]
  *             if i1 > -1:
  *                 l1 = queue.arr[ptr1+1]             # <<<<<<<<<<<<<<
@@ -31070,7 +31230,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
       __pyx_v_l1 = (__pyx_v_queue->arr[(__pyx_v_ptr1 + 1)]);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":337
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":354
  *             if i1 > -1:
  *                 l1 = queue.arr[ptr1+1]
  *                 ptr2 = ptr1 + 2             # <<<<<<<<<<<<<<
@@ -31079,7 +31239,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
       __pyx_v_ptr2 = (__pyx_v_ptr1 + 2);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":338
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":355
  *                 l1 = queue.arr[ptr1+1]
  *                 ptr2 = ptr1 + 2
  *                 while ptr2 < N:             # <<<<<<<<<<<<<<
@@ -31090,7 +31250,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_t_11 = (__pyx_v_ptr2 < __pyx_v_N);
         if (!__pyx_t_11) break;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":339
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":356
  *                 ptr2 = ptr1 + 2
  *                 while ptr2 < N:
  *                     i2 = queue.arr[ptr2]             # <<<<<<<<<<<<<<
@@ -31099,7 +31259,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
         __pyx_v_i2 = (__pyx_v_queue->arr[__pyx_v_ptr2]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":340
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":357
  *                 while ptr2 < N:
  *                     i2 = queue.arr[ptr2]
  *                     if i2 == -1 or i2 - i1 >= self.train_max_initial_size:             # <<<<<<<<<<<<<<
@@ -31115,7 +31275,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         if (__pyx_t_18) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":341
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":358
  *                     i2 = queue.arr[ptr2]
  *                     if i2 == -1 or i2 - i1 >= self.train_max_initial_size:
  *                         break             # <<<<<<<<<<<<<<
@@ -31127,7 +31287,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         __pyx_L20:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":342
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":359
  *                     if i2 == -1 or i2 - i1 >= self.train_max_initial_size:
  *                         break
  *                     l2 = queue.arr[ptr2+1]             # <<<<<<<<<<<<<<
@@ -31136,7 +31296,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
         __pyx_v_l2 = (__pyx_v_queue->arr[(__pyx_v_ptr2 + 1)]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":343
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":360
  *                         break
  *                     l2 = queue.arr[ptr2+1]
  *                     if (i2 - i1 - l1 >= self.train_min_gap_size and             # <<<<<<<<<<<<<<
@@ -31146,7 +31306,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_t_18 = (((__pyx_v_i2 - __pyx_v_i1) - __pyx_v_l1) >= __pyx_v_self->train_min_gap_size);
         if (__pyx_t_18) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":344
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":361
  *                     l2 = queue.arr[ptr2+1]
  *                     if (i2 - i1 - l1 >= self.train_min_gap_size and
  *                             i2 + l2 - i1 <= self.train_max_initial_size and             # <<<<<<<<<<<<<<
@@ -31156,7 +31316,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
           __pyx_t_11 = (((__pyx_v_i2 + __pyx_v_l2) - __pyx_v_i1) <= __pyx_v_self->train_max_initial_size);
           if (__pyx_t_11) {
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":345
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":362
  *                     if (i2 - i1 - l1 >= self.train_min_gap_size and
  *                             i2 + l2 - i1 <= self.train_max_initial_size and
  *                             l1+l2+1 <= self.max_length):             # <<<<<<<<<<<<<<
@@ -31174,7 +31334,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         if (__pyx_t_11) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":346
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":363
  *                             i2 + l2 - i1 <= self.train_max_initial_size and
  *                             l1+l2+1 <= self.max_length):
  *                         node = collocations._insert(data.arr+i1, l1)             # <<<<<<<<<<<<<<
@@ -31183,7 +31343,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
           __pyx_v_node = ((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_collocations->__pyx_vtab)->_insert(__pyx_v_collocations, (__pyx_v_data->arr + __pyx_v_i1), __pyx_v_l1);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":347
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":364
  *                             l1+l2+1 <= self.max_length):
  *                         node = collocations._insert(data.arr+i1, l1)
  *                         node = trie_insert(node, -1)             # <<<<<<<<<<<<<<
@@ -31192,7 +31352,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
           __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, -1);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":348
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":365
  *                         node = collocations._insert(data.arr+i1, l1)
  *                         node = trie_insert(node, -1)
  *                         for i from i2 <= i < i2+l2:             # <<<<<<<<<<<<<<
@@ -31202,7 +31362,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
           __pyx_t_13 = (__pyx_v_i2 + __pyx_v_l2);
           for (__pyx_v_i = __pyx_v_i2; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":349
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":366
  *                         node = trie_insert(node, -1)
  *                         for i from i2 <= i < i2+l2:
  *                             node = trie_insert(node, data.arr[i])             # <<<<<<<<<<<<<<
@@ -31212,29 +31372,29 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
             __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, (__pyx_v_data->arr[__pyx_v_i]));
           }
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":350
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":367
  *                         for i from i2 <= i < i2+l2:
  *                             node = trie_insert(node, data.arr[i])
  *                         trie_node_data_append(node, i1)             # <<<<<<<<<<<<<<
  *                         trie_node_data_append(node, i2)
  *                         if super_frequent_patterns._contains(data.arr+i2, l2) != NULL:
  */
-          __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 350; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 367; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":351
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":368
  *                             node = trie_insert(node, data.arr[i])
  *                         trie_node_data_append(node, i1)
  *                         trie_node_data_append(node, i2)             # <<<<<<<<<<<<<<
  *                         if super_frequent_patterns._contains(data.arr+i2, l2) != NULL:
  *                             if super_frequent_patterns._contains(data.arr+i1, l1) != NULL:
  */
-          __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 351; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":352
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":369
  *                         trie_node_data_append(node, i1)
  *                         trie_node_data_append(node, i2)
  *                         if super_frequent_patterns._contains(data.arr+i2, l2) != NULL:             # <<<<<<<<<<<<<<
@@ -31244,7 +31404,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
           __pyx_t_11 = (((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_super_frequent_patterns->__pyx_vtab)->_contains(__pyx_v_super_frequent_patterns, (__pyx_v_data->arr + __pyx_v_i2), __pyx_v_l2) != NULL);
           if (__pyx_t_11) {
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":353
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":370
  *                         trie_node_data_append(node, i2)
  *                         if super_frequent_patterns._contains(data.arr+i2, l2) != NULL:
  *                             if super_frequent_patterns._contains(data.arr+i1, l1) != NULL:             # <<<<<<<<<<<<<<
@@ -31254,7 +31414,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
             __pyx_t_11 = (((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_super_frequent_patterns->__pyx_vtab)->_contains(__pyx_v_super_frequent_patterns, (__pyx_v_data->arr + __pyx_v_i1), __pyx_v_l1) != NULL);
             if (__pyx_t_11) {
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":354
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":371
  *                         if super_frequent_patterns._contains(data.arr+i2, l2) != NULL:
  *                             if super_frequent_patterns._contains(data.arr+i1, l1) != NULL:
  *                                 is_super = 1             # <<<<<<<<<<<<<<
@@ -31266,7 +31426,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
             }
             /*else*/ {
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":356
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":373
  *                                 is_super = 1
  *                             else:
  *                                 is_super = 0             # <<<<<<<<<<<<<<
@@ -31277,7 +31437,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
             }
             __pyx_L25:;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":357
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":374
  *                             else:
  *                                 is_super = 0
  *                             ptr3 = ptr2 + 2             # <<<<<<<<<<<<<<
@@ -31286,7 +31446,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
             __pyx_v_ptr3 = (__pyx_v_ptr2 + 2);
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":358
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":375
  *                                 is_super = 0
  *                             ptr3 = ptr2 + 2
  *                             while ptr3 < N:             # <<<<<<<<<<<<<<
@@ -31297,7 +31457,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               __pyx_t_11 = (__pyx_v_ptr3 < __pyx_v_N);
               if (!__pyx_t_11) break;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":359
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":376
  *                             ptr3 = ptr2 + 2
  *                             while ptr3 < N:
  *                                 i3 = queue.arr[ptr3]             # <<<<<<<<<<<<<<
@@ -31306,7 +31466,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
               __pyx_v_i3 = (__pyx_v_queue->arr[__pyx_v_ptr3]);
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":360
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":377
  *                             while ptr3 < N:
  *                                 i3 = queue.arr[ptr3]
  *                                 if i3 == -1 or i3 - i1 >= self.train_max_initial_size:             # <<<<<<<<<<<<<<
@@ -31322,7 +31482,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               }
               if (__pyx_t_19) {
 
-                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":361
+                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":378
  *                                 i3 = queue.arr[ptr3]
  *                                 if i3 == -1 or i3 - i1 >= self.train_max_initial_size:
  *                                     break             # <<<<<<<<<<<<<<
@@ -31334,7 +31494,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               }
               __pyx_L28:;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":362
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":379
  *                                 if i3 == -1 or i3 - i1 >= self.train_max_initial_size:
  *                                     break
  *                                 l3 = queue.arr[ptr3+1]             # <<<<<<<<<<<<<<
@@ -31343,7 +31503,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
               __pyx_v_l3 = (__pyx_v_queue->arr[(__pyx_v_ptr3 + 1)]);
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":363
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":380
  *                                     break
  *                                 l3 = queue.arr[ptr3+1]
  *                                 if (i3 - i2 - l2 >= self.train_min_gap_size and             # <<<<<<<<<<<<<<
@@ -31353,7 +31513,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               __pyx_t_19 = (((__pyx_v_i3 - __pyx_v_i2) - __pyx_v_l2) >= __pyx_v_self->train_min_gap_size);
               if (__pyx_t_19) {
 
-                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":364
+                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":381
  *                                 l3 = queue.arr[ptr3+1]
  *                                 if (i3 - i2 - l2 >= self.train_min_gap_size and
  *                                         i3 + l3 - i1 <= self.train_max_initial_size and             # <<<<<<<<<<<<<<
@@ -31363,7 +31523,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                 __pyx_t_11 = (((__pyx_v_i3 + __pyx_v_l3) - __pyx_v_i1) <= __pyx_v_self->train_max_initial_size);
                 if (__pyx_t_11) {
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":365
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":382
  *                                 if (i3 - i2 - l2 >= self.train_min_gap_size and
  *                                         i3 + l3 - i1 <= self.train_max_initial_size and
  *                                         l1+l2+l3+2 <= self.max_length):             # <<<<<<<<<<<<<<
@@ -31381,7 +31541,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               }
               if (__pyx_t_11) {
 
-                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":366
+                /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":383
  *                                         i3 + l3 - i1 <= self.train_max_initial_size and
  *                                         l1+l2+l3+2 <= self.max_length):
  *                                     if is_super or super_frequent_patterns._contains(data.arr+i3, l3) != NULL:             # <<<<<<<<<<<<<<
@@ -31396,7 +31556,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                 }
                 if (__pyx_t_19) {
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":367
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":384
  *                                         l1+l2+l3+2 <= self.max_length):
  *                                     if is_super or super_frequent_patterns._contains(data.arr+i3, l3) != NULL:
  *                                         node = collocations._insert(data.arr+i1, l1)             # <<<<<<<<<<<<<<
@@ -31405,7 +31565,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
                   __pyx_v_node = ((struct __pyx_vtabstruct_3_sa_TrieMap *)__pyx_v_collocations->__pyx_vtab)->_insert(__pyx_v_collocations, (__pyx_v_data->arr + __pyx_v_i1), __pyx_v_l1);
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":368
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":385
  *                                     if is_super or super_frequent_patterns._contains(data.arr+i3, l3) != NULL:
  *                                         node = collocations._insert(data.arr+i1, l1)
  *                                         node = trie_insert(node, -1)             # <<<<<<<<<<<<<<
@@ -31414,7 +31574,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
                   __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, -1);
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":369
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":386
  *                                         node = collocations._insert(data.arr+i1, l1)
  *                                         node = trie_insert(node, -1)
  *                                         for i from i2 <= i < i2+l2:             # <<<<<<<<<<<<<<
@@ -31424,7 +31584,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                   __pyx_t_13 = (__pyx_v_i2 + __pyx_v_l2);
                   for (__pyx_v_i = __pyx_v_i2; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-                    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":370
+                    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":387
  *                                         node = trie_insert(node, -1)
  *                                         for i from i2 <= i < i2+l2:
  *                                             node = trie_insert(node, data.arr[i])             # <<<<<<<<<<<<<<
@@ -31434,7 +31594,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                     __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, (__pyx_v_data->arr[__pyx_v_i]));
                   }
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":371
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":388
  *                                         for i from i2 <= i < i2+l2:
  *                                             node = trie_insert(node, data.arr[i])
  *                                         node = trie_insert(node, -1)             # <<<<<<<<<<<<<<
@@ -31443,7 +31603,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
                   __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, -1);
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":372
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":389
  *                                             node = trie_insert(node, data.arr[i])
  *                                         node = trie_insert(node, -1)
  *                                         for i from i3 <= i < i3+l3:             # <<<<<<<<<<<<<<
@@ -31453,7 +31613,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                   __pyx_t_13 = (__pyx_v_i3 + __pyx_v_l3);
                   for (__pyx_v_i = __pyx_v_i3; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-                    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":373
+                    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":390
  *                                         node = trie_insert(node, -1)
  *                                         for i from i3 <= i < i3+l3:
  *                                             node = trie_insert(node, data.arr[i])             # <<<<<<<<<<<<<<
@@ -31463,36 +31623,36 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
                     __pyx_v_node = __pyx_f_3_sa_trie_insert(__pyx_v_node, (__pyx_v_data->arr[__pyx_v_i]));
                   }
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":374
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":391
  *                                         for i from i3 <= i < i3+l3:
  *                                             node = trie_insert(node, data.arr[i])
  *                                         trie_node_data_append(node, i1)             # <<<<<<<<<<<<<<
  *                                         trie_node_data_append(node, i2)
  *                                         trie_node_data_append(node, i3)
  */
-                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 374; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 391; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                   __Pyx_GOTREF(__pyx_t_3);
                   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":375
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":392
  *                                             node = trie_insert(node, data.arr[i])
  *                                         trie_node_data_append(node, i1)
  *                                         trie_node_data_append(node, i2)             # <<<<<<<<<<<<<<
  *                                         trie_node_data_append(node, i3)
  *                                 ptr3 = ptr3 + 2
  */
-                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 375; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                   __Pyx_GOTREF(__pyx_t_3);
                   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
-                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":376
+                  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":393
  *                                         trie_node_data_append(node, i1)
  *                                         trie_node_data_append(node, i2)
  *                                         trie_node_data_append(node, i3)             # <<<<<<<<<<<<<<
  *                                 ptr3 = ptr3 + 2
  *                     ptr2 = ptr2 + 2
  */
-                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 376; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+                  __pyx_t_3 = __pyx_f_3_sa_trie_node_data_append(__pyx_v_node, __pyx_v_i3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                   __Pyx_GOTREF(__pyx_t_3);
                   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
                   goto __pyx_L30;
@@ -31502,7 +31662,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
               }
               __pyx_L29:;
 
-              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":377
+              /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":394
  *                                         trie_node_data_append(node, i2)
  *                                         trie_node_data_append(node, i3)
  *                                 ptr3 = ptr3 + 2             # <<<<<<<<<<<<<<
@@ -31519,7 +31679,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         __pyx_L21:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":378
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":395
  *                                         trie_node_data_append(node, i3)
  *                                 ptr3 = ptr3 + 2
  *                     ptr2 = ptr2 + 2             # <<<<<<<<<<<<<<
@@ -31530,7 +31690,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       }
       __pyx_L19_break:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":379
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":396
  *                                 ptr3 = ptr3 + 2
  *                     ptr2 = ptr2 + 2
  *                 ptr1 = ptr1 + 2             # <<<<<<<<<<<<<<
@@ -31542,7 +31702,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":381
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":398
  *                 ptr1 = ptr1 + 2
  *             else:
  *                 sent_count = sent_count + 1             # <<<<<<<<<<<<<<
@@ -31551,7 +31711,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
       __pyx_v_sent_count = (__pyx_v_sent_count + 1);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":382
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":399
  *             else:
  *                 sent_count = sent_count + 1
  *                 if sent_count % 10000 == 0:             # <<<<<<<<<<<<<<
@@ -31561,29 +31721,29 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __pyx_t_19 = (__Pyx_mod_long(__pyx_v_sent_count, 10000) == 0);
       if (__pyx_t_19) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":383
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":400
  *                 sent_count = sent_count + 1
  *                 if sent_count % 10000 == 0:
  *                     logger.debug("        %d sentences", sent_count)             # <<<<<<<<<<<<<<
  *                 ptr1 = ptr1 + 1
  * 
  */
-        __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__debug); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyObject_GetAttr(__pyx_t_3, __pyx_n_s__debug); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __pyx_t_3 = PyInt_FromLong(__pyx_v_sent_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyInt_FromLong(__pyx_v_sent_count); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_INCREF(((PyObject *)__pyx_kp_s_78));
-        PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_kp_s_78));
-        __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_78));
+        __Pyx_INCREF(((PyObject *)__pyx_kp_s_80));
+        PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_kp_s_80));
+        __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_80));
         PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
         __Pyx_GIVEREF(__pyx_t_3);
         __pyx_t_3 = 0;
-        __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 383; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_3);
         __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
         __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -31592,7 +31752,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       }
       __pyx_L35:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":384
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":401
  *                 if sent_count % 10000 == 0:
  *                     logger.debug("        %d sentences", sent_count)
  *                 ptr1 = ptr1 + 1             # <<<<<<<<<<<<<<
@@ -31604,23 +31764,23 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_L17:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":386
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":403
  *                 ptr1 = ptr1 + 1
  * 
  *         self.precomputed_collocations = collocations.toMap(False)             # <<<<<<<<<<<<<<
  *         self.precomputed_index = frequent_patterns.toMap(True)
  * 
  */
-  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_collocations), __pyx_n_s__toMap); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_collocations), __pyx_n_s__toMap); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_8 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_8);
   __Pyx_GIVEREF(__pyx_t_8);
   __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 386; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
@@ -31630,23 +31790,23 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __pyx_v_self->precomputed_collocations = __pyx_t_8;
   __pyx_t_8 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":387
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":404
  * 
  *         self.precomputed_collocations = collocations.toMap(False)
  *         self.precomputed_index = frequent_patterns.toMap(True)             # <<<<<<<<<<<<<<
  * 
  *         x = 0
  */
-  __pyx_t_8 = PyObject_GetAttr(((PyObject *)__pyx_v_frequent_patterns), __pyx_n_s__toMap); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_GetAttr(((PyObject *)__pyx_v_frequent_patterns), __pyx_n_s__toMap); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_1 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(__pyx_t_8, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 387; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_t_8, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
@@ -31656,7 +31816,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __pyx_v_self->precomputed_index = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":389
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":406
  *         self.precomputed_index = frequent_patterns.toMap(True)
  * 
  *         x = 0             # <<<<<<<<<<<<<<
@@ -31666,14 +31826,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __Pyx_INCREF(__pyx_int_0);
   __pyx_v_x = __pyx_int_0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":390
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":407
  * 
  *         x = 0
  *         for pattern1 in J_set:             # <<<<<<<<<<<<<<
  *             for pattern2 in J_set:
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:
  */
-  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_J_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_J_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_4 = Py_TYPE(__pyx_t_1)->tp_iternext;
   for (;;) {
@@ -31682,7 +31842,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       if (unlikely(!__pyx_t_3)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 390; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -31692,14 +31852,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_v_pattern1 = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":391
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":408
  *         x = 0
  *         for pattern1 in J_set:
  *             for pattern2 in J_set:             # <<<<<<<<<<<<<<
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  */
-    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_J_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 391; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_J_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_t_20 = Py_TYPE(__pyx_t_3)->tp_iternext;
     for (;;) {
@@ -31708,7 +31868,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         if (unlikely(!__pyx_t_8)) {
           if (PyErr_Occurred()) {
             if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-            else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 391; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           break;
         }
@@ -31718,42 +31878,42 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __pyx_v_pattern2 = __pyx_t_8;
       __pyx_t_8 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":392
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":409
  *         for pattern1 in J_set:
  *             for pattern2 in J_set:
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:             # <<<<<<<<<<<<<<
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     J2_set.add(combined_pattern)
  */
-      __pyx_t_2 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_14 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_14 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_19 = (((__pyx_t_2 + __pyx_t_14) + 1) < __pyx_v_self->max_length);
       if (__pyx_t_19) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":393
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":410
  *             for pattern2 in J_set:
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     J2_set.add(combined_pattern)
  * 
  */
-        __pyx_t_8 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_79)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_81)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_7 = PyNumber_Add(__pyx_t_8, __pyx_v_pattern2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyNumber_Add(__pyx_t_8, __pyx_v_pattern2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
         __Pyx_XDECREF(__pyx_v_combined_pattern);
         __pyx_v_combined_pattern = __pyx_t_7;
         __pyx_t_7 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":394
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":411
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     J2_set.add(combined_pattern)             # <<<<<<<<<<<<<<
  * 
  *         for pattern1 in I_set:
  */
-        __pyx_t_15 = PySet_Add(__pyx_v_J2_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 394; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_15 = PySet_Add(__pyx_v_J2_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 411; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L40;
       }
       __pyx_L40:;
@@ -31762,14 +31922,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":396
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":413
  *                     J2_set.add(combined_pattern)
  * 
  *         for pattern1 in I_set:             # <<<<<<<<<<<<<<
  *             for pattern2 in I_set:
  *                 x = x+1
  */
-  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 396; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_4 = Py_TYPE(__pyx_t_1)->tp_iternext;
   for (;;) {
@@ -31778,7 +31938,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       if (unlikely(!__pyx_t_3)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 396; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -31788,14 +31948,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_v_pattern1 = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":397
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":414
  * 
  *         for pattern1 in I_set:
  *             for pattern2 in I_set:             # <<<<<<<<<<<<<<
  *                 x = x+1
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:
  */
-    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 397; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_t_20 = Py_TYPE(__pyx_t_3)->tp_iternext;
     for (;;) {
@@ -31804,7 +31964,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         if (unlikely(!__pyx_t_7)) {
           if (PyErr_Occurred()) {
             if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-            else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 397; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           break;
         }
@@ -31814,55 +31974,55 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __pyx_v_pattern2 = __pyx_t_7;
       __pyx_t_7 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":398
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":415
  *         for pattern1 in I_set:
  *             for pattern2 in I_set:
  *                 x = x+1             # <<<<<<<<<<<<<<
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  */
-      __pyx_t_7 = PyNumber_Add(__pyx_v_x, __pyx_int_1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 398; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyNumber_Add(__pyx_v_x, __pyx_int_1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 415; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_DECREF(__pyx_v_x);
       __pyx_v_x = __pyx_t_7;
       __pyx_t_7 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":399
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":416
  *             for pattern2 in I_set:
  *                 x = x+1
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:             # <<<<<<<<<<<<<<
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)
  */
-      __pyx_t_14 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 399; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_2 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 399; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_14 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 416; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 416; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_19 = (((__pyx_t_14 + __pyx_t_2) + 1) <= __pyx_v_self->max_length);
       if (__pyx_t_19) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":400
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":417
  *                 x = x+1
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  * 
  */
-        __pyx_t_7 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_80)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_82)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = PyNumber_Add(__pyx_t_7, __pyx_v_pattern2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyNumber_Add(__pyx_t_7, __pyx_v_pattern2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
         __Pyx_XDECREF(__pyx_v_combined_pattern);
         __pyx_v_combined_pattern = __pyx_t_8;
         __pyx_t_8 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":401
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":418
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)             # <<<<<<<<<<<<<<
  * 
  *         for pattern1 in I_set:
  */
-        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 401; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L45;
       }
       __pyx_L45:;
@@ -31871,14 +32031,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":403
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":420
  *                     IJ_set.add(combined_pattern)
  * 
  *         for pattern1 in I_set:             # <<<<<<<<<<<<<<
  *             for pattern2 in J2_set:
  *                 x = x+2
  */
-  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_I_set)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 420; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_4 = Py_TYPE(__pyx_t_1)->tp_iternext;
   for (;;) {
@@ -31887,7 +32047,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       if (unlikely(!__pyx_t_3)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 403; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 420; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -31897,14 +32057,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_v_pattern1 = __pyx_t_3;
     __pyx_t_3 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":404
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":421
  * 
  *         for pattern1 in I_set:
  *             for pattern2 in J2_set:             # <<<<<<<<<<<<<<
  *                 x = x+2
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:
  */
-    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_J2_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_GetIter(((PyObject *)__pyx_v_J2_set)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_t_20 = Py_TYPE(__pyx_t_3)->tp_iternext;
     for (;;) {
@@ -31913,7 +32073,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         if (unlikely(!__pyx_t_8)) {
           if (PyErr_Occurred()) {
             if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-            else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 421; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           }
           break;
         }
@@ -31923,80 +32083,80 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __pyx_v_pattern2 = __pyx_t_8;
       __pyx_t_8 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":405
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":422
  *         for pattern1 in I_set:
  *             for pattern2 in J2_set:
  *                 x = x+2             # <<<<<<<<<<<<<<
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  */
-      __pyx_t_8 = PyNumber_Add(__pyx_v_x, __pyx_int_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 405; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyNumber_Add(__pyx_v_x, __pyx_int_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
       __Pyx_DECREF(__pyx_v_x);
       __pyx_v_x = __pyx_t_8;
       __pyx_t_8 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":406
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":423
  *             for pattern2 in J2_set:
  *                 x = x+2
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:             # <<<<<<<<<<<<<<
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)
  */
-      __pyx_t_2 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_14 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 406; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyObject_Length(__pyx_v_pattern1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_14 = PyObject_Length(__pyx_v_pattern2); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_19 = (((__pyx_t_2 + __pyx_t_14) + 1) <= __pyx_v_self->max_length);
       if (__pyx_t_19) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":407
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":424
  *                 x = x+2
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  *                     combined_pattern = pattern2 + (-1,) + pattern1
  */
-        __pyx_t_8 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_81)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyNumber_Add(__pyx_v_pattern1, ((PyObject *)__pyx_k_tuple_83)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_7 = PyNumber_Add(__pyx_t_8, __pyx_v_pattern2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyNumber_Add(__pyx_t_8, __pyx_v_pattern2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
         __Pyx_XDECREF(__pyx_v_combined_pattern);
         __pyx_v_combined_pattern = __pyx_t_7;
         __pyx_t_7 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":408
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":425
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)             # <<<<<<<<<<<<<<
  *                     combined_pattern = pattern2 + (-1,) + pattern1
  *                     IJ_set.add(combined_pattern)
  */
-        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 408; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 425; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":409
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":426
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)
  *                     combined_pattern = pattern2 + (-1,) + pattern1             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  * 
  */
-        __pyx_t_7 = PyNumber_Add(__pyx_v_pattern2, ((PyObject *)__pyx_k_tuple_82)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_7 = PyNumber_Add(__pyx_v_pattern2, ((PyObject *)__pyx_k_tuple_84)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = PyNumber_Add(__pyx_t_7, __pyx_v_pattern1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyNumber_Add(__pyx_t_7, __pyx_v_pattern1); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
         __Pyx_DECREF(__pyx_v_combined_pattern);
         __pyx_v_combined_pattern = __pyx_t_8;
         __pyx_t_8 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":410
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":427
  *                     IJ_set.add(combined_pattern)
  *                     combined_pattern = pattern2 + (-1,) + pattern1
  *                     IJ_set.add(combined_pattern)             # <<<<<<<<<<<<<<
  * 
  *         N = len(pattern_rank)
  */
-        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_15 = PySet_Add(__pyx_v_IJ_set, __pyx_v_combined_pattern); if (unlikely(__pyx_t_15 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 427; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         goto __pyx_L50;
       }
       __pyx_L50:;
@@ -32005,55 +32165,55 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":412
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":429
  *                     IJ_set.add(combined_pattern)
  * 
  *         N = len(pattern_rank)             # <<<<<<<<<<<<<<
  *         cost_by_rank = IntList(initial_len=N)
  *         count_by_rank = IntList(initial_len=N)
  */
-  __pyx_t_14 = PyDict_Size(((PyObject *)__pyx_v_pattern_rank)); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 412; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_14 = PyDict_Size(((PyObject *)__pyx_v_pattern_rank)); if (unlikely(__pyx_t_14 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_v_N = __pyx_t_14;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":413
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":430
  * 
  *         N = len(pattern_rank)
  *         cost_by_rank = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *         count_by_rank = IntList(initial_len=N)
  *         for pattern, arr in self.precomputed_collocations.iteritems():
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __pyx_t_3 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_3) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 413; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __pyx_v_cost_by_rank = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_3);
   __pyx_t_3 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":414
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":431
  *         N = len(pattern_rank)
  *         cost_by_rank = IntList(initial_len=N)
  *         count_by_rank = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *         for pattern, arr in self.precomputed_collocations.iteritems():
  *             if pattern not in IJ_set:
  */
-  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyDict_New(); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_3, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 414; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __pyx_v_count_by_rank = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":415
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":432
  *         cost_by_rank = IntList(initial_len=N)
  *         count_by_rank = IntList(initial_len=N)
  *         for pattern, arr in self.precomputed_collocations.iteritems():             # <<<<<<<<<<<<<<
@@ -32063,9 +32223,9 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __pyx_t_14 = 0;
   if (unlikely(__pyx_v_self->precomputed_collocations == Py_None)) {
     PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%s'", "iteritems");
-    {__pyx_filename = __pyx_f[11]; __pyx_lineno = 415; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[13]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
-  __pyx_t_3 = __Pyx_dict_iterator(__pyx_v_self->precomputed_collocations, 0, ((PyObject *)__pyx_n_s__iteritems), (&__pyx_t_2), (&__pyx_t_13)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 415; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_dict_iterator(__pyx_v_self->precomputed_collocations, 0, ((PyObject *)__pyx_n_s__iteritems), (&__pyx_t_2), (&__pyx_t_13)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_1);
   __pyx_t_1 = __pyx_t_3;
@@ -32073,7 +32233,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   while (1) {
     __pyx_t_16 = __Pyx_dict_iter_next(__pyx_t_1, __pyx_t_2, &__pyx_t_14, &__pyx_t_3, &__pyx_t_8, NULL, __pyx_t_13);
     if (unlikely(__pyx_t_16 == 0)) break;
-    if (unlikely(__pyx_t_16 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 415; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__pyx_t_16 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 432; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_GOTREF(__pyx_t_8);
     __Pyx_XDECREF(__pyx_v_pattern);
@@ -32083,28 +32243,28 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_v_arr = __pyx_t_8;
     __pyx_t_8 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":416
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":433
  *         count_by_rank = IntList(initial_len=N)
  *         for pattern, arr in self.precomputed_collocations.iteritems():
  *             if pattern not in IJ_set:             # <<<<<<<<<<<<<<
  *                 s = ""
  *                 for word_id in pattern:
  */
-    __pyx_t_19 = (__Pyx_PySequence_Contains(__pyx_v_pattern, ((PyObject *)__pyx_v_IJ_set), Py_NE)); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 416; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_19 = (__Pyx_PySequence_Contains(__pyx_v_pattern, ((PyObject *)__pyx_v_IJ_set), Py_NE)); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 433; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     if (__pyx_t_19) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":417
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":434
  *         for pattern, arr in self.precomputed_collocations.iteritems():
  *             if pattern not in IJ_set:
  *                 s = ""             # <<<<<<<<<<<<<<
  *                 for word_id in pattern:
  *                     if word_id == -1:
  */
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_45));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_60));
       __Pyx_XDECREF(__pyx_v_s);
-      __pyx_v_s = ((PyObject *)__pyx_kp_s_45);
+      __pyx_v_s = ((PyObject *)__pyx_kp_s_60);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":418
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":435
  *             if pattern not in IJ_set:
  *                 s = ""
  *                 for word_id in pattern:             # <<<<<<<<<<<<<<
@@ -32115,7 +32275,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_t_8 = __pyx_v_pattern; __Pyx_INCREF(__pyx_t_8); __pyx_t_12 = 0;
         __pyx_t_4 = NULL;
       } else {
-        __pyx_t_12 = -1; __pyx_t_8 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_12 = -1; __pyx_t_8 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_8);
         __pyx_t_4 = Py_TYPE(__pyx_t_8)->tp_iternext;
       }
@@ -32123,23 +32283,23 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         if (!__pyx_t_4 && PyList_CheckExact(__pyx_t_8)) {
           if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_8)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_3 = PyList_GET_ITEM(__pyx_t_8, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyList_GET_ITEM(__pyx_t_8, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_3 = PySequence_ITEM(__pyx_t_8, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PySequence_ITEM(__pyx_t_8, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else if (!__pyx_t_4 && PyTuple_CheckExact(__pyx_t_8)) {
           if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_8)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_8, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_8, __pyx_t_12); __Pyx_INCREF(__pyx_t_3); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_3 = PySequence_ITEM(__pyx_t_8, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PySequence_ITEM(__pyx_t_8, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else {
           __pyx_t_3 = __pyx_t_4(__pyx_t_8);
           if (unlikely(!__pyx_t_3)) {
             if (PyErr_Occurred()) {
               if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-              else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+              else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             }
             break;
           }
@@ -32149,26 +32309,26 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_v_word_id = __pyx_t_3;
         __pyx_t_3 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":419
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":436
  *                 s = ""
  *                 for word_id in pattern:
  *                     if word_id == -1:             # <<<<<<<<<<<<<<
  *                         s = s + "X "
  *                     else:
  */
-        __pyx_t_3 = PyObject_RichCompare(__pyx_v_word_id, __pyx_int_neg_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 419; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_3 = PyObject_RichCompare(__pyx_v_word_id, __pyx_int_neg_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
         if (__pyx_t_19) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":420
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":437
  *                 for word_id in pattern:
  *                     if word_id == -1:
  *                         s = s + "X "             # <<<<<<<<<<<<<<
  *                     else:
- *                         s = s + darray.id2word[word_id] + " "
+ *                         s = s + darray.voc.id2word[word_id] + " "
  */
-          __pyx_t_3 = PyNumber_Add(__pyx_v_s, ((PyObject *)__pyx_kp_s_83)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 420; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyNumber_Add(__pyx_v_s, ((PyObject *)__pyx_kp_s_85)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_v_s);
           __pyx_v_s = __pyx_t_3;
@@ -32177,19 +32337,19 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         /*else*/ {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":422
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":439
  *                         s = s + "X "
  *                     else:
- *                         s = s + darray.id2word[word_id] + " "             # <<<<<<<<<<<<<<
+ *                         s = s + darray.voc.id2word[word_id] + " "             # <<<<<<<<<<<<<<
  *                 logger.warn("ERROR: unexpected pattern %s in set of precomputed collocations", s)
  *             else:
  */
-          __pyx_t_3 = PyObject_GetItem(__pyx_v_darray->id2word, __pyx_v_word_id); if (!__pyx_t_3) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyObject_GetItem(__pyx_v_darray->voc->id2word, __pyx_v_word_id); if (!__pyx_t_3) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 439; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
-          __pyx_t_7 = PyNumber_Add(__pyx_v_s, __pyx_t_3); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_7 = PyNumber_Add(__pyx_v_s, __pyx_t_3); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 439; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_7);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          __pyx_t_3 = PyNumber_Add(__pyx_t_7, ((PyObject *)__pyx_kp_s_67)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyNumber_Add(__pyx_t_7, ((PyObject *)__pyx_kp_s_68)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 439; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
           __Pyx_DECREF(__pyx_v_s);
@@ -32200,27 +32360,27 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       }
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":423
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":440
  *                     else:
- *                         s = s + darray.id2word[word_id] + " "
+ *                         s = s + darray.voc.id2word[word_id] + " "
  *                 logger.warn("ERROR: unexpected pattern %s in set of precomputed collocations", s)             # <<<<<<<<<<<<<<
  *             else:
  *                 chunk = ()
  */
-      __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_3 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__warn); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__warn); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_84));
-      PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_kp_s_84));
-      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_84));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_86));
+      PyTuple_SET_ITEM(__pyx_t_8, 0, ((PyObject *)__pyx_kp_s_86));
+      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_86));
       __Pyx_INCREF(__pyx_v_s);
       PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_s);
       __Pyx_GIVEREF(__pyx_v_s);
-      __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 423; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
       __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
@@ -32229,7 +32389,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":425
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":442
  *                 logger.warn("ERROR: unexpected pattern %s in set of precomputed collocations", s)
  *             else:
  *                 chunk = ()             # <<<<<<<<<<<<<<
@@ -32240,7 +32400,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __Pyx_XDECREF(((PyObject *)__pyx_v_chunk));
       __pyx_v_chunk = __pyx_empty_tuple;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":426
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":443
  *             else:
  *                 chunk = ()
  *                 max_rank = 0             # <<<<<<<<<<<<<<
@@ -32249,7 +32409,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
       __pyx_v_max_rank = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":427
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":444
  *                 chunk = ()
  *                 max_rank = 0
  *                 arity = 0             # <<<<<<<<<<<<<<
@@ -32260,7 +32420,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       __Pyx_XDECREF(__pyx_v_arity);
       __pyx_v_arity = __pyx_int_0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":428
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":445
  *                 max_rank = 0
  *                 arity = 0
  *                 for word_id in pattern:             # <<<<<<<<<<<<<<
@@ -32271,7 +32431,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_t_7 = __pyx_v_pattern; __Pyx_INCREF(__pyx_t_7); __pyx_t_12 = 0;
         __pyx_t_4 = NULL;
       } else {
-        __pyx_t_12 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_12 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_v_pattern); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_4 = Py_TYPE(__pyx_t_7)->tp_iternext;
       }
@@ -32279,23 +32439,23 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         if (!__pyx_t_4 && PyList_CheckExact(__pyx_t_7)) {
           if (__pyx_t_12 >= PyList_GET_SIZE(__pyx_t_7)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_8 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_8 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else if (!__pyx_t_4 && PyTuple_CheckExact(__pyx_t_7)) {
           if (__pyx_t_12 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
           #if CYTHON_COMPILING_IN_CPYTHON
-          __pyx_t_8 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_12); __Pyx_INCREF(__pyx_t_8); __pyx_t_12++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #else
-          __pyx_t_8 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = PySequence_ITEM(__pyx_t_7, __pyx_t_12); __pyx_t_12++; if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           #endif
         } else {
           __pyx_t_8 = __pyx_t_4(__pyx_t_7);
           if (unlikely(!__pyx_t_8)) {
             if (PyErr_Occurred()) {
               if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-              else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 428; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+              else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 445; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             }
             break;
           }
@@ -32305,62 +32465,62 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         __pyx_v_word_id = __pyx_t_8;
         __pyx_t_8 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":429
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":446
  *                 arity = 0
  *                 for word_id in pattern:
  *                     if word_id == -1:             # <<<<<<<<<<<<<<
  *                         max_rank = max(max_rank, pattern_rank[chunk])
  *                         arity = arity + 1
  */
-        __pyx_t_8 = PyObject_RichCompare(__pyx_v_word_id, __pyx_int_neg_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 429; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_8 = PyObject_RichCompare(__pyx_v_word_id, __pyx_int_neg_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
         if (__pyx_t_19) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":430
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":447
  *                 for word_id in pattern:
  *                     if word_id == -1:
  *                         max_rank = max(max_rank, pattern_rank[chunk])             # <<<<<<<<<<<<<<
  *                         arity = arity + 1
  *                         chunk = ()
  */
-          __pyx_t_8 = __Pyx_PyDict_GetItem(((PyObject *)__pyx_v_pattern_rank), ((PyObject *)__pyx_v_chunk)); if (!__pyx_t_8) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = __Pyx_PyDict_GetItem(((PyObject *)__pyx_v_pattern_rank), ((PyObject *)__pyx_v_chunk)); if (!__pyx_t_8) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_8);
           __pyx_t_16 = __pyx_v_max_rank;
-          __pyx_t_5 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_5 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_5);
-          __pyx_t_6 = PyObject_RichCompare(__pyx_t_8, __pyx_t_5, Py_GT); __Pyx_XGOTREF(__pyx_t_6); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_6 = PyObject_RichCompare(__pyx_t_8, __pyx_t_5, Py_GT); __Pyx_XGOTREF(__pyx_t_6); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-          __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
           if (__pyx_t_19) {
             __Pyx_INCREF(__pyx_t_8);
             __pyx_t_3 = __pyx_t_8;
           } else {
-            __pyx_t_6 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_6 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(__pyx_t_6);
             __pyx_t_3 = __pyx_t_6;
             __pyx_t_6 = 0;
           }
           __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-          __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 430; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
           __pyx_v_max_rank = __pyx_t_16;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":431
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":448
  *                     if word_id == -1:
  *                         max_rank = max(max_rank, pattern_rank[chunk])
  *                         arity = arity + 1             # <<<<<<<<<<<<<<
  *                         chunk = ()
  *                     else:
  */
-          __pyx_t_3 = PyNumber_Add(__pyx_v_arity, __pyx_int_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 431; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyNumber_Add(__pyx_v_arity, __pyx_int_1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 448; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_DECREF(__pyx_v_arity);
           __pyx_v_arity = __pyx_t_3;
           __pyx_t_3 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":432
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":449
  *                         max_rank = max(max_rank, pattern_rank[chunk])
  *                         arity = arity + 1
  *                         chunk = ()             # <<<<<<<<<<<<<<
@@ -32374,19 +32534,19 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
         }
         /*else*/ {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":434
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":451
  *                         chunk = ()
  *                     else:
  *                         chunk = chunk + (word_id,)             # <<<<<<<<<<<<<<
  *                 max_rank = max(max_rank, pattern_rank[chunk])
  *                 cost_by_rank.arr[max_rank] = cost_by_rank.arr[max_rank] + (4*len(arr))
  */
-          __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(__pyx_t_3);
           __Pyx_INCREF(__pyx_v_word_id);
           PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_word_id);
           __Pyx_GIVEREF(__pyx_v_word_id);
-          __pyx_t_8 = PyNumber_Add(((PyObject *)__pyx_v_chunk), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 434; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          __pyx_t_8 = PyNumber_Add(((PyObject *)__pyx_v_chunk), ((PyObject *)__pyx_t_3)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
           __Pyx_GOTREF(((PyObject *)__pyx_t_8));
           __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
           __Pyx_DECREF(((PyObject *)__pyx_v_chunk));
@@ -32397,69 +32557,69 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       }
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":435
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":452
  *                     else:
  *                         chunk = chunk + (word_id,)
  *                 max_rank = max(max_rank, pattern_rank[chunk])             # <<<<<<<<<<<<<<
  *                 cost_by_rank.arr[max_rank] = cost_by_rank.arr[max_rank] + (4*len(arr))
  *                 count_by_rank.arr[max_rank] = count_by_rank.arr[max_rank] + (len(arr)/(arity+1))
  */
-      __pyx_t_7 = __Pyx_PyDict_GetItem(((PyObject *)__pyx_v_pattern_rank), ((PyObject *)__pyx_v_chunk)); if (!__pyx_t_7) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = __Pyx_PyDict_GetItem(((PyObject *)__pyx_v_pattern_rank), ((PyObject *)__pyx_v_chunk)); if (!__pyx_t_7) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __pyx_t_16 = __pyx_v_max_rank;
-      __pyx_t_3 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_6 = PyObject_RichCompare(__pyx_t_7, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_6); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyObject_RichCompare(__pyx_t_7, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_6); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_19 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       if (__pyx_t_19) {
         __Pyx_INCREF(__pyx_t_7);
         __pyx_t_8 = __pyx_t_7;
       } else {
-        __pyx_t_6 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_6 = PyInt_FromLong(__pyx_t_16); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_6);
         __pyx_t_8 = __pyx_t_6;
         __pyx_t_6 = 0;
       }
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_8); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 435; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_8); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       __pyx_v_max_rank = __pyx_t_16;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":436
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":453
  *                         chunk = chunk + (word_id,)
  *                 max_rank = max(max_rank, pattern_rank[chunk])
  *                 cost_by_rank.arr[max_rank] = cost_by_rank.arr[max_rank] + (4*len(arr))             # <<<<<<<<<<<<<<
  *                 count_by_rank.arr[max_rank] = count_by_rank.arr[max_rank] + (len(arr)/(arity+1))
  * 
  */
-      __pyx_t_12 = PyObject_Length(__pyx_v_arr); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_12 = PyObject_Length(__pyx_v_arr); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       (__pyx_v_cost_by_rank->arr[__pyx_v_max_rank]) = ((__pyx_v_cost_by_rank->arr[__pyx_v_max_rank]) + (4 * __pyx_t_12));
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":437
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":454
  *                 max_rank = max(max_rank, pattern_rank[chunk])
  *                 cost_by_rank.arr[max_rank] = cost_by_rank.arr[max_rank] + (4*len(arr))
  *                 count_by_rank.arr[max_rank] = count_by_rank.arr[max_rank] + (len(arr)/(arity+1))             # <<<<<<<<<<<<<<
  * 
  *         cumul_cost = 0
  */
-      __pyx_t_8 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_max_rank])); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_8 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_max_rank])); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_12 = PyObject_Length(__pyx_v_arr); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_7 = PyInt_FromSsize_t(__pyx_t_12); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_12 = PyObject_Length(__pyx_v_arr); if (unlikely(__pyx_t_12 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyInt_FromSsize_t(__pyx_t_12); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_6 = PyNumber_Add(__pyx_v_arity, __pyx_int_1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyNumber_Add(__pyx_v_arity, __pyx_int_1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_3 = __Pyx_PyNumber_Divide(__pyx_t_7, __pyx_t_6); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_3 = __Pyx_PyNumber_Divide(__pyx_t_7, __pyx_t_6); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_3);
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_t_6 = PyNumber_Add(__pyx_t_8, __pyx_t_3); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PyNumber_Add(__pyx_t_8, __pyx_t_3); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_6);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_6); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 437; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_16 = __Pyx_PyInt_AsInt(__pyx_t_6); if (unlikely((__pyx_t_16 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
       (__pyx_v_count_by_rank->arr[__pyx_v_max_rank]) = __pyx_t_16;
     }
@@ -32467,7 +32627,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":439
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":456
  *                 count_by_rank.arr[max_rank] = count_by_rank.arr[max_rank] + (len(arr)/(arity+1))
  * 
  *         cumul_cost = 0             # <<<<<<<<<<<<<<
@@ -32477,7 +32637,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __Pyx_INCREF(__pyx_int_0);
   __pyx_v_cumul_cost = __pyx_int_0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":440
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":457
  * 
  *         cumul_cost = 0
  *         cumul_count = 0             # <<<<<<<<<<<<<<
@@ -32487,7 +32647,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __Pyx_INCREF(__pyx_int_0);
   __pyx_v_cumul_count = __pyx_int_0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":441
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":458
  *         cumul_cost = 0
  *         cumul_count = 0
  *         for i from 0 <= i < N:             # <<<<<<<<<<<<<<
@@ -32497,61 +32657,61 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   __pyx_t_13 = __pyx_v_N;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_13; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":442
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":459
  *         cumul_count = 0
  *         for i from 0 <= i < N:
  *             cumul_cost = cumul_cost + cost_by_rank.arr[i]             # <<<<<<<<<<<<<<
  *             cumul_count = cumul_count + count_by_rank.arr[i]
  *             logger.debug("RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d", i, count_by_rank.arr[i], cost_by_rank.arr[i], cumul_count, cumul_cost)
  */
-    __pyx_t_1 = PyInt_FromLong((__pyx_v_cost_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong((__pyx_v_cost_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_6 = PyNumber_Add(__pyx_v_cumul_cost, __pyx_t_1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyNumber_Add(__pyx_v_cumul_cost, __pyx_t_1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
     __Pyx_DECREF(__pyx_v_cumul_cost);
     __pyx_v_cumul_cost = __pyx_t_6;
     __pyx_t_6 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":443
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":460
  *         for i from 0 <= i < N:
  *             cumul_cost = cumul_cost + cost_by_rank.arr[i]
  *             cumul_count = cumul_count + count_by_rank.arr[i]             # <<<<<<<<<<<<<<
  *             logger.debug("RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d", i, count_by_rank.arr[i], cost_by_rank.arr[i], cumul_count, cumul_cost)
  * 
  */
-    __pyx_t_6 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_1 = PyNumber_Add(__pyx_v_cumul_count, __pyx_t_6); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 443; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyNumber_Add(__pyx_v_cumul_count, __pyx_t_6); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __Pyx_DECREF(__pyx_v_cumul_count);
     __pyx_v_cumul_count = __pyx_t_1;
     __pyx_t_1 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":444
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":461
  *             cumul_cost = cumul_cost + cost_by_rank.arr[i]
  *             cumul_count = cumul_count + count_by_rank.arr[i]
  *             logger.debug("RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d", i, count_by_rank.arr[i], cost_by_rank.arr[i], cumul_count, cumul_cost)             # <<<<<<<<<<<<<<
  * 
  *         num_found_patterns = len(self.precomputed_collocations)
  */
-    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_6 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__debug); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__debug); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_1 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_count_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_8 = PyInt_FromLong((__pyx_v_cost_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyInt_FromLong((__pyx_v_cost_by_rank->arr[__pyx_v_i])); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_7 = PyTuple_New(6); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_7 = PyTuple_New(6); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_85));
-    PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_kp_s_85));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_85));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_87));
+    PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_kp_s_87));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_87));
     PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_1);
     __Pyx_GIVEREF(__pyx_t_1);
     PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_t_3);
@@ -32567,14 +32727,14 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_t_1 = 0;
     __pyx_t_3 = 0;
     __pyx_t_8 = 0;
-    __pyx_t_8 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_8 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 461; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_8);
     __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
     __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":446
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":463
  *             logger.debug("RANK %d\tCOUNT, COST: %d    %d\tCUMUL: %d, %d", i, count_by_rank.arr[i], cost_by_rank.arr[i], cumul_count, cumul_cost)
  * 
  *         num_found_patterns = len(self.precomputed_collocations)             # <<<<<<<<<<<<<<
@@ -32583,21 +32743,21 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_t_8 = __pyx_v_self->precomputed_collocations;
   __Pyx_INCREF(__pyx_t_8);
-  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 463; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 463; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_v_num_found_patterns = __pyx_t_8;
   __pyx_t_8 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":447
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":464
  * 
  *         num_found_patterns = len(self.precomputed_collocations)
  *         for pattern in IJ_set:             # <<<<<<<<<<<<<<
  *             if pattern not in self.precomputed_collocations:
  *                 self.precomputed_collocations[pattern] = IntList()
  */
-  __pyx_t_8 = PyObject_GetIter(((PyObject *)__pyx_v_IJ_set)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_GetIter(((PyObject *)__pyx_v_IJ_set)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __pyx_t_4 = Py_TYPE(__pyx_t_8)->tp_iternext;
   for (;;) {
@@ -32606,7 +32766,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
       if (unlikely(!__pyx_t_7)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[11]; __pyx_lineno = 447; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 464; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -32616,26 +32776,26 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
     __pyx_v_pattern = __pyx_t_7;
     __pyx_t_7 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":448
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":465
  *         num_found_patterns = len(self.precomputed_collocations)
  *         for pattern in IJ_set:
  *             if pattern not in self.precomputed_collocations:             # <<<<<<<<<<<<<<
  *                 self.precomputed_collocations[pattern] = IntList()
  * 
  */
-    __pyx_t_19 = (__Pyx_PySequence_Contains(__pyx_v_pattern, __pyx_v_self->precomputed_collocations, Py_NE)); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 448; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_19 = (__Pyx_PySequence_Contains(__pyx_v_pattern, __pyx_v_self->precomputed_collocations, Py_NE)); if (unlikely(__pyx_t_19 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 465; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     if (__pyx_t_19) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":449
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":466
  *         for pattern in IJ_set:
  *             if pattern not in self.precomputed_collocations:
  *                 self.precomputed_collocations[pattern] = IntList()             # <<<<<<<<<<<<<<
  * 
  *         cdef float stop_time = monitor_cpu()
  */
-      __pyx_t_7 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 449; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 466; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
-      if (PyObject_SetItem(__pyx_v_self->precomputed_collocations, __pyx_v_pattern, __pyx_t_7) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 449; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (PyObject_SetItem(__pyx_v_self->precomputed_collocations, __pyx_v_pattern, __pyx_t_7) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 466; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
       goto __pyx_L64;
     }
@@ -32643,7 +32803,7 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   }
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":451
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":468
  *                 self.precomputed_collocations[pattern] = IntList()
  * 
  *         cdef float stop_time = monitor_cpu()             # <<<<<<<<<<<<<<
@@ -32652,29 +32812,29 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
  */
   __pyx_v_stop_time = __pyx_f_3_sa_monitor_cpu();
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":452
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":469
  * 
  *         cdef float stop_time = monitor_cpu()
  *         logger.info("Precomputed collocations for %d patterns out of %d possible (upper bound %d)", num_found_patterns, len(self.precomputed_collocations), x)             # <<<<<<<<<<<<<<
  *         logger.info("Precomputed inverted index for %d patterns ", len(self.precomputed_index))
  *         logger.info("Precomputation took %f seconds", (stop_time - start_time))
  */
-  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_7 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   __pyx_t_8 = __pyx_v_self->precomputed_collocations;
   __Pyx_INCREF(__pyx_t_8);
-  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_6 = PyTuple_New(4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyTuple_New(4); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_86));
-  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_kp_s_86));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_86));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_88));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_kp_s_88));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_88));
   __Pyx_INCREF(__pyx_v_num_found_patterns);
   PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_v_num_found_patterns);
   __Pyx_GIVEREF(__pyx_v_num_found_patterns);
@@ -32684,64 +32844,64 @@ static PyObject *__pyx_pf_3_sa_14Precomputation_6precompute(struct __pyx_obj_3_s
   PyTuple_SET_ITEM(__pyx_t_6, 3, __pyx_v_x);
   __Pyx_GIVEREF(__pyx_v_x);
   __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 452; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 469; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":453
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":470
  *         cdef float stop_time = monitor_cpu()
  *         logger.info("Precomputed collocations for %d patterns out of %d possible (upper bound %d)", num_found_patterns, len(self.precomputed_collocations), x)
  *         logger.info("Precomputed inverted index for %d patterns ", len(self.precomputed_index))             # <<<<<<<<<<<<<<
  *         logger.info("Precomputation took %f seconds", (stop_time - start_time))
  */
-  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_6 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
   __pyx_t_8 = __pyx_v_self->precomputed_index;
   __Pyx_INCREF(__pyx_t_8);
-  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Length(__pyx_t_8); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_87));
-  PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_kp_s_87));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_87));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_89));
+  PyTuple_SET_ITEM(__pyx_t_7, 0, ((PyObject *)__pyx_kp_s_89));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_89));
   PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8);
   __Pyx_GIVEREF(__pyx_t_8);
   __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 453; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_Call(__pyx_t_6, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 470; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":454
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":471
  *         logger.info("Precomputed collocations for %d patterns out of %d possible (upper bound %d)", num_found_patterns, len(self.precomputed_collocations), x)
  *         logger.info("Precomputed inverted index for %d patterns ", len(self.precomputed_index))
  *         logger.info("Precomputation took %f seconds", (stop_time - start_time))             # <<<<<<<<<<<<<<
  */
-  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_7 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyObject_GetAttr(__pyx_t_8, __pyx_n_s__info); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyFloat_FromDouble((__pyx_v_stop_time - __pyx_v_start_time)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyFloat_FromDouble((__pyx_v_stop_time - __pyx_v_start_time)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_88));
-  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_kp_s_88));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_88));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_90));
+  PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_kp_s_90));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_90));
   PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_8);
   __Pyx_GIVEREF(__pyx_t_8);
   __pyx_t_8 = 0;
-  __pyx_t_8 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 471; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -32799,28 +32959,31 @@ static int __pyx_pw_3_sa_11SuffixArray_1__cinit__(PyObject *__pyx_v_self, PyObje
 static int __pyx_pw_3_sa_11SuffixArray_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_from_binary = 0;
   PyObject *__pyx_v_from_text = 0;
+  PyObject *__pyx_v_mmaped = 0;
   PyObject *__pyx_v_side = 0;
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,&__pyx_n_s__side,0};
-    PyObject* values[3] = {0,0,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__from_binary,&__pyx_n_s__from_text,&__pyx_n_s__mmaped,&__pyx_n_s__side,0};
+    PyObject* values[4] = {0,0,0,0};
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":11
  *     cdef IntList ha
  * 
- *     def __cinit__(self, from_binary=None, from_text=None, side=None):             # <<<<<<<<<<<<<<
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False, side=None):             # <<<<<<<<<<<<<<
  *         self.darray = DataArray()
  *         self.sa = IntList()
  */
     values[0] = ((PyObject *)Py_None);
     values[1] = ((PyObject *)Py_None);
-    values[2] = ((PyObject *)Py_None);
+    values[2] = __pyx_k_91;
+    values[3] = ((PyObject *)Py_None);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
         case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
@@ -32841,15 +33004,21 @@ static int __pyx_pw_3_sa_11SuffixArray_1__cinit__(PyObject *__pyx_v_self, PyObje
         }
         case  2:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__side);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__mmaped);
           if (value) { values[2] = value; kw_args--; }
         }
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s__side);
+          if (value) { values[3] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__cinit__") < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
         case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
@@ -32859,22 +33028,23 @@ static int __pyx_pw_3_sa_11SuffixArray_1__cinit__(PyObject *__pyx_v_self, PyObje
     }
     __pyx_v_from_binary = values[0];
     __pyx_v_from_text = values[1];
-    __pyx_v_side = values[2];
+    __pyx_v_mmaped = values[2];
+    __pyx_v_side = values[3];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 0, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.SuffixArray.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return -1;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray___cinit__(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text, __pyx_v_side);
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray___cinit__(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), __pyx_v_from_binary, __pyx_v_from_text, __pyx_v_mmaped, __pyx_v_side);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_side) {
+static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_from_binary, PyObject *__pyx_v_from_text, PyObject *__pyx_v_mmaped, PyObject *__pyx_v_side) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -32888,12 +33058,12 @@ static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArr
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":12
  * 
- *     def __cinit__(self, from_binary=None, from_text=None, side=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False, side=None):
  *         self.darray = DataArray()             # <<<<<<<<<<<<<<
  *         self.sa = IntList()
  *         self.ha = IntList()
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_DataArray)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_DataArray)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->darray);
@@ -32902,13 +33072,13 @@ static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArr
   __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":13
- *     def __cinit__(self, from_binary=None, from_text=None, side=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False, side=None):
  *         self.darray = DataArray()
  *         self.sa = IntList()             # <<<<<<<<<<<<<<
  *         self.ha = IntList()
  *         if from_binary:
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->sa);
@@ -32921,9 +33091,9 @@ static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArr
  *         self.sa = IntList()
  *         self.ha = IntList()             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __Pyx_GOTREF(__pyx_v_self->ha);
@@ -32935,54 +33105,97 @@ static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArr
  *         self.sa = IntList()
  *         self.ha = IntList()
  *         if from_binary:             # <<<<<<<<<<<<<<
- *             self.read_binary(from_binary)
- *         elif from_text:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_binary); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":16
  *         self.ha = IntList()
  *         if from_binary:
- *             self.read_binary(from_binary)             # <<<<<<<<<<<<<<
+ *             if mmaped:             # <<<<<<<<<<<<<<
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ */
+    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_mmaped); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (__pyx_t_2) {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":17
+ *         if from_binary:
+ *             if mmaped:
+ *                 self.read_mmaped(MemoryMap(from_binary))             # <<<<<<<<<<<<<<
+ *             else:
+ *                 self.read_binary(from_binary)
+ */
+      __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_mmaped); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_4 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_MemoryMap)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);
+      __Pyx_GIVEREF(__pyx_t_4);
+      __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      goto __pyx_L4;
+    }
+    /*else*/ {
+
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":19
+ *                 self.read_mmaped(MemoryMap(from_binary))
+ *             else:
+ *                 self.read_binary(from_binary)             # <<<<<<<<<<<<<<
  *         elif from_text:
  *             self.read_text(from_text, side)
  */
-    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_from_binary);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
-    __Pyx_GIVEREF(__pyx_v_from_binary);
-    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_binary); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_v_from_binary);
+      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_binary);
+      __Pyx_GIVEREF(__pyx_v_from_binary);
+      __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
+    __pyx_L4:;
     goto __pyx_L3;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":17
- *         if from_binary:
- *             self.read_binary(from_binary)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":20
+ *             else:
+ *                 self.read_binary(from_binary)
  *         elif from_text:             # <<<<<<<<<<<<<<
  *             self.read_text(from_text, side)
  * 
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_from_text); if (unlikely(__pyx_t_2 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_2) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":18
- *             self.read_binary(from_binary)
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":21
+ *                 self.read_binary(from_binary)
  *         elif from_text:
  *             self.read_text(from_text, side)             # <<<<<<<<<<<<<<
  * 
  *     def __getitem__(self, i):
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__read_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_INCREF(__pyx_v_from_text);
     PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_from_text);
@@ -32990,11 +33203,11 @@ static int __pyx_pf_3_sa_11SuffixArray___cinit__(struct __pyx_obj_3_sa_SuffixArr
     __Pyx_INCREF(__pyx_v_side);
     PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_side);
     __Pyx_GIVEREF(__pyx_v_side);
-    __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     goto __pyx_L3;
   }
   __pyx_L3:;
@@ -33023,7 +33236,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_3__getitem__(PyObject *__pyx_v_self
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":20
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":23
  *             self.read_text(from_text, side)
  * 
  *     def __getitem__(self, i):             # <<<<<<<<<<<<<<
@@ -33041,7 +33254,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_2__getitem__(struct __pyx_obj_3_sa_
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__getitem__", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":21
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":24
  * 
  *     def __getitem__(self, i):
  *         return self.sa.arr[i]             # <<<<<<<<<<<<<<
@@ -33049,8 +33262,8 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_2__getitem__(struct __pyx_obj_3_sa_
  *     def read_text(self, filename, side):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->sa->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_1 == (Py_ssize_t)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong((__pyx_v_self->sa->arr[__pyx_t_1])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_r = __pyx_t_2;
   __pyx_t_2 = 0;
@@ -33097,11 +33310,11 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_5read_text(PyObject *__pyx_v_self,
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__side)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("read_text", 1, 2, 2, 1); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("read_text", 1, 2, 2, 1); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_text") < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "read_text") < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -33114,7 +33327,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_5read_text(PyObject *__pyx_v_self,
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("read_text", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("read_text", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.SuffixArray.read_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -33125,7 +33338,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_5read_text(PyObject *__pyx_v_self,
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":23
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":26
  *         return self.sa.arr[i]
  * 
  *     def read_text(self, filename, side):             # <<<<<<<<<<<<<<
@@ -33165,22 +33378,22 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":29
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":32
  *         cdef IntList isa, word_count
  * 
  *         self.darray = DataArray(from_text=filename, side=side, use_sent_id=True)             # <<<<<<<<<<<<<<
  *         N = len(self.darray)
- *         V = len(self.darray.id2word)
+ *         V = len(self.darray.voc)
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__from_text), __pyx_v_filename) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__side), __pyx_v_side) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_t_2 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__from_text), __pyx_v_filename) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__side), __pyx_v_side) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__use_sent_id), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__use_sent_id), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_DataArray)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_DataArray)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
@@ -33189,46 +33402,46 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_v_self->darray = ((struct __pyx_obj_3_sa_DataArray *)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":30
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":33
  * 
  *         self.darray = DataArray(from_text=filename, side=side, use_sent_id=True)
  *         N = len(self.darray)             # <<<<<<<<<<<<<<
- *         V = len(self.darray.id2word)
+ *         V = len(self.darray.voc)
  * 
  */
   __pyx_t_2 = ((PyObject *)__pyx_v_self->darray);
   __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_v_N = __pyx_t_3;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":31
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":34
  *         self.darray = DataArray(from_text=filename, side=side, use_sent_id=True)
  *         N = len(self.darray)
- *         V = len(self.darray.id2word)             # <<<<<<<<<<<<<<
+ *         V = len(self.darray.voc)             # <<<<<<<<<<<<<<
  * 
  *         self.sa = IntList(initial_len=N)
  */
-  __pyx_t_2 = __pyx_v_self->darray->id2word;
+  __pyx_t_2 = ((PyObject *)__pyx_v_self->darray->voc);
   __Pyx_INCREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __pyx_v_V = __pyx_t_3;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":33
- *         V = len(self.darray.id2word)
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":36
+ *         V = len(self.darray.voc)
  * 
  *         self.sa = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *         self.ha = IntList(initial_len=V+1)
  * 
  */
-  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __Pyx_GIVEREF(__pyx_t_1);
@@ -33237,20 +33450,20 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_v_self->sa = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":34
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":37
  * 
  *         self.sa = IntList(initial_len=N)
  *         self.ha = IntList(initial_len=V+1)             # <<<<<<<<<<<<<<
  * 
  *         isa = IntList(initial_len=N)
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_V + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong((__pyx_v_V + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
@@ -33259,45 +33472,45 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_v_self->ha = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":36
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":39
  *         self.ha = IntList(initial_len=V+1)
  * 
  *         isa = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *         word_count = IntList(initial_len=V+1)
  * 
  */
-  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(__pyx_v_N); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_2, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_1) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
   __pyx_v_isa = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":37
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":40
  * 
  *         isa = IntList(initial_len=N)
  *         word_count = IntList(initial_len=V+1)             # <<<<<<<<<<<<<<
  * 
  *         '''Step 1: bucket sort data'''
  */
-  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_V + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong((__pyx_v_V + 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_t_1, ((PyObject *)__pyx_n_s__initial_len), __pyx_t_2) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 37; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_empty_tuple), ((PyObject *)__pyx_t_1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 40; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __pyx_v_word_count = ((struct __pyx_obj_3_sa_IntList *)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":40
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":43
  * 
  *         '''Step 1: bucket sort data'''
  *         cdef float sort_start_time = monitor_cpu()             # <<<<<<<<<<<<<<
@@ -33306,7 +33519,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
   __pyx_v_sort_start_time = __pyx_f_3_sa_monitor_cpu();
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":41
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":44
  *         '''Step 1: bucket sort data'''
  *         cdef float sort_start_time = monitor_cpu()
  *         cdef float start_time = sort_start_time             # <<<<<<<<<<<<<<
@@ -33315,7 +33528,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
   __pyx_v_start_time = __pyx_v_sort_start_time;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":42
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":45
  *         cdef float sort_start_time = monitor_cpu()
  *         cdef float start_time = sort_start_time
  *         for i from 0 <= i < N:             # <<<<<<<<<<<<<<
@@ -33325,7 +33538,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_t_4 = __pyx_v_N;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_4; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":43
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":46
  *         cdef float start_time = sort_start_time
  *         for i from 0 <= i < N:
  *             a_i = self.darray.data.arr[i]             # <<<<<<<<<<<<<<
@@ -33334,7 +33547,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_a_i = (__pyx_v_self->darray->data->arr[__pyx_v_i]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":44
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":47
  *         for i from 0 <= i < N:
  *             a_i = self.darray.data.arr[i]
  *             word_count.arr[a_i] = word_count.arr[a_i] + 1             # <<<<<<<<<<<<<<
@@ -33344,7 +33557,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     (__pyx_v_word_count->arr[__pyx_v_a_i]) = ((__pyx_v_word_count->arr[__pyx_v_a_i]) + 1);
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":46
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":49
  *             word_count.arr[a_i] = word_count.arr[a_i] + 1
  * 
  *         n = 0             # <<<<<<<<<<<<<<
@@ -33353,7 +33566,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
   __pyx_v_n = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":47
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":50
  * 
  *         n = 0
  *         for i from 0 <= i < V+1:             # <<<<<<<<<<<<<<
@@ -33363,7 +33576,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_t_5 = (__pyx_v_V + 1);
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_5; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":48
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":51
  *         n = 0
  *         for i from 0 <= i < V+1:
  *             self.ha.arr[i] = n             # <<<<<<<<<<<<<<
@@ -33372,7 +33585,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     (__pyx_v_self->ha->arr[__pyx_v_i]) = __pyx_v_n;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":49
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":52
  *         for i from 0 <= i < V+1:
  *             self.ha.arr[i] = n
  *             n = n + word_count.arr[i]             # <<<<<<<<<<<<<<
@@ -33381,7 +33594,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_n = (__pyx_v_n + (__pyx_v_word_count->arr[__pyx_v_i]));
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":50
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":53
  *             self.ha.arr[i] = n
  *             n = n + word_count.arr[i]
  *             word_count.arr[i] = 0             # <<<<<<<<<<<<<<
@@ -33391,7 +33604,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     (__pyx_v_word_count->arr[__pyx_v_i]) = 0;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":52
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":55
  *             word_count.arr[i] = 0
  * 
  *         for i from 0 <= i < N:             # <<<<<<<<<<<<<<
@@ -33401,7 +33614,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_t_4 = __pyx_v_N;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_4; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":53
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":56
  * 
  *         for i from 0 <= i < N:
  *             a_i = self.darray.data.arr[i]             # <<<<<<<<<<<<<<
@@ -33410,7 +33623,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_a_i = (__pyx_v_self->darray->data->arr[__pyx_v_i]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":54
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":57
  *         for i from 0 <= i < N:
  *             a_i = self.darray.data.arr[i]
  *             self.sa.arr[self.ha.arr[a_i] + word_count.arr[a_i]] = i             # <<<<<<<<<<<<<<
@@ -33419,7 +33632,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     (__pyx_v_self->sa->arr[((__pyx_v_self->ha->arr[__pyx_v_a_i]) + (__pyx_v_word_count->arr[__pyx_v_a_i]))]) = __pyx_v_i;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":55
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":58
  *             a_i = self.darray.data.arr[i]
  *             self.sa.arr[self.ha.arr[a_i] + word_count.arr[a_i]] = i
  *             isa.arr[i] = self.ha.arr[a_i + 1] - 1 # bucket pointer is last index in bucket             # <<<<<<<<<<<<<<
@@ -33428,7 +33641,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     (__pyx_v_isa->arr[__pyx_v_i]) = ((__pyx_v_self->ha->arr[(__pyx_v_a_i + 1)]) - 1);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":56
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":59
  *             self.sa.arr[self.ha.arr[a_i] + word_count.arr[a_i]] = i
  *             isa.arr[i] = self.ha.arr[a_i + 1] - 1 # bucket pointer is last index in bucket
  *             word_count.arr[a_i] = word_count.arr[a_i] + 1             # <<<<<<<<<<<<<<
@@ -33438,7 +33651,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     (__pyx_v_word_count->arr[__pyx_v_a_i]) = ((__pyx_v_word_count->arr[__pyx_v_a_i]) + 1);
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":59
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":62
  * 
  *         '''Determine size of initial runs'''
  *         current_run = 0             # <<<<<<<<<<<<<<
@@ -33447,7 +33660,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
   __pyx_v_current_run = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":60
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":63
  *         '''Determine size of initial runs'''
  *         current_run = 0
  *         for i from 0 <= i < V+1:             # <<<<<<<<<<<<<<
@@ -33457,7 +33670,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_t_5 = (__pyx_v_V + 1);
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_5; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":61
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":64
  *         current_run = 0
  *         for i from 0 <= i < V+1:
  *             if i < V and self.ha.arr[i+1] - self.ha.arr[i] == 1:             # <<<<<<<<<<<<<<
@@ -33473,7 +33686,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     }
     if (__pyx_t_8) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":62
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":65
  *         for i from 0 <= i < V+1:
  *             if i < V and self.ha.arr[i+1] - self.ha.arr[i] == 1:
  *                 current_run = current_run + 1             # <<<<<<<<<<<<<<
@@ -33485,7 +33698,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":64
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":67
  *                 current_run = current_run + 1
  *             else:
  *                 if current_run > 0:             # <<<<<<<<<<<<<<
@@ -33495,7 +33708,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
       __pyx_t_8 = (__pyx_v_current_run > 0);
       if (__pyx_t_8) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":65
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":68
  *             else:
  *                 if current_run > 0:
  *                     self.sa.arr[self.ha.arr[i] - current_run] = -current_run             # <<<<<<<<<<<<<<
@@ -33504,7 +33717,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
         (__pyx_v_self->sa->arr[((__pyx_v_self->ha->arr[__pyx_v_i]) - __pyx_v_current_run)]) = (-__pyx_v_current_run);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":66
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":69
  *                 if current_run > 0:
  *                     self.sa.arr[self.ha.arr[i] - current_run] = -current_run
  *                     current_run = 0             # <<<<<<<<<<<<<<
@@ -33519,35 +33732,35 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     __pyx_L11:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":68
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":71
  *                     current_run = 0
  * 
  *         logger.info("    Bucket sort took %f seconds", (monitor_cpu() - sort_start_time))             # <<<<<<<<<<<<<<
  * 
  *         '''Step 2: prefix-doubling sort'''
  */
-  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__info); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_sort_start_time)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_sort_start_time)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_9 = PyTuple_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_9 = PyTuple_New(2); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_89));
-  PyTuple_SET_ITEM(__pyx_t_9, 0, ((PyObject *)__pyx_kp_s_89));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_89));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_92));
+  PyTuple_SET_ITEM(__pyx_t_9, 0, ((PyObject *)__pyx_kp_s_92));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_92));
   PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_9), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 68; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_9), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_9)); __pyx_t_9 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":71
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":74
  * 
  *         '''Step 2: prefix-doubling sort'''
  *         h = 1             # <<<<<<<<<<<<<<
@@ -33556,7 +33769,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
   __pyx_v_h = 1;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":72
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":75
  *         '''Step 2: prefix-doubling sort'''
  *         h = 1
  *         while self.sa.arr[0] != -N:             # <<<<<<<<<<<<<<
@@ -33567,7 +33780,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     __pyx_t_8 = ((__pyx_v_self->sa->arr[0]) != (-__pyx_v_N));
     if (!__pyx_t_8) break;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":73
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":76
  *         h = 1
  *         while self.sa.arr[0] != -N:
  *             sort_start_time = monitor_cpu()             # <<<<<<<<<<<<<<
@@ -33576,35 +33789,35 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_sort_start_time = __pyx_f_3_sa_monitor_cpu();
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":74
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":77
  *         while self.sa.arr[0] != -N:
  *             sort_start_time = monitor_cpu()
  *             logger.debug("    Refining, sort depth = %d", h)             # <<<<<<<<<<<<<<
  *             i = 0
  *             skip = 0
  */
-    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_9 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__debug); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_9 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__debug); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_9);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_90));
-    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_kp_s_90));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_90));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_93));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_kp_s_93));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_93));
     PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2);
     __Pyx_GIVEREF(__pyx_t_2);
     __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_t_9, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 77; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":75
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":78
  *             sort_start_time = monitor_cpu()
  *             logger.debug("    Refining, sort depth = %d", h)
  *             i = 0             # <<<<<<<<<<<<<<
@@ -33613,7 +33826,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_i = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":76
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":79
  *             logger.debug("    Refining, sort depth = %d", h)
  *             i = 0
  *             skip = 0             # <<<<<<<<<<<<<<
@@ -33622,7 +33835,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_skip = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":77
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":80
  *             i = 0
  *             skip = 0
  *             while i < N:             # <<<<<<<<<<<<<<
@@ -33633,7 +33846,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
       __pyx_t_8 = (__pyx_v_i < __pyx_v_N);
       if (!__pyx_t_8) break;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":78
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":81
  *             skip = 0
  *             while i < N:
  *                 if self.sa.arr[i] < 0:             # <<<<<<<<<<<<<<
@@ -33643,7 +33856,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
       __pyx_t_8 = ((__pyx_v_self->sa->arr[__pyx_v_i]) < 0);
       if (__pyx_t_8) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":79
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":82
  *             while i < N:
  *                 if self.sa.arr[i] < 0:
  *                     skip = skip + self.sa.arr[i]             # <<<<<<<<<<<<<<
@@ -33652,7 +33865,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
         __pyx_v_skip = (__pyx_v_skip + (__pyx_v_self->sa->arr[__pyx_v_i]));
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":80
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":83
  *                 if self.sa.arr[i] < 0:
  *                     skip = skip + self.sa.arr[i]
  *                     i = i - self.sa.arr[i]             # <<<<<<<<<<<<<<
@@ -33664,7 +33877,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
       }
       /*else*/ {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":82
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":85
  *                     i = i - self.sa.arr[i]
  *                 else:
  *                     if skip < 0:             # <<<<<<<<<<<<<<
@@ -33674,7 +33887,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
         __pyx_t_8 = (__pyx_v_skip < 0);
         if (__pyx_t_8) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":83
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":86
  *                 else:
  *                     if skip < 0:
  *                         self.sa.arr[i+skip] = skip             # <<<<<<<<<<<<<<
@@ -33683,7 +33896,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
           (__pyx_v_self->sa->arr[(__pyx_v_i + __pyx_v_skip)]) = __pyx_v_skip;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":84
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":87
  *                     if skip < 0:
  *                         self.sa.arr[i+skip] = skip
  *                         skip = 0             # <<<<<<<<<<<<<<
@@ -33695,7 +33908,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
         }
         __pyx_L18:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":85
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":88
  *                         self.sa.arr[i+skip] = skip
  *                         skip = 0
  *                     j = isa.arr[self.sa.arr[i]]             # <<<<<<<<<<<<<<
@@ -33704,22 +33917,22 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
         __pyx_v_j = (__pyx_v_isa->arr[(__pyx_v_self->sa->arr[__pyx_v_i])]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":86
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":89
  *                         skip = 0
  *                     j = isa.arr[self.sa.arr[i]]
  *                     self.q3sort(i, j, h, isa)             # <<<<<<<<<<<<<<
  *                     i = j+1
  *             if skip < 0:
  */
-        __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_2);
-        __pyx_t_1 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_1 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_1);
-        __pyx_t_9 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_9 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_9);
-        __pyx_t_10 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_10 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_10);
-        __pyx_t_11 = PyTuple_New(4); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_11 = PyTuple_New(4); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_11);
         PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_1);
         __Pyx_GIVEREF(__pyx_t_1);
@@ -33733,13 +33946,13 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
         __pyx_t_1 = 0;
         __pyx_t_9 = 0;
         __pyx_t_10 = 0;
-        __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 86; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 89; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_10);
         __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
         __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":87
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":90
  *                     j = isa.arr[self.sa.arr[i]]
  *                     self.q3sort(i, j, h, isa)
  *                     i = j+1             # <<<<<<<<<<<<<<
@@ -33751,7 +33964,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
       __pyx_L17:;
     }
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":88
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":91
  *                     self.q3sort(i, j, h, isa)
  *                     i = j+1
  *             if skip < 0:             # <<<<<<<<<<<<<<
@@ -33761,7 +33974,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     __pyx_t_8 = (__pyx_v_skip < 0);
     if (__pyx_t_8) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":89
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":92
  *                     i = j+1
  *             if skip < 0:
  *                 self.sa.arr[i+skip] = skip             # <<<<<<<<<<<<<<
@@ -33773,7 +33986,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     }
     __pyx_L19:;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":90
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":93
  *             if skip < 0:
  *                 self.sa.arr[i+skip] = skip
  *             h = h * 2             # <<<<<<<<<<<<<<
@@ -33782,53 +33995,53 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_h = (__pyx_v_h * 2);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":91
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":94
  *                 self.sa.arr[i+skip] = skip
  *             h = h * 2
  *             logger.debug("    Refinement took %f seconds", (monitor_cpu() - sort_start_time))             # <<<<<<<<<<<<<<
  * 
  *         '''Step 3: read off suffix array from inverse suffix array'''
  */
-    __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_10);
-    __pyx_t_11 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__debug); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_11 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__debug); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_11);
     __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-    __pyx_t_10 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_sort_start_time)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_10 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_sort_start_time)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_10);
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_91));
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_91));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_91));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_94));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_94));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_94));
     PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_10);
     __Pyx_GIVEREF(__pyx_t_10);
     __pyx_t_10 = 0;
-    __pyx_t_10 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 91; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_10 = PyObject_Call(__pyx_t_11, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_10);
     __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":94
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":97
  * 
  *         '''Step 3: read off suffix array from inverse suffix array'''
  *         logger.info("    Finalizing sort...")             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < N:
  *             j = isa.arr[i]
  */
-  __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_10);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-  __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_93), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_96), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_10);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":95
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":98
  *         '''Step 3: read off suffix array from inverse suffix array'''
  *         logger.info("    Finalizing sort...")
  *         for i from 0 <= i < N:             # <<<<<<<<<<<<<<
@@ -33838,7 +34051,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
   __pyx_t_4 = __pyx_v_N;
   for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_4; __pyx_v_i++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":96
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":99
  *         logger.info("    Finalizing sort...")
  *         for i from 0 <= i < N:
  *             j = isa.arr[i]             # <<<<<<<<<<<<<<
@@ -33847,7 +34060,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
  */
     __pyx_v_j = (__pyx_v_isa->arr[__pyx_v_i]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":97
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":100
  *         for i from 0 <= i < N:
  *             j = isa.arr[i]
  *             self.sa.arr[j] = i             # <<<<<<<<<<<<<<
@@ -33857,29 +34070,29 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_4read_text(struct __pyx_obj_3_sa_Su
     (__pyx_v_self->sa->arr[__pyx_v_j]) = __pyx_v_i;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":98
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":101
  *             j = isa.arr[i]
  *             self.sa.arr[j] = i
  *         logger.info("Suffix array construction took %f seconds", (monitor_cpu() - start_time))             # <<<<<<<<<<<<<<
  * 
  *     def q3sort(self, int i, int j, int h, IntList isa, pad=""):
  */
-  __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = __Pyx_GetName(__pyx_m, __pyx_n_s__logger); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_10);
-  __pyx_t_2 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_GetAttr(__pyx_t_10, __pyx_n_s__info); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-  __pyx_t_10 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_start_time)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = PyFloat_FromDouble((__pyx_f_3_sa_monitor_cpu() - __pyx_v_start_time)); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_10);
-  __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_11 = PyTuple_New(2); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_94));
-  PyTuple_SET_ITEM(__pyx_t_11, 0, ((PyObject *)__pyx_kp_s_94));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_94));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_97));
+  PyTuple_SET_ITEM(__pyx_t_11, 0, ((PyObject *)__pyx_kp_s_97));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_97));
   PyTuple_SET_ITEM(__pyx_t_11, 1, __pyx_t_10);
   __Pyx_GIVEREF(__pyx_t_10);
   __pyx_t_10 = 0;
-  __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 98; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_11), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_10);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_11)); __pyx_t_11 = 0;
@@ -33918,7 +34131,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_7q3sort(PyObject *__pyx_v_self, PyO
   {
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__i,&__pyx_n_s__j,&__pyx_n_s__h,&__pyx_n_s__isa,&__pyx_n_s__pad,0};
     PyObject* values[5] = {0,0,0,0,0};
-    values[4] = ((PyObject *)__pyx_kp_s_45);
+    values[4] = ((PyObject *)__pyx_kp_s_60);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -33939,17 +34152,17 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_7q3sort(PyObject *__pyx_v_self, PyO
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__j)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 1); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 1); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__h)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 2); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 2); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__isa)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 3); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, 3); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  4:
         if (kw_args > 0) {
@@ -33958,7 +34171,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_7q3sort(PyObject *__pyx_v_self, PyO
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "q3sort") < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "q3sort") < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -33971,21 +34184,21 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_7q3sort(PyObject *__pyx_v_self, PyO
         default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_v_i = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_i == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_j = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_j == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_h = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_h == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_i = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_i == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_j = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_j == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_h = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_h == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_isa = ((struct __pyx_obj_3_sa_IntList *)values[3]);
     __pyx_v_pad = values[4];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("q3sort", 0, 4, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.SuffixArray.q3sort", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isa), __pyx_ptype_3_sa_IntList, 1, "isa", 0))) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_isa), __pyx_ptype_3_sa_IntList, 1, "isa", 0))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 103; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_3_sa_11SuffixArray_6q3sort(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), __pyx_v_i, __pyx_v_j, __pyx_v_h, __pyx_v_isa, __pyx_v_pad);
   goto __pyx_L0;
   __pyx_L1_error:;
@@ -33995,7 +34208,7 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_7q3sort(PyObject *__pyx_v_self, PyO
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":100
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":103
  *         logger.info("Suffix array construction took %f seconds", (monitor_cpu() - start_time))
  * 
  *     def q3sort(self, int i, int j, int h, IntList isa, pad=""):             # <<<<<<<<<<<<<<
@@ -34025,7 +34238,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("q3sort", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":107
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":110
  *         cdef int k, midpoint, pval, phead, ptail, tmp
  * 
  *         if j-i < -1:             # <<<<<<<<<<<<<<
@@ -34035,18 +34248,18 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_1 = ((__pyx_v_j - __pyx_v_i) < -1);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":108
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":111
  * 
  *         if j-i < -1:
  *             raise Exception("Unexpected condition found in q3sort: sort from %d to %d" % (i,j))             # <<<<<<<<<<<<<<
  *         if j-i == -1:    # recursive base case -- empty interval
  *             return
  */
-    __pyx_t_2 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
     __Pyx_GIVEREF(__pyx_t_2);
@@ -34054,25 +34267,25 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
     __Pyx_GIVEREF(__pyx_t_3);
     __pyx_t_2 = 0;
     __pyx_t_3 = 0;
-    __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_95), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_98), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
     __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
-    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_t_3));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
     __pyx_t_3 = 0;
-    __pyx_t_3 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
     __Pyx_Raise(__pyx_t_3, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    {__pyx_filename = __pyx_f[14]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     goto __pyx_L3;
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":109
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":112
  *         if j-i < -1:
  *             raise Exception("Unexpected condition found in q3sort: sort from %d to %d" % (i,j))
  *         if j-i == -1:    # recursive base case -- empty interval             # <<<<<<<<<<<<<<
@@ -34082,7 +34295,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_1 = ((__pyx_v_j - __pyx_v_i) == -1);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":110
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":113
  *             raise Exception("Unexpected condition found in q3sort: sort from %d to %d" % (i,j))
  *         if j-i == -1:    # recursive base case -- empty interval
  *             return             # <<<<<<<<<<<<<<
@@ -34096,7 +34309,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":111
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":114
  *         if j-i == -1:    # recursive base case -- empty interval
  *             return
  *         if (j-i == 0):    # recursive base case -- singleton interval             # <<<<<<<<<<<<<<
@@ -34106,7 +34319,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_1 = ((__pyx_v_j - __pyx_v_i) == 0);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":112
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":115
  *             return
  *         if (j-i == 0):    # recursive base case -- singleton interval
  *             isa.arr[self.sa.arr[i]] = i             # <<<<<<<<<<<<<<
@@ -34115,7 +34328,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
     (__pyx_v_isa->arr[(__pyx_v_self->sa->arr[__pyx_v_i])]) = __pyx_v_i;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":113
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":116
  *         if (j-i == 0):    # recursive base case -- singleton interval
  *             isa.arr[self.sa.arr[i]] = i
  *             self.sa.arr[i] = -1             # <<<<<<<<<<<<<<
@@ -34124,7 +34337,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
     (__pyx_v_self->sa->arr[__pyx_v_i]) = -1;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":114
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":117
  *             isa.arr[self.sa.arr[i]] = i
  *             self.sa.arr[i] = -1
  *             return             # <<<<<<<<<<<<<<
@@ -34138,7 +34351,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   }
   __pyx_L5:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":123
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":126
  *         # If the method of assigning word_id's is changed, this method
  *         # may need to be reconsidered as well.
  *         midpoint = (i+j)/2             # <<<<<<<<<<<<<<
@@ -34147,7 +34360,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
   __pyx_v_midpoint = __Pyx_div_long((__pyx_v_i + __pyx_v_j), 2);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":124
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":127
  *         # may need to be reconsidered as well.
  *         midpoint = (i+j)/2
  *         pval = isa.arr[self.sa.arr[midpoint] + h]             # <<<<<<<<<<<<<<
@@ -34156,7 +34369,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
   __pyx_v_pval = (__pyx_v_isa->arr[((__pyx_v_self->sa->arr[__pyx_v_midpoint]) + __pyx_v_h)]);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":125
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":128
  *         midpoint = (i+j)/2
  *         pval = isa.arr[self.sa.arr[midpoint] + h]
  *         if i != midpoint:             # <<<<<<<<<<<<<<
@@ -34166,7 +34379,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_1 = (__pyx_v_i != __pyx_v_midpoint);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":126
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":129
  *         pval = isa.arr[self.sa.arr[midpoint] + h]
  *         if i != midpoint:
  *             tmp = self.sa.arr[midpoint]             # <<<<<<<<<<<<<<
@@ -34175,7 +34388,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
     __pyx_v_tmp = (__pyx_v_self->sa->arr[__pyx_v_midpoint]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":127
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":130
  *         if i != midpoint:
  *             tmp = self.sa.arr[midpoint]
  *             self.sa.arr[midpoint] = self.sa.arr[i]             # <<<<<<<<<<<<<<
@@ -34184,7 +34397,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
     (__pyx_v_self->sa->arr[__pyx_v_midpoint]) = (__pyx_v_self->sa->arr[__pyx_v_i]);
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":128
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":131
  *             tmp = self.sa.arr[midpoint]
  *             self.sa.arr[midpoint] = self.sa.arr[i]
  *             self.sa.arr[i] = tmp             # <<<<<<<<<<<<<<
@@ -34196,7 +34409,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   }
   __pyx_L6:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":129
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":132
  *             self.sa.arr[midpoint] = self.sa.arr[i]
  *             self.sa.arr[i] = tmp
  *         phead = i             # <<<<<<<<<<<<<<
@@ -34205,7 +34418,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
   __pyx_v_phead = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":130
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":133
  *             self.sa.arr[i] = tmp
  *         phead = i
  *         ptail = i             # <<<<<<<<<<<<<<
@@ -34214,7 +34427,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
   __pyx_v_ptail = __pyx_v_i;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":134
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":137
  *         # find the three partitions.    phead marks the first element
  *         # of the middle partition, and ptail marks the last element
  *         for k from i+1 <= k < j+1:             # <<<<<<<<<<<<<<
@@ -34224,7 +34437,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_5 = (__pyx_v_j + 1);
   for (__pyx_v_k = (__pyx_v_i + 1); __pyx_v_k < __pyx_t_5; __pyx_v_k++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":135
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":138
  *         # of the middle partition, and ptail marks the last element
  *         for k from i+1 <= k < j+1:
  *             if isa.arr[self.sa.arr[k] + h] < pval:             # <<<<<<<<<<<<<<
@@ -34234,7 +34447,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
     __pyx_t_1 = ((__pyx_v_isa->arr[((__pyx_v_self->sa->arr[__pyx_v_k]) + __pyx_v_h)]) < __pyx_v_pval);
     if (__pyx_t_1) {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":136
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":139
  *         for k from i+1 <= k < j+1:
  *             if isa.arr[self.sa.arr[k] + h] < pval:
  *                 if k > ptail+1:             # <<<<<<<<<<<<<<
@@ -34244,7 +34457,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
       __pyx_t_1 = (__pyx_v_k > (__pyx_v_ptail + 1));
       if (__pyx_t_1) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":137
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":140
  *             if isa.arr[self.sa.arr[k] + h] < pval:
  *                 if k > ptail+1:
  *                     tmp = self.sa.arr[phead]             # <<<<<<<<<<<<<<
@@ -34253,7 +34466,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
         __pyx_v_tmp = (__pyx_v_self->sa->arr[__pyx_v_phead]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":138
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":141
  *                 if k > ptail+1:
  *                     tmp = self.sa.arr[phead]
  *                     self.sa.arr[phead] = self.sa.arr[k]             # <<<<<<<<<<<<<<
@@ -34262,7 +34475,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
         (__pyx_v_self->sa->arr[__pyx_v_phead]) = (__pyx_v_self->sa->arr[__pyx_v_k]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":139
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":142
  *                     tmp = self.sa.arr[phead]
  *                     self.sa.arr[phead] = self.sa.arr[k]
  *                     self.sa.arr[k] = self.sa.arr[ptail+1]             # <<<<<<<<<<<<<<
@@ -34271,7 +34484,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
         (__pyx_v_self->sa->arr[__pyx_v_k]) = (__pyx_v_self->sa->arr[(__pyx_v_ptail + 1)]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":140
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":143
  *                     self.sa.arr[phead] = self.sa.arr[k]
  *                     self.sa.arr[k] = self.sa.arr[ptail+1]
  *                     self.sa.arr[ptail+1] = tmp             # <<<<<<<<<<<<<<
@@ -34283,7 +34496,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
       }
       /*else*/ {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":142
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":145
  *                     self.sa.arr[ptail+1] = tmp
  *                 else: # k == ptail+1
  *                     tmp = self.sa.arr[phead]             # <<<<<<<<<<<<<<
@@ -34292,7 +34505,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
         __pyx_v_tmp = (__pyx_v_self->sa->arr[__pyx_v_phead]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":143
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":146
  *                 else: # k == ptail+1
  *                     tmp = self.sa.arr[phead]
  *                     self.sa.arr[phead] = self.sa.arr[k]             # <<<<<<<<<<<<<<
@@ -34301,7 +34514,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
         (__pyx_v_self->sa->arr[__pyx_v_phead]) = (__pyx_v_self->sa->arr[__pyx_v_k]);
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":144
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":147
  *                     tmp = self.sa.arr[phead]
  *                     self.sa.arr[phead] = self.sa.arr[k]
  *                     self.sa.arr[k] = tmp             # <<<<<<<<<<<<<<
@@ -34312,7 +34525,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
       }
       __pyx_L10:;
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":145
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":148
  *                     self.sa.arr[phead] = self.sa.arr[k]
  *                     self.sa.arr[k] = tmp
  *                 phead = phead + 1             # <<<<<<<<<<<<<<
@@ -34321,7 +34534,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
       __pyx_v_phead = (__pyx_v_phead + 1);
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":146
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":149
  *                     self.sa.arr[k] = tmp
  *                 phead = phead + 1
  *                 ptail = ptail + 1             # <<<<<<<<<<<<<<
@@ -34333,7 +34546,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
     }
     /*else*/ {
 
-      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":148
+      /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":151
  *                 ptail = ptail + 1
  *             else:
  *                 if isa.arr[self.sa.arr[k] + h] == pval:             # <<<<<<<<<<<<<<
@@ -34343,7 +34556,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
       __pyx_t_1 = ((__pyx_v_isa->arr[((__pyx_v_self->sa->arr[__pyx_v_k]) + __pyx_v_h)]) == __pyx_v_pval);
       if (__pyx_t_1) {
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":149
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":152
  *             else:
  *                 if isa.arr[self.sa.arr[k] + h] == pval:
  *                     if k > ptail+1:             # <<<<<<<<<<<<<<
@@ -34353,7 +34566,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
         __pyx_t_1 = (__pyx_v_k > (__pyx_v_ptail + 1));
         if (__pyx_t_1) {
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":150
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":153
  *                 if isa.arr[self.sa.arr[k] + h] == pval:
  *                     if k > ptail+1:
  *                         tmp = self.sa.arr[ptail+1]             # <<<<<<<<<<<<<<
@@ -34362,7 +34575,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
           __pyx_v_tmp = (__pyx_v_self->sa->arr[(__pyx_v_ptail + 1)]);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":151
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":154
  *                     if k > ptail+1:
  *                         tmp = self.sa.arr[ptail+1]
  *                         self.sa.arr[ptail+1] = self.sa.arr[k]             # <<<<<<<<<<<<<<
@@ -34371,7 +34584,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
  */
           (__pyx_v_self->sa->arr[(__pyx_v_ptail + 1)]) = (__pyx_v_self->sa->arr[__pyx_v_k]);
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":152
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":155
  *                         tmp = self.sa.arr[ptail+1]
  *                         self.sa.arr[ptail+1] = self.sa.arr[k]
  *                         self.sa.arr[k] = tmp             # <<<<<<<<<<<<<<
@@ -34383,7 +34596,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
         }
         __pyx_L12:;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":153
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":156
  *                         self.sa.arr[ptail+1] = self.sa.arr[k]
  *                         self.sa.arr[k] = tmp
  *                     ptail = ptail + 1             # <<<<<<<<<<<<<<
@@ -34398,24 +34611,24 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
     __pyx_L9:;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":156
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":159
  * 
  *         # recursively sort smaller suffixes
  *         self.q3sort(i, phead-1, h, isa, pad+"    ")             # <<<<<<<<<<<<<<
  * 
  *         # update suffixes with pivot value
  */
-  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_2 = PyInt_FromLong((__pyx_v_phead - 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong((__pyx_v_phead - 1)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_6 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_48)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_99)); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_8 = PyTuple_New(5); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyTuple_New(5); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
   PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_4);
   __Pyx_GIVEREF(__pyx_t_4);
@@ -34432,13 +34645,13 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_2 = 0;
   __pyx_t_6 = 0;
   __pyx_t_7 = 0;
-  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_8), NULL); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 159; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_8)); __pyx_t_8 = 0;
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":160
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":163
  *         # update suffixes with pivot value
  *         # corresponds to update_group function in Larsson & Sadakane
  *         for k from phead <= k < ptail+1:             # <<<<<<<<<<<<<<
@@ -34448,7 +34661,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_5 = (__pyx_v_ptail + 1);
   for (__pyx_v_k = __pyx_v_phead; __pyx_v_k < __pyx_t_5; __pyx_v_k++) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":161
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":164
  *         # corresponds to update_group function in Larsson & Sadakane
  *         for k from phead <= k < ptail+1:
  *             isa.arr[self.sa.arr[k]] = ptail             # <<<<<<<<<<<<<<
@@ -34458,7 +34671,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
     (__pyx_v_isa->arr[(__pyx_v_self->sa->arr[__pyx_v_k])]) = __pyx_v_ptail;
   }
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":162
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":165
  *         for k from phead <= k < ptail+1:
  *             isa.arr[self.sa.arr[k]] = ptail
  *         if phead == ptail:             # <<<<<<<<<<<<<<
@@ -34468,7 +34681,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_1 = (__pyx_v_phead == __pyx_v_ptail);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":163
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":166
  *             isa.arr[self.sa.arr[k]] = ptail
  *         if phead == ptail:
  *             self.sa.arr[phead] = -1             # <<<<<<<<<<<<<<
@@ -34480,24 +34693,24 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   }
   __pyx_L15:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":166
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":169
  * 
  *         # recursively sort larger suffixes
  *         self.q3sort(ptail+1, j, h, isa, pad+"    ")             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_t_7 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_7 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s__q3sort); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_8 = PyInt_FromLong((__pyx_v_ptail + 1)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_8 = PyInt_FromLong((__pyx_v_ptail + 1)); if (unlikely(!__pyx_t_8)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_3 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyInt_FromLong(__pyx_v_j); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_6 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_6 = PyInt_FromLong(__pyx_v_h); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_2 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_48)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyNumber_Add(__pyx_v_pad, ((PyObject *)__pyx_kp_s_99)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_4 = PyTuple_New(5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = PyTuple_New(5); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
   PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_8);
   __Pyx_GIVEREF(__pyx_t_8);
@@ -34514,7 +34727,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
   __pyx_t_3 = 0;
   __pyx_t_6 = 0;
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 166; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_t_7, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
@@ -34538,35 +34751,30 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_6q3sort(struct __pyx_obj_3_sa_Suffi
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_11SuffixArray_9write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_11SuffixArray_9write_text(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_11SuffixArray_9write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_9write_text(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_text (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 169; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.SuffixArray.write_text", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray_8write_text(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_8write_text(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":169
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":172
  * 
  * 
- *     def write_text(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_text(self, bytes filename):             # <<<<<<<<<<<<<<
  *         self.darray.write_text(filename)
  * 
  */
 
-static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -34577,27 +34785,25 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_S
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_text", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":170
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":173
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         self.darray.write_text(filename)             # <<<<<<<<<<<<<<
  * 
- *     def read_binary(self, char* filename):
+ *     def read_binary(self, bytes filename):
  */
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self->darray), __pyx_n_s__write_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self->darray), __pyx_n_s__write_text); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(((PyObject *)__pyx_t_2));
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_t_3);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)__pyx_t_2));
-  __Pyx_GIVEREF(((PyObject *)__pyx_t_2));
-  __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 170; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_filename));
+  __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
+  __pyx_t_3 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
@@ -34614,50 +34820,50 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_8write_text(struct __pyx_obj_3_sa_S
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_11SuffixArray_11read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_11SuffixArray_11read_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_11SuffixArray_11read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_11read_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("read_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 172; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.SuffixArray.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray_10read_binary(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 175; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_10read_binary(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":172
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":175
  *         self.darray.write_text(filename)
  * 
- *     def read_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE *f
  *         f = fopen(filename, "r")
  */
 
-static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("read_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":174
- *     def read_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":177
+ *     def read_binary(self, bytes filename):
  *         cdef FILE *f
  *         f = fopen(filename, "r")             # <<<<<<<<<<<<<<
  *         self.darray.read_handle(f)
  *         self.sa.read_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__r);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 177; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__r);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":175
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":178
  *         cdef FILE *f
  *         f = fopen(filename, "r")
  *         self.darray.read_handle(f)             # <<<<<<<<<<<<<<
@@ -34666,7 +34872,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa
  */
   ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->darray->__pyx_vtab)->read_handle(__pyx_v_self->darray, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":176
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":179
  *         f = fopen(filename, "r")
  *         self.darray.read_handle(f)
  *         self.sa.read_handle(f)             # <<<<<<<<<<<<<<
@@ -34675,7 +34881,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sa->__pyx_vtab)->read_handle(__pyx_v_self->sa, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":177
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":180
  *         self.darray.read_handle(f)
  *         self.sa.read_handle(f)
  *         self.ha.read_handle(f)             # <<<<<<<<<<<<<<
@@ -34684,66 +34890,133 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_10read_binary(struct __pyx_obj_3_sa
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->ha->__pyx_vtab)->read_handle(__pyx_v_self->ha, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":178
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":181
  *         self.sa.read_handle(f)
  *         self.ha.read_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- *     def write_binary(self, char* filename):
+ *     def read_mmaped(self, MemoryMap buf):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.SuffixArray.read_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_11SuffixArray_13write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_11SuffixArray_13write_binary(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_11SuffixArray_13read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_13read_mmaped(PyObject *__pyx_v_self, PyObject *__pyx_v_buf) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 180; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.SuffixArray.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray_12write_binary(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  __Pyx_RefNannySetupContext("read_mmaped (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_buf), __pyx_ptype_3_sa_MemoryMap, 1, "buf", 0))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_12read_mmaped(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((struct __pyx_obj_3_sa_MemoryMap *)__pyx_v_buf));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":180
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":183
  *         fclose(f)
  * 
- *     def write_binary(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def read_mmaped(self, MemoryMap buf):             # <<<<<<<<<<<<<<
+ *         self.darray.read_mmaped(buf)
+ *         self.sa.read_mmaped(buf)
+ */
+
+static PyObject *__pyx_pf_3_sa_11SuffixArray_12read_mmaped(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, struct __pyx_obj_3_sa_MemoryMap *__pyx_v_buf) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("read_mmaped", 0);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":184
+ * 
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.darray.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.sa.read_mmaped(buf)
+ *         self.ha.read_mmaped(buf)
+ */
+  ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->darray->__pyx_vtab)->read_mmaped(__pyx_v_self->darray, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":185
+ *     def read_mmaped(self, MemoryMap buf):
+ *         self.darray.read_mmaped(buf)
+ *         self.sa.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ *         self.ha.read_mmaped(buf)
+ * 
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sa->__pyx_vtab)->read_mmaped(__pyx_v_self->sa, __pyx_v_buf);
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":186
+ *         self.darray.read_mmaped(buf)
+ *         self.sa.read_mmaped(buf)
+ *         self.ha.read_mmaped(buf)             # <<<<<<<<<<<<<<
+ * 
+ *     def write_binary(self, bytes filename):
+ */
+  ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->ha->__pyx_vtab)->read_mmaped(__pyx_v_self->ha, __pyx_v_buf);
+
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_3_sa_11SuffixArray_15write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_15write_binary(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("write_binary (wrapper)", 0);
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_14write_binary(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":188
+ *         self.ha.read_mmaped(buf)
+ * 
+ *     def write_binary(self, bytes filename):             # <<<<<<<<<<<<<<
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  */
 
-static PyObject *__pyx_pf_3_sa_11SuffixArray_12write_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_binary(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   FILE *__pyx_v_f;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  const char *__pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_binary", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":182
- *     def write_binary(self, char* filename):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":190
+ *     def write_binary(self, bytes filename):
  *         cdef FILE* f
  *         f = fopen(filename, "w")             # <<<<<<<<<<<<<<
  *         self.darray.write_handle(f)
  *         self.sa.write_handle(f)
  */
-  __pyx_v_f = fopen(__pyx_v_filename, __pyx_k__w);
+  __pyx_t_1 = PyBytes_AsString(((PyObject *)__pyx_v_filename)); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_v_f = fopen(__pyx_t_1, __pyx_k__w);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":183
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":191
  *         cdef FILE* f
  *         f = fopen(filename, "w")
  *         self.darray.write_handle(f)             # <<<<<<<<<<<<<<
@@ -34752,7 +35025,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_12write_binary(struct __pyx_obj_3_s
  */
   ((struct __pyx_vtabstruct_3_sa_DataArray *)__pyx_v_self->darray->__pyx_vtab)->write_handle(__pyx_v_self->darray, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":184
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":192
  *         f = fopen(filename, "w")
  *         self.darray.write_handle(f)
  *         self.sa.write_handle(f)             # <<<<<<<<<<<<<<
@@ -34761,7 +35034,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_12write_binary(struct __pyx_obj_3_s
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->sa->__pyx_vtab)->write_handle(__pyx_v_self->sa, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":185
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":193
  *         self.darray.write_handle(f)
  *         self.sa.write_handle(f)
  *         self.ha.write_handle(f)             # <<<<<<<<<<<<<<
@@ -34770,51 +35043,51 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_12write_binary(struct __pyx_obj_3_s
  */
   ((struct __pyx_vtabstruct_3_sa_IntList *)__pyx_v_self->ha->__pyx_vtab)->write_handle(__pyx_v_self->ha, __pyx_v_f);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":186
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":194
  *         self.sa.write_handle(f)
  *         self.ha.write_handle(f)
  *         fclose(f)             # <<<<<<<<<<<<<<
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  */
   fclose(__pyx_v_f);
 
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("_sa.SuffixArray.write_binary", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_11SuffixArray_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename); /*proto*/
-static PyObject *__pyx_pw_3_sa_11SuffixArray_15write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_arg_filename) {
-  char *__pyx_v_filename;
+static PyObject *__pyx_pw_3_sa_11SuffixArray_17write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_17write_enhanced(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("write_enhanced (wrapper)", 0);
-  assert(__pyx_arg_filename); {
-    __pyx_v_filename = PyBytes_AsString(__pyx_arg_filename); if (unlikely((!__pyx_v_filename) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("_sa.SuffixArray.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray_14write_enhanced(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((char *)__pyx_v_filename));
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_filename), (&PyBytes_Type), 1, "filename", 1))) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_16write_enhanced(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), ((PyObject*)__pyx_v_filename));
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":188
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":196
  *         fclose(f)
  * 
- *     def write_enhanced(self, char* filename):             # <<<<<<<<<<<<<<
+ *     def write_enhanced(self, bytes filename):             # <<<<<<<<<<<<<<
  *         with open(filename, "w") as f:
  *             self.darray.write_enhanced_handle(f)
  */
 
-static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, char *__pyx_v_filename) {
+static PyObject *__pyx_pf_3_sa_11SuffixArray_16write_enhanced(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_filename) {
   PyObject *__pyx_v_f = NULL;
   PyObject *__pyx_v_a_i = NULL;
   PyObject *__pyx_v_w_i = NULL;
@@ -34838,35 +35111,33 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("write_enhanced", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":189
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":197
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.darray.write_enhanced_handle(f)
  *             for a_i in self.sa:
  */
   /*with:*/ {
-    __pyx_t_1 = PyBytes_FromString(__pyx_v_filename); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_1));
-    __Pyx_GIVEREF(((PyObject *)__pyx_t_1));
+    __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)__pyx_v_filename));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_filename));
+    __Pyx_GIVEREF(((PyObject *)__pyx_v_filename));
     __Pyx_INCREF(((PyObject *)__pyx_n_s__w));
-    PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_n_s__w));
+    PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_n_s__w));
     __Pyx_GIVEREF(((PyObject *)__pyx_n_s__w));
-    __pyx_t_1 = 0;
-    __pyx_t_1 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s____enter__); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_open, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____exit__); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s____enter__); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     /*try:*/ {
       {
         __Pyx_ExceptionSave(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7);
@@ -34878,27 +35149,27 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
           __pyx_v_f = __pyx_t_4;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":190
- *     def write_enhanced(self, char* filename):
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":198
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:
  *             self.darray.write_enhanced_handle(f)             # <<<<<<<<<<<<<<
  *             for a_i in self.sa:
  *                 f.write("%d " % a_i)
  */
-          __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self->darray), __pyx_n_s_27); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_self->darray), __pyx_n_s_26); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_2);
           __Pyx_INCREF(__pyx_v_f);
-          PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_f);
+          PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_f);
           __Pyx_GIVEREF(__pyx_v_f);
-          __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 190; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 198; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":191
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":199
  *         with open(filename, "w") as f:
  *             self.darray.write_enhanced_handle(f)
  *             for a_i in self.sa:             # <<<<<<<<<<<<<<
@@ -34906,82 +35177,82 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
  *             f.write("\n")
  */
           if (PyList_CheckExact(((PyObject *)__pyx_v_self->sa)) || PyTuple_CheckExact(((PyObject *)__pyx_v_self->sa))) {
-            __pyx_t_2 = ((PyObject *)__pyx_v_self->sa); __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;
+            __pyx_t_1 = ((PyObject *)__pyx_v_self->sa); __Pyx_INCREF(__pyx_t_1); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(((PyObject *)__pyx_v_self->sa)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext;
+            __pyx_t_8 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_v_self->sa)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_1);
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
           }
           for (;;) {
-            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;
+            if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
-            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_2)) {
-              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+            } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_1)) {
+              if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_1 = __pyx_t_9(__pyx_t_2);
-              if (unlikely(!__pyx_t_1)) {
+              __pyx_t_2 = __pyx_t_9(__pyx_t_1);
+              if (unlikely(!__pyx_t_2)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 191; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[14]; __pyx_lineno = 199; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_1);
+              __Pyx_GOTREF(__pyx_t_2);
             }
             __Pyx_XDECREF(__pyx_v_a_i);
-            __pyx_v_a_i = __pyx_t_1;
-            __pyx_t_1 = 0;
+            __pyx_v_a_i = __pyx_t_2;
+            __pyx_t_2 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":192
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":200
  *             self.darray.write_enhanced_handle(f)
  *             for a_i in self.sa:
  *                 f.write("%d " % a_i)             # <<<<<<<<<<<<<<
  *             f.write("\n")
  *             for w_i in self.ha:
  */
-            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_1);
-            __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_a_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_a_i); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_4));
-            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyTuple_New(1); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
             PyTuple_SET_ITEM(__pyx_t_10, 0, ((PyObject *)__pyx_t_4));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_4));
             __pyx_t_4 = 0;
-            __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 192; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_10), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 200; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
             __Pyx_DECREF(((PyObject *)__pyx_t_10)); __pyx_t_10 = 0;
             __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           }
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":193
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":201
  *             for a_i in self.sa:
  *                 f.write("%d " % a_i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for w_i in self.ha:
  *                 f.write("%d " % w_i)
  */
-          __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-          __Pyx_GOTREF(__pyx_t_2);
-          __pyx_t_4 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_96), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __Pyx_GOTREF(__pyx_t_1);
+          __pyx_t_4 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_k_tuple_100), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":194
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":202
  *                 f.write("%d " % a_i)
  *             f.write("\n")
  *             for w_i in self.ha:             # <<<<<<<<<<<<<<
@@ -34992,7 +35263,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
             __pyx_t_4 = ((PyObject *)__pyx_v_self->ha); __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
             __pyx_t_9 = NULL;
           } else {
-            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->ha)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(((PyObject *)__pyx_v_self->ha)); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_4);
             __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext;
           }
@@ -35000,66 +35271,66 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
             if (!__pyx_t_9 && PyList_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else if (!__pyx_t_9 && PyTuple_CheckExact(__pyx_t_4)) {
               if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
               #if CYTHON_COMPILING_IN_CPYTHON
-              __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_2); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_1); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #else
-              __pyx_t_2 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+              __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
               #endif
             } else {
-              __pyx_t_2 = __pyx_t_9(__pyx_t_4);
-              if (unlikely(!__pyx_t_2)) {
+              __pyx_t_1 = __pyx_t_9(__pyx_t_4);
+              if (unlikely(!__pyx_t_1)) {
                 if (PyErr_Occurred()) {
                   if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-                  else {__pyx_filename = __pyx_f[12]; __pyx_lineno = 194; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+                  else {__pyx_filename = __pyx_f[14]; __pyx_lineno = 202; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
                 }
                 break;
               }
-              __Pyx_GOTREF(__pyx_t_2);
+              __Pyx_GOTREF(__pyx_t_1);
             }
             __Pyx_XDECREF(__pyx_v_w_i);
-            __pyx_v_w_i = __pyx_t_2;
-            __pyx_t_2 = 0;
+            __pyx_v_w_i = __pyx_t_1;
+            __pyx_t_1 = 0;
 
-            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":195
+            /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":203
  *             f.write("\n")
  *             for w_i in self.ha:
  *                 f.write("%d " % w_i)             # <<<<<<<<<<<<<<
  *             f.write("\n")
  * 
  */
-            __pyx_t_2 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(__pyx_t_2);
-            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_v_w_i); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
-            __Pyx_GOTREF(((PyObject *)__pyx_t_10));
-            __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_1 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_1);
-            PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_t_10));
+            __pyx_t_10 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_v_w_i); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(((PyObject *)__pyx_t_10));
+            __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __Pyx_GOTREF(__pyx_t_2);
+            PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_t_10));
             __Pyx_GIVEREF(((PyObject *)__pyx_t_10));
             __pyx_t_10 = 0;
-            __pyx_t_10 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 195; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+            __pyx_t_10 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 203; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
             __Pyx_GOTREF(__pyx_t_10);
-            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-            __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
             __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
           }
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":196
+          /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":204
  *             for w_i in self.ha:
  *                 f.write("%d " % w_i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  *     cdef int __search_high(self, int word_id, int offset, int low, int high):
  */
-          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_4 = PyObject_GetAttr(__pyx_v_f, __pyx_n_s__write); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_10 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_97), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
+          __pyx_t_10 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_101), NULL); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L7_error;}
           __Pyx_GOTREF(__pyx_t_10);
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
           __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
@@ -35069,57 +35340,57 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
         __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
         goto __pyx_L14_try_end;
         __pyx_L7_error:;
-        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
         __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
         __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
 
-        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":189
+        /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":197
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.darray.write_enhanced_handle(f)
  *             for a_i in self.sa:
  */
         /*except:*/ {
           __Pyx_AddTraceback("_sa.SuffixArray.write_enhanced", __pyx_clineno, __pyx_lineno, __pyx_filename);
-          if (__Pyx_GetException(&__pyx_t_10, &__pyx_t_4, &__pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (__Pyx_GetException(&__pyx_t_10, &__pyx_t_4, &__pyx_t_2) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_10);
           __Pyx_GOTREF(__pyx_t_4);
-          __Pyx_GOTREF(__pyx_t_1);
-          __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          __Pyx_GOTREF(__pyx_t_1);
           __Pyx_INCREF(__pyx_t_10);
-          PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_10);
+          PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_10);
           __Pyx_GIVEREF(__pyx_t_10);
           __Pyx_INCREF(__pyx_t_4);
-          PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_4);
+          PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_4);
           __Pyx_GIVEREF(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_1);
-          PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_1);
-          __Pyx_GIVEREF(__pyx_t_1);
-          __pyx_t_12 = PyObject_Call(__pyx_t_3, __pyx_t_2, NULL);
+          __Pyx_INCREF(__pyx_t_2);
+          PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_2);
+          __Pyx_GIVEREF(__pyx_t_2);
+          __pyx_t_12 = PyObject_Call(__pyx_t_3, __pyx_t_1, NULL);
           __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(!__pyx_t_12)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __Pyx_GOTREF(__pyx_t_12);
           __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_12);
           __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+          if (unlikely(__pyx_t_11 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
           __pyx_t_13 = (!__pyx_t_11);
           if (__pyx_t_13) {
             __Pyx_GIVEREF(__pyx_t_10);
             __Pyx_GIVEREF(__pyx_t_4);
-            __Pyx_GIVEREF(__pyx_t_1);
-            __Pyx_ErrRestore(__pyx_t_10, __pyx_t_4, __pyx_t_1);
-            __pyx_t_10 = 0; __pyx_t_4 = 0; __pyx_t_1 = 0; 
-            {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
+            __Pyx_GIVEREF(__pyx_t_2);
+            __Pyx_ErrRestore(__pyx_t_10, __pyx_t_4, __pyx_t_2);
+            __pyx_t_10 = 0; __pyx_t_4 = 0; __pyx_t_2 = 0; 
+            {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L9_except_error;}
             goto __pyx_L22;
           }
           __pyx_L22:;
-          __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
+          __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
           __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
           __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
           goto __pyx_L8_exception_handled;
         }
         __pyx_L9_except_error:;
@@ -35138,13 +35409,13 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
     }
     /*finally:*/ {
       if (__pyx_t_3) {
-        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_98, NULL);
+        __pyx_t_7 = PyObject_Call(__pyx_t_3, __pyx_k_tuple_102, NULL);
         __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         __Pyx_GOTREF(__pyx_t_7);
         __pyx_t_13 = __Pyx_PyObject_IsTrue(__pyx_t_7);
         __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(__pyx_t_13 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        if (unlikely(__pyx_t_13 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
     }
     goto __pyx_L23;
@@ -35172,7 +35443,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_14write_enhanced(struct __pyx_obj_3
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":198
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":206
  *             f.write("\n")
  * 
  *     cdef int __search_high(self, int word_id, int offset, int low, int high):             # <<<<<<<<<<<<<<
@@ -35187,7 +35458,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("__search_high", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":201
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":209
  *         cdef int midpoint
  * 
  *         if low >= high:             # <<<<<<<<<<<<<<
@@ -35197,7 +35468,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   __pyx_t_1 = (__pyx_v_low >= __pyx_v_high);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":202
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":210
  * 
  *         if low >= high:
  *             return high             # <<<<<<<<<<<<<<
@@ -35210,7 +35481,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":203
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":211
  *         if low >= high:
  *             return high
  *         midpoint = (high + low) / 2             # <<<<<<<<<<<<<<
@@ -35219,7 +35490,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
  */
   __pyx_v_midpoint = __Pyx_div_long((__pyx_v_high + __pyx_v_low), 2);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":204
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":212
  *             return high
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:             # <<<<<<<<<<<<<<
@@ -35229,7 +35500,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   __pyx_t_1 = ((__pyx_v_self->darray->data->arr[((__pyx_v_self->sa->arr[__pyx_v_midpoint]) + __pyx_v_offset)]) == __pyx_v_word_id);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":205
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":213
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:
  *             return self.__search_high(word_id, offset, midpoint+1, high)             # <<<<<<<<<<<<<<
@@ -35242,7 +35513,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":207
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":215
  *             return self.__search_high(word_id, offset, midpoint+1, high)
  *         else:
  *             return self.__search_high(word_id, offset, low, midpoint)             # <<<<<<<<<<<<<<
@@ -35260,7 +35531,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_high(struct __pyx_obj_3_sa_Suffix
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":209
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":217
  *             return self.__search_high(word_id, offset, low, midpoint)
  * 
  *     cdef int __search_low(self, int word_id, int offset, int low, int high):             # <<<<<<<<<<<<<<
@@ -35275,7 +35546,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   int __pyx_t_1;
   __Pyx_RefNannySetupContext("__search_low", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":212
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":220
  *         cdef int midpoint
  * 
  *         if low >= high:             # <<<<<<<<<<<<<<
@@ -35285,7 +35556,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   __pyx_t_1 = (__pyx_v_low >= __pyx_v_high);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":213
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":221
  * 
  *         if low >= high:
  *             return high             # <<<<<<<<<<<<<<
@@ -35298,7 +35569,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":214
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":222
  *         if low >= high:
  *             return high
  *         midpoint = (high + low) / 2             # <<<<<<<<<<<<<<
@@ -35307,7 +35578,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
  */
   __pyx_v_midpoint = __Pyx_div_long((__pyx_v_high + __pyx_v_low), 2);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":215
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":223
  *             return high
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:             # <<<<<<<<<<<<<<
@@ -35317,7 +35588,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   __pyx_t_1 = ((__pyx_v_self->darray->data->arr[((__pyx_v_self->sa->arr[__pyx_v_midpoint]) + __pyx_v_offset)]) == __pyx_v_word_id);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":216
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":224
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:
  *             return self.__search_low(word_id, offset, low, midpoint)             # <<<<<<<<<<<<<<
@@ -35330,7 +35601,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":218
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":226
  *             return self.__search_low(word_id, offset, low, midpoint)
  *         else:
  *             return self.__search_low(word_id, offset, midpoint+1, high)             # <<<<<<<<<<<<<<
@@ -35348,7 +35619,7 @@ static int __pyx_f_3_sa_11SuffixArray___search_low(struct __pyx_obj_3_sa_SuffixA
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":220
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":228
  *             return self.__search_low(word_id, offset, midpoint+1, high)
  * 
  *     cdef __get_range(self, int word_id, int offset, int low, int high, int midpoint):             # <<<<<<<<<<<<<<
@@ -35367,7 +35638,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___get_range(struct __pyx_obj_3_sa_Su
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get_range", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":221
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":229
  * 
  *     cdef __get_range(self, int word_id, int offset, int low, int high, int midpoint):
  *         return (self.__search_low(word_id, offset, low, midpoint),             # <<<<<<<<<<<<<<
@@ -35375,19 +35646,19 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___get_range(struct __pyx_obj_3_sa_Su
  * 
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___search_low(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_midpoint)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___search_low(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_midpoint)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 229; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":222
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":230
  *     cdef __get_range(self, int word_id, int offset, int low, int high, int midpoint):
  *         return (self.__search_low(word_id, offset, low, midpoint),
  *                 self.__search_high(word_id, offset, midpoint, high))             # <<<<<<<<<<<<<<
  * 
  *     cdef __lookup_helper(self, int word_id, int offset, int low, int high):
  */
-  __pyx_t_2 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___search_high(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_midpoint, __pyx_v_high)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 222; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___search_high(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_midpoint, __pyx_v_high)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 230; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 221; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 229; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
@@ -35413,7 +35684,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___get_range(struct __pyx_obj_3_sa_Su
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":224
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":232
  *                 self.__search_high(word_id, offset, midpoint, high))
  * 
  *     cdef __lookup_helper(self, int word_id, int offset, int low, int high):             # <<<<<<<<<<<<<<
@@ -35434,7 +35705,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__lookup_helper", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":227
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":235
  *         cdef int midpoint
  * 
  *         if offset == 0:             # <<<<<<<<<<<<<<
@@ -35444,7 +35715,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   __pyx_t_1 = (__pyx_v_offset == 0);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":228
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":236
  * 
  *         if offset == 0:
  *             return (self.ha.arr[word_id], self.ha.arr[word_id+1])             # <<<<<<<<<<<<<<
@@ -35452,11 +35723,11 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
  *             return None
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = PyInt_FromLong((__pyx_v_self->ha->arr[__pyx_v_word_id])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyInt_FromLong((__pyx_v_self->ha->arr[__pyx_v_word_id])); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->ha->arr[(__pyx_v_word_id + 1)])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyInt_FromLong((__pyx_v_self->ha->arr[(__pyx_v_word_id + 1)])); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 228; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_2);
     __Pyx_GIVEREF(__pyx_t_2);
@@ -35471,7 +35742,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":229
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":237
  *         if offset == 0:
  *             return (self.ha.arr[word_id], self.ha.arr[word_id+1])
  *         if low >= high:             # <<<<<<<<<<<<<<
@@ -35481,7 +35752,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   __pyx_t_1 = (__pyx_v_low >= __pyx_v_high);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":230
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":238
  *             return (self.ha.arr[word_id], self.ha.arr[word_id+1])
  *         if low >= high:
  *             return None             # <<<<<<<<<<<<<<
@@ -35496,7 +35767,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":232
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":240
  *             return None
  * 
  *         midpoint = (high + low) / 2             # <<<<<<<<<<<<<<
@@ -35505,7 +35776,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
  */
   __pyx_v_midpoint = __Pyx_div_long((__pyx_v_high + __pyx_v_low), 2);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":233
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":241
  * 
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:             # <<<<<<<<<<<<<<
@@ -35515,7 +35786,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   __pyx_t_1 = ((__pyx_v_self->darray->data->arr[((__pyx_v_self->sa->arr[__pyx_v_midpoint]) + __pyx_v_offset)]) == __pyx_v_word_id);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":234
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":242
  *         midpoint = (high + low) / 2
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:
  *             return self.__get_range(word_id, offset, low, high, midpoint)             # <<<<<<<<<<<<<<
@@ -35523,7 +35794,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
  *             return self.__lookup_helper(word_id, offset, low, midpoint)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___get_range(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_high, __pyx_v_midpoint); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 234; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___get_range(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_high, __pyx_v_midpoint); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 242; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_r = __pyx_t_4;
     __pyx_t_4 = 0;
@@ -35532,7 +35803,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   }
   __pyx_L5:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":235
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":243
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] == word_id:
  *             return self.__get_range(word_id, offset, low, high, midpoint)
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] > word_id:             # <<<<<<<<<<<<<<
@@ -35542,7 +35813,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   __pyx_t_1 = ((__pyx_v_self->darray->data->arr[((__pyx_v_self->sa->arr[__pyx_v_midpoint]) + __pyx_v_offset)]) > __pyx_v_word_id);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":236
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":244
  *             return self.__get_range(word_id, offset, low, high, midpoint)
  *         if self.darray.data.arr[self.sa.arr[midpoint] + offset] > word_id:
  *             return self.__lookup_helper(word_id, offset, low, midpoint)             # <<<<<<<<<<<<<<
@@ -35550,7 +35821,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
  *             return self.__lookup_helper(word_id, offset, midpoint+1, high)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_midpoint); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 236; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, __pyx_v_low, __pyx_v_midpoint); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 244; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_r = __pyx_t_4;
     __pyx_t_4 = 0;
@@ -35559,7 +35830,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":238
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":246
  *             return self.__lookup_helper(word_id, offset, low, midpoint)
  *         else:
  *             return self.__lookup_helper(word_id, offset, midpoint+1, high)             # <<<<<<<<<<<<<<
@@ -35567,7 +35838,7 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
  *     def lookup(self, word, int offset, int low, int high):
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, (__pyx_v_midpoint + 1), __pyx_v_high); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 238; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_v_word_id, __pyx_v_offset, (__pyx_v_midpoint + 1), __pyx_v_high); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_r = __pyx_t_4;
     __pyx_t_4 = 0;
@@ -35590,8 +35861,8 @@ static PyObject *__pyx_f_3_sa_11SuffixArray___lookup_helper(struct __pyx_obj_3_s
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_3_sa_11SuffixArray_17lookup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_3_sa_11SuffixArray_17lookup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_3_sa_11SuffixArray_19lookup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_3_sa_11SuffixArray_19lookup(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_word = 0;
   int __pyx_v_offset;
   int __pyx_v_low;
@@ -35621,21 +35892,21 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_17lookup(PyObject *__pyx_v_self, Py
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__offset)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 1); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 1); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__low)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 2); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 2); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__high)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 3); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, 3); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "lookup") < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "lookup") < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -35646,24 +35917,24 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_17lookup(PyObject *__pyx_v_self, Py
       values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
     }
     __pyx_v_word = values[0];
-    __pyx_v_offset = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_offset == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_low = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_low == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_high = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_high == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_offset = __Pyx_PyInt_AsInt(values[1]); if (unlikely((__pyx_v_offset == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_low = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_low == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_high = __Pyx_PyInt_AsInt(values[3]); if (unlikely((__pyx_v_high == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[12]; __pyx_lineno = 240; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("lookup", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[14]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.SuffixArray.lookup", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_3_sa_11SuffixArray_16lookup(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), __pyx_v_word, __pyx_v_offset, __pyx_v_low, __pyx_v_high);
+  __pyx_r = __pyx_pf_3_sa_11SuffixArray_18lookup(((struct __pyx_obj_3_sa_SuffixArray *)__pyx_v_self), __pyx_v_word, __pyx_v_offset, __pyx_v_low, __pyx_v_high);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":240
+/* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":248
  *             return self.__lookup_helper(word_id, offset, midpoint+1, high)
  * 
  *     def lookup(self, word, int offset, int low, int high):             # <<<<<<<<<<<<<<
@@ -35671,20 +35942,22 @@ static PyObject *__pyx_pw_3_sa_11SuffixArray_17lookup(PyObject *__pyx_v_self, Py
  *         if low == -1:
  */
 
-static PyObject *__pyx_pf_3_sa_11SuffixArray_16lookup(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_word, int __pyx_v_offset, int __pyx_v_low, int __pyx_v_high) {
+static PyObject *__pyx_pf_3_sa_11SuffixArray_18lookup(struct __pyx_obj_3_sa_SuffixArray *__pyx_v_self, PyObject *__pyx_v_word, int __pyx_v_offset, int __pyx_v_low, int __pyx_v_high) {
   PyObject *__pyx_v_word_id = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   PyObject *__pyx_t_2 = NULL;
   Py_ssize_t __pyx_t_3;
-  int __pyx_t_4;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("lookup", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":242
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":250
  *     def lookup(self, word, int offset, int low, int high):
  *         cdef int wordid
  *         if low == -1:             # <<<<<<<<<<<<<<
@@ -35694,7 +35967,7 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_16lookup(struct __pyx_obj_3_sa_Suff
   __pyx_t_1 = (__pyx_v_low == -1);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":243
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":251
  *         cdef int wordid
  *         if low == -1:
  *             low = 0             # <<<<<<<<<<<<<<
@@ -35706,73 +35979,87 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_16lookup(struct __pyx_obj_3_sa_Suff
   }
   __pyx_L3:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":244
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":252
  *         if low == -1:
  *             low = 0
  *         if high == -1:             # <<<<<<<<<<<<<<
  *             high = len(self.sa)
- *         if word in self.darray.word2id:
+ *         word_id = self.darray.voc.get(word, -1)
  */
   __pyx_t_1 = (__pyx_v_high == -1);
   if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":245
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":253
  *             low = 0
  *         if high == -1:
  *             high = len(self.sa)             # <<<<<<<<<<<<<<
- *         if word in self.darray.word2id:
- *             word_id = self.darray.word2id[word]
+ *         word_id = self.darray.voc.get(word, -1)
+ *         if word_id != -1:
  */
     __pyx_t_2 = ((PyObject *)__pyx_v_self->sa);
     __Pyx_INCREF(__pyx_t_2);
-    __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 245; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyObject_Length(__pyx_t_2); if (unlikely(__pyx_t_3 == -1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 253; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __pyx_v_high = __pyx_t_3;
     goto __pyx_L4;
   }
   __pyx_L4:;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":246
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":254
  *         if high == -1:
  *             high = len(self.sa)
- *         if word in self.darray.word2id:             # <<<<<<<<<<<<<<
- *             word_id = self.darray.word2id[word]
+ *         word_id = self.darray.voc.get(word, -1)             # <<<<<<<<<<<<<<
+ *         if word_id != -1:
  *             return self.__lookup_helper(word_id, offset, low, high)
  */
-  __pyx_t_1 = (__Pyx_PySequence_Contains(__pyx_v_word, __pyx_v_self->darray->word2id, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 246; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__pyx_t_1) {
+  __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_self->darray->voc), __pyx_n_s__get); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_INCREF(__pyx_v_word);
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_word);
+  __Pyx_GIVEREF(__pyx_v_word);
+  __Pyx_INCREF(__pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_int_neg_1);
+  __Pyx_GIVEREF(__pyx_int_neg_1);
+  __pyx_t_5 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_4), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 254; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
+  __pyx_v_word_id = __pyx_t_5;
+  __pyx_t_5 = 0;
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":247
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":255
  *             high = len(self.sa)
- *         if word in self.darray.word2id:
- *             word_id = self.darray.word2id[word]             # <<<<<<<<<<<<<<
+ *         word_id = self.darray.voc.get(word, -1)
+ *         if word_id != -1:             # <<<<<<<<<<<<<<
  *             return self.__lookup_helper(word_id, offset, low, high)
  *         else:
  */
-    __pyx_t_2 = PyObject_GetItem(__pyx_v_self->darray->word2id, __pyx_v_word); if (!__pyx_t_2) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 247; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_v_word_id = __pyx_t_2;
-    __pyx_t_2 = 0;
+  __pyx_t_5 = PyObject_RichCompare(__pyx_v_word_id, __pyx_int_neg_1, Py_NE); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 255; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (__pyx_t_1) {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":248
- *         if word in self.darray.word2id:
- *             word_id = self.darray.word2id[word]
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":256
+ *         word_id = self.darray.voc.get(word, -1)
+ *         if word_id != -1:
  *             return self.__lookup_helper(word_id, offset, low, high)             # <<<<<<<<<<<<<<
  *         else:
  *             return None
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_v_word_id); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __pyx_t_2 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_t_4, __pyx_v_offset, __pyx_v_low, __pyx_v_high); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 248; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_r = __pyx_t_2;
-    __pyx_t_2 = 0;
+    __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_v_word_id); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = ((struct __pyx_vtabstruct_3_sa_SuffixArray *)__pyx_v_self->__pyx_vtab)->__pyx___lookup_helper(__pyx_v_self, __pyx_t_6, __pyx_v_offset, __pyx_v_low, __pyx_v_high); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 256; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_r = __pyx_t_5;
+    __pyx_t_5 = 0;
     goto __pyx_L0;
     goto __pyx_L5;
   }
   /*else*/ {
 
-    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":250
+    /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":258
  *             return self.__lookup_helper(word_id, offset, low, high)
  *         else:
  *             return None             # <<<<<<<<<<<<<<
@@ -35788,6 +36075,8 @@ static PyObject *__pyx_pf_3_sa_11SuffixArray_16lookup(struct __pyx_obj_3_sa_Suff
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_AddTraceback("_sa.SuffixArray.lookup", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -36341,7 +36630,7 @@ static int __pyx_pw_3_sa_9TrieTable_1__cinit__(PyObject *__pyx_v_self, PyObject
   {
     static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__extended,0};
     PyObject* values[1] = {0};
-    values[0] = __pyx_k_99;
+    values[0] = __pyx_k_103;
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -37088,9 +37377,9 @@ static int __pyx_pf_3_sa_7Sampler___cinit__(struct __pyx_obj_3_sa_Sampler *__pyx
     __Pyx_GOTREF(__pyx_t_2);
     __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_100));
-    PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_s_100));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_100));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_104));
+    PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)__pyx_kp_s_104));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_104));
     PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2);
     __Pyx_GIVEREF(__pyx_t_2);
     __pyx_t_2 = 0;
@@ -37115,7 +37404,7 @@ static int __pyx_pf_3_sa_7Sampler___cinit__(struct __pyx_obj_3_sa_Sampler *__pyx
     __pyx_t_4 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__info); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_102), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_k_tuple_106), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -37903,7 +38192,7 @@ static int __pyx_pw_3_sa_23HieroCachingRuleFactory_1__cinit__(PyObject *__pyx_v_
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__alignment,&__pyx_n_s__by_slack_factor,&__pyx_n_s__category,&__pyx_n_s__max_chunks,&__pyx_n_s__max_initial_size,&__pyx_n_s__max_length,&__pyx_n_s__max_nonterminals,&__pyx_n_s__max_target_chunks,&__pyx_n_s__max_target_length,&__pyx_n_s__min_gap_size,&__pyx_n_s__precompute_file,&__pyx_n_s_70,&__pyx_n_s__precompute_rank,&__pyx_n_s_103,&__pyx_n_s_104,&__pyx_n_s_71,&__pyx_n_s__train_min_gap_size,&__pyx_n_s__tight_phrases,&__pyx_n_s__use_baeza_yates,&__pyx_n_s__use_collocations,&__pyx_n_s__use_index,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s__alignment,&__pyx_n_s__by_slack_factor,&__pyx_n_s__category,&__pyx_n_s__max_chunks,&__pyx_n_s__max_initial_size,&__pyx_n_s__max_length,&__pyx_n_s__max_nonterminals,&__pyx_n_s__max_target_chunks,&__pyx_n_s__max_target_length,&__pyx_n_s__min_gap_size,&__pyx_n_s__precompute_file,&__pyx_n_s_71,&__pyx_n_s__precompute_rank,&__pyx_n_s_107,&__pyx_n_s_108,&__pyx_n_s_72,&__pyx_n_s__train_min_gap_size,&__pyx_n_s__tight_phrases,&__pyx_n_s__use_baeza_yates,&__pyx_n_s__use_collocations,&__pyx_n_s__use_index,0};
     PyObject* values[21] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":275
@@ -38026,7 +38315,7 @@ static int __pyx_pw_3_sa_23HieroCachingRuleFactory_1__cinit__(PyObject *__pyx_v_
         }
         case 11:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_70);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_71);
           if (value) { values[11] = value; kw_args--; }
         }
         case 12:
@@ -38036,17 +38325,17 @@ static int __pyx_pw_3_sa_23HieroCachingRuleFactory_1__cinit__(PyObject *__pyx_v_
         }
         case 13:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_103);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_107);
           if (value) { values[13] = value; kw_args--; }
         }
         case 14:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_104);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_108);
           if (value) { values[14] = value; kw_args--; }
         }
         case 15:
         if (kw_args > 0) {
-          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_71);
+          PyObject* value = PyDict_GetItem(__pyx_kwds, __pyx_n_s_72);
           if (value) { values[15] = value; kw_args--; }
         }
         case 16:
@@ -38122,7 +38411,7 @@ static int __pyx_pw_3_sa_23HieroCachingRuleFactory_1__cinit__(PyObject *__pyx_v_
     if (values[2]) {
       __pyx_v_category = PyBytes_AsString(values[2]); if (unlikely((!__pyx_v_category) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     } else {
-      __pyx_v_category = ((char *)__pyx_k_105);
+      __pyx_v_category = ((char *)__pyx_k_109);
     }
     __pyx_v_max_chunks = values[3];
     if (values[4]) {
@@ -38347,7 +38636,7 @@ static int __pyx_pf_3_sa_23HieroCachingRuleFactory___cinit__(struct __pyx_obj_3_
  *         self.alignment = alignment
  * 
  */
-    __pyx_t_2 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_107), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_111), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_Raise(__pyx_t_2, 0, 0, 0);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -39040,11 +39329,11 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":392
  *         cdef IntList idmap
  * 
- *         N = len(darray.id2word)             # <<<<<<<<<<<<<<
+ *         N = len(darray.voc)             # <<<<<<<<<<<<<<
  *         idmap = IntList(initial_len=N)
  *         for word_id from 0 <= word_id < N:
  */
-  __pyx_t_1 = __pyx_v_darray->id2word;
+  __pyx_t_1 = ((PyObject *)__pyx_v_darray->voc);
   __Pyx_INCREF(__pyx_t_1);
   __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == -1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 392; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -39052,10 +39341,10 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":393
  * 
- *         N = len(darray.id2word)
+ *         N = len(darray.voc)
  *         idmap = IntList(initial_len=N)             # <<<<<<<<<<<<<<
  *         for word_id from 0 <= word_id < N:
- *             new_word_id = sym_fromstring(darray.id2word[word_id], True)
+ *             new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)
  */
   __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
@@ -39070,10 +39359,10 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
   __pyx_t_3 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":394
- *         N = len(darray.id2word)
+ *         N = len(darray.voc)
  *         idmap = IntList(initial_len=N)
  *         for word_id from 0 <= word_id < N:             # <<<<<<<<<<<<<<
- *             new_word_id = sym_fromstring(darray.id2word[word_id], True)
+ *             new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)
  *             idmap.arr[word_id] = new_word_id
  */
   __pyx_t_4 = __pyx_v_N;
@@ -39082,11 +39371,11 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":395
  *         idmap = IntList(initial_len=N)
  *         for word_id from 0 <= word_id < N:
- *             new_word_id = sym_fromstring(darray.id2word[word_id], True)             # <<<<<<<<<<<<<<
+ *             new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)             # <<<<<<<<<<<<<<
  *             idmap.arr[word_id] = new_word_id
  *         return idmap
  */
-    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_darray->id2word, __pyx_v_word_id, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_darray->voc->id2word, __pyx_v_word_id, sizeof(int), PyInt_FromLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __pyx_t_5 = PyBytes_AsString(__pyx_t_3); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 395; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -39094,7 +39383,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":396
  *         for word_id from 0 <= word_id < N:
- *             new_word_id = sym_fromstring(darray.id2word[word_id], True)
+ *             new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)
  *             idmap.arr[word_id] = new_word_id             # <<<<<<<<<<<<<<
  *         return idmap
  * 
@@ -39103,7 +39392,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_set_idmap(CYTHON_UNUSED
   }
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":397
- *             new_word_id = sym_fromstring(darray.id2word[word_id], True)
+ *             new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)
  *             idmap.arr[word_id] = new_word_id
  *         return idmap             # <<<<<<<<<<<<<<
  * 
@@ -39262,7 +39551,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_4pattern2phrase(struct
  *                 arity = arity + 1
  *                 new_id = sym_setindex(self.category, arity)             # <<<<<<<<<<<<<<
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  */
       __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_v_arity); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_new_id = __pyx_f_3_sa_sym_setindex(__pyx_v_self->category, __pyx_t_6);
@@ -39273,11 +39562,11 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_4pattern2phrase(struct
       /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":409
  *                 new_id = sym_setindex(self.category, arity)
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)             # <<<<<<<<<<<<<<
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)             # <<<<<<<<<<<<<<
  *             result = result + (new_id,)
  *         return Phrase(result)
  */
-      __pyx_t_4 = PyObject_GetItem(__pyx_v_self->fda->id2word, __pyx_v_word_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetItem(__pyx_v_self->fda->voc->id2word, __pyx_v_word_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __pyx_t_7 = PyBytes_AsString(__pyx_t_4); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -39287,7 +39576,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_4pattern2phrase(struct
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":410
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  *             result = result + (new_id,)             # <<<<<<<<<<<<<<
  *         return Phrase(result)
  * 
@@ -39309,7 +39598,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_4pattern2phrase(struct
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":411
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  *             result = result + (new_id,)
  *         return Phrase(result)             # <<<<<<<<<<<<<<
  * 
@@ -39493,7 +39782,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_6pattern2phrase_plus(st
  *                 arity = arity + 1
  *                 new_id = sym_setindex(self.category, arity)             # <<<<<<<<<<<<<<
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  */
       __pyx_t_6 = __Pyx_PyInt_AsInt(__pyx_v_arity); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 422; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_v_new_id = __pyx_f_3_sa_sym_setindex(__pyx_v_self->category, __pyx_t_6);
@@ -39504,11 +39793,11 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_6pattern2phrase_plus(st
       /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":424
  *                 new_id = sym_setindex(self.category, arity)
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)             # <<<<<<<<<<<<<<
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)             # <<<<<<<<<<<<<<
  *             result = result + (new_id,)
  *         patterns.append(Phrase(result))
  */
-      __pyx_t_4 = PyObject_GetItem(__pyx_v_self->fda->id2word, __pyx_v_word_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyObject_GetItem(__pyx_v_self->fda->voc->id2word, __pyx_v_word_id); if (!__pyx_t_4) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
       __pyx_t_7 = PyBytes_AsString(__pyx_t_4); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
@@ -39518,7 +39807,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_6pattern2phrase_plus(st
 
     /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":425
  *             else:
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  *             result = result + (new_id,)             # <<<<<<<<<<<<<<
  *         patterns.append(Phrase(result))
  *         patterns.append(Phrase(result + (sym_setindex(self.category, 1),)))
@@ -39540,7 +39829,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_6pattern2phrase_plus(st
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":426
- *                 new_id = sym_fromstring(self.fda.id2word[word_id], True)
+ *                 new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
  *             result = result + (new_id,)
  *         patterns.append(Phrase(result))             # <<<<<<<<<<<<<<
  *         patterns.append(Phrase(result + (sym_setindex(self.category, 1),)))
@@ -39724,9 +40013,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 436; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_108));
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_108));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_108));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_112));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_112));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_112));
     __Pyx_INCREF(__pyx_v_self->precompute_file);
     PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_self->precompute_file);
     __Pyx_GIVEREF(__pyx_v_self->precompute_file);
@@ -39780,9 +40069,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GOTREF(__pyx_t_3);
       __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 440; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_109));
-      PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_s_109));
-      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_109));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_113));
+      PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)__pyx_kp_s_113));
+      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_113));
       PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_2);
       __Pyx_GIVEREF(__pyx_t_2);
       PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_t_3);
@@ -39826,9 +40115,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GOTREF(__pyx_t_4);
       __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 442; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_110));
-      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_110));
-      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_110));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_114));
+      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_114));
+      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_114));
       PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);
       __Pyx_GIVEREF(__pyx_t_3);
       PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_4);
@@ -39873,7 +40162,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GIVEREF(__pyx_t_2);
       __pyx_t_4 = 0;
       __pyx_t_2 = 0;
-      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_111), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_115), ((PyObject *)__pyx_t_5)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_2));
       __Pyx_DECREF(((PyObject *)__pyx_t_5)); __pyx_t_5 = 0;
       __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 444; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -39920,7 +40209,7 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GIVEREF(__pyx_t_5);
       __pyx_t_2 = 0;
       __pyx_t_5 = 0;
-      __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_112), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_116), ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_5));
       __Pyx_DECREF(((PyObject *)__pyx_t_4)); __pyx_t_4 = 0;
       __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 446; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -39967,9 +40256,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GOTREF(__pyx_t_5);
       __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 448; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_113));
-      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_113));
-      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_113));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_117));
+      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_117));
+      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_117));
       PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_5);
       __Pyx_GIVEREF(__pyx_t_5);
       __pyx_t_5 = 0;
@@ -40121,9 +40410,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
       __Pyx_GOTREF(__pyx_t_5);
       __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_114));
-      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_114));
-      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_114));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_118));
+      PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_118));
+      __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_118));
       PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_5);
       __Pyx_GIVEREF(__pyx_t_5);
       __pyx_t_5 = 0;
@@ -40227,9 +40516,9 @@ static PyObject *__pyx_pf_3_sa_23HieroCachingRuleFactory_8precompute(struct __py
     __Pyx_GOTREF(__pyx_t_5);
     __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 459; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_INCREF(((PyObject *)__pyx_kp_s_115));
-    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_115));
-    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_115));
+    __Pyx_INCREF(((PyObject *)__pyx_kp_s_119));
+    PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_119));
+    __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_119));
     PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_5);
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_5 = 0;
@@ -42949,8 +43238,8 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_loc2str(CYTHON_UNUSED st
  *         i = 0
  *         while i < loc.arr_high:
  */
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_116));
-  __pyx_v_result = ((PyObject *)__pyx_kp_s_116);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_120));
+  __pyx_v_result = ((PyObject *)__pyx_kp_s_120);
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":807
  *         cdef int i, j
@@ -42979,7 +43268,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_loc2str(CYTHON_UNUSED st
  *             for j from i <= j < i + loc.num_subpatterns:
  *                 result = result + ("%d " %loc.arr[j])
  */
-    __pyx_t_2 = PyNumber_Add(__pyx_v_result, ((PyObject *)__pyx_kp_s_117)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyNumber_Add(__pyx_v_result, ((PyObject *)__pyx_kp_s_121)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 809; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_v_result);
     __pyx_v_result = __pyx_t_2;
@@ -43004,7 +43293,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_loc2str(CYTHON_UNUSED st
  */
       __pyx_t_2 = __Pyx_GetItemInt(((PyObject *)__pyx_v_loc->arr), __pyx_v_j, sizeof(int), PyInt_FromLong); if (!__pyx_t_2) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 811; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_21), __pyx_t_2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 811; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_20), __pyx_t_2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 811; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(((PyObject *)__pyx_t_4));
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
       __pyx_t_2 = PyNumber_Add(__pyx_v_result, ((PyObject *)__pyx_t_4)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 811; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -43045,7 +43334,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_loc2str(CYTHON_UNUSED st
  *         return result
  * 
  */
-  __pyx_t_2 = PyNumber_Add(__pyx_v_result, ((PyObject *)__pyx_kp_s_118)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyNumber_Add(__pyx_v_result, ((PyObject *)__pyx_kp_s_122)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 814; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_v_result);
   __pyx_v_result = __pyx_t_2;
@@ -43162,7 +43451,7 @@ static struct __pyx_obj_3_sa_PhraseLocation *__pyx_f_3_sa_23HieroCachingRuleFact
  *         if result is not None:
  *             intersect_method = "precomputed"
  */
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s_119); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_v_self), __pyx_n_s_123); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 826; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
@@ -43240,9 +43529,9 @@ static struct __pyx_obj_3_sa_PhraseLocation *__pyx_f_3_sa_23HieroCachingRuleFact
  *             else:
  *                 result = self.intersect_helper(prefix, suffix, prefix_loc, suffix_loc, MERGE)
  */
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_120));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_124));
       __Pyx_XDECREF(__pyx_v_intersect_method);
-      __pyx_v_intersect_method = ((PyObject *)__pyx_kp_s_120);
+      __pyx_v_intersect_method = ((PyObject *)__pyx_kp_s_124);
       goto __pyx_L5;
     }
     /*else*/ {
@@ -47019,7 +47308,7 @@ static PyObject *__pyx_gb_3_sa_23HieroCachingRuleFactory_24generator4(__pyx_Gene
  *                 # checking whether lookup_required
  *                 if lookup_required:
  */
-            __pyx_t_3 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_122), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1018; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_3 = PyObject_Call(__pyx_builtin_Exception, ((PyObject *)__pyx_k_tuple_126), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1018; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(__pyx_t_3);
             __Pyx_Raise(__pyx_t_3, 0, 0, 0);
             __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
@@ -48852,7 +49141,7 @@ static PyObject *__pyx_gb_3_sa_23HieroCachingRuleFactory_24generator4(__pyx_Gene
  *                             nodes_isteps_away_buffer[key] = frontier_nodes
  * 
  */
-            __pyx_t_9 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_self), __pyx_n_s_123); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1124; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_9 = PyObject_GetAttr(((PyObject *)__pyx_cur_scope->__pyx_v_self), __pyx_n_s_127); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1124; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(__pyx_t_9);
             __pyx_t_11 = PyInt_FromLong(__pyx_cur_scope->__pyx_v_self->min_gap_size); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1124; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(__pyx_t_11);
@@ -49129,9 +49418,9 @@ static PyObject *__pyx_gb_3_sa_23HieroCachingRuleFactory_24generator4(__pyx_Gene
   __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
   __pyx_t_13 = PyTuple_New(2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1132; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_124));
-  PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)__pyx_kp_s_124));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_124));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_128));
+  PyTuple_SET_ITEM(__pyx_t_13, 0, ((PyObject *)__pyx_kp_s_128));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_128));
   PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_t_15);
   __Pyx_GIVEREF(__pyx_t_15);
   __pyx_t_15 = 0;
@@ -49174,9 +49463,9 @@ static PyObject *__pyx_gb_3_sa_23HieroCachingRuleFactory_24generator4(__pyx_Gene
   __Pyx_GOTREF(__pyx_t_15);
   __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_125));
-  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_125));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_125));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_129));
+  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_kp_s_129));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_129));
   PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_15);
   __Pyx_GIVEREF(__pyx_t_15);
   __pyx_t_15 = 0;
@@ -51970,8 +52259,8 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  * 
  *         for i from 0 <= i < e_sent_len:
  */
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_45));
-  __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_45);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_60));
+  __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_60);
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1453
  *         reason_for_failure = ""
@@ -52345,9 +52634,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                 met_constraints = 0
  *             if self.require_aligned_chunks and num_aligned_chunks < num_chunks:
  */
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_126));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_130));
       __Pyx_DECREF(__pyx_v_reason_for_failure);
-      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_126);
+      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_130);
 
       /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1493
  *             if num_aligned_chunks == 0:
@@ -52383,9 +52672,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                 met_constraints = 0
  * 
  */
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_127));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_131));
       __Pyx_DECREF(__pyx_v_reason_for_failure);
-      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_127);
+      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_131);
 
       /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1496
  *             if self.require_aligned_chunks and num_aligned_chunks < num_chunks:
@@ -52444,9 +52733,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                     met_constraints = 0
  *                     break
  */
-        __Pyx_INCREF(((PyObject *)__pyx_kp_s_128));
+        __Pyx_INCREF(((PyObject *)__pyx_kp_s_132));
         __Pyx_DECREF(__pyx_v_reason_for_failure);
-        __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_128);
+        __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_132);
 
         /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1503
  *                 if f_links_low[matching.arr[matching.start+i]+chunklen[i]-f_sent_start] == -1:
@@ -52486,9 +52775,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                     met_constraints = 0
  *                     break
  */
-        __Pyx_INCREF(((PyObject *)__pyx_kp_s_128));
+        __Pyx_INCREF(((PyObject *)__pyx_kp_s_132));
         __Pyx_DECREF(__pyx_v_reason_for_failure);
-        __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_128);
+        __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_132);
 
         /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1507
  *                 if f_links_low[matching.arr[matching.start+i+1]-1-f_sent_start] == -1:
@@ -52700,9 +52989,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                 else:
  *                     gap_start = 1
  */
-            __Pyx_INCREF(((PyObject *)__pyx_kp_s_129));
+            __Pyx_INCREF(((PyObject *)__pyx_kp_s_133));
             __Pyx_DECREF(__pyx_v_reason_for_failure);
-            __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_129);
+            __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_133);
             goto __pyx_L38;
           }
           __pyx_L38:;
@@ -52898,9 +53187,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  *                 else:
  *                     if self.tight_phrases and f_links_low[f_high-1] == -1:
  */
-            __Pyx_INCREF(((PyObject *)__pyx_kp_s_130));
+            __Pyx_INCREF(((PyObject *)__pyx_kp_s_134));
             __Pyx_DECREF(__pyx_v_reason_for_failure);
-            __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_130);
+            __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_134);
             goto __pyx_L45;
           }
           __pyx_L45:;
@@ -53018,7 +53307,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
             __Pyx_GIVEREF(__pyx_t_1);
             __pyx_t_10 = 0;
             __pyx_t_1 = 0;
-            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_131), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_1 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_135), ((PyObject *)__pyx_t_2)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1572; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_1));
             __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
             __Pyx_DECREF(__pyx_v_reason_for_failure);
@@ -53334,7 +53623,7 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
             __pyx_t_2 = 0;
             __pyx_t_1 = 0;
             __pyx_t_14 = 0;
-            __pyx_t_14 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_132), ((PyObject *)__pyx_t_15)); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1602; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+            __pyx_t_14 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_136), ((PyObject *)__pyx_t_15)); if (unlikely(!__pyx_t_14)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1602; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
             __Pyx_GOTREF(((PyObject *)__pyx_t_14));
             __Pyx_DECREF(((PyObject *)__pyx_t_15)); __pyx_t_15 = 0;
             __Pyx_DECREF(__pyx_v_reason_for_failure);
@@ -55552,9 +55841,9 @@ static PyObject *__pyx_f_3_sa_23HieroCachingRuleFactory_extract(struct __pyx_obj
  * 
  *         free(sent_links)
  */
-      __Pyx_INCREF(((PyObject *)__pyx_kp_s_133));
+      __Pyx_INCREF(((PyObject *)__pyx_kp_s_137));
       __Pyx_DECREF(__pyx_v_reason_for_failure);
-      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_133);
+      __pyx_v_reason_for_failure = ((PyObject *)__pyx_kp_s_137);
     }
     __pyx_L34:;
     goto __pyx_L33;
@@ -55722,11 +56011,11 @@ static int __pyx_pf_3_sa_13FeatureVector___cinit__(struct __pyx_obj_3_sa_Feature
  *         self.values = FloatList(INITIAL_CAPACITY, INCREMENT)
  * 
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__INCREMENT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__INCREMENT); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
@@ -55734,7 +56023,7 @@ static int __pyx_pf_3_sa_13FeatureVector___cinit__(struct __pyx_obj_3_sa_Feature
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_1 = 0;
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_IntList)), ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
@@ -55750,11 +56039,11 @@ static int __pyx_pf_3_sa_13FeatureVector___cinit__(struct __pyx_obj_3_sa_Feature
  * 
  *     def set(self, unsigned name, float value):
  */
-  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__INCREMENT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = __Pyx_GetName(__pyx_m, __pyx_n_s__INCREMENT); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
@@ -55762,7 +56051,7 @@ static int __pyx_pf_3_sa_13FeatureVector___cinit__(struct __pyx_obj_3_sa_Feature
   __Pyx_GIVEREF(__pyx_t_3);
   __pyx_t_2 = 0;
   __pyx_t_3 = 0;
-  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FloatList)), ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_3);
@@ -55812,11 +56101,11 @@ static PyObject *__pyx_pw_3_sa_13FeatureVector_3set(PyObject *__pyx_v_self, PyOb
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__value)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("set", 1, 2, 2, 1); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("set", 1, 2, 2, 1); {__pyx_filename = __pyx_f[15]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set") < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set") < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
       goto __pyx_L5_argtuple_error;
@@ -55824,12 +56113,12 @@ static PyObject *__pyx_pw_3_sa_13FeatureVector_3set(PyObject *__pyx_v_self, PyOb
       values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __pyx_v_name = __Pyx_PyInt_AsUnsignedInt(values[0]); if (unlikely((__pyx_v_name == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
-    __pyx_v_value = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_name = __Pyx_PyInt_AsUnsignedInt(values[0]); if (unlikely((__pyx_v_name == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_value = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_value == (float)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("set", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[15]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("_sa.FeatureVector.set", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -55865,9 +56154,9 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_2set(struct __pyx_obj_3_sa_Featur
  *         self.values.append(value)
  * 
  */
-  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_name); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyLong_FromUnsignedLong(__pyx_v_name); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->names), __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->names), __pyx_t_1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -55879,9 +56168,9 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_2set(struct __pyx_obj_3_sa_Featur
  * 
  *     def __iter__(self):
  */
-  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_value); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_value); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->values), __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_Append(((PyObject *)__pyx_v_self->values), __pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -55937,7 +56226,7 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_4__iter__(struct __pyx_obj_3_sa_F
   __Pyx_INCREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   __Pyx_GIVEREF((PyObject *)__pyx_cur_scope->__pyx_v_self);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_13FeatureVector_6generator5, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_13FeatureVector_6generator5, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -55975,7 +56264,7 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_6generator5(__pyx_GeneratorObject
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/features.pxi":17
  *     def __iter__(self):
@@ -55995,15 +56284,15 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_6generator5(__pyx_GeneratorObject
  * 
  *     def __str__(self):
  */
-    __pyx_t_3 = __Pyx_GetItemInt(((PyObject *)__pyx_cur_scope->__pyx_v_self->names), __pyx_cur_scope->__pyx_v_i, sizeof(unsigned int)+1, PyLong_FromUnsignedLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_GetItemInt(((PyObject *)__pyx_cur_scope->__pyx_v_self->names), __pyx_cur_scope->__pyx_v_i, sizeof(unsigned int)+1, PyLong_FromUnsignedLong); if (!__pyx_t_3) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_3 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_StringMap *)__pyx_v_3_sa_FD->__pyx_vtab)->word(__pyx_v_3_sa_FD, __pyx_t_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = PyBytes_FromString(((struct __pyx_vtabstruct_3_sa_StringMap *)__pyx_v_3_sa_FD->__pyx_vtab)->word(__pyx_v_3_sa_FD, __pyx_t_4)); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_3));
-    __pyx_t_5 = __Pyx_GetItemInt(((PyObject *)__pyx_cur_scope->__pyx_v_self->values), __pyx_cur_scope->__pyx_v_i, sizeof(unsigned int)+1, PyLong_FromUnsignedLong); if (!__pyx_t_5) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_GetItemInt(((PyObject *)__pyx_cur_scope->__pyx_v_self->values), __pyx_cur_scope->__pyx_v_i, sizeof(unsigned int)+1, PyLong_FromUnsignedLong); if (!__pyx_t_5) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_t_3));
     __Pyx_GIVEREF(((PyObject *)__pyx_t_3));
@@ -56023,7 +56312,7 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_6generator5(__pyx_GeneratorObject
     __pyx_L6_resume_from_yield:;
     __pyx_t_1 = __pyx_cur_scope->__pyx_t_0;
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   PyErr_SetNone(PyExc_StopIteration);
   goto __pyx_L0;
@@ -56078,7 +56367,7 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_7__str___genexpr(PyObject *__pyx_
   __Pyx_INCREF(((PyObject *)__pyx_cur_scope->__pyx_outer_scope));
   __Pyx_GIVEREF(__pyx_cur_scope->__pyx_outer_scope);
   {
-    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_13FeatureVector_7__str___2generator12, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_GeneratorObject *gen = __Pyx_Generator_New((__pyx_generator_body_t) __pyx_gb_3_sa_13FeatureVector_7__str___2generator12, (PyObject *) __pyx_cur_scope); if (unlikely(!gen)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_cur_scope);
     __Pyx_RefNannyFinishContext();
     return (PyObject *) gen;
@@ -56114,13 +56403,13 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_7__str___2generator12(__pyx_Gener
     return NULL;
   }
   __pyx_L3_first_run:;
-  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)) { __Pyx_RaiseClosureNameError("self"); {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
+  if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)) { __Pyx_RaiseClosureNameError("self"); {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;} }
   if (PyList_CheckExact(((PyObject *)__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)) || PyTuple_CheckExact(((PyObject *)__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self))) {
     __pyx_t_1 = ((PyObject *)__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self); __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(((PyObject *)__pyx_cur_scope->__pyx_outer_scope->__pyx_v_self)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -56128,23 +56417,23 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_7__str___2generator12(__pyx_Gener
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -56155,7 +56444,7 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_7__str___2generator12(__pyx_Gener
     __Pyx_GIVEREF(__pyx_t_4);
     __pyx_cur_scope->__pyx_v_feat = __pyx_t_4;
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_134), __pyx_cur_scope->__pyx_v_feat); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyNumber_Remainder(((PyObject *)__pyx_kp_s_138), __pyx_cur_scope->__pyx_v_feat); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(((PyObject *)__pyx_t_4));
     __pyx_r = ((PyObject *)__pyx_t_4);
     __pyx_t_4 = 0;
@@ -56174,7 +56463,7 @@ static PyObject *__pyx_gb_3_sa_13FeatureVector_7__str___2generator12(__pyx_Gener
     __Pyx_XGOTREF(__pyx_t_1);
     __pyx_t_2 = __pyx_cur_scope->__pyx_t_1;
     __pyx_t_3 = __pyx_cur_scope->__pyx_t_2;
-    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(!__pyx_sent_value)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   PyErr_SetNone(PyExc_StopIteration);
@@ -56228,16 +56517,16 @@ static PyObject *__pyx_pf_3_sa_13FeatureVector_7__str__(struct __pyx_obj_3_sa_Fe
  * cdef class Scorer:
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_67), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_GetAttr(((PyObject *)__pyx_kp_s_68), __pyx_n_s__join); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_pf_3_sa_13FeatureVector_7__str___genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = __pyx_pf_3_sa_13FeatureVector_7__str___genexpr(((PyObject*)__pyx_cur_scope)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_3);
   PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
   __Pyx_GIVEREF(__pyx_t_2);
   __pyx_t_2 = 0;
-  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_t_1, ((PyObject *)__pyx_t_3), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
   __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
@@ -56306,26 +56595,26 @@ static int __pyx_pf_3_sa_6Scorer___init__(struct __pyx_obj_3_sa_Scorer *__pyx_v_
  *         self.models = zip(names, models)
  * 
  */
-  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_2 = ((PyObject *)__pyx_v_models); __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
   for (;;) {
     if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
     #if CYTHON_COMPILING_IN_CPYTHON
-    __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_4); __pyx_t_3++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #else
-    __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     #endif
     __Pyx_XDECREF(__pyx_v_model);
     __pyx_v_model = __pyx_t_4;
     __pyx_t_4 = 0;
-    __pyx_t_4 = PyObject_GetAttr(__pyx_v_model, __pyx_n_s____name__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(__pyx_v_model, __pyx_n_s____name__); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyBytes_AsString(__pyx_t_4); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyBytes_AsString(__pyx_t_4); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_4 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_StringMap *)__pyx_v_3_sa_FD->__pyx_vtab)->index(__pyx_v_3_sa_FD, ((char *)__pyx_t_5))); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyInt_FromLong(((struct __pyx_vtabstruct_3_sa_StringMap *)__pyx_v_3_sa_FD->__pyx_vtab)->index(__pyx_v_3_sa_FD, ((char *)__pyx_t_5))); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    if (unlikely(__Pyx_PyList_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_PyList_Append(__pyx_t_1, (PyObject*)__pyx_t_4))) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   }
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
@@ -56340,7 +56629,7 @@ static int __pyx_pf_3_sa_6Scorer___init__(struct __pyx_obj_3_sa_Scorer *__pyx_v_
  * 
  *     cdef FeatureVector score(self, ctx):
  */
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_INCREF(((PyObject *)__pyx_v_names));
   PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)__pyx_v_names));
@@ -56348,7 +56637,7 @@ static int __pyx_pf_3_sa_6Scorer___init__(struct __pyx_obj_3_sa_Scorer *__pyx_v_
   __Pyx_INCREF(((PyObject *)__pyx_v_models));
   PyTuple_SET_ITEM(__pyx_t_1, 1, ((PyObject *)__pyx_v_models));
   __Pyx_GIVEREF(((PyObject *)__pyx_v_models));
-  __pyx_t_2 = PyObject_Call(__pyx_builtin_zip, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyObject_Call(__pyx_builtin_zip, ((PyObject *)__pyx_t_1), NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
   __Pyx_GIVEREF(__pyx_t_2);
@@ -56406,7 +56695,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
  *         for name, model in self.models:
  *             scores.set(name, model(ctx))
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FeatureVector)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_FeatureVector)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_v_scores = ((struct __pyx_obj_3_sa_FeatureVector *)__pyx_t_1);
   __pyx_t_1 = 0;
@@ -56422,7 +56711,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
     __pyx_t_1 = __pyx_v_self->models; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_self->models); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_self->models); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -56430,23 +56719,23 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
@@ -56462,7 +56751,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
       if (unlikely(size != 2)) {
         if (size > 2) __Pyx_RaiseTooManyValuesError(2);
         else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+        {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       }
       #if CYTHON_COMPILING_IN_CPYTHON
       if (likely(PyTuple_CheckExact(sequence))) {
@@ -56475,14 +56764,14 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
       __Pyx_INCREF(__pyx_t_5);
       __Pyx_INCREF(__pyx_t_6);
       #else
-      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     } else
     {
       Py_ssize_t index = -1;
-      __pyx_t_7 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_7 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_7);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
       __pyx_t_8 = Py_TYPE(__pyx_t_7)->tp_iternext;
@@ -56490,7 +56779,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
       __Pyx_GOTREF(__pyx_t_5);
       index = 1; __pyx_t_6 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L5_unpacking_failed;
       __Pyx_GOTREF(__pyx_t_6);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_t_8 = NULL;
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
       goto __pyx_L6_unpacking_done;
@@ -56498,7 +56787,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
       __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
       __pyx_t_8 = NULL;
       if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      {__pyx_filename = __pyx_f[13]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      {__pyx_filename = __pyx_f[15]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __pyx_L6_unpacking_done:;
     }
     __Pyx_XDECREF(__pyx_v_name);
@@ -56514,17 +56803,17 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
  *             scores.set(name, model(ctx))             # <<<<<<<<<<<<<<
  *         return scores
  */
-    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_scores), __pyx_n_s__set); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_scores), __pyx_n_s__set); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_INCREF(__pyx_v_ctx);
     PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_ctx);
     __Pyx_GIVEREF(__pyx_v_ctx);
-    __pyx_t_5 = PyObject_Call(__pyx_v_model, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_v_model, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
-    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_6);
     __Pyx_INCREF(__pyx_v_name);
     PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_name);
@@ -56532,7 +56821,7 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
     PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_5);
     __Pyx_GIVEREF(__pyx_t_5);
     __pyx_t_5 = 0;
-    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = PyObject_Call(__pyx_t_4, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_5);
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
@@ -56568,6 +56857,187 @@ static struct __pyx_obj_3_sa_FeatureVector *__pyx_f_3_sa_6Scorer_score(struct __
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
+static struct __pyx_vtabstruct_3_sa_MemoryMap __pyx_vtable_3_sa_MemoryMap;
+
+static PyObject *__pyx_tp_new_3_sa_MemoryMap(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  struct __pyx_obj_3_sa_MemoryMap *p;
+  PyObject *o = (*t->tp_alloc)(t, 0);
+  if (!o) return 0;
+  p = ((struct __pyx_obj_3_sa_MemoryMap *)o);
+  p->__pyx_vtab = __pyx_vtabptr_3_sa_MemoryMap;
+  return o;
+}
+
+static void __pyx_tp_dealloc_3_sa_MemoryMap(PyObject *o) {
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_3_sa_9MemoryMap_3__dealloc__(o);
+    if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
+  }
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static PyMethodDef __pyx_methods_3_sa_MemoryMap[] = {
+  {0, 0, 0, 0}
+};
+
+static PyNumberMethods __pyx_tp_as_number_MemoryMap = {
+  0, /*nb_add*/
+  0, /*nb_subtract*/
+  0, /*nb_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_divide*/
+  #endif
+  0, /*nb_remainder*/
+  0, /*nb_divmod*/
+  0, /*nb_power*/
+  0, /*nb_negative*/
+  0, /*nb_positive*/
+  0, /*nb_absolute*/
+  0, /*nb_nonzero*/
+  0, /*nb_invert*/
+  0, /*nb_lshift*/
+  0, /*nb_rshift*/
+  0, /*nb_and*/
+  0, /*nb_xor*/
+  0, /*nb_or*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_coerce*/
+  #endif
+  0, /*nb_int*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_long*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*nb_float*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_oct*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_hex*/
+  #endif
+  0, /*nb_inplace_add*/
+  0, /*nb_inplace_subtract*/
+  0, /*nb_inplace_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_inplace_divide*/
+  #endif
+  0, /*nb_inplace_remainder*/
+  0, /*nb_inplace_power*/
+  0, /*nb_inplace_lshift*/
+  0, /*nb_inplace_rshift*/
+  0, /*nb_inplace_and*/
+  0, /*nb_inplace_xor*/
+  0, /*nb_inplace_or*/
+  0, /*nb_floor_divide*/
+  0, /*nb_true_divide*/
+  0, /*nb_inplace_floor_divide*/
+  0, /*nb_inplace_true_divide*/
+  #if PY_VERSION_HEX >= 0x02050000
+  0, /*nb_index*/
+  #endif
+};
+
+static PySequenceMethods __pyx_tp_as_sequence_MemoryMap = {
+  0, /*sq_length*/
+  0, /*sq_concat*/
+  0, /*sq_repeat*/
+  0, /*sq_item*/
+  0, /*sq_slice*/
+  0, /*sq_ass_item*/
+  0, /*sq_ass_slice*/
+  0, /*sq_contains*/
+  0, /*sq_inplace_concat*/
+  0, /*sq_inplace_repeat*/
+};
+
+static PyMappingMethods __pyx_tp_as_mapping_MemoryMap = {
+  0, /*mp_length*/
+  0, /*mp_subscript*/
+  0, /*mp_ass_subscript*/
+};
+
+static PyBufferProcs __pyx_tp_as_buffer_MemoryMap = {
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getreadbuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getwritebuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getsegcount*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getcharbuffer*/
+  #endif
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*bf_getbuffer*/
+  #endif
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*bf_releasebuffer*/
+  #endif
+};
+
+static PyTypeObject __pyx_type_3_sa_MemoryMap = {
+  PyVarObject_HEAD_INIT(0, 0)
+  __Pyx_NAMESTR("_sa.MemoryMap"), /*tp_name*/
+  sizeof(struct __pyx_obj_3_sa_MemoryMap), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_3_sa_MemoryMap, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  &__pyx_tp_as_number_MemoryMap, /*tp_as_number*/
+  &__pyx_tp_as_sequence_MemoryMap, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_MemoryMap, /*tp_as_mapping*/
+  0, /*tp_hash*/
+  0, /*tp_call*/
+  0, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  &__pyx_tp_as_buffer_MemoryMap, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  0, /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  0, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_3_sa_MemoryMap, /*tp_methods*/
+  0, /*tp_members*/
+  0, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  __pyx_pw_3_sa_9MemoryMap_1__init__, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_3_sa_MemoryMap, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*tp_version_tag*/
+  #endif
+};
 static struct __pyx_vtabstruct_3_sa_FloatList __pyx_vtable_3_sa_FloatList;
 
 static PyObject *__pyx_tp_new_3_sa_FloatList(PyTypeObject *t, PyObject *a, PyObject *k) {
@@ -56576,6 +57046,7 @@ static PyObject *__pyx_tp_new_3_sa_FloatList(PyTypeObject *t, PyObject *a, PyObj
   if (!o) return 0;
   p = ((struct __pyx_obj_3_sa_FloatList *)o);
   p->__pyx_vtab = __pyx_vtabptr_3_sa_FloatList;
+  p->memory = Py_None; Py_INCREF(Py_None);
   if (__pyx_pw_3_sa_9FloatList_1__cinit__(o, a, k) < 0) {
     Py_DECREF(o); o = 0;
   }
@@ -56583,6 +57054,7 @@ static PyObject *__pyx_tp_new_3_sa_FloatList(PyTypeObject *t, PyObject *a, PyObj
 }
 
 static void __pyx_tp_dealloc_3_sa_FloatList(PyObject *o) {
+  struct __pyx_obj_3_sa_FloatList *p = (struct __pyx_obj_3_sa_FloatList *)o;
   {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
@@ -56592,8 +57064,27 @@ static void __pyx_tp_dealloc_3_sa_FloatList(PyObject *o) {
     --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
   }
+  Py_CLEAR(p->memory);
   (*Py_TYPE(o)->tp_free)(o);
 }
+
+static int __pyx_tp_traverse_3_sa_FloatList(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_3_sa_FloatList *p = (struct __pyx_obj_3_sa_FloatList *)o;
+  if (p->memory) {
+    e = (*v)(p->memory, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_3_sa_FloatList(PyObject *o) {
+  struct __pyx_obj_3_sa_FloatList *p = (struct __pyx_obj_3_sa_FloatList *)o;
+  PyObject* tmp;
+  tmp = ((PyObject*)p->memory);
+  p->memory = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
 static PyObject *__pyx_sq_item_3_sa_FloatList(PyObject *o, Py_ssize_t i) {
   PyObject *r;
   PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;
@@ -56615,8 +57106,6 @@ static int __pyx_mp_ass_subscript_3_sa_FloatList(PyObject *o, PyObject *i, PyObj
 
 static PyMethodDef __pyx_methods_3_sa_FloatList[] = {
   {__Pyx_NAMESTR("append"), (PyCFunction)__pyx_pw_3_sa_9FloatList_11append, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write"), (PyCFunction)__pyx_pw_3_sa_9FloatList_13write, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("read"), (PyCFunction)__pyx_pw_3_sa_9FloatList_15read, METH_O, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -56742,10 +57231,10 @@ static PyTypeObject __pyx_type_3_sa_FloatList = {
   0, /*tp_getattro*/
   0, /*tp_setattro*/
   &__pyx_tp_as_buffer_FloatList, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
   0, /*tp_doc*/
-  0, /*tp_traverse*/
-  0, /*tp_clear*/
+  __pyx_tp_traverse_3_sa_FloatList, /*tp_traverse*/
+  __pyx_tp_clear_3_sa_FloatList, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
   0, /*tp_iter*/
@@ -56781,6 +57270,7 @@ static PyObject *__pyx_tp_new_3_sa_IntList(PyTypeObject *t, PyObject *a, PyObjec
   if (!o) return 0;
   p = ((struct __pyx_obj_3_sa_IntList *)o);
   p->__pyx_vtab = __pyx_vtabptr_3_sa_IntList;
+  p->memory = Py_None; Py_INCREF(Py_None);
   if (__pyx_pw_3_sa_7IntList_1__cinit__(o, a, k) < 0) {
     Py_DECREF(o); o = 0;
   }
@@ -56788,17 +57278,37 @@ static PyObject *__pyx_tp_new_3_sa_IntList(PyTypeObject *t, PyObject *a, PyObjec
 }
 
 static void __pyx_tp_dealloc_3_sa_IntList(PyObject *o) {
+  struct __pyx_obj_3_sa_IntList *p = (struct __pyx_obj_3_sa_IntList *)o;
   {
     PyObject *etype, *eval, *etb;
     PyErr_Fetch(&etype, &eval, &etb);
     ++Py_REFCNT(o);
-    __pyx_pw_3_sa_7IntList_15__dealloc__(o);
+    __pyx_pw_3_sa_7IntList_9__dealloc__(o);
     if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
     --Py_REFCNT(o);
     PyErr_Restore(etype, eval, etb);
   }
+  Py_CLEAR(p->memory);
   (*Py_TYPE(o)->tp_free)(o);
 }
+
+static int __pyx_tp_traverse_3_sa_IntList(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_3_sa_IntList *p = (struct __pyx_obj_3_sa_IntList *)o;
+  if (p->memory) {
+    e = (*v)(p->memory, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_3_sa_IntList(PyObject *o) {
+  struct __pyx_obj_3_sa_IntList *p = (struct __pyx_obj_3_sa_IntList *)o;
+  PyObject* tmp;
+  tmp = ((PyObject*)p->memory);
+  p->memory = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
 static PyObject *__pyx_sq_item_3_sa_IntList(PyObject *o, Py_ssize_t i) {
   PyObject *r;
   PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;
@@ -56809,7 +57319,7 @@ static PyObject *__pyx_sq_item_3_sa_IntList(PyObject *o, Py_ssize_t i) {
 
 static int __pyx_mp_ass_subscript_3_sa_IntList(PyObject *o, PyObject *i, PyObject *v) {
   if (v) {
-    return __pyx_pw_3_sa_7IntList_22__setitem__(o, i, v);
+    return __pyx_pw_3_sa_7IntList_16__setitem__(o, i, v);
   }
   else {
     PyErr_Format(PyExc_NotImplementedError,
@@ -56820,15 +57330,9 @@ static int __pyx_mp_ass_subscript_3_sa_IntList(PyObject *o, PyObject *i, PyObjec
 
 static PyMethodDef __pyx_methods_3_sa_IntList[] = {
   {__Pyx_NAMESTR("index"), (PyCFunction)__pyx_pw_3_sa_7IntList_5index, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("partition"), (PyCFunction)__pyx_pw_3_sa_7IntList_7partition, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("_doquicksort"), (PyCFunction)__pyx_pw_3_sa_7IntList_9_doquicksort, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("sort"), (PyCFunction)__pyx_pw_3_sa_7IntList_11sort, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("reset"), (PyCFunction)__pyx_pw_3_sa_7IntList_13reset, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("get_size"), (PyCFunction)__pyx_pw_3_sa_7IntList_26get_size, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("append"), (PyCFunction)__pyx_pw_3_sa_7IntList_28append, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("extend"), (PyCFunction)__pyx_pw_3_sa_7IntList_30extend, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write"), (PyCFunction)__pyx_pw_3_sa_7IntList_32write, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("read"), (PyCFunction)__pyx_pw_3_sa_7IntList_34read, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("reset"), (PyCFunction)__pyx_pw_3_sa_7IntList_7reset, METH_NOARGS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("append"), (PyCFunction)__pyx_pw_3_sa_7IntList_20append, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("extend"), (PyCFunction)__pyx_pw_3_sa_7IntList_22extend, METH_O, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -56891,7 +57395,7 @@ static PyNumberMethods __pyx_tp_as_number_IntList = {
 };
 
 static PySequenceMethods __pyx_tp_as_sequence_IntList = {
-  __pyx_pw_3_sa_7IntList_24__len__, /*sq_length*/
+  __pyx_pw_3_sa_7IntList_18__len__, /*sq_length*/
   0, /*sq_concat*/
   0, /*sq_repeat*/
   __pyx_sq_item_3_sa_IntList, /*sq_item*/
@@ -56904,8 +57408,8 @@ static PySequenceMethods __pyx_tp_as_sequence_IntList = {
 };
 
 static PyMappingMethods __pyx_tp_as_mapping_IntList = {
-  __pyx_pw_3_sa_7IntList_24__len__, /*mp_length*/
-  __pyx_pw_3_sa_7IntList_20__getitem__, /*mp_subscript*/
+  __pyx_pw_3_sa_7IntList_18__len__, /*mp_length*/
+  __pyx_pw_3_sa_7IntList_14__getitem__, /*mp_subscript*/
   __pyx_mp_ass_subscript_3_sa_IntList, /*mp_ass_subscript*/
 };
 
@@ -56944,23 +57448,23 @@ static PyTypeObject __pyx_type_3_sa_IntList = {
   #else
   0, /*reserved*/
   #endif
-  0, /*tp_repr*/
+  __pyx_pw_3_sa_7IntList_3__repr__, /*tp_repr*/
   &__pyx_tp_as_number_IntList, /*tp_as_number*/
   &__pyx_tp_as_sequence_IntList, /*tp_as_sequence*/
   &__pyx_tp_as_mapping_IntList, /*tp_as_mapping*/
   0, /*tp_hash*/
   0, /*tp_call*/
-  __pyx_pw_3_sa_7IntList_3__str__, /*tp_str*/
+  0, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
   &__pyx_tp_as_buffer_IntList, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
   0, /*tp_doc*/
-  0, /*tp_traverse*/
-  0, /*tp_clear*/
+  __pyx_tp_traverse_3_sa_IntList, /*tp_traverse*/
+  __pyx_tp_clear_3_sa_IntList, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
-  __pyx_pw_3_sa_7IntList_17__iter__, /*tp_iter*/
+  __pyx_pw_3_sa_7IntList_11__iter__, /*tp_iter*/
   0, /*tp_iternext*/
   __pyx_methods_3_sa_IntList, /*tp_methods*/
   0, /*tp_members*/
@@ -57301,11 +57805,246 @@ static PyNumberMethods __pyx_tp_as_number_Phrase = {
   #endif
 };
 
-static PySequenceMethods __pyx_tp_as_sequence_Phrase = {
-  __pyx_pw_3_sa_6Phrase_25__len__, /*sq_length*/
+static PySequenceMethods __pyx_tp_as_sequence_Phrase = {
+  __pyx_pw_3_sa_6Phrase_25__len__, /*sq_length*/
+  0, /*sq_concat*/
+  0, /*sq_repeat*/
+  __pyx_sq_item_3_sa_Phrase, /*sq_item*/
+  0, /*sq_slice*/
+  0, /*sq_ass_item*/
+  0, /*sq_ass_slice*/
+  0, /*sq_contains*/
+  0, /*sq_inplace_concat*/
+  0, /*sq_inplace_repeat*/
+};
+
+static PyMappingMethods __pyx_tp_as_mapping_Phrase = {
+  __pyx_pw_3_sa_6Phrase_25__len__, /*mp_length*/
+  __pyx_pw_3_sa_6Phrase_27__getitem__, /*mp_subscript*/
+  0, /*mp_ass_subscript*/
+};
+
+static PyBufferProcs __pyx_tp_as_buffer_Phrase = {
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getreadbuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getwritebuffer*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getsegcount*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*bf_getcharbuffer*/
+  #endif
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*bf_getbuffer*/
+  #endif
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*bf_releasebuffer*/
+  #endif
+};
+
+static PyTypeObject __pyx_type_3_sa_Phrase = {
+  PyVarObject_HEAD_INIT(0, 0)
+  __Pyx_NAMESTR("_sa.Phrase"), /*tp_name*/
+  sizeof(struct __pyx_obj_3_sa_Phrase), /*tp_basicsize*/
+  0, /*tp_itemsize*/
+  __pyx_tp_dealloc_3_sa_Phrase, /*tp_dealloc*/
+  0, /*tp_print*/
+  0, /*tp_getattr*/
+  0, /*tp_setattr*/
+  #if PY_MAJOR_VERSION < 3
+  __pyx_pw_3_sa_6Phrase_21__cmp__, /*tp_compare*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*tp_repr*/
+  &__pyx_tp_as_number_Phrase, /*tp_as_number*/
+  &__pyx_tp_as_sequence_Phrase, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_Phrase, /*tp_as_mapping*/
+  __pyx_pw_3_sa_6Phrase_23__hash__, /*tp_hash*/
+  0, /*tp_call*/
+  __pyx_pw_3_sa_6Phrase_5__str__, /*tp_str*/
+  0, /*tp_getattro*/
+  0, /*tp_setattro*/
+  &__pyx_tp_as_buffer_Phrase, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  0, /*tp_doc*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
+  0, /*tp_richcompare*/
+  0, /*tp_weaklistoffset*/
+  __pyx_pw_3_sa_6Phrase_29__iter__, /*tp_iter*/
+  0, /*tp_iternext*/
+  __pyx_methods_3_sa_Phrase, /*tp_methods*/
+  0, /*tp_members*/
+  __pyx_getsets_3_sa_Phrase, /*tp_getset*/
+  0, /*tp_base*/
+  0, /*tp_dict*/
+  0, /*tp_descr_get*/
+  0, /*tp_descr_set*/
+  0, /*tp_dictoffset*/
+  0, /*tp_init*/
+  0, /*tp_alloc*/
+  __pyx_tp_new_3_sa_Phrase, /*tp_new*/
+  0, /*tp_free*/
+  0, /*tp_is_gc*/
+  0, /*tp_bases*/
+  0, /*tp_mro*/
+  0, /*tp_cache*/
+  0, /*tp_subclasses*/
+  0, /*tp_weaklist*/
+  0, /*tp_del*/
+  #if PY_VERSION_HEX >= 0x02060000
+  0, /*tp_version_tag*/
+  #endif
+};
+
+static PyObject *__pyx_tp_new_3_sa_Rule(PyTypeObject *t, PyObject *a, PyObject *k) {
+  struct __pyx_obj_3_sa_Rule *p;
+  PyObject *o = (*t->tp_alloc)(t, 0);
+  if (!o) return 0;
+  p = ((struct __pyx_obj_3_sa_Rule *)o);
+  p->f = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
+  p->e = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
+  p->scores = ((struct __pyx_obj_3_sa_FeatureVector *)Py_None); Py_INCREF(Py_None);
+  p->word_alignments = Py_None; Py_INCREF(Py_None);
+  if (__pyx_pw_3_sa_4Rule_1__cinit__(o, a, k) < 0) {
+    Py_DECREF(o); o = 0;
+  }
+  return o;
+}
+
+static void __pyx_tp_dealloc_3_sa_Rule(PyObject *o) {
+  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
+  Py_CLEAR(p->f);
+  Py_CLEAR(p->e);
+  Py_CLEAR(p->scores);
+  Py_CLEAR(p->word_alignments);
+  (*Py_TYPE(o)->tp_free)(o);
+}
+
+static int __pyx_tp_traverse_3_sa_Rule(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
+  if (p->f) {
+    e = (*v)(((PyObject*)p->f), a); if (e) return e;
+  }
+  if (p->e) {
+    e = (*v)(((PyObject*)p->e), a); if (e) return e;
+  }
+  if (p->scores) {
+    e = (*v)(((PyObject*)p->scores), a); if (e) return e;
+  }
+  if (p->word_alignments) {
+    e = (*v)(p->word_alignments, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_3_sa_Rule(PyObject *o) {
+  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
+  PyObject* tmp;
+  tmp = ((PyObject*)p->f);
+  p->f = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->e);
+  p->e = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->scores);
+  p->scores = ((struct __pyx_obj_3_sa_FeatureVector *)Py_None); Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->word_alignments);
+  p->word_alignments = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+
+static PyObject *__pyx_getprop_3_sa_4Rule_f(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_3_sa_4Rule_1f_1__get__(o);
+}
+
+static PyObject *__pyx_getprop_3_sa_4Rule_e(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_3_sa_4Rule_1e_1__get__(o);
+}
+
+static PyMethodDef __pyx_methods_3_sa_Rule[] = {
+  {__Pyx_NAMESTR("fmerge"), (PyCFunction)__pyx_pw_3_sa_4Rule_7fmerge, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("arity"), (PyCFunction)__pyx_pw_3_sa_4Rule_9arity, METH_NOARGS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("alignments"), (PyCFunction)__pyx_pw_3_sa_4Rule_13alignments, METH_NOARGS, __Pyx_DOCSTR(0)},
+  {0, 0, 0, 0}
+};
+
+static struct PyGetSetDef __pyx_getsets_3_sa_Rule[] = {
+  {(char *)"f", __pyx_getprop_3_sa_4Rule_f, 0, 0, 0},
+  {(char *)"e", __pyx_getprop_3_sa_4Rule_e, 0, 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static PyNumberMethods __pyx_tp_as_number_Rule = {
+  0, /*nb_add*/
+  0, /*nb_subtract*/
+  0, /*nb_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_divide*/
+  #endif
+  0, /*nb_remainder*/
+  0, /*nb_divmod*/
+  0, /*nb_power*/
+  0, /*nb_negative*/
+  0, /*nb_positive*/
+  0, /*nb_absolute*/
+  0, /*nb_nonzero*/
+  0, /*nb_invert*/
+  0, /*nb_lshift*/
+  0, /*nb_rshift*/
+  0, /*nb_and*/
+  0, /*nb_xor*/
+  0, /*nb_or*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_coerce*/
+  #endif
+  0, /*nb_int*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_long*/
+  #else
+  0, /*reserved*/
+  #endif
+  0, /*nb_float*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_oct*/
+  #endif
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_hex*/
+  #endif
+  0, /*nb_inplace_add*/
+  0, /*nb_inplace_subtract*/
+  0, /*nb_inplace_multiply*/
+  #if PY_MAJOR_VERSION < 3
+  0, /*nb_inplace_divide*/
+  #endif
+  0, /*nb_inplace_remainder*/
+  0, /*nb_inplace_power*/
+  0, /*nb_inplace_lshift*/
+  0, /*nb_inplace_rshift*/
+  0, /*nb_inplace_and*/
+  0, /*nb_inplace_xor*/
+  0, /*nb_inplace_or*/
+  0, /*nb_floor_divide*/
+  0, /*nb_true_divide*/
+  0, /*nb_inplace_floor_divide*/
+  0, /*nb_inplace_true_divide*/
+  #if PY_VERSION_HEX >= 0x02050000
+  0, /*nb_index*/
+  #endif
+};
+
+static PySequenceMethods __pyx_tp_as_sequence_Rule = {
+  0, /*sq_length*/
   0, /*sq_concat*/
   0, /*sq_repeat*/
-  __pyx_sq_item_3_sa_Phrase, /*sq_item*/
+  0, /*sq_item*/
   0, /*sq_slice*/
   0, /*sq_ass_item*/
   0, /*sq_ass_slice*/
@@ -57314,13 +58053,13 @@ static PySequenceMethods __pyx_tp_as_sequence_Phrase = {
   0, /*sq_inplace_repeat*/
 };
 
-static PyMappingMethods __pyx_tp_as_mapping_Phrase = {
-  __pyx_pw_3_sa_6Phrase_25__len__, /*mp_length*/
-  __pyx_pw_3_sa_6Phrase_27__getitem__, /*mp_subscript*/
+static PyMappingMethods __pyx_tp_as_mapping_Rule = {
+  0, /*mp_length*/
+  0, /*mp_subscript*/
   0, /*mp_ass_subscript*/
 };
 
-static PyBufferProcs __pyx_tp_as_buffer_Phrase = {
+static PyBufferProcs __pyx_tp_as_buffer_Rule = {
   #if PY_MAJOR_VERSION < 3
   0, /*bf_getreadbuffer*/
   #endif
@@ -57341,41 +58080,41 @@ static PyBufferProcs __pyx_tp_as_buffer_Phrase = {
   #endif
 };
 
-static PyTypeObject __pyx_type_3_sa_Phrase = {
+static PyTypeObject __pyx_type_3_sa_Rule = {
   PyVarObject_HEAD_INIT(0, 0)
-  __Pyx_NAMESTR("_sa.Phrase"), /*tp_name*/
-  sizeof(struct __pyx_obj_3_sa_Phrase), /*tp_basicsize*/
+  __Pyx_NAMESTR("_sa.Rule"), /*tp_name*/
+  sizeof(struct __pyx_obj_3_sa_Rule), /*tp_basicsize*/
   0, /*tp_itemsize*/
-  __pyx_tp_dealloc_3_sa_Phrase, /*tp_dealloc*/
+  __pyx_tp_dealloc_3_sa_Rule, /*tp_dealloc*/
   0, /*tp_print*/
   0, /*tp_getattr*/
   0, /*tp_setattr*/
   #if PY_MAJOR_VERSION < 3
-  __pyx_pw_3_sa_6Phrase_21__cmp__, /*tp_compare*/
+  __pyx_pw_3_sa_4Rule_5__cmp__, /*tp_compare*/
   #else
   0, /*reserved*/
   #endif
   0, /*tp_repr*/
-  &__pyx_tp_as_number_Phrase, /*tp_as_number*/
-  &__pyx_tp_as_sequence_Phrase, /*tp_as_sequence*/
-  &__pyx_tp_as_mapping_Phrase, /*tp_as_mapping*/
-  __pyx_pw_3_sa_6Phrase_23__hash__, /*tp_hash*/
+  &__pyx_tp_as_number_Rule, /*tp_as_number*/
+  &__pyx_tp_as_sequence_Rule, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_Rule, /*tp_as_mapping*/
+  __pyx_pw_3_sa_4Rule_3__hash__, /*tp_hash*/
   0, /*tp_call*/
-  __pyx_pw_3_sa_6Phrase_5__str__, /*tp_str*/
+  __pyx_pw_3_sa_4Rule_11__str__, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
-  &__pyx_tp_as_buffer_Phrase, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  &__pyx_tp_as_buffer_Rule, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
   0, /*tp_doc*/
-  0, /*tp_traverse*/
-  0, /*tp_clear*/
+  __pyx_tp_traverse_3_sa_Rule, /*tp_traverse*/
+  __pyx_tp_clear_3_sa_Rule, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
-  __pyx_pw_3_sa_6Phrase_29__iter__, /*tp_iter*/
+  0, /*tp_iter*/
   0, /*tp_iternext*/
-  __pyx_methods_3_sa_Phrase, /*tp_methods*/
+  __pyx_methods_3_sa_Rule, /*tp_methods*/
   0, /*tp_members*/
-  __pyx_getsets_3_sa_Phrase, /*tp_getset*/
+  __pyx_getsets_3_sa_Rule, /*tp_getset*/
   0, /*tp_base*/
   0, /*tp_dict*/
   0, /*tp_descr_get*/
@@ -57383,7 +58122,7 @@ static PyTypeObject __pyx_type_3_sa_Phrase = {
   0, /*tp_dictoffset*/
   0, /*tp_init*/
   0, /*tp_alloc*/
-  __pyx_tp_new_3_sa_Phrase, /*tp_new*/
+  __pyx_tp_new_3_sa_Rule, /*tp_new*/
   0, /*tp_free*/
   0, /*tp_is_gc*/
   0, /*tp_bases*/
@@ -57396,89 +58135,38 @@ static PyTypeObject __pyx_type_3_sa_Phrase = {
   0, /*tp_version_tag*/
   #endif
 };
+static struct __pyx_vtabstruct_3_sa_StringMap __pyx_vtable_3_sa_StringMap;
 
-static PyObject *__pyx_tp_new_3_sa_Rule(PyTypeObject *t, PyObject *a, PyObject *k) {
-  struct __pyx_obj_3_sa_Rule *p;
+static PyObject *__pyx_tp_new_3_sa_StringMap(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  struct __pyx_obj_3_sa_StringMap *p;
   PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
-  p = ((struct __pyx_obj_3_sa_Rule *)o);
-  p->f = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
-  p->e = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
-  p->scores = ((struct __pyx_obj_3_sa_FeatureVector *)Py_None); Py_INCREF(Py_None);
-  p->word_alignments = Py_None; Py_INCREF(Py_None);
-  if (__pyx_pw_3_sa_4Rule_1__cinit__(o, a, k) < 0) {
+  p = ((struct __pyx_obj_3_sa_StringMap *)o);
+  p->__pyx_vtab = __pyx_vtabptr_3_sa_StringMap;
+  if (__pyx_pw_3_sa_9StringMap_1__cinit__(o, __pyx_empty_tuple, NULL) < 0) {
     Py_DECREF(o); o = 0;
   }
   return o;
 }
 
-static void __pyx_tp_dealloc_3_sa_Rule(PyObject *o) {
-  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
-  Py_CLEAR(p->f);
-  Py_CLEAR(p->e);
-  Py_CLEAR(p->scores);
-  Py_CLEAR(p->word_alignments);
-  (*Py_TYPE(o)->tp_free)(o);
-}
-
-static int __pyx_tp_traverse_3_sa_Rule(PyObject *o, visitproc v, void *a) {
-  int e;
-  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
-  if (p->f) {
-    e = (*v)(((PyObject*)p->f), a); if (e) return e;
-  }
-  if (p->e) {
-    e = (*v)(((PyObject*)p->e), a); if (e) return e;
-  }
-  if (p->scores) {
-    e = (*v)(((PyObject*)p->scores), a); if (e) return e;
-  }
-  if (p->word_alignments) {
-    e = (*v)(p->word_alignments, a); if (e) return e;
+static void __pyx_tp_dealloc_3_sa_StringMap(PyObject *o) {
+  {
+    PyObject *etype, *eval, *etb;
+    PyErr_Fetch(&etype, &eval, &etb);
+    ++Py_REFCNT(o);
+    __pyx_pw_3_sa_9StringMap_3__dealloc__(o);
+    if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
+    --Py_REFCNT(o);
+    PyErr_Restore(etype, eval, etb);
   }
-  return 0;
-}
-
-static int __pyx_tp_clear_3_sa_Rule(PyObject *o) {
-  struct __pyx_obj_3_sa_Rule *p = (struct __pyx_obj_3_sa_Rule *)o;
-  PyObject* tmp;
-  tmp = ((PyObject*)p->f);
-  p->f = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->e);
-  p->e = ((struct __pyx_obj_3_sa_Phrase *)Py_None); Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->scores);
-  p->scores = ((struct __pyx_obj_3_sa_FeatureVector *)Py_None); Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->word_alignments);
-  p->word_alignments = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  return 0;
-}
-
-static PyObject *__pyx_getprop_3_sa_4Rule_f(PyObject *o, CYTHON_UNUSED void *x) {
-  return __pyx_pw_3_sa_4Rule_1f_1__get__(o);
-}
-
-static PyObject *__pyx_getprop_3_sa_4Rule_e(PyObject *o, CYTHON_UNUSED void *x) {
-  return __pyx_pw_3_sa_4Rule_1e_1__get__(o);
+  (*Py_TYPE(o)->tp_free)(o);
 }
 
-static PyMethodDef __pyx_methods_3_sa_Rule[] = {
-  {__Pyx_NAMESTR("fmerge"), (PyCFunction)__pyx_pw_3_sa_4Rule_7fmerge, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("arity"), (PyCFunction)__pyx_pw_3_sa_4Rule_9arity, METH_NOARGS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("alignments"), (PyCFunction)__pyx_pw_3_sa_4Rule_13alignments, METH_NOARGS, __Pyx_DOCSTR(0)},
+static PyMethodDef __pyx_methods_3_sa_StringMap[] = {
   {0, 0, 0, 0}
 };
 
-static struct PyGetSetDef __pyx_getsets_3_sa_Rule[] = {
-  {(char *)"f", __pyx_getprop_3_sa_4Rule_f, 0, 0, 0},
-  {(char *)"e", __pyx_getprop_3_sa_4Rule_e, 0, 0, 0},
-  {0, 0, 0, 0, 0}
-};
-
-static PyNumberMethods __pyx_tp_as_number_Rule = {
+static PyNumberMethods __pyx_tp_as_number_StringMap = {
   0, /*nb_add*/
   0, /*nb_subtract*/
   0, /*nb_multiply*/
@@ -57536,7 +58224,7 @@ static PyNumberMethods __pyx_tp_as_number_Rule = {
   #endif
 };
 
-static PySequenceMethods __pyx_tp_as_sequence_Rule = {
+static PySequenceMethods __pyx_tp_as_sequence_StringMap = {
   0, /*sq_length*/
   0, /*sq_concat*/
   0, /*sq_repeat*/
@@ -57549,13 +58237,13 @@ static PySequenceMethods __pyx_tp_as_sequence_Rule = {
   0, /*sq_inplace_repeat*/
 };
 
-static PyMappingMethods __pyx_tp_as_mapping_Rule = {
+static PyMappingMethods __pyx_tp_as_mapping_StringMap = {
   0, /*mp_length*/
   0, /*mp_subscript*/
   0, /*mp_ass_subscript*/
 };
 
-static PyBufferProcs __pyx_tp_as_buffer_Rule = {
+static PyBufferProcs __pyx_tp_as_buffer_StringMap = {
   #if PY_MAJOR_VERSION < 3
   0, /*bf_getreadbuffer*/
   #endif
@@ -57576,41 +58264,41 @@ static PyBufferProcs __pyx_tp_as_buffer_Rule = {
   #endif
 };
 
-static PyTypeObject __pyx_type_3_sa_Rule = {
+static PyTypeObject __pyx_type_3_sa_StringMap = {
   PyVarObject_HEAD_INIT(0, 0)
-  __Pyx_NAMESTR("_sa.Rule"), /*tp_name*/
-  sizeof(struct __pyx_obj_3_sa_Rule), /*tp_basicsize*/
+  __Pyx_NAMESTR("_sa.StringMap"), /*tp_name*/
+  sizeof(struct __pyx_obj_3_sa_StringMap), /*tp_basicsize*/
   0, /*tp_itemsize*/
-  __pyx_tp_dealloc_3_sa_Rule, /*tp_dealloc*/
+  __pyx_tp_dealloc_3_sa_StringMap, /*tp_dealloc*/
   0, /*tp_print*/
   0, /*tp_getattr*/
   0, /*tp_setattr*/
   #if PY_MAJOR_VERSION < 3
-  __pyx_pw_3_sa_4Rule_5__cmp__, /*tp_compare*/
+  0, /*tp_compare*/
   #else
   0, /*reserved*/
   #endif
   0, /*tp_repr*/
-  &__pyx_tp_as_number_Rule, /*tp_as_number*/
-  &__pyx_tp_as_sequence_Rule, /*tp_as_sequence*/
-  &__pyx_tp_as_mapping_Rule, /*tp_as_mapping*/
-  __pyx_pw_3_sa_4Rule_3__hash__, /*tp_hash*/
+  &__pyx_tp_as_number_StringMap, /*tp_as_number*/
+  &__pyx_tp_as_sequence_StringMap, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_StringMap, /*tp_as_mapping*/
+  0, /*tp_hash*/
   0, /*tp_call*/
-  __pyx_pw_3_sa_4Rule_11__str__, /*tp_str*/
+  0, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
-  &__pyx_tp_as_buffer_Rule, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+  &__pyx_tp_as_buffer_StringMap, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
   0, /*tp_doc*/
-  __pyx_tp_traverse_3_sa_Rule, /*tp_traverse*/
-  __pyx_tp_clear_3_sa_Rule, /*tp_clear*/
+  0, /*tp_traverse*/
+  0, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
   0, /*tp_iter*/
   0, /*tp_iternext*/
-  __pyx_methods_3_sa_Rule, /*tp_methods*/
+  __pyx_methods_3_sa_StringMap, /*tp_methods*/
   0, /*tp_members*/
-  __pyx_getsets_3_sa_Rule, /*tp_getset*/
+  0, /*tp_getset*/
   0, /*tp_base*/
   0, /*tp_dict*/
   0, /*tp_descr_get*/
@@ -57618,7 +58306,7 @@ static PyTypeObject __pyx_type_3_sa_Rule = {
   0, /*tp_dictoffset*/
   0, /*tp_init*/
   0, /*tp_alloc*/
-  __pyx_tp_new_3_sa_Rule, /*tp_new*/
+  __pyx_tp_new_3_sa_StringMap, /*tp_new*/
   0, /*tp_free*/
   0, /*tp_is_gc*/
   0, /*tp_bases*/
@@ -57631,38 +58319,64 @@ static PyTypeObject __pyx_type_3_sa_Rule = {
   0, /*tp_version_tag*/
   #endif
 };
-static struct __pyx_vtabstruct_3_sa_StringMap __pyx_vtable_3_sa_StringMap;
+static struct __pyx_vtabstruct_3_sa_Vocabulary __pyx_vtable_3_sa_Vocabulary;
 
-static PyObject *__pyx_tp_new_3_sa_StringMap(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
-  struct __pyx_obj_3_sa_StringMap *p;
+static PyObject *__pyx_tp_new_3_sa_Vocabulary(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
+  struct __pyx_obj_3_sa_Vocabulary *p;
   PyObject *o = (*t->tp_alloc)(t, 0);
   if (!o) return 0;
-  p = ((struct __pyx_obj_3_sa_StringMap *)o);
-  p->__pyx_vtab = __pyx_vtabptr_3_sa_StringMap;
-  if (__pyx_pw_3_sa_9StringMap_1__cinit__(o, __pyx_empty_tuple, NULL) < 0) {
-    Py_DECREF(o); o = 0;
-  }
+  p = ((struct __pyx_obj_3_sa_Vocabulary *)o);
+  p->__pyx_vtab = __pyx_vtabptr_3_sa_Vocabulary;
+  p->id2word = Py_None; Py_INCREF(Py_None);
+  p->word2id = Py_None; Py_INCREF(Py_None);
   return o;
 }
 
-static void __pyx_tp_dealloc_3_sa_StringMap(PyObject *o) {
-  {
-    PyObject *etype, *eval, *etb;
-    PyErr_Fetch(&etype, &eval, &etb);
-    ++Py_REFCNT(o);
-    __pyx_pw_3_sa_9StringMap_3__dealloc__(o);
-    if (PyErr_Occurred()) PyErr_WriteUnraisable(o);
-    --Py_REFCNT(o);
-    PyErr_Restore(etype, eval, etb);
-  }
+static void __pyx_tp_dealloc_3_sa_Vocabulary(PyObject *o) {
+  struct __pyx_obj_3_sa_Vocabulary *p = (struct __pyx_obj_3_sa_Vocabulary *)o;
+  Py_CLEAR(p->id2word);
+  Py_CLEAR(p->word2id);
   (*Py_TYPE(o)->tp_free)(o);
 }
 
-static PyMethodDef __pyx_methods_3_sa_StringMap[] = {
+static int __pyx_tp_traverse_3_sa_Vocabulary(PyObject *o, visitproc v, void *a) {
+  int e;
+  struct __pyx_obj_3_sa_Vocabulary *p = (struct __pyx_obj_3_sa_Vocabulary *)o;
+  if (p->id2word) {
+    e = (*v)(p->id2word, a); if (e) return e;
+  }
+  if (p->word2id) {
+    e = (*v)(p->word2id, a); if (e) return e;
+  }
+  return 0;
+}
+
+static int __pyx_tp_clear_3_sa_Vocabulary(PyObject *o) {
+  struct __pyx_obj_3_sa_Vocabulary *p = (struct __pyx_obj_3_sa_Vocabulary *)o;
+  PyObject* tmp;
+  tmp = ((PyObject*)p->id2word);
+  p->id2word = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  tmp = ((PyObject*)p->word2id);
+  p->word2id = Py_None; Py_INCREF(Py_None);
+  Py_XDECREF(tmp);
+  return 0;
+}
+static PyObject *__pyx_sq_item_3_sa_Vocabulary(PyObject *o, Py_ssize_t i) {
+  PyObject *r;
+  PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;
+  r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x);
+  Py_DECREF(x);
+  return r;
+}
+
+static PyMethodDef __pyx_methods_3_sa_Vocabulary[] = {
+  {__Pyx_NAMESTR("extend"), (PyCFunction)__pyx_pw_3_sa_10Vocabulary_3extend, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("get"), (PyCFunction)__pyx_pw_3_sa_10Vocabulary_9get, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
-static PyNumberMethods __pyx_tp_as_number_StringMap = {
+static PyNumberMethods __pyx_tp_as_number_Vocabulary = {
   0, /*nb_add*/
   0, /*nb_subtract*/
   0, /*nb_multiply*/
@@ -57720,11 +58434,11 @@ static PyNumberMethods __pyx_tp_as_number_StringMap = {
   #endif
 };
 
-static PySequenceMethods __pyx_tp_as_sequence_StringMap = {
-  0, /*sq_length*/
+static PySequenceMethods __pyx_tp_as_sequence_Vocabulary = {
+  __pyx_pw_3_sa_10Vocabulary_11__len__, /*sq_length*/
   0, /*sq_concat*/
   0, /*sq_repeat*/
-  0, /*sq_item*/
+  __pyx_sq_item_3_sa_Vocabulary, /*sq_item*/
   0, /*sq_slice*/
   0, /*sq_ass_item*/
   0, /*sq_ass_slice*/
@@ -57733,13 +58447,13 @@ static PySequenceMethods __pyx_tp_as_sequence_StringMap = {
   0, /*sq_inplace_repeat*/
 };
 
-static PyMappingMethods __pyx_tp_as_mapping_StringMap = {
-  0, /*mp_length*/
-  0, /*mp_subscript*/
+static PyMappingMethods __pyx_tp_as_mapping_Vocabulary = {
+  __pyx_pw_3_sa_10Vocabulary_11__len__, /*mp_length*/
+  __pyx_pw_3_sa_10Vocabulary_7__getitem__, /*mp_subscript*/
   0, /*mp_ass_subscript*/
 };
 
-static PyBufferProcs __pyx_tp_as_buffer_StringMap = {
+static PyBufferProcs __pyx_tp_as_buffer_Vocabulary = {
   #if PY_MAJOR_VERSION < 3
   0, /*bf_getreadbuffer*/
   #endif
@@ -57760,12 +58474,12 @@ static PyBufferProcs __pyx_tp_as_buffer_StringMap = {
   #endif
 };
 
-static PyTypeObject __pyx_type_3_sa_StringMap = {
+static PyTypeObject __pyx_type_3_sa_Vocabulary = {
   PyVarObject_HEAD_INIT(0, 0)
-  __Pyx_NAMESTR("_sa.StringMap"), /*tp_name*/
-  sizeof(struct __pyx_obj_3_sa_StringMap), /*tp_basicsize*/
+  __Pyx_NAMESTR("_sa.Vocabulary"), /*tp_name*/
+  sizeof(struct __pyx_obj_3_sa_Vocabulary), /*tp_basicsize*/
   0, /*tp_itemsize*/
-  __pyx_tp_dealloc_3_sa_StringMap, /*tp_dealloc*/
+  __pyx_tp_dealloc_3_sa_Vocabulary, /*tp_dealloc*/
   0, /*tp_print*/
   0, /*tp_getattr*/
   0, /*tp_setattr*/
@@ -57775,24 +58489,24 @@ static PyTypeObject __pyx_type_3_sa_StringMap = {
   0, /*reserved*/
   #endif
   0, /*tp_repr*/
-  &__pyx_tp_as_number_StringMap, /*tp_as_number*/
-  &__pyx_tp_as_sequence_StringMap, /*tp_as_sequence*/
-  &__pyx_tp_as_mapping_StringMap, /*tp_as_mapping*/
+  &__pyx_tp_as_number_Vocabulary, /*tp_as_number*/
+  &__pyx_tp_as_sequence_Vocabulary, /*tp_as_sequence*/
+  &__pyx_tp_as_mapping_Vocabulary, /*tp_as_mapping*/
   0, /*tp_hash*/
   0, /*tp_call*/
   0, /*tp_str*/
   0, /*tp_getattro*/
   0, /*tp_setattro*/
-  &__pyx_tp_as_buffer_StringMap, /*tp_as_buffer*/
-  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  &__pyx_tp_as_buffer_Vocabulary, /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
   0, /*tp_doc*/
-  0, /*tp_traverse*/
-  0, /*tp_clear*/
+  __pyx_tp_traverse_3_sa_Vocabulary, /*tp_traverse*/
+  __pyx_tp_clear_3_sa_Vocabulary, /*tp_clear*/
   0, /*tp_richcompare*/
   0, /*tp_weaklistoffset*/
-  0, /*tp_iter*/
+  __pyx_pw_3_sa_10Vocabulary_5__iter__, /*tp_iter*/
   0, /*tp_iternext*/
-  __pyx_methods_3_sa_StringMap, /*tp_methods*/
+  __pyx_methods_3_sa_Vocabulary, /*tp_methods*/
   0, /*tp_members*/
   0, /*tp_getset*/
   0, /*tp_base*/
@@ -57800,9 +58514,9 @@ static PyTypeObject __pyx_type_3_sa_StringMap = {
   0, /*tp_descr_get*/
   0, /*tp_descr_set*/
   0, /*tp_dictoffset*/
-  0, /*tp_init*/
+  __pyx_pw_3_sa_10Vocabulary_1__init__, /*tp_init*/
   0, /*tp_alloc*/
-  __pyx_tp_new_3_sa_StringMap, /*tp_new*/
+  __pyx_tp_new_3_sa_Vocabulary, /*tp_new*/
   0, /*tp_free*/
   0, /*tp_is_gc*/
   0, /*tp_bases*/
@@ -57823,8 +58537,7 @@ static PyObject *__pyx_tp_new_3_sa_DataArray(PyTypeObject *t, PyObject *a, PyObj
   if (!o) return 0;
   p = ((struct __pyx_obj_3_sa_DataArray *)o);
   p->__pyx_vtab = __pyx_vtabptr_3_sa_DataArray;
-  p->word2id = Py_None; Py_INCREF(Py_None);
-  p->id2word = Py_None; Py_INCREF(Py_None);
+  p->voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
   p->data = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
   p->sent_id = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
   p->sent_index = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
@@ -57836,8 +58549,7 @@ static PyObject *__pyx_tp_new_3_sa_DataArray(PyTypeObject *t, PyObject *a, PyObj
 
 static void __pyx_tp_dealloc_3_sa_DataArray(PyObject *o) {
   struct __pyx_obj_3_sa_DataArray *p = (struct __pyx_obj_3_sa_DataArray *)o;
-  Py_CLEAR(p->word2id);
-  Py_CLEAR(p->id2word);
+  Py_CLEAR(p->voc);
   Py_CLEAR(p->data);
   Py_CLEAR(p->sent_id);
   Py_CLEAR(p->sent_index);
@@ -57847,11 +58559,8 @@ static void __pyx_tp_dealloc_3_sa_DataArray(PyObject *o) {
 static int __pyx_tp_traverse_3_sa_DataArray(PyObject *o, visitproc v, void *a) {
   int e;
   struct __pyx_obj_3_sa_DataArray *p = (struct __pyx_obj_3_sa_DataArray *)o;
-  if (p->word2id) {
-    e = (*v)(p->word2id, a); if (e) return e;
-  }
-  if (p->id2word) {
-    e = (*v)(p->id2word, a); if (e) return e;
+  if (p->voc) {
+    e = (*v)(((PyObject*)p->voc), a); if (e) return e;
   }
   if (p->data) {
     e = (*v)(((PyObject*)p->data), a); if (e) return e;
@@ -57868,11 +58577,8 @@ static int __pyx_tp_traverse_3_sa_DataArray(PyObject *o, visitproc v, void *a) {
 static int __pyx_tp_clear_3_sa_DataArray(PyObject *o) {
   struct __pyx_obj_3_sa_DataArray *p = (struct __pyx_obj_3_sa_DataArray *)o;
   PyObject* tmp;
-  tmp = ((PyObject*)p->word2id);
-  p->word2id = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->id2word);
-  p->id2word = Py_None; Py_INCREF(Py_None);
+  tmp = ((PyObject*)p->voc);
+  p->voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   tmp = ((PyObject*)p->data);
   p->data = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
@@ -57893,29 +58599,16 @@ static PyObject *__pyx_sq_item_3_sa_DataArray(PyObject *o, Py_ssize_t i) {
   return r;
 }
 
-static PyObject *__pyx_getprop_3_sa_9DataArray_word2id(PyObject *o, CYTHON_UNUSED void *x) {
-  return __pyx_pw_3_sa_9DataArray_7word2id_1__get__(o);
+static PyObject *__pyx_getprop_3_sa_9DataArray_voc(PyObject *o, CYTHON_UNUSED void *x) {
+  return __pyx_pw_3_sa_9DataArray_3voc_1__get__(o);
 }
 
-static int __pyx_setprop_3_sa_9DataArray_word2id(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) {
+static int __pyx_setprop_3_sa_9DataArray_voc(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) {
   if (v) {
-    return __pyx_pw_3_sa_9DataArray_7word2id_3__set__(o, v);
+    return __pyx_pw_3_sa_9DataArray_3voc_3__set__(o, v);
   }
   else {
-    return __pyx_pw_3_sa_9DataArray_7word2id_5__del__(o);
-  }
-}
-
-static PyObject *__pyx_getprop_3_sa_9DataArray_id2word(PyObject *o, CYTHON_UNUSED void *x) {
-  return __pyx_pw_3_sa_9DataArray_7id2word_1__get__(o);
-}
-
-static int __pyx_setprop_3_sa_9DataArray_id2word(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) {
-  if (v) {
-    return __pyx_pw_3_sa_9DataArray_7id2word_3__set__(o, v);
-  }
-  else {
-    return __pyx_pw_3_sa_9DataArray_7id2word_5__del__(o);
+    return __pyx_pw_3_sa_9DataArray_3voc_5__del__(o);
   }
 }
 
@@ -57975,8 +58668,7 @@ static PyMethodDef __pyx_methods_3_sa_DataArray[] = {
 };
 
 static struct PyGetSetDef __pyx_getsets_3_sa_DataArray[] = {
-  {(char *)"word2id", __pyx_getprop_3_sa_9DataArray_word2id, __pyx_setprop_3_sa_9DataArray_word2id, 0, 0},
-  {(char *)"id2word", __pyx_getprop_3_sa_9DataArray_id2word, __pyx_setprop_3_sa_9DataArray_id2word, 0, 0},
+  {(char *)"voc", __pyx_getprop_3_sa_9DataArray_voc, __pyx_setprop_3_sa_9DataArray_voc, 0, 0},
   {(char *)"data", __pyx_getprop_3_sa_9DataArray_data, __pyx_setprop_3_sa_9DataArray_data, 0, 0},
   {(char *)"sent_id", __pyx_getprop_3_sa_9DataArray_sent_id, __pyx_setprop_3_sa_9DataArray_sent_id, 0, 0},
   {(char *)"sent_index", __pyx_getprop_3_sa_9DataArray_sent_index, __pyx_setprop_3_sa_9DataArray_sent_index, 0, 0},
@@ -58188,10 +58880,11 @@ static PyMethodDef __pyx_methods_3_sa_Alignment[] = {
   {__Pyx_NAMESTR("get_sent_links"), (PyCFunction)__pyx_pw_3_sa_9Alignment_3get_sent_links, METH_O, __Pyx_DOCSTR(0)},
   {__Pyx_NAMESTR("read_text"), (PyCFunction)__pyx_pw_3_sa_9Alignment_7read_text, METH_O, __Pyx_DOCSTR(0)},
   {__Pyx_NAMESTR("read_binary"), (PyCFunction)__pyx_pw_3_sa_9Alignment_9read_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_text"), (PyCFunction)__pyx_pw_3_sa_9Alignment_11write_text, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_9Alignment_13write_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_9Alignment_15write_enhanced, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("alignment"), (PyCFunction)__pyx_pw_3_sa_9Alignment_17alignment, METH_O, __Pyx_DOCSTR(__pyx_doc_3_sa_9Alignment_16alignment)},
+  {__Pyx_NAMESTR("read_mmaped"), (PyCFunction)__pyx_pw_3_sa_9Alignment_11read_mmaped, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_text"), (PyCFunction)__pyx_pw_3_sa_9Alignment_13write_text, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_9Alignment_15write_binary, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_9Alignment_17write_enhanced, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("alignment"), (PyCFunction)__pyx_pw_3_sa_9Alignment_19alignment, METH_O, __Pyx_DOCSTR(__pyx_doc_3_sa_9Alignment_18alignment)},
   {0, 0, 0, 0}
 };
 
@@ -58360,10 +59053,8 @@ static PyObject *__pyx_tp_new_3_sa_BiLex(PyTypeObject *t, PyObject *a, PyObject
   p->col2 = ((struct __pyx_obj_3_sa_FloatList *)Py_None); Py_INCREF(Py_None);
   p->f_index = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
   p->e_index = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
-  p->id2eword = Py_None; Py_INCREF(Py_None);
-  p->id2fword = Py_None; Py_INCREF(Py_None);
-  p->eword2id = Py_None; Py_INCREF(Py_None);
-  p->fword2id = Py_None; Py_INCREF(Py_None);
+  p->f_voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
+  p->e_voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
   if (__pyx_pw_3_sa_5BiLex_1__cinit__(o, a, k) < 0) {
     Py_DECREF(o); o = 0;
   }
@@ -58376,10 +59067,8 @@ static void __pyx_tp_dealloc_3_sa_BiLex(PyObject *o) {
   Py_CLEAR(p->col2);
   Py_CLEAR(p->f_index);
   Py_CLEAR(p->e_index);
-  Py_CLEAR(p->id2eword);
-  Py_CLEAR(p->id2fword);
-  Py_CLEAR(p->eword2id);
-  Py_CLEAR(p->fword2id);
+  Py_CLEAR(p->f_voc);
+  Py_CLEAR(p->e_voc);
   (*Py_TYPE(o)->tp_free)(o);
 }
 
@@ -58398,17 +59087,11 @@ static int __pyx_tp_traverse_3_sa_BiLex(PyObject *o, visitproc v, void *a) {
   if (p->e_index) {
     e = (*v)(((PyObject*)p->e_index), a); if (e) return e;
   }
-  if (p->id2eword) {
-    e = (*v)(p->id2eword, a); if (e) return e;
+  if (p->f_voc) {
+    e = (*v)(((PyObject*)p->f_voc), a); if (e) return e;
   }
-  if (p->id2fword) {
-    e = (*v)(p->id2fword, a); if (e) return e;
-  }
-  if (p->eword2id) {
-    e = (*v)(p->eword2id, a); if (e) return e;
-  }
-  if (p->fword2id) {
-    e = (*v)(p->fword2id, a); if (e) return e;
+  if (p->e_voc) {
+    e = (*v)(((PyObject*)p->e_voc), a); if (e) return e;
   }
   return 0;
 }
@@ -58428,17 +59111,11 @@ static int __pyx_tp_clear_3_sa_BiLex(PyObject *o) {
   tmp = ((PyObject*)p->e_index);
   p->e_index = ((struct __pyx_obj_3_sa_IntList *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->id2eword);
-  p->id2eword = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->id2fword);
-  p->id2fword = Py_None; Py_INCREF(Py_None);
-  Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->eword2id);
-  p->eword2id = Py_None; Py_INCREF(Py_None);
+  tmp = ((PyObject*)p->f_voc);
+  p->f_voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
-  tmp = ((PyObject*)p->fword2id);
-  p->fword2id = Py_None; Py_INCREF(Py_None);
+  tmp = ((PyObject*)p->e_voc);
+  p->e_voc = ((struct __pyx_obj_3_sa_Vocabulary *)Py_None); Py_INCREF(Py_None);
   Py_XDECREF(tmp);
   return 0;
 }
@@ -58446,12 +59123,13 @@ static int __pyx_tp_clear_3_sa_BiLex(PyObject *o) {
 static PyMethodDef __pyx_methods_3_sa_BiLex[] = {
   {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_5BiLex_3write_binary, METH_O, __Pyx_DOCSTR(0)},
   {__Pyx_NAMESTR("read_binary"), (PyCFunction)__pyx_pw_3_sa_5BiLex_5read_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("get_e_id"), (PyCFunction)__pyx_pw_3_sa_5BiLex_7get_e_id, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("get_f_id"), (PyCFunction)__pyx_pw_3_sa_5BiLex_9get_f_id, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("read_text"), (PyCFunction)__pyx_pw_3_sa_5BiLex_11read_text, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_5BiLex_13write_enhanced, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("get_score"), (PyCFunction)__pyx_pw_3_sa_5BiLex_15get_score, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_text"), (PyCFunction)__pyx_pw_3_sa_5BiLex_17write_text, METH_O, __Pyx_DOCSTR(__pyx_doc_3_sa_5BiLex_16write_text)},
+  {__Pyx_NAMESTR("read_mmaped"), (PyCFunction)__pyx_pw_3_sa_5BiLex_7read_mmaped, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("get_e_id"), (PyCFunction)__pyx_pw_3_sa_5BiLex_9get_e_id, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("get_f_id"), (PyCFunction)__pyx_pw_3_sa_5BiLex_11get_f_id, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("read_text"), (PyCFunction)__pyx_pw_3_sa_5BiLex_13read_text, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_5BiLex_15write_enhanced, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("get_score"), (PyCFunction)__pyx_pw_3_sa_5BiLex_17get_score, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_text"), (PyCFunction)__pyx_pw_3_sa_5BiLex_19write_text, METH_O, __Pyx_DOCSTR(__pyx_doc_3_sa_5BiLex_18write_text)},
   {0, 0, 0, 0}
 };
 
@@ -59990,8 +60668,9 @@ static int __pyx_tp_clear_3_sa_Precomputation(PyObject *o) {
 
 static PyMethodDef __pyx_methods_3_sa_Precomputation[] = {
   {__Pyx_NAMESTR("read_binary"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_3read_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_5write_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("precompute"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_7precompute, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("read_mmaped"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_5read_mmaped, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_7write_binary, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("precompute"), (PyCFunction)__pyx_pw_3_sa_14Precomputation_9precompute, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -60215,9 +60894,10 @@ static PyMethodDef __pyx_methods_3_sa_SuffixArray[] = {
   {__Pyx_NAMESTR("q3sort"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_7q3sort, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_3_sa_11SuffixArray_6q3sort)},
   {__Pyx_NAMESTR("write_text"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_9write_text, METH_O, __Pyx_DOCSTR(0)},
   {__Pyx_NAMESTR("read_binary"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_11read_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_13write_binary, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_15write_enhanced, METH_O, __Pyx_DOCSTR(0)},
-  {__Pyx_NAMESTR("lookup"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_17lookup, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("read_mmaped"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_13read_mmaped, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_binary"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_15write_binary, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("write_enhanced"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_17write_enhanced, METH_O, __Pyx_DOCSTR(0)},
+  {__Pyx_NAMESTR("lookup"), (PyCFunction)__pyx_pw_3_sa_11SuffixArray_19lookup, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(0)},
   {0, 0, 0, 0}
 };
 
@@ -66271,15 +66951,11 @@ static struct PyModuleDef __pyx_moduledef = {
 
 static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 0},
-  {&__pyx_kp_s_100, __pyx_k_100, sizeof(__pyx_k_100), 0, 0, 1, 0},
-  {&__pyx_kp_s_101, __pyx_k_101, sizeof(__pyx_k_101), 0, 0, 1, 0},
-  {&__pyx_n_s_103, __pyx_k_103, sizeof(__pyx_k_103), 0, 0, 1, 1},
-  {&__pyx_n_s_104, __pyx_k_104, sizeof(__pyx_k_104), 0, 0, 1, 1},
-  {&__pyx_kp_s_106, __pyx_k_106, sizeof(__pyx_k_106), 0, 0, 1, 0},
-  {&__pyx_kp_s_108, __pyx_k_108, sizeof(__pyx_k_108), 0, 0, 1, 0},
-  {&__pyx_kp_s_109, __pyx_k_109, sizeof(__pyx_k_109), 0, 0, 1, 0},
+  {&__pyx_kp_s_104, __pyx_k_104, sizeof(__pyx_k_104), 0, 0, 1, 0},
+  {&__pyx_kp_s_105, __pyx_k_105, sizeof(__pyx_k_105), 0, 0, 1, 0},
+  {&__pyx_n_s_107, __pyx_k_107, sizeof(__pyx_k_107), 0, 0, 1, 1},
+  {&__pyx_n_s_108, __pyx_k_108, sizeof(__pyx_k_108), 0, 0, 1, 1},
   {&__pyx_kp_s_110, __pyx_k_110, sizeof(__pyx_k_110), 0, 0, 1, 0},
-  {&__pyx_kp_s_111, __pyx_k_111, sizeof(__pyx_k_111), 0, 0, 1, 0},
   {&__pyx_kp_s_112, __pyx_k_112, sizeof(__pyx_k_112), 0, 0, 1, 0},
   {&__pyx_kp_s_113, __pyx_k_113, sizeof(__pyx_k_113), 0, 0, 1, 0},
   {&__pyx_kp_s_114, __pyx_k_114, sizeof(__pyx_k_114), 0, 0, 1, 0},
@@ -66287,14 +66963,15 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_s_116, __pyx_k_116, sizeof(__pyx_k_116), 0, 0, 1, 0},
   {&__pyx_kp_s_117, __pyx_k_117, sizeof(__pyx_k_117), 0, 0, 1, 0},
   {&__pyx_kp_s_118, __pyx_k_118, sizeof(__pyx_k_118), 0, 0, 1, 0},
-  {&__pyx_n_s_119, __pyx_k_119, sizeof(__pyx_k_119), 0, 0, 1, 1},
+  {&__pyx_kp_s_119, __pyx_k_119, sizeof(__pyx_k_119), 0, 0, 1, 0},
+  {&__pyx_kp_s_12, __pyx_k_12, sizeof(__pyx_k_12), 0, 0, 1, 0},
   {&__pyx_kp_s_120, __pyx_k_120, sizeof(__pyx_k_120), 0, 0, 1, 0},
   {&__pyx_kp_s_121, __pyx_k_121, sizeof(__pyx_k_121), 0, 0, 1, 0},
+  {&__pyx_kp_s_122, __pyx_k_122, sizeof(__pyx_k_122), 0, 0, 1, 0},
   {&__pyx_n_s_123, __pyx_k_123, sizeof(__pyx_k_123), 0, 0, 1, 1},
   {&__pyx_kp_s_124, __pyx_k_124, sizeof(__pyx_k_124), 0, 0, 1, 0},
   {&__pyx_kp_s_125, __pyx_k_125, sizeof(__pyx_k_125), 0, 0, 1, 0},
-  {&__pyx_kp_s_126, __pyx_k_126, sizeof(__pyx_k_126), 0, 0, 1, 0},
-  {&__pyx_kp_s_127, __pyx_k_127, sizeof(__pyx_k_127), 0, 0, 1, 0},
+  {&__pyx_n_s_127, __pyx_k_127, sizeof(__pyx_k_127), 0, 0, 1, 1},
   {&__pyx_kp_s_128, __pyx_k_128, sizeof(__pyx_k_128), 0, 0, 1, 0},
   {&__pyx_kp_s_129, __pyx_k_129, sizeof(__pyx_k_129), 0, 0, 1, 0},
   {&__pyx_kp_s_13, __pyx_k_13, sizeof(__pyx_k_13), 0, 0, 1, 0},
@@ -66303,81 +66980,83 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_s_132, __pyx_k_132, sizeof(__pyx_k_132), 0, 0, 1, 0},
   {&__pyx_kp_s_133, __pyx_k_133, sizeof(__pyx_k_133), 0, 0, 1, 0},
   {&__pyx_kp_s_134, __pyx_k_134, sizeof(__pyx_k_134), 0, 0, 1, 0},
+  {&__pyx_kp_s_135, __pyx_k_135, sizeof(__pyx_k_135), 0, 0, 1, 0},
+  {&__pyx_kp_s_136, __pyx_k_136, sizeof(__pyx_k_136), 0, 0, 1, 0},
   {&__pyx_kp_s_137, __pyx_k_137, sizeof(__pyx_k_137), 0, 0, 1, 0},
   {&__pyx_kp_s_138, __pyx_k_138, sizeof(__pyx_k_138), 0, 0, 1, 0},
-  {&__pyx_kp_s_14, __pyx_k_14, sizeof(__pyx_k_14), 0, 0, 1, 0},
+  {&__pyx_kp_s_141, __pyx_k_141, sizeof(__pyx_k_141), 0, 0, 1, 0},
   {&__pyx_kp_s_142, __pyx_k_142, sizeof(__pyx_k_142), 0, 0, 1, 0},
-  {&__pyx_kp_s_18, __pyx_k_18, sizeof(__pyx_k_18), 0, 0, 1, 0},
+  {&__pyx_kp_s_147, __pyx_k_147, sizeof(__pyx_k_147), 0, 0, 1, 0},
+  {&__pyx_kp_s_17, __pyx_k_17, sizeof(__pyx_k_17), 0, 0, 1, 0},
   {&__pyx_kp_s_2, __pyx_k_2, sizeof(__pyx_k_2), 0, 0, 1, 0},
-  {&__pyx_kp_s_21, __pyx_k_21, sizeof(__pyx_k_21), 0, 0, 1, 0},
-  {&__pyx_kp_s_25, __pyx_k_25, sizeof(__pyx_k_25), 0, 0, 1, 0},
-  {&__pyx_n_s_27, __pyx_k_27, sizeof(__pyx_k_27), 0, 0, 1, 1},
+  {&__pyx_kp_s_20, __pyx_k_20, sizeof(__pyx_k_20), 0, 0, 1, 0},
+  {&__pyx_kp_s_24, __pyx_k_24, sizeof(__pyx_k_24), 0, 0, 1, 0},
+  {&__pyx_n_s_26, __pyx_k_26, sizeof(__pyx_k_26), 0, 0, 1, 1},
   {&__pyx_kp_s_3, __pyx_k_3, sizeof(__pyx_k_3), 0, 0, 1, 0},
   {&__pyx_kp_s_31, __pyx_k_31, sizeof(__pyx_k_31), 0, 0, 1, 0},
   {&__pyx_kp_s_35, __pyx_k_35, sizeof(__pyx_k_35), 0, 0, 1, 0},
   {&__pyx_kp_s_4, __pyx_k_4, sizeof(__pyx_k_4), 0, 0, 1, 0},
-  {&__pyx_kp_s_42, __pyx_k_42, sizeof(__pyx_k_42), 0, 0, 1, 0},
-  {&__pyx_kp_s_45, __pyx_k_45, sizeof(__pyx_k_45), 0, 0, 1, 0},
+  {&__pyx_kp_s_43, __pyx_k_43, sizeof(__pyx_k_43), 0, 0, 1, 0},
   {&__pyx_kp_s_46, __pyx_k_46, sizeof(__pyx_k_46), 0, 0, 1, 0},
-  {&__pyx_kp_s_48, __pyx_k_48, sizeof(__pyx_k_48), 0, 0, 1, 0},
+  {&__pyx_kp_s_49, __pyx_k_49, sizeof(__pyx_k_49), 0, 0, 1, 0},
   {&__pyx_kp_s_5, __pyx_k_5, sizeof(__pyx_k_5), 0, 0, 1, 0},
-  {&__pyx_kp_s_50, __pyx_k_50, sizeof(__pyx_k_50), 0, 0, 1, 0},
-  {&__pyx_kp_s_52, __pyx_k_52, sizeof(__pyx_k_52), 0, 0, 1, 0},
-  {&__pyx_kp_s_56, __pyx_k_56, sizeof(__pyx_k_56), 0, 0, 1, 0},
+  {&__pyx_kp_s_51, __pyx_k_51, sizeof(__pyx_k_51), 0, 0, 1, 0},
+  {&__pyx_kp_s_55, __pyx_k_55, sizeof(__pyx_k_55), 0, 0, 1, 0},
+  {&__pyx_kp_s_57, __pyx_k_57, sizeof(__pyx_k_57), 0, 0, 1, 0},
   {&__pyx_kp_s_58, __pyx_k_58, sizeof(__pyx_k_58), 0, 0, 1, 0},
   {&__pyx_kp_s_59, __pyx_k_59, sizeof(__pyx_k_59), 0, 0, 1, 0},
   {&__pyx_kp_s_6, __pyx_k_6, sizeof(__pyx_k_6), 0, 0, 1, 0},
   {&__pyx_kp_s_60, __pyx_k_60, sizeof(__pyx_k_60), 0, 0, 1, 0},
-  {&__pyx_kp_s_62, __pyx_k_62, sizeof(__pyx_k_62), 0, 0, 1, 0},
-  {&__pyx_kp_s_64, __pyx_k_64, sizeof(__pyx_k_64), 0, 0, 1, 0},
+  {&__pyx_kp_s_61, __pyx_k_61, sizeof(__pyx_k_61), 0, 0, 1, 0},
+  {&__pyx_kp_s_63, __pyx_k_63, sizeof(__pyx_k_63), 0, 0, 1, 0},
   {&__pyx_kp_s_65, __pyx_k_65, sizeof(__pyx_k_65), 0, 0, 1, 0},
   {&__pyx_kp_s_66, __pyx_k_66, sizeof(__pyx_k_66), 0, 0, 1, 0},
   {&__pyx_kp_s_67, __pyx_k_67, sizeof(__pyx_k_67), 0, 0, 1, 0},
   {&__pyx_kp_s_68, __pyx_k_68, sizeof(__pyx_k_68), 0, 0, 1, 0},
   {&__pyx_kp_s_69, __pyx_k_69, sizeof(__pyx_k_69), 0, 0, 1, 0},
   {&__pyx_kp_s_7, __pyx_k_7, sizeof(__pyx_k_7), 0, 0, 1, 0},
-  {&__pyx_n_s_70, __pyx_k_70, sizeof(__pyx_k_70), 0, 0, 1, 1},
+  {&__pyx_kp_s_70, __pyx_k_70, sizeof(__pyx_k_70), 0, 0, 1, 0},
   {&__pyx_n_s_71, __pyx_k_71, sizeof(__pyx_k_71), 0, 0, 1, 1},
-  {&__pyx_kp_s_72, __pyx_k_72, sizeof(__pyx_k_72), 0, 0, 1, 0},
+  {&__pyx_n_s_72, __pyx_k_72, sizeof(__pyx_k_72), 0, 0, 1, 1},
   {&__pyx_kp_s_74, __pyx_k_74, sizeof(__pyx_k_74), 0, 0, 1, 0},
   {&__pyx_kp_s_76, __pyx_k_76, sizeof(__pyx_k_76), 0, 0, 1, 0},
   {&__pyx_kp_s_78, __pyx_k_78, sizeof(__pyx_k_78), 0, 0, 1, 0},
-  {&__pyx_kp_s_8, __pyx_k_8, sizeof(__pyx_k_8), 0, 0, 1, 0},
-  {&__pyx_kp_s_83, __pyx_k_83, sizeof(__pyx_k_83), 0, 0, 1, 0},
-  {&__pyx_kp_s_84, __pyx_k_84, sizeof(__pyx_k_84), 0, 0, 1, 0},
+  {&__pyx_kp_s_80, __pyx_k_80, sizeof(__pyx_k_80), 0, 0, 1, 0},
   {&__pyx_kp_s_85, __pyx_k_85, sizeof(__pyx_k_85), 0, 0, 1, 0},
   {&__pyx_kp_s_86, __pyx_k_86, sizeof(__pyx_k_86), 0, 0, 1, 0},
   {&__pyx_kp_s_87, __pyx_k_87, sizeof(__pyx_k_87), 0, 0, 1, 0},
   {&__pyx_kp_s_88, __pyx_k_88, sizeof(__pyx_k_88), 0, 0, 1, 0},
   {&__pyx_kp_s_89, __pyx_k_89, sizeof(__pyx_k_89), 0, 0, 1, 0},
-  {&__pyx_kp_s_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 0, 1, 0},
   {&__pyx_kp_s_90, __pyx_k_90, sizeof(__pyx_k_90), 0, 0, 1, 0},
-  {&__pyx_kp_s_91, __pyx_k_91, sizeof(__pyx_k_91), 0, 0, 1, 0},
   {&__pyx_kp_s_92, __pyx_k_92, sizeof(__pyx_k_92), 0, 0, 1, 0},
+  {&__pyx_kp_s_93, __pyx_k_93, sizeof(__pyx_k_93), 0, 0, 1, 0},
   {&__pyx_kp_s_94, __pyx_k_94, sizeof(__pyx_k_94), 0, 0, 1, 0},
   {&__pyx_kp_s_95, __pyx_k_95, sizeof(__pyx_k_95), 0, 0, 1, 0},
+  {&__pyx_kp_s_97, __pyx_k_97, sizeof(__pyx_k_97), 0, 0, 1, 0},
+  {&__pyx_kp_s_98, __pyx_k_98, sizeof(__pyx_k_98), 0, 0, 1, 0},
+  {&__pyx_kp_s_99, __pyx_k_99, sizeof(__pyx_k_99), 0, 0, 1, 0},
   {&__pyx_kp_s__0, __pyx_k__0, sizeof(__pyx_k__0), 0, 0, 1, 0},
   {&__pyx_kp_s__1, __pyx_k__1, sizeof(__pyx_k__1), 0, 0, 1, 0},
   {&__pyx_n_s__Counter, __pyx_k__Counter, sizeof(__pyx_k__Counter), 0, 0, 1, 1},
-  {&__pyx_n_s__END_OF_FILE, __pyx_k__END_OF_FILE, sizeof(__pyx_k__END_OF_FILE), 0, 0, 1, 1},
   {&__pyx_n_s__END_OF_LINE, __pyx_k__END_OF_LINE, sizeof(__pyx_k__END_OF_LINE), 0, 0, 1, 1},
   {&__pyx_n_s__Exception, __pyx_k__Exception, sizeof(__pyx_k__Exception), 0, 0, 1, 1},
   {&__pyx_n_s__FeatureContext, __pyx_k__FeatureContext, sizeof(__pyx_k__FeatureContext), 0, 0, 1, 1},
   {&__pyx_n_s__GzipFile, __pyx_k__GzipFile, sizeof(__pyx_k__GzipFile), 0, 0, 1, 1},
   {&__pyx_n_s__INCREMENT, __pyx_k__INCREMENT, sizeof(__pyx_k__INCREMENT), 0, 0, 1, 1},
   {&__pyx_n_s__INITIAL_CAPACITY, __pyx_k__INITIAL_CAPACITY, sizeof(__pyx_k__INITIAL_CAPACITY), 0, 0, 1, 1},
+  {&__pyx_n_s__INIT_VOCABULARY, __pyx_k__INIT_VOCABULARY, sizeof(__pyx_k__INIT_VOCABULARY), 0, 0, 1, 1},
   {&__pyx_n_s__IndexError, __pyx_k__IndexError, sizeof(__pyx_k__IndexError), 0, 0, 1, 1},
   {&__pyx_n_s__NULL, __pyx_k__NULL, sizeof(__pyx_k__NULL), 0, 0, 1, 1},
   {&__pyx_n_s__RUSAGE_SELF, __pyx_k__RUSAGE_SELF, sizeof(__pyx_k__RUSAGE_SELF), 0, 0, 1, 1},
   {&__pyx_n_s__StopIteration, __pyx_k__StopIteration, sizeof(__pyx_k__StopIteration), 0, 0, 1, 1},
   {&__pyx_n_s__TypeError, __pyx_k__TypeError, sizeof(__pyx_k__TypeError), 0, 0, 1, 1},
+  {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
   {&__pyx_n_s____enter__, __pyx_k____enter__, sizeof(__pyx_k____enter__), 0, 0, 1, 1},
   {&__pyx_n_s____exit__, __pyx_k____exit__, sizeof(__pyx_k____exit__), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
   {&__pyx_n_s____name__, __pyx_k____name__, sizeof(__pyx_k____name__), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
   {&__pyx_n_s___columns, __pyx_k___columns, sizeof(__pyx_k___columns), 0, 0, 1, 1},
-  {&__pyx_n_s___doquicksort, __pyx_k___doquicksort, sizeof(__pyx_k___doquicksort), 0, 0, 1, 1},
   {&__pyx_n_s___sa, __pyx_k___sa, sizeof(__pyx_k___sa), 0, 0, 1, 1},
   {&__pyx_n_s__advance, __pyx_k__advance, sizeof(__pyx_k__advance), 0, 0, 1, 1},
   {&__pyx_n_s__alignment, __pyx_k__alignment, sizeof(__pyx_k__alignment), 0, 0, 1, 1},
@@ -66399,13 +67078,13 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__debug, __pyx_k__debug, sizeof(__pyx_k__debug), 0, 0, 1, 1},
   {&__pyx_n_s__decode_lattice, __pyx_k__decode_lattice, sizeof(__pyx_k__decode_lattice), 0, 0, 1, 1},
   {&__pyx_n_s__decode_sentence, __pyx_k__decode_sentence, sizeof(__pyx_k__decode_sentence), 0, 0, 1, 1},
+  {&__pyx_n_s__default, __pyx_k__default, sizeof(__pyx_k__default), 0, 0, 1, 1},
   {&__pyx_n_s__defaultdict, __pyx_k__defaultdict, sizeof(__pyx_k__defaultdict), 0, 0, 1, 1},
   {&__pyx_n_s__dist, __pyx_k__dist, sizeof(__pyx_k__dist), 0, 0, 1, 1},
   {&__pyx_n_s__e, __pyx_k__e, sizeof(__pyx_k__e), 0, 0, 1, 1},
   {&__pyx_n_s__e_text, __pyx_k__e_text, sizeof(__pyx_k__e_text), 0, 0, 1, 1},
   {&__pyx_n_s__earray, __pyx_k__earray, sizeof(__pyx_k__earray), 0, 0, 1, 1},
   {&__pyx_n_s__edarray, __pyx_k__edarray, sizeof(__pyx_k__edarray), 0, 0, 1, 1},
-  {&__pyx_n_s__end, __pyx_k__end, sizeof(__pyx_k__end), 0, 0, 1, 1},
   {&__pyx_n_s__enumerate, __pyx_k__enumerate, sizeof(__pyx_k__enumerate), 0, 0, 1, 1},
   {&__pyx_n_s__ephrase, __pyx_k__ephrase, sizeof(__pyx_k__ephrase), 0, 0, 1, 1},
   {&__pyx_n_s__eword, __pyx_k__eword, sizeof(__pyx_k__eword), 0, 0, 1, 1},
@@ -66421,6 +67100,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__from_iterable, __pyx_k__from_iterable, sizeof(__pyx_k__from_iterable), 0, 0, 1, 1},
   {&__pyx_n_s__from_stats, __pyx_k__from_stats, sizeof(__pyx_k__from_stats), 0, 0, 1, 1},
   {&__pyx_n_s__from_text, __pyx_k__from_text, sizeof(__pyx_k__from_text), 0, 0, 1, 1},
+  {&__pyx_n_s__from_vocabulary, __pyx_k__from_vocabulary, sizeof(__pyx_k__from_vocabulary), 0, 0, 1, 1},
   {&__pyx_n_s__frontier, __pyx_k__frontier, sizeof(__pyx_k__frontier), 0, 0, 1, 1},
   {&__pyx_n_s__fsample_count, __pyx_k__fsample_count, sizeof(__pyx_k__fsample_count), 0, 0, 1, 1},
   {&__pyx_n_s__fsarray, __pyx_k__fsarray, sizeof(__pyx_k__fsarray), 0, 0, 1, 1},
@@ -66428,6 +67108,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__fwords, __pyx_k__fwords, sizeof(__pyx_k__fwords), 0, 0, 1, 1},
   {&__pyx_n_s__gc, __pyx_k__gc, sizeof(__pyx_k__gc), 0, 0, 1, 1},
   {&__pyx_n_s__genexpr, __pyx_k__genexpr, sizeof(__pyx_k__genexpr), 0, 0, 1, 1},
+  {&__pyx_n_s__get, __pyx_k__get, sizeof(__pyx_k__get), 0, 0, 1, 1},
   {&__pyx_n_s__getLogger, __pyx_k__getLogger, sizeof(__pyx_k__getLogger), 0, 0, 1, 1},
   {&__pyx_n_s__get_e_id, __pyx_k__get_e_id, sizeof(__pyx_k__get_e_id), 0, 0, 1, 1},
   {&__pyx_n_s__get_f_id, __pyx_k__get_f_id, sizeof(__pyx_k__get_f_id), 0, 0, 1, 1},
@@ -66477,6 +67158,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__meta, __pyx_k__meta, sizeof(__pyx_k__meta), 0, 0, 1, 1},
   {&__pyx_n_s__min_dist, __pyx_k__min_dist, sizeof(__pyx_k__min_dist), 0, 0, 1, 1},
   {&__pyx_n_s__min_gap_size, __pyx_k__min_gap_size, sizeof(__pyx_k__min_gap_size), 0, 0, 1, 1},
+  {&__pyx_n_s__mmaped, __pyx_k__mmaped, sizeof(__pyx_k__mmaped), 0, 0, 1, 1},
   {&__pyx_n_s__name, __pyx_k__name, sizeof(__pyx_k__name), 0, 0, 1, 1},
   {&__pyx_n_s__namedtuple, __pyx_k__namedtuple, sizeof(__pyx_k__namedtuple), 0, 0, 1, 1},
   {&__pyx_n_s__next_states, __pyx_k__next_states, sizeof(__pyx_k__next_states), 0, 0, 1, 1},
@@ -66485,7 +67167,6 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__open, __pyx_k__open, sizeof(__pyx_k__open), 0, 0, 1, 1},
   {&__pyx_n_s__pad, __pyx_k__pad, sizeof(__pyx_k__pad), 0, 0, 1, 1},
   {&__pyx_n_s__paircount, __pyx_k__paircount, sizeof(__pyx_k__paircount), 0, 0, 1, 1},
-  {&__pyx_n_s__partition, __pyx_k__partition, sizeof(__pyx_k__partition), 0, 0, 1, 1},
   {&__pyx_n_s__pathlen, __pyx_k__pathlen, sizeof(__pyx_k__pathlen), 0, 0, 1, 1},
   {&__pyx_n_s__pattern2phrase, __pyx_k__pattern2phrase, sizeof(__pyx_k__pattern2phrase), 0, 0, 1, 1},
   {&__pyx_n_s__pattern2phrase_plus, __pyx_k__pattern2phrase_plus, sizeof(__pyx_k__pattern2phrase_plus), 0, 0, 1, 1},
@@ -66501,6 +67182,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__reachable_buffer, __pyx_k__reachable_buffer, sizeof(__pyx_k__reachable_buffer), 0, 0, 1, 1},
   {&__pyx_n_s__read_binary, __pyx_k__read_binary, sizeof(__pyx_k__read_binary), 0, 0, 1, 1},
   {&__pyx_n_s__read_bitext, __pyx_k__read_bitext, sizeof(__pyx_k__read_bitext), 0, 0, 1, 1},
+  {&__pyx_n_s__read_mmaped, __pyx_k__read_mmaped, sizeof(__pyx_k__read_mmaped), 0, 0, 1, 1},
   {&__pyx_n_s__read_text, __pyx_k__read_text, sizeof(__pyx_k__read_text), 0, 0, 1, 1},
   {&__pyx_n_s__read_text_data, __pyx_k__read_text_data, sizeof(__pyx_k__read_text_data), 0, 0, 1, 1},
   {&__pyx_n_s__res, __pyx_k__res, sizeof(__pyx_k__res), 0, 0, 1, 1},
@@ -66554,13 +67236,14 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
 };
 static int __Pyx_InitCachedBuiltins(void) {
   __pyx_builtin_open = __Pyx_GetName(__pyx_b, __pyx_n_s__open); if (!__pyx_builtin_open) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_IndexError = __Pyx_GetName(__pyx_b, __pyx_n_s__IndexError); if (!__pyx_builtin_IndexError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_TypeError = __Pyx_GetName(__pyx_b, __pyx_n_s__TypeError); if (!__pyx_builtin_TypeError) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_IndexError = __Pyx_GetName(__pyx_b, __pyx_n_s__IndexError); if (!__pyx_builtin_IndexError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 29; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_TypeError = __Pyx_GetName(__pyx_b, __pyx_n_s__TypeError); if (!__pyx_builtin_TypeError) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_enumerate = __Pyx_GetName(__pyx_b, __pyx_n_s__enumerate); if (!__pyx_builtin_enumerate) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 79; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_map = __Pyx_GetName(__pyx_b, __pyx_n_s__map); if (!__pyx_builtin_map) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_Exception = __Pyx_GetName(__pyx_b, __pyx_n_s__Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 123; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_zip = __Pyx_GetName(__pyx_b, __pyx_n_s__zip); if (!__pyx_builtin_zip) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 363; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_map = __Pyx_GetName(__pyx_b, __pyx_n_s__map); if (!__pyx_builtin_map) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_Exception = __Pyx_GetName(__pyx_b, __pyx_n_s__Exception); if (!__pyx_builtin_Exception) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 113; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_zip = __Pyx_GetName(__pyx_b, __pyx_n_s__zip); if (!__pyx_builtin_zip) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 323; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_StopIteration = __Pyx_GetName(__pyx_b, __pyx_n_s__StopIteration); if (!__pyx_builtin_StopIteration) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_cmp = __Pyx_GetName(__pyx_b, __pyx_n_s__cmp); if (!__pyx_builtin_cmp) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 173; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_builtin_sorted = __Pyx_GetName(__pyx_b, __pyx_n_s__sorted); if (!__pyx_builtin_sorted) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 931; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -66574,223 +67257,223 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":20
- *         self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":23
+ *         self.voc = Vocabulary()
+ *         self.voc.extend(INIT_VOCABULARY)
  *         self.data = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_id = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)
  */
-  __pyx_k_tuple_10 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_10);
+  __pyx_k_tuple_9 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_9)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_9);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_9, 0, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_10, 1, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_9, 1, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_9));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":21
- *         self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":24
+ *         self.voc.extend(INIT_VOCABULARY)
  *         self.data = IntList(1000,1000)
  *         self.sent_id = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_index = IntList(1000,1000)
  *         self.use_sent_id = use_sent_id
  */
-  __pyx_k_tuple_11 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_11);
+  __pyx_k_tuple_10 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 24; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_10);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_11, 0, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_11, 1, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_10, 1, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_11));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":22
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":25
  *         self.data = IntList(1000,1000)
  *         self.sent_id = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.use_sent_id = use_sent_id
  *         if from_binary:
  */
-  __pyx_k_tuple_12 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_12)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 22; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_12);
+  __pyx_k_tuple_11 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_11)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_11);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_12, 0, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_11, 0, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
   __Pyx_INCREF(__pyx_int_1000);
-  PyTuple_SET_ITEM(__pyx_k_tuple_12, 1, __pyx_int_1000);
+  PyTuple_SET_ITEM(__pyx_k_tuple_11, 1, __pyx_int_1000);
   __Pyx_GIVEREF(__pyx_int_1000);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_12));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_11));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":66
  *                     f.write("%s " % self.get_word(w_id))
  *                 if w_id == 1:
  *                     f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  */
-  __pyx_k_tuple_15 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_15)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_15);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_15, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_15));
+  __pyx_k_tuple_14 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_14);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":61
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for w_id in self.data:
  *                 if w_id > 1:
  */
-  __pyx_k_tuple_16 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_16);
+  __pyx_k_tuple_15 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_15)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 61; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_15);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_15, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_16, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_15, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_16, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_15, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_15));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":69
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             self.read_text_data(fp)
  * 
  */
-  __pyx_k_tuple_17 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_17)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_17);
+  __pyx_k_tuple_16 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_16)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_16);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_16, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_16, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_17, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_16, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_17));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_16));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":74
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:
  *             data = (line.split(' ||| ')[side] for line in fp)             # <<<<<<<<<<<<<<
  *             self.read_text_data(data)
  * 
  */
-  __pyx_k_tuple_19 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_19)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_19);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_18));
-  PyTuple_SET_ITEM(__pyx_k_tuple_19, 0, ((PyObject *)__pyx_kp_s_18));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_18));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_19));
+  __pyx_k_tuple_18 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_18)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_18);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_17));
+  PyTuple_SET_ITEM(__pyx_k_tuple_18, 0, ((PyObject *)__pyx_kp_s_17));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_17));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_18));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":73
  * 
- *     def read_bitext(self, char* filename, int side):
+ *     def read_bitext(self, bytes filename, int side):
  *         with gzip_or_text(filename) as fp:             # <<<<<<<<<<<<<<
  *             data = (line.split(' ||| ')[side] for line in fp)
  *             self.read_text_data(data)
  */
-  __pyx_k_tuple_20 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_20)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_20);
+  __pyx_k_tuple_19 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_19)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 73; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_19);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_19, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_19, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_19, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_20));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_19));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":144
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":128
  *         for i in self.data:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
  *         for i in self.sent_index:
  *             f.write("%d " %i)
  */
-  __pyx_k_tuple_22 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 144; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
+  __pyx_k_tuple_21 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_21)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 128; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_21);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_21, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_21));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":147
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":131
  *         for i in self.sent_index:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
  *         for i in self.sent_id:
  *             f.write("%d " %i)
  */
-  __pyx_k_tuple_23 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_23)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 147; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_23);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_23, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_23));
+  __pyx_k_tuple_22 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 131; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_22);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":150
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":134
  *         for i in self.sent_id:
  *             f.write("%d " %i)
  *         f.write("\n")             # <<<<<<<<<<<<<<
- *         for word in self.id2word:
- *             f.write("%s %d " % (word, self.word2id[word]))
- */
-  __pyx_k_tuple_24 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_24)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 150; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_24);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_24, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_24));
-
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":153
- *         for word in self.id2word:
- *             f.write("%s %d " % (word, self.word2id[word]))
+ *         for w, word in enumerate(self.voc.id2word):
+ *             f.write("%s %d " % (word, w))
+ */
+  __pyx_k_tuple_23 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_23)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 134; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_23);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_23, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_23));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":137
+ *         for w, word in enumerate(self.voc.id2word):
+ *             f.write("%s %d " % (word, w))
  *         f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  */
-  __pyx_k_tuple_26 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_26)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 153; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_26);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_26, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_26));
+  __pyx_k_tuple_25 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_25)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 137; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_25);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_25, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_25));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":156
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":140
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.write_enhanced_handle(self, f)
  */
-  __pyx_k_tuple_28 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_28)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 156; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_28);
+  __pyx_k_tuple_27 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_27)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 140; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_27);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_28, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_27, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_28, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_27, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_28, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_27, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_28));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_27));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":46
  * 
- *     def __cinit__(self, from_binary=None, from_text=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
  *         self.links = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         self.sent_index = IntList(1000,1000)
  *         if from_binary:
@@ -66806,11 +67489,11 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_29));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":47
- *     def __cinit__(self, from_binary=None, from_text=None):
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
  *         self.links = IntList(1000,1000)
  *         self.sent_index = IntList(1000,1000)             # <<<<<<<<<<<<<<
  *         if from_binary:
- *             self.read_binary(from_binary)
+ *             if mmaped:
  */
   __pyx_k_tuple_30 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_30)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_30);
@@ -66822,28 +67505,28 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GIVEREF(__pyx_int_1000);
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_30));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":59
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":62
  *                 pairs = line.split()
  *                 for pair in pairs:
  *                     (i, j) = map(int, pair.split('-'))             # <<<<<<<<<<<<<<
  *                     self.links.append(self.link(i, j))
  *             self.sent_index.append(len(self.links))
  */
-  __pyx_k_tuple_32 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_32)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_32 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_32)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_32);
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_31));
   PyTuple_SET_ITEM(__pyx_k_tuple_32, 0, ((PyObject *)__pyx_kp_s_31));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_31));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_32));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":54
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":57
  * 
- *     def read_text(self, char* filename):
+ *     def read_text(self, bytes filename):
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
  *             for line in f:
  *                 self.sent_index.append(len(self.links))
  */
-  __pyx_k_tuple_33 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_33)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_33 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_33)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_33);
   __Pyx_INCREF(Py_None);
   PyTuple_SET_ITEM(__pyx_k_tuple_33, 0, Py_None);
@@ -66856,42 +67539,42 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GIVEREF(Py_None);
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_33));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":75
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":82
  *             for i, link in enumerate(self.links):
  *                 while i >= self.sent_index[sent_num]:
  *                     f.write("\n")             # <<<<<<<<<<<<<<
  *                     sent_num = sent_num + 1
  *                 f.write("%d-%d " % self.unlink(link))
  */
-  __pyx_k_tuple_34 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_34)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_34 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_34)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_34);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_34, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_34, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_34));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":78
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":85
  *                     sent_num = sent_num + 1
  *                 f.write("%d-%d " % self.unlink(link))
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
- *     def write_binary(self, char* filename):
+ *     def write_binary(self, bytes filename):
  */
-  __pyx_k_tuple_36 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_36)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_36 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_36)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 85; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_36);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_36, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_36, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_36));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":71
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":78
  * 
- *     def write_text(self, char* filename):
+ *     def write_text(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 0
  *             for i, link in enumerate(self.links):
  */
-  __pyx_k_tuple_37 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_37)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 71; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_37 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_37)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 78; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_37);
   __Pyx_INCREF(Py_None);
   PyTuple_SET_ITEM(__pyx_k_tuple_37, 0, Py_None);
@@ -66904,42 +67587,42 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GIVEREF(Py_None);
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_37));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":92
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":99
  *             for link in self.links:
  *                 f.write("%d " % link)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for i in self.sent_index:
  *                 f.write("%d " % i)
  */
-  __pyx_k_tuple_38 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_38)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 92; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_38 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_38)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_38);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_38, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_38, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_38));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":95
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":102
  *             for i in self.sent_index:
  *                 f.write("%d " % i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  *     def alignment(self, i):
  */
-  __pyx_k_tuple_39 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_39)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_39 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_39)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 102; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_39);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_39, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_39, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_39));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":88
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":95
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             sent_num = 1
  *             for link in self.links:
  */
-  __pyx_k_tuple_40 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_40)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 88; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_40 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_40)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_40);
   __Pyx_INCREF(Py_None);
   PyTuple_SET_ITEM(__pyx_k_tuple_40, 0, Py_None);
@@ -66952,149 +67635,149 @@ static int __Pyx_InitCachedConstants(void) {
   __Pyx_GIVEREF(Py_None);
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_40));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":297
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":257
  * 
  *             # Re-read file, placing words into buckets
  *             f.seek(0)             # <<<<<<<<<<<<<<
  *             for line in f:
  *                 (fword, eword, score1, score2) = line.split()
  */
-  __pyx_k_tuple_43 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_43)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_43);
+  __pyx_k_tuple_44 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_44)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_44);
   __Pyx_INCREF(__pyx_int_0);
-  PyTuple_SET_ITEM(__pyx_k_tuple_43, 0, __pyx_int_0);
+  PyTuple_SET_ITEM(__pyx_k_tuple_44, 0, __pyx_int_0);
   __Pyx_GIVEREF(__pyx_int_0);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_43));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_44));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":273
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":233
  * 
  *         fcount = IntList()
  *         with gzip_or_text(filename) as f:             # <<<<<<<<<<<<<<
  *             # first loop merely establishes size of array objects
  *             for line in f:
  */
-  __pyx_k_tuple_44 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_44)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 273; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_44);
+  __pyx_k_tuple_45 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_45)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 233; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_45);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_44, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_45, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_44, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_45, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_44, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_45, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_44));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_45));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":339
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":299
  * 
  *         if i > j:
  *             raise Exception("Sort error in CLex")             # <<<<<<<<<<<<<<
  *         if i == j: #empty interval
  *             return
  */
-  __pyx_k_tuple_47 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_47)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 339; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_47 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_47)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 299; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_47);
   __Pyx_INCREF(((PyObject *)__pyx_kp_s_46));
   PyTuple_SET_ITEM(__pyx_k_tuple_47, 0, ((PyObject *)__pyx_kp_s_46));
   __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_46));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_47));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":362
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":322
  *             for i in self.f_index:
  *                 f.write("%d " % i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  *                 f.write("%d %f %f " % (i, s1, s2))
  */
-  __pyx_k_tuple_49 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_49)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_49);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_49, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_49));
+  __pyx_k_tuple_48 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_48)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 322; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_48);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_48, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_48));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":365
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":325
  *             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
  *                 f.write("%d %f %f " % (i, s1, s2))
  *             f.write("\n")             # <<<<<<<<<<<<<<
- *             for i, w in enumerate(self.id2fword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  */
-  __pyx_k_tuple_51 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_51)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 365; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_51);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_51, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_51));
+  __pyx_k_tuple_50 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_50)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 325; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_50);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_50, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_50));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":368
- *             for i, w in enumerate(self.id2fword):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":328
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")             # <<<<<<<<<<<<<<
- *             for i, w in enumerate(self.id2eword):
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  */
-  __pyx_k_tuple_53 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_53)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 368; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_53);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_53, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_53));
+  __pyx_k_tuple_52 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_52)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 328; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_52);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_52, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_52));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":371
- *             for i, w in enumerate(self.id2eword):
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":331
+ *             for i, w in enumerate(self.f_voc.id2word):
  *                 f.write("%d %s " % (i, w))
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  * 
  */
-  __pyx_k_tuple_54 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_54)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 371; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_54);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_54, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_54));
+  __pyx_k_tuple_53 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_53)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_53);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_53, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_53));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":359
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":319
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             for i in self.f_index:
  *                 f.write("%d " % i)
  */
-  __pyx_k_tuple_55 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_55)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 359; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_55);
+  __pyx_k_tuple_54 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_54)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 319; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_54);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_55, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_54, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_55, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_54, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_55, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_54, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_55));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_54));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":404
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":362
  *         cdef i, N, e_id, f_id
  * 
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             N = len(self.e_index)
  *             f_id = 0
  */
-  __pyx_k_tuple_57 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_57)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 404; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_57);
+  __pyx_k_tuple_56 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_56)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 362; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_56);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_57, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_56, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_57, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_56, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_57, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_56, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_57));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_56));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/lcp.pxi":13
  *         cdef IntList rank
@@ -67103,12 +67786,12 @@ static int __Pyx_InitCachedConstants(void) {
  *         self.sa = sa
  *         n = self.sa.sa.len
  */
-  __pyx_k_tuple_61 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_61)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_61);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_60));
-  PyTuple_SET_ITEM(__pyx_k_tuple_61, 0, ((PyObject *)__pyx_kp_s_60));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_60));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_61));
+  __pyx_k_tuple_62 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_62)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_62);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_61));
+  PyTuple_SET_ITEM(__pyx_k_tuple_62, 0, ((PyObject *)__pyx_kp_s_61));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_61));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_62));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/lcp.pxi":34
  *             if h > 0:
@@ -67117,172 +67800,172 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *     def compute_stats(self, int max_n):
  */
-  __pyx_k_tuple_63 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_63)) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_63);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_62));
-  PyTuple_SET_ITEM(__pyx_k_tuple_63, 0, ((PyObject *)__pyx_kp_s_62));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_62));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_63));
+  __pyx_k_tuple_64 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_64)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_64);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_63));
+  PyTuple_SET_ITEM(__pyx_k_tuple_64, 0, ((PyObject *)__pyx_kp_s_63));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_63));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_64));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":297
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":314
  *         pattern_rank = {}
  * 
  *         logger.info("Precomputing frequent intersections")             # <<<<<<<<<<<<<<
  *         cdef float start_time = monitor_cpu()
  * 
  */
-  __pyx_k_tuple_73 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_73)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 297; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_73);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_72));
-  PyTuple_SET_ITEM(__pyx_k_tuple_73, 0, ((PyObject *)__pyx_kp_s_72));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_72));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_73));
+  __pyx_k_tuple_75 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_75)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_75);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_74));
+  PyTuple_SET_ITEM(__pyx_k_tuple_75, 0, ((PyObject *)__pyx_kp_s_74));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_74));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_75));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":314
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":331
  *         queue = IntList(increment=1000)
  * 
  *         logger.info("    Computing inverted indexes...")             # <<<<<<<<<<<<<<
  *         N = len(data)
  *         for i from 0 <= i < N:
  */
-  __pyx_k_tuple_75 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_75)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 314; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_75);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_74));
-  PyTuple_SET_ITEM(__pyx_k_tuple_75, 0, ((PyObject *)__pyx_kp_s_74));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_74));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_75));
+  __pyx_k_tuple_77 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_77)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 331; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_77);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_76));
+  PyTuple_SET_ITEM(__pyx_k_tuple_77, 0, ((PyObject *)__pyx_kp_s_76));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_76));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_77));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":329
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":346
  *                     trie_node_data_append(node, i)
  * 
  *         logger.info("    Computing collocations...")             # <<<<<<<<<<<<<<
  *         N = len(queue)
  *         ptr1 = 0
  */
-  __pyx_k_tuple_77 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_77)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 329; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_77);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_76));
-  PyTuple_SET_ITEM(__pyx_k_tuple_77, 0, ((PyObject *)__pyx_kp_s_76));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_76));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_77));
+  __pyx_k_tuple_79 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_79)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 346; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_79);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_78));
+  PyTuple_SET_ITEM(__pyx_k_tuple_79, 0, ((PyObject *)__pyx_kp_s_78));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_78));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_79));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":393
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":410
  *             for pattern2 in J_set:
  *                 if len(pattern1) + len(pattern2) + 1 < self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     J2_set.add(combined_pattern)
  * 
  */
-  __pyx_k_tuple_79 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_79)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 393; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_79);
+  __pyx_k_tuple_81 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_81)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 410; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_81);
   __Pyx_INCREF(__pyx_int_neg_1);
-  PyTuple_SET_ITEM(__pyx_k_tuple_79, 0, __pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_k_tuple_81, 0, __pyx_int_neg_1);
   __Pyx_GIVEREF(__pyx_int_neg_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_79));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_81));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":400
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":417
  *                 x = x+1
  *                 if len(pattern1) + len(pattern2) + 1 <= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  * 
  */
-  __pyx_k_tuple_80 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_80)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 400; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_80);
+  __pyx_k_tuple_82 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_82)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_82);
   __Pyx_INCREF(__pyx_int_neg_1);
-  PyTuple_SET_ITEM(__pyx_k_tuple_80, 0, __pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_k_tuple_82, 0, __pyx_int_neg_1);
   __Pyx_GIVEREF(__pyx_int_neg_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_80));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_82));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":407
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":424
  *                 x = x+2
  *                 if len(pattern1) + len(pattern2) + 1<= self.max_length:
  *                     combined_pattern = pattern1 + (-1,) + pattern2             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  *                     combined_pattern = pattern2 + (-1,) + pattern1
  */
-  __pyx_k_tuple_81 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_81)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 407; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_81);
+  __pyx_k_tuple_83 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_83)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 424; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_83);
   __Pyx_INCREF(__pyx_int_neg_1);
-  PyTuple_SET_ITEM(__pyx_k_tuple_81, 0, __pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_k_tuple_83, 0, __pyx_int_neg_1);
   __Pyx_GIVEREF(__pyx_int_neg_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_81));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_83));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":409
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":426
  *                     combined_pattern = pattern1 + (-1,) + pattern2
  *                     IJ_set.add(combined_pattern)
  *                     combined_pattern = pattern2 + (-1,) + pattern1             # <<<<<<<<<<<<<<
  *                     IJ_set.add(combined_pattern)
  * 
  */
-  __pyx_k_tuple_82 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_82)) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 409; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_82);
+  __pyx_k_tuple_84 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_84)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 426; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_84);
   __Pyx_INCREF(__pyx_int_neg_1);
-  PyTuple_SET_ITEM(__pyx_k_tuple_82, 0, __pyx_int_neg_1);
+  PyTuple_SET_ITEM(__pyx_k_tuple_84, 0, __pyx_int_neg_1);
   __Pyx_GIVEREF(__pyx_int_neg_1);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_82));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_84));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":94
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":97
  * 
  *         '''Step 3: read off suffix array from inverse suffix array'''
  *         logger.info("    Finalizing sort...")             # <<<<<<<<<<<<<<
  *         for i from 0 <= i < N:
  *             j = isa.arr[i]
  */
-  __pyx_k_tuple_93 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_93)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_93);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_92));
-  PyTuple_SET_ITEM(__pyx_k_tuple_93, 0, ((PyObject *)__pyx_kp_s_92));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_92));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_93));
+  __pyx_k_tuple_96 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_96)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 97; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_96);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_95));
+  PyTuple_SET_ITEM(__pyx_k_tuple_96, 0, ((PyObject *)__pyx_kp_s_95));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_95));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_96));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":193
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":201
  *             for a_i in self.sa:
  *                 f.write("%d " % a_i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  *             for w_i in self.ha:
  *                 f.write("%d " % w_i)
  */
-  __pyx_k_tuple_96 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_96)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_96);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_96, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_96));
+  __pyx_k_tuple_100 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_100)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 201; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_100);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_100, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_100));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":196
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":204
  *             for w_i in self.ha:
  *                 f.write("%d " % w_i)
  *             f.write("\n")             # <<<<<<<<<<<<<<
  * 
  *     cdef int __search_high(self, int word_id, int offset, int low, int high):
  */
-  __pyx_k_tuple_97 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_97)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 196; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_97);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_14));
-  PyTuple_SET_ITEM(__pyx_k_tuple_97, 0, ((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_14));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_97));
+  __pyx_k_tuple_101 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_101)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 204; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_101);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_13));
+  PyTuple_SET_ITEM(__pyx_k_tuple_101, 0, ((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_13));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_101));
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":189
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":197
  * 
- *     def write_enhanced(self, char* filename):
+ *     def write_enhanced(self, bytes filename):
  *         with open(filename, "w") as f:             # <<<<<<<<<<<<<<
  *             self.darray.write_enhanced_handle(f)
  *             for a_i in self.sa:
  */
-  __pyx_k_tuple_98 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_98)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 189; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_98);
+  __pyx_k_tuple_102 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_102)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 197; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_102);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_98, 0, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_102, 0, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_98, 1, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_102, 1, Py_None);
   __Pyx_GIVEREF(Py_None);
   __Pyx_INCREF(Py_None);
-  PyTuple_SET_ITEM(__pyx_k_tuple_98, 2, Py_None);
+  PyTuple_SET_ITEM(__pyx_k_tuple_102, 2, Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_98));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_102));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":109
  *             logger.info("Sampling strategy: uniform, max sample size = %d", sample_size)
@@ -67291,12 +67974,12 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *     def sample(self, PhraseLocation phrase_location):
  */
-  __pyx_k_tuple_102 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_102)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_102);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_101));
-  PyTuple_SET_ITEM(__pyx_k_tuple_102, 0, ((PyObject *)__pyx_kp_s_101));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_101));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_102));
+  __pyx_k_tuple_106 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_106)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_106);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_105));
+  PyTuple_SET_ITEM(__pyx_k_tuple_106, 0, ((PyObject *)__pyx_kp_s_105));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_105));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_106));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":318
  *         self.rules.root = ExtendedTrieNode(phrase_location=PhraseLocation())
@@ -67305,12 +67988,12 @@ static int __Pyx_InitCachedConstants(void) {
  *         self.alignment = alignment
  * 
  */
-  __pyx_k_tuple_107 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_107)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_107);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_106));
-  PyTuple_SET_ITEM(__pyx_k_tuple_107, 0, ((PyObject *)__pyx_kp_s_106));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_106));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_107));
+  __pyx_k_tuple_111 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_111)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 318; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_111);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_110));
+  PyTuple_SET_ITEM(__pyx_k_tuple_111, 0, ((PyObject *)__pyx_kp_s_110));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_110));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_111));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":1018
  *                         else:
@@ -67319,12 +68002,12 @@ static int __Pyx_InitCachedConstants(void) {
  *                 # checking whether lookup_required
  *                 if lookup_required:
  */
-  __pyx_k_tuple_122 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_122)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1018; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_122);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_121));
-  PyTuple_SET_ITEM(__pyx_k_tuple_122, 0, ((PyObject *)__pyx_kp_s_121));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_121));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_122));
+  __pyx_k_tuple_126 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_126)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 1018; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_126);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_125));
+  PyTuple_SET_ITEM(__pyx_k_tuple_126, 0, ((PyObject *)__pyx_kp_s_125));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_125));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_126));
 
   /* "_sa.pyx":9
  *             resource.getrusage(resource.RUSAGE_SELF).ru_stime)
@@ -67333,30 +68016,47 @@ static int __Pyx_InitCachedConstants(void) {
  *     if filename.endswith('.gz'):
  *         return gzip.GzipFile(filename)
  */
-  __pyx_k_tuple_135 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_135)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_135);
+  __pyx_k_tuple_139 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_139)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_139);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__filename));
-  PyTuple_SET_ITEM(__pyx_k_tuple_135, 0, ((PyObject *)__pyx_n_s__filename));
+  PyTuple_SET_ITEM(__pyx_k_tuple_139, 0, ((PyObject *)__pyx_n_s__filename));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__filename));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__filename));
-  PyTuple_SET_ITEM(__pyx_k_tuple_135, 1, ((PyObject *)__pyx_n_s__filename));
+  PyTuple_SET_ITEM(__pyx_k_tuple_139, 1, ((PyObject *)__pyx_n_s__filename));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__filename));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_135));
-  __pyx_k_codeobj_136 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_135, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_137, __pyx_n_s__gzip_or_text, 9, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_136)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_139));
+  __pyx_k_codeobj_140 = (PyObject*)__Pyx_PyCode_New(1, 0, 2, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_139, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_141, __pyx_n_s__gzip_or_text, 9, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_140)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "_sa.pyx":15
  *         return open(filename)
  * 
  * logger = logging.getLogger('cdec.sa')             # <<<<<<<<<<<<<<
  * 
- * include "float_list.pxi"
+ * include "mmap.pxi"
  */
-  __pyx_k_tuple_139 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_139)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_139);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_s_138));
-  PyTuple_SET_ITEM(__pyx_k_tuple_139, 0, ((PyObject *)__pyx_kp_s_138));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_138));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_139));
+  __pyx_k_tuple_143 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_143)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_143);
+  __Pyx_INCREF(((PyObject *)__pyx_kp_s_142));
+  PyTuple_SET_ITEM(__pyx_k_tuple_143, 0, ((PyObject *)__pyx_kp_s_142));
+  __Pyx_GIVEREF(((PyObject *)__pyx_kp_s_142));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_143));
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":10
+ * 
+ * # kept for compatibility
+ * INIT_VOCABULARY = ('NULL', 'END_OF_LINE')             # <<<<<<<<<<<<<<
+ * 
+ * cdef class DataArray:
+ */
+  __pyx_k_tuple_144 = PyTuple_New(2); if (unlikely(!__pyx_k_tuple_144)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_144);
+  __Pyx_INCREF(((PyObject *)__pyx_n_s__NULL));
+  PyTuple_SET_ITEM(__pyx_k_tuple_144, 0, ((PyObject *)__pyx_n_s__NULL));
+  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__NULL));
+  __Pyx_INCREF(((PyObject *)__pyx_n_s__END_OF_LINE));
+  PyTuple_SET_ITEM(__pyx_k_tuple_144, 1, ((PyObject *)__pyx_n_s__END_OF_LINE));
+  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__END_OF_LINE));
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_144));
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":107
  *     return ALPHABET.fromstring(string, terminal)
@@ -67365,25 +68065,25 @@ static int __Pyx_InitCachedConstants(void) {
  *     word_ids = (sym_fromstring(word, True) for word in words)
  *     return tuple(((word, None, 1), ) for word in word_ids)
  */
-  __pyx_k_tuple_140 = PyTuple_New(5); if (unlikely(!__pyx_k_tuple_140)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_140);
+  __pyx_k_tuple_145 = PyTuple_New(5); if (unlikely(!__pyx_k_tuple_145)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_145);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__words));
-  PyTuple_SET_ITEM(__pyx_k_tuple_140, 0, ((PyObject *)__pyx_n_s__words));
+  PyTuple_SET_ITEM(__pyx_k_tuple_145, 0, ((PyObject *)__pyx_n_s__words));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__words));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__word_ids));
-  PyTuple_SET_ITEM(__pyx_k_tuple_140, 1, ((PyObject *)__pyx_n_s__word_ids));
+  PyTuple_SET_ITEM(__pyx_k_tuple_145, 1, ((PyObject *)__pyx_n_s__word_ids));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__word_ids));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_140, 2, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_145, 2, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_140, 3, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_145, 3, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_140, 4, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_145, 4, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_140));
-  __pyx_k_codeobj_141 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_140, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_142, __pyx_n_s__make_lattice, 107, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_141)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_145));
+  __pyx_k_codeobj_146 = (PyObject*)__Pyx_PyCode_New(1, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_145, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_147, __pyx_n_s__make_lattice, 107, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_146)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":111
  *     return tuple(((word, None, 1), ) for word in word_ids)
@@ -67392,19 +68092,19 @@ static int __Pyx_InitCachedConstants(void) {
  *     return tuple((sym_tostring(sym), weight, dist) for (sym, weight, dist) in arc
  *             for arc in node for node in lattice)
  */
-  __pyx_k_tuple_143 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_143)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_143);
+  __pyx_k_tuple_148 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_148)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_148);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__lattice));
-  PyTuple_SET_ITEM(__pyx_k_tuple_143, 0, ((PyObject *)__pyx_n_s__lattice));
+  PyTuple_SET_ITEM(__pyx_k_tuple_148, 0, ((PyObject *)__pyx_n_s__lattice));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__lattice));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_143, 1, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_148, 1, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_143, 2, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_148, 2, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_143));
-  __pyx_k_codeobj_144 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_143, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_142, __pyx_n_s__decode_lattice, 111, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_144)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_148));
+  __pyx_k_codeobj_149 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_148, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_147, __pyx_n_s__decode_lattice, 111, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_149)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":115
  *             for arc in node for node in lattice)
@@ -67412,19 +68112,19 @@ static int __Pyx_InitCachedConstants(void) {
  * def decode_sentence(lattice):             # <<<<<<<<<<<<<<
  *     return tuple(sym_tostring(sym) for ((sym, _, _),) in lattice)
  */
-  __pyx_k_tuple_145 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_145)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __Pyx_GOTREF(__pyx_k_tuple_145);
+  __pyx_k_tuple_150 = PyTuple_New(3); if (unlikely(!__pyx_k_tuple_150)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_k_tuple_150);
   __Pyx_INCREF(((PyObject *)__pyx_n_s__lattice));
-  PyTuple_SET_ITEM(__pyx_k_tuple_145, 0, ((PyObject *)__pyx_n_s__lattice));
+  PyTuple_SET_ITEM(__pyx_k_tuple_150, 0, ((PyObject *)__pyx_n_s__lattice));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__lattice));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_145, 1, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_150, 1, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
   __Pyx_INCREF(((PyObject *)__pyx_n_s__genexpr));
-  PyTuple_SET_ITEM(__pyx_k_tuple_145, 2, ((PyObject *)__pyx_n_s__genexpr));
+  PyTuple_SET_ITEM(__pyx_k_tuple_150, 2, ((PyObject *)__pyx_n_s__genexpr));
   __Pyx_GIVEREF(((PyObject *)__pyx_n_s__genexpr));
-  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_145));
-  __pyx_k_codeobj_146 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_145, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_142, __pyx_n_s__decode_sentence, 115, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_146)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_150));
+  __pyx_k_codeobj_151 = (PyObject*)__Pyx_PyCode_New(1, 0, 3, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_150, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_147, __pyx_n_s__decode_sentence, 115, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_151)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -67521,10 +68221,20 @@ PyMODINIT_FUNC PyInit__sa(void)
   if (__Pyx_ExportFunction("sym_isvar", (void (*)(void))__pyx_f_3_sa_sym_isvar, "int (int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_ExportFunction("sym_getindex", (void (*)(void))__pyx_f_3_sa_sym_getindex, "int (int)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   /*--- Type init code ---*/
+  __pyx_vtabptr_3_sa_MemoryMap = &__pyx_vtable_3_sa_MemoryMap;
+  __pyx_vtable_3_sa_MemoryMap.read_int = (int (*)(struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_9MemoryMap_read_int;
+  __pyx_vtable_3_sa_MemoryMap.read_int_array = (int *(*)(struct __pyx_obj_3_sa_MemoryMap *, int))__pyx_f_3_sa_9MemoryMap_read_int_array;
+  __pyx_vtable_3_sa_MemoryMap.read_char_array = (char *(*)(struct __pyx_obj_3_sa_MemoryMap *, int))__pyx_f_3_sa_9MemoryMap_read_char_array;
+  __pyx_vtable_3_sa_MemoryMap.read_float_array = (float *(*)(struct __pyx_obj_3_sa_MemoryMap *, int))__pyx_f_3_sa_9MemoryMap_read_float_array;
+  if (PyType_Ready(&__pyx_type_3_sa_MemoryMap) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_MemoryMap.tp_dict, __pyx_vtabptr_3_sa_MemoryMap) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "MemoryMap", (PyObject *)&__pyx_type_3_sa_MemoryMap) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_3_sa_MemoryMap = &__pyx_type_3_sa_MemoryMap;
   __pyx_vtabptr_3_sa_FloatList = &__pyx_vtable_3_sa_FloatList;
   __pyx_vtable_3_sa_FloatList.set = (void (*)(struct __pyx_obj_3_sa_FloatList *, int, float))__pyx_f_3_sa_9FloatList_set;
   __pyx_vtable_3_sa_FloatList.write_handle = (void (*)(struct __pyx_obj_3_sa_FloatList *, FILE *))__pyx_f_3_sa_9FloatList_write_handle;
   __pyx_vtable_3_sa_FloatList.read_handle = (void (*)(struct __pyx_obj_3_sa_FloatList *, FILE *))__pyx_f_3_sa_9FloatList_read_handle;
+  __pyx_vtable_3_sa_FloatList.read_mmaped = (void (*)(struct __pyx_obj_3_sa_FloatList *, struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_9FloatList_read_mmaped;
   if (PyType_Ready(&__pyx_type_3_sa_FloatList) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetVtable(__pyx_type_3_sa_FloatList.tp_dict, __pyx_vtabptr_3_sa_FloatList) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "FloatList", (PyObject *)&__pyx_type_3_sa_FloatList) < 0) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -67532,17 +68242,17 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_vtabptr_3_sa_IntList = &__pyx_vtable_3_sa_IntList;
   __pyx_vtable_3_sa_IntList.set = (void (*)(struct __pyx_obj_3_sa_IntList *, int, int))__pyx_f_3_sa_7IntList_set;
   __pyx_vtable_3_sa_IntList._append = (void (*)(struct __pyx_obj_3_sa_IntList *, int))__pyx_f_3_sa_7IntList__append;
-  __pyx_vtable_3_sa_IntList._extend = (void (*)(struct __pyx_obj_3_sa_IntList *, struct __pyx_obj_3_sa_IntList *))__pyx_f_3_sa_7IntList__extend;
   __pyx_vtable_3_sa_IntList._extend_arr = (void (*)(struct __pyx_obj_3_sa_IntList *, int *, int))__pyx_f_3_sa_7IntList__extend_arr;
   __pyx_vtable_3_sa_IntList._clear = (void (*)(struct __pyx_obj_3_sa_IntList *))__pyx_f_3_sa_7IntList__clear;
   __pyx_vtable_3_sa_IntList.write_handle = (void (*)(struct __pyx_obj_3_sa_IntList *, FILE *))__pyx_f_3_sa_7IntList_write_handle;
   __pyx_vtable_3_sa_IntList.read_handle = (void (*)(struct __pyx_obj_3_sa_IntList *, FILE *))__pyx_f_3_sa_7IntList_read_handle;
+  __pyx_vtable_3_sa_IntList.read_mmaped = (void (*)(struct __pyx_obj_3_sa_IntList *, struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_7IntList_read_mmaped;
   if (PyType_Ready(&__pyx_type_3_sa_IntList) < 0) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetVtable(__pyx_type_3_sa_IntList.tp_dict, __pyx_vtabptr_3_sa_IntList) < 0) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "IntList", (PyObject *)&__pyx_type_3_sa_IntList) < 0) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_IntList = &__pyx_type_3_sa_IntList;
-  if (PyType_Ready(&__pyx_type_3_sa_FeatureVector) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "FeatureVector", (PyObject *)&__pyx_type_3_sa_FeatureVector) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_FeatureVector) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "FeatureVector", (PyObject *)&__pyx_type_3_sa_FeatureVector) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_FeatureVector = &__pyx_type_3_sa_FeatureVector;
   __pyx_vtabptr_3_sa_Phrase = &__pyx_vtable_3_sa_Phrase;
   __pyx_vtable_3_sa_Phrase.chunkpos = (int (*)(struct __pyx_obj_3_sa_Phrase *, int))__pyx_f_3_sa_6Phrase_chunkpos;
@@ -67557,16 +68267,25 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_vtabptr_3_sa_StringMap = &__pyx_vtable_3_sa_StringMap;
   __pyx_vtable_3_sa_StringMap.word = (char *(*)(struct __pyx_obj_3_sa_StringMap *, int))__pyx_f_3_sa_9StringMap_word;
   __pyx_vtable_3_sa_StringMap.index = (int (*)(struct __pyx_obj_3_sa_StringMap *, char *))__pyx_f_3_sa_9StringMap_index;
-  if (PyType_Ready(&__pyx_type_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_StringMap.tp_dict, __pyx_vtabptr_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "StringMap", (PyObject *)&__pyx_type_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[16]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_StringMap.tp_dict, __pyx_vtabptr_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[16]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "StringMap", (PyObject *)&__pyx_type_3_sa_StringMap) < 0) {__pyx_filename = __pyx_f[16]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_StringMap = &__pyx_type_3_sa_StringMap;
+  __pyx_vtabptr_3_sa_Vocabulary = &__pyx_vtable_3_sa_Vocabulary;
+  __pyx_vtable_3_sa_Vocabulary.write_handle = (void (*)(struct __pyx_obj_3_sa_Vocabulary *, FILE *, struct __pyx_opt_args_3_sa_10Vocabulary_write_handle *__pyx_optional_args))__pyx_f_3_sa_10Vocabulary_write_handle;
+  __pyx_vtable_3_sa_Vocabulary.read_handle = (void (*)(struct __pyx_obj_3_sa_Vocabulary *, FILE *))__pyx_f_3_sa_10Vocabulary_read_handle;
+  __pyx_vtable_3_sa_Vocabulary.read_mmaped = (void (*)(struct __pyx_obj_3_sa_Vocabulary *, struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_10Vocabulary_read_mmaped;
+  if (PyType_Ready(&__pyx_type_3_sa_Vocabulary) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_Vocabulary.tp_dict, __pyx_vtabptr_3_sa_Vocabulary) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Vocabulary", (PyObject *)&__pyx_type_3_sa_Vocabulary) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_ptype_3_sa_Vocabulary = &__pyx_type_3_sa_Vocabulary;
   __pyx_vtabptr_3_sa_DataArray = &__pyx_vtable_3_sa_DataArray;
+  __pyx_vtable_3_sa_DataArray.read_mmaped = (void (*)(struct __pyx_obj_3_sa_DataArray *, struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_9DataArray_read_mmaped;
   __pyx_vtable_3_sa_DataArray.read_handle = (void (*)(struct __pyx_obj_3_sa_DataArray *, FILE *))__pyx_f_3_sa_9DataArray_read_handle;
   __pyx_vtable_3_sa_DataArray.write_handle = (void (*)(struct __pyx_obj_3_sa_DataArray *, FILE *))__pyx_f_3_sa_9DataArray_write_handle;
-  if (PyType_Ready(&__pyx_type_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_DataArray.tp_dict, __pyx_vtabptr_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "DataArray", (PyObject *)&__pyx_type_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_DataArray.tp_dict, __pyx_vtabptr_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "DataArray", (PyObject *)&__pyx_type_3_sa_DataArray) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_DataArray = &__pyx_type_3_sa_DataArray;
   __pyx_vtabptr_3_sa_Alignment = &__pyx_vtable_3_sa_Alignment;
   __pyx_vtable_3_sa_Alignment.link = (int (*)(struct __pyx_obj_3_sa_Alignment *, int, int))__pyx_f_3_sa_9Alignment_link;
@@ -67579,13 +68298,11 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_vtabptr_3_sa_BiLex = &__pyx_vtable_3_sa_BiLex;
   __pyx_vtable_3_sa_BiLex.compute_from_data = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, struct __pyx_obj_3_sa_SuffixArray *, struct __pyx_obj_3_sa_DataArray *, struct __pyx_obj_3_sa_Alignment *))__pyx_f_3_sa_5BiLex_compute_from_data;
   __pyx_vtable_3_sa_BiLex._add_node = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, struct __pyx_t_3_sa__node *, int *, float, int *))__pyx_f_3_sa_5BiLex__add_node;
-  __pyx_vtable_3_sa_BiLex.write_wordlist = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, PyObject *, FILE *))__pyx_f_3_sa_5BiLex_write_wordlist;
-  __pyx_vtable_3_sa_BiLex.read_wordlist = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, PyObject *, PyObject *, FILE *))__pyx_f_3_sa_5BiLex_read_wordlist;
   __pyx_vtable_3_sa_BiLex.swap = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, int, int))__pyx_f_3_sa_5BiLex_swap;
-  __pyx_vtable_3_sa_BiLex.qsort = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, int, int, PyObject *))__pyx_f_3_sa_5BiLex_qsort;
-  if (PyType_Ready(&__pyx_type_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_BiLex.tp_dict, __pyx_vtabptr_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "BiLex", (PyObject *)&__pyx_type_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 47; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtable_3_sa_BiLex.qsort = (PyObject *(*)(struct __pyx_obj_3_sa_BiLex *, int, int))__pyx_f_3_sa_5BiLex_qsort;
+  if (PyType_Ready(&__pyx_type_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_BiLex.tp_dict, __pyx_vtabptr_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "BiLex", (PyObject *)&__pyx_type_3_sa_BiLex) < 0) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 48; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_BiLex = &__pyx_type_3_sa_BiLex;
   if (PyType_Ready(&__pyx_type_3_sa_BitSetIterator) < 0) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "BitSetIterator", (PyObject *)&__pyx_type_3_sa_BitSetIterator) < 0) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -67604,8 +68321,8 @@ PyMODINIT_FUNC PyInit__sa(void)
   if (__Pyx_SetVtable(__pyx_type_3_sa_VEB.tp_dict, __pyx_vtabptr_3_sa_VEB) < 0) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "VEB", (PyObject *)&__pyx_type_3_sa_VEB) < 0) {__pyx_filename = __pyx_f[6]; __pyx_lineno = 354; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_VEB = &__pyx_type_3_sa_VEB;
-  if (PyType_Ready(&__pyx_type_3_sa_LCP) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "LCP", (PyObject *)&__pyx_type_3_sa_LCP) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_LCP) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "LCP", (PyObject *)&__pyx_type_3_sa_LCP) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_LCP = &__pyx_type_3_sa_LCP;
   __pyx_vtabptr_3_sa_Alphabet = &__pyx_vtable_3_sa_Alphabet;
   __pyx_vtable_3_sa_Alphabet.isvar = (int (*)(struct __pyx_obj_3_sa_Alphabet *, int))__pyx_f_3_sa_8Alphabet_isvar;
@@ -67618,32 +68335,33 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_vtable_3_sa_Alphabet.fromcat = (int (*)(struct __pyx_obj_3_sa_Alphabet *, char *))__pyx_f_3_sa_8Alphabet_fromcat;
   __pyx_vtable_3_sa_Alphabet.tostring = (char *(*)(struct __pyx_obj_3_sa_Alphabet *, int))__pyx_f_3_sa_8Alphabet_tostring;
   __pyx_vtable_3_sa_Alphabet.fromstring = (int (*)(struct __pyx_obj_3_sa_Alphabet *, char *, int))__pyx_f_3_sa_8Alphabet_fromstring;
-  if (PyType_Ready(&__pyx_type_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_Alphabet.tp_dict, __pyx_vtabptr_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Alphabet", (PyObject *)&__pyx_type_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_Alphabet.tp_dict, __pyx_vtabptr_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Alphabet", (PyObject *)&__pyx_type_3_sa_Alphabet) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_Alphabet = &__pyx_type_3_sa_Alphabet;
   __pyx_vtabptr_3_sa_TrieMap = &__pyx_vtable_3_sa_TrieMap;
   __pyx_vtable_3_sa_TrieMap._insert = (struct __pyx_t_3_sa__Trie_Node *(*)(struct __pyx_obj_3_sa_TrieMap *, int *, int))__pyx_f_3_sa_7TrieMap__insert;
   __pyx_vtable_3_sa_TrieMap._contains = (struct __pyx_t_3_sa__Trie_Node *(*)(struct __pyx_obj_3_sa_TrieMap *, int *, int))__pyx_f_3_sa_7TrieMap__contains;
-  if (PyType_Ready(&__pyx_type_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_TrieMap.tp_dict, __pyx_vtabptr_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "TrieMap", (PyObject *)&__pyx_type_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_TrieMap.tp_dict, __pyx_vtabptr_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "TrieMap", (PyObject *)&__pyx_type_3_sa_TrieMap) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_TrieMap = &__pyx_type_3_sa_TrieMap;
   __pyx_vtabptr_3_sa_Precomputation = &__pyx_vtable_3_sa_Precomputation;
-  __pyx_vtable_3_sa_Precomputation.read_map = (PyObject *(*)(struct __pyx_obj_3_sa_Precomputation *, FILE *))__pyx_f_3_sa_14Precomputation_read_map;
   __pyx_vtable_3_sa_Precomputation.write_map = (PyObject *(*)(struct __pyx_obj_3_sa_Precomputation *, PyObject *, FILE *))__pyx_f_3_sa_14Precomputation_write_map;
-  if (PyType_Ready(&__pyx_type_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_Precomputation.tp_dict, __pyx_vtabptr_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Precomputation", (PyObject *)&__pyx_type_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 188; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_vtable_3_sa_Precomputation.read_map = (PyObject *(*)(struct __pyx_obj_3_sa_Precomputation *, FILE *))__pyx_f_3_sa_14Precomputation_read_map;
+  __pyx_vtable_3_sa_Precomputation.read_mmaped_map = (PyObject *(*)(struct __pyx_obj_3_sa_Precomputation *, struct __pyx_obj_3_sa_MemoryMap *))__pyx_f_3_sa_14Precomputation_read_mmaped_map;
+  if (PyType_Ready(&__pyx_type_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_Precomputation.tp_dict, __pyx_vtabptr_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Precomputation", (PyObject *)&__pyx_type_3_sa_Precomputation) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 183; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_Precomputation = &__pyx_type_3_sa_Precomputation;
   __pyx_vtabptr_3_sa_SuffixArray = &__pyx_vtable_3_sa_SuffixArray;
   __pyx_vtable_3_sa_SuffixArray.__pyx___search_high = (int (*)(struct __pyx_obj_3_sa_SuffixArray *, int, int, int, int))__pyx_f_3_sa_11SuffixArray___search_high;
   __pyx_vtable_3_sa_SuffixArray.__pyx___search_low = (int (*)(struct __pyx_obj_3_sa_SuffixArray *, int, int, int, int))__pyx_f_3_sa_11SuffixArray___search_low;
   __pyx_vtable_3_sa_SuffixArray.__pyx___get_range = (PyObject *(*)(struct __pyx_obj_3_sa_SuffixArray *, int, int, int, int, int))__pyx_f_3_sa_11SuffixArray___get_range;
   __pyx_vtable_3_sa_SuffixArray.__pyx___lookup_helper = (PyObject *(*)(struct __pyx_obj_3_sa_SuffixArray *, int, int, int, int))__pyx_f_3_sa_11SuffixArray___lookup_helper;
-  if (PyType_Ready(&__pyx_type_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_SuffixArray.tp_dict, __pyx_vtabptr_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "SuffixArray", (PyObject *)&__pyx_type_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_SuffixArray.tp_dict, __pyx_vtabptr_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "SuffixArray", (PyObject *)&__pyx_type_3_sa_SuffixArray) < 0) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_SuffixArray = &__pyx_type_3_sa_SuffixArray;
   if (PyType_Ready(&__pyx_type_3_sa_TrieNode) < 0) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__Pyx_SetAttrString(__pyx_m, "TrieNode", (PyObject *)&__pyx_type_3_sa_TrieNode) < 0) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -67686,31 +68404,31 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_ptype_3_sa_HieroCachingRuleFactory = &__pyx_type_3_sa_HieroCachingRuleFactory;
   __pyx_vtabptr_3_sa_Scorer = &__pyx_vtable_3_sa_Scorer;
   __pyx_vtable_3_sa_Scorer.score = (struct __pyx_obj_3_sa_FeatureVector *(*)(struct __pyx_obj_3_sa_Scorer *, PyObject *))__pyx_f_3_sa_6Scorer_score;
-  if (PyType_Ready(&__pyx_type_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetVtable(__pyx_type_3_sa_Scorer.tp_dict, __pyx_vtabptr_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (__Pyx_SetAttrString(__pyx_m, "Scorer", (PyObject *)&__pyx_type_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetVtable(__pyx_type_3_sa_Scorer.tp_dict, __pyx_vtabptr_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (__Pyx_SetAttrString(__pyx_m, "Scorer", (PyObject *)&__pyx_type_3_sa_Scorer) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa_Scorer = &__pyx_type_3_sa_Scorer;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct____iter__) < 0) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 81; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct____iter__) < 0) {__pyx_filename = __pyx_f[2]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct____iter__ = &__pyx_type_3_sa___pyx_scope_struct____iter__;
   if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_1_read_bitext) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_1_read_bitext = &__pyx_type_3_sa___pyx_scope_struct_1_read_bitext;
   if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_2_genexpr) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 74; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_2_genexpr = &__pyx_type_3_sa___pyx_scope_struct_2_genexpr;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_3_compute_stats) < 0) {__pyx_filename = __pyx_f[9]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_3_compute_stats) < 0) {__pyx_filename = __pyx_f[11]; __pyx_lineno = 36; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_3_compute_stats = &__pyx_type_3_sa___pyx_scope_struct_3_compute_stats;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_4_make_lattice) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_4_make_lattice) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_4_make_lattice = &__pyx_type_3_sa___pyx_scope_struct_4_make_lattice;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_5_genexpr) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_5_genexpr) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 108; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_5_genexpr = &__pyx_type_3_sa___pyx_scope_struct_5_genexpr;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_6_genexpr) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_6_genexpr) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 109; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_6_genexpr = &__pyx_type_3_sa___pyx_scope_struct_6_genexpr;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_7_decode_lattice) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_7_decode_lattice) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_7_decode_lattice = &__pyx_type_3_sa___pyx_scope_struct_7_decode_lattice;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_8_genexpr) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_8_genexpr) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 112; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_8_genexpr = &__pyx_type_3_sa___pyx_scope_struct_8_genexpr;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_9_decode_sentence) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_9_decode_sentence) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_9_decode_sentence = &__pyx_type_3_sa___pyx_scope_struct_9_decode_sentence;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_10_genexpr) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_10_genexpr) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_10_genexpr = &__pyx_type_3_sa___pyx_scope_struct_10_genexpr;
   if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_11___iter__) < 0) {__pyx_filename = __pyx_f[7]; __pyx_lineno = 141; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_11___iter__ = &__pyx_type_3_sa___pyx_scope_struct_11___iter__;
@@ -67722,11 +68440,11 @@ PyMODINIT_FUNC PyInit__sa(void)
   __pyx_ptype_3_sa___pyx_scope_struct_14_alignments = &__pyx_type_3_sa___pyx_scope_struct_14_alignments;
   if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_15_input) < 0) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 933; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_15_input = &__pyx_type_3_sa___pyx_scope_struct_15_input;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_16___iter__) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_16___iter__) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_16___iter__ = &__pyx_type_3_sa___pyx_scope_struct_16___iter__;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_17___str__) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_17___str__) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_17___str__ = &__pyx_type_3_sa___pyx_scope_struct_17___str__;
-  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_18_genexpr) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyType_Ready(&__pyx_type_3_sa___pyx_scope_struct_18_genexpr) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_ptype_3_sa___pyx_scope_struct_18_genexpr = &__pyx_type_3_sa___pyx_scope_struct_18_genexpr;
   /*--- Type import code ---*/
   /*--- Variable import code ---*/
@@ -67783,32 +68501,89 @@ PyMODINIT_FUNC PyInit__sa(void)
  * 
  * logger = logging.getLogger('cdec.sa')             # <<<<<<<<<<<<<<
  * 
- * include "float_list.pxi"
+ * include "mmap.pxi"
  */
   __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__logging); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_t_2 = PyObject_GetAttr(__pyx_t_1, __pyx_n_s__getLogger); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_139), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_k_tuple_143), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   if (PyObject_SetAttr(__pyx_m, __pyx_n_s__logger, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":54
- *     cdef id2eword, id2fword, eword2id, fword2id
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":10
+ * 
+ * # kept for compatibility
+ * INIT_VOCABULARY = ('NULL', 'END_OF_LINE')             # <<<<<<<<<<<<<<
+ * 
+ * cdef class DataArray:
+ */
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__INIT_VOCABULARY, ((PyObject *)__pyx_k_tuple_144)) < 0) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/data_array.pxi":20
+ * 
+ *     def __cinit__(self, from_binary=None, from_text=None, side=None,
+ *             bint use_sent_id=False, mmaped=False):             # <<<<<<<<<<<<<<
+ *         self.voc = Vocabulary()
+ *         self.voc.extend(INIT_VOCABULARY)
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[3]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_k_8 = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/alignment.pxi":45
+ *         return sent_links
+ * 
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False):             # <<<<<<<<<<<<<<
+ *         self.links = IntList(1000,1000)
+ *         self.sent_index = IntList(1000,1000)
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[4]; __pyx_lineno = 45; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_k_28 = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":46
+ *         return get_val(n.bigger, key)
+ * 
+ * cdef int NULL_WORD = 0             # <<<<<<<<<<<<<<
+ * 
+ * cdef class BiLex:
+ */
+  __pyx_v_3_sa_NULL_WORD = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":53
+ *     cdef Vocabulary f_voc, e_voc
  * 
  *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,             # <<<<<<<<<<<<<<
- *             earray=None, fsarray=None, alignment=None):
- *         self.id2eword = []
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):
+ *         self.f_voc = Vocabulary()
  */
-  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 53; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_k_41 = __pyx_t_1;
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/bilex.pxi":54
+ * 
+ *     def __cinit__(self, from_text=None, from_data=False, from_binary=None,
+ *             earray=None, fsarray=None, alignment=None, mmaped=False):             # <<<<<<<<<<<<<<
+ *         self.f_voc = Vocabulary()
+ *         self.e_voc = Vocabulary()
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[5]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_k_42 = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/veb.pxi":17
  * from libc.string cimport memset
  * 
@@ -67861,7 +68636,7 @@ PyMODINIT_FUNC PyInit__sa(void)
  * 
  * cdef char* sym_tostring(int sym):
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_Alphabet)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_Alphabet)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 87; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_XGOTREF(((PyObject *)__pyx_v_3_sa_ALPHABET));
   __Pyx_DECREF(((PyObject *)__pyx_v_3_sa_ALPHABET));
@@ -67876,9 +68651,9 @@ PyMODINIT_FUNC PyInit__sa(void)
  *     word_ids = (sym_fromstring(word, True) for word in words)
  *     return tuple(((word, None, 1), ) for word in word_ids)
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_3make_lattice, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_3make_lattice, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__make_lattice, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__make_lattice, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 107; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":111
@@ -67888,9 +68663,9 @@ PyMODINIT_FUNC PyInit__sa(void)
  *     return tuple((sym_tostring(sym), weight, dist) for (sym, weight, dist) in arc
  *             for arc in node for node in lattice)
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_5decode_lattice, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_5decode_lattice, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__decode_lattice, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__decode_lattice, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/sym.pxi":115
@@ -67899,11 +68674,37 @@ PyMODINIT_FUNC PyInit__sa(void)
  * def decode_sentence(lattice):             # <<<<<<<<<<<<<<
  *     return tuple(sym_tostring(sym) for ((sym, _, _),) in lattice)
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_7decode_sentence, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_3_sa_7decode_sentence, NULL, __pyx_n_s___sa); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__decode_sentence, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[10]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__decode_sentence, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[12]; __pyx_lineno = 115; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/precomputation.pxi":193
+ *     cdef precomputed_collocations
+ * 
+ *     def __cinit__(self, fsarray=None, from_stats=None, from_binary=None, mmaped=False,             # <<<<<<<<<<<<<<
+ *             precompute_rank=1000, precompute_secondary_rank=20,
+ *             max_length=5, max_nonterminals=2,
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 193; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_k_73 = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+
+  /* "/Users/vchahun/Sandbox/cdec/python/src/sa/suffix_array.pxi":11
+ *     cdef IntList ha
+ * 
+ *     def __cinit__(self, from_binary=None, from_text=None, mmaped=False, side=None):             # <<<<<<<<<<<<<<
+ *         self.darray = DataArray()
+ *         self.sa = IntList()
+ */
+  __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[14]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_k_91 = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __pyx_t_1 = 0;
+
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":5
  * # Much faster than the Python numbers reported there.
  * # Note to reader: this code is closer to C than Python
@@ -68079,7 +68880,7 @@ PyMODINIT_FUNC PyInit__sa(void)
  * 
  * cdef class TrieNode:
  */
-  __pyx_v_3_sa_EPSILON = __pyx_f_3_sa_sym_fromstring(__pyx_k_147, 1);
+  __pyx_v_3_sa_EPSILON = __pyx_f_3_sa_sym_fromstring(__pyx_k_152, 1);
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/rulefactory.pxi":57
  *     cdef public int count
@@ -68090,7 +68891,7 @@ PyMODINIT_FUNC PyInit__sa(void)
  */
   __pyx_t_1 = __Pyx_PyBool_FromLong(0); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[8]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_k_99 = __pyx_t_1;
+  __pyx_k_103 = __pyx_t_1;
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
 
@@ -68099,7 +68900,7 @@ PyMODINIT_FUNC PyInit__sa(void)
  * 
  * INITIAL_CAPACITY = 7 # default number of features
  */
-  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyObject_Call(((PyObject *)((PyObject*)__pyx_ptype_3_sa_StringMap)), ((PyObject *)__pyx_empty_tuple), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_XGOTREF(((PyObject *)__pyx_v_3_sa_FD));
   __Pyx_DECREF(((PyObject *)__pyx_v_3_sa_FD));
@@ -68114,7 +68915,7 @@ PyMODINIT_FUNC PyInit__sa(void)
  * INCREMENT = INITIAL_CAPACITY # double size
  * 
  */
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__INITIAL_CAPACITY, __pyx_int_7) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__INITIAL_CAPACITY, __pyx_int_7) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
   /* "/Users/vchahun/Sandbox/cdec/python/src/sa/features.pxi":4
  * 
@@ -68123,9 +68924,9 @@ PyMODINIT_FUNC PyInit__sa(void)
  * 
  * cdef class FeatureVector:
  */
-  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_GetName(__pyx_m, __pyx_n_s__INITIAL_CAPACITY); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__INCREMENT, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[13]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__INCREMENT, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[15]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "_sa.pyx":1
@@ -68509,15 +69310,23 @@ bad:
 }
 #endif
 
-static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
-    if (unlikely(!type)) {
+static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
+    const char *name, int exact)
+{
+    if (!type) {
         PyErr_Format(PyExc_SystemError, "Missing type object");
         return 0;
     }
-    if (likely(PyObject_TypeCheck(obj, type)))
-        return 1;
-    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
-                 Py_TYPE(obj)->tp_name, type->tp_name);
+    if (none_allowed && obj == Py_None) return 1;
+    else if (exact) {
+        if (Py_TYPE(obj) == type) return 1;
+    }
+    else {
+        if (PyObject_TypeCheck(obj, type)) return 1;
+    }
+    PyErr_Format(PyExc_TypeError,
+        "Argument '%s' has incorrect type (expected %s, got %s)",
+        name, type->tp_name, Py_TYPE(obj)->tp_name);
     return 0;
 }
 
@@ -68621,6 +69430,18 @@ static CYTHON_INLINE void __Pyx_RaiseClosureNameError(const char *varname) {
     PyErr_Format(PyExc_NameError, "free variable '%s' referenced before assignment in enclosing scope", varname);
 }
 
+static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
+    if (unlikely(!type)) {
+        PyErr_Format(PyExc_SystemError, "Missing type object");
+        return 0;
+    }
+    if (likely(PyObject_TypeCheck(obj, type)))
+        return 1;
+    PyErr_Format(PyExc_TypeError, "Cannot convert %.200s to %.200s",
+                 Py_TYPE(obj)->tp_name, type->tp_name);
+    return 0;
+}
+
 static CYTHON_INLINE long __Pyx_div_long(long a, long b) {
     long q = a / b;
     long r = a - q*b;
@@ -68725,26 +69546,6 @@ static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) {
     PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname);
 }
 
-static int __Pyx_ArgTypeTest(PyObject *obj, PyTypeObject *type, int none_allowed,
-    const char *name, int exact)
-{
-    if (!type) {
-        PyErr_Format(PyExc_SystemError, "Missing type object");
-        return 0;
-    }
-    if (none_allowed && obj == Py_None) return 1;
-    else if (exact) {
-        if (Py_TYPE(obj) == type) return 1;
-    }
-    else {
-        if (PyObject_TypeCheck(obj, type)) return 1;
-    }
-    PyErr_Format(PyExc_TypeError,
-        "Argument '%s' has incorrect type (expected %s, got %s)",
-        name, type->tp_name, Py_TYPE(obj)->tp_name);
-    return 0;
-}
-
 static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
     PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
 }
diff --git a/python/src/sa/_sa.pxd b/python/src/sa/_sa.pxd
index f1cd8e29..5c1fce27 100644
--- a/python/src/sa/_sa.pxd
+++ b/python/src/sa/_sa.pxd
@@ -1,26 +1,40 @@
 from libc.stdio cimport FILE
+from posix.unistd cimport off_t
+
+cdef class MemoryMap:
+    cdef int fd
+    cdef off_t fs
+    cdef void* map_start
+    cdef void* map_ptr
+    cdef int read_int(self)
+    cdef int* read_int_array(self, int size)
+    cdef char* read_char_array(self, int size)
+    cdef float* read_float_array(self, int size)
 
 cdef class FloatList:
     cdef int size
     cdef int increment
     cdef int len
     cdef float* arr
+    cdef object memory
     cdef void set(self, int i, float v)
     cdef void write_handle(self, FILE* f)
     cdef void read_handle(self, FILE* f)
+    cdef void read_mmaped(self, MemoryMap buf)
 
 cdef class IntList:
     cdef int size
     cdef int increment
     cdef int len
     cdef int* arr
+    cdef object memory
     cdef void set(self, int i, int val)
     cdef void _append(self, int val)
-    cdef void _extend(self, IntList other)
     cdef void _extend_arr(self, int* other, int other_len)
     cdef void _clear(self)
     cdef void write_handle(self, FILE* f)
     cdef void read_handle(self, FILE* f)
+    cdef void read_mmaped(self, MemoryMap buf)
 
 cdef class FeatureVector:
     cdef IntList names
diff --git a/python/src/sa/_sa.pyx b/python/src/sa/_sa.pyx
index 50da4235..549b3a98 100644
--- a/python/src/sa/_sa.pyx
+++ b/python/src/sa/_sa.pyx
@@ -14,9 +14,11 @@ def gzip_or_text(char* filename):
 
 logger = logging.getLogger('cdec.sa')
 
+include "mmap.pxi"
 include "float_list.pxi"
 include "int_list.pxi"
 include "str_map.pxi"
+include "vocabulary.pxi"
 include "data_array.pxi"
 include "alignment.pxi"
 include "bilex.pxi"
diff --git a/python/src/sa/alignment.pxi b/python/src/sa/alignment.pxi
index 842899ad..7914dfa3 100644
--- a/python/src/sa/alignment.pxi
+++ b/python/src/sa/alignment.pxi
@@ -42,15 +42,18 @@ cdef class Alignment:
             self._unlink(self.links.arr[start + i], sent_links + (2*i), sent_links + (2*i) + 1)
         return sent_links
 
-    def __cinit__(self, from_binary=None, from_text=None):
+    def __cinit__(self, from_binary=None, from_text=None, mmaped=False):
         self.links = IntList(1000,1000)
         self.sent_index = IntList(1000,1000)
         if from_binary:
-            self.read_binary(from_binary)
+            if mmaped:
+                self.read_mmaped(MemoryMap(from_binary))
+            else:
+                self.read_binary(from_binary)
         elif from_text:
             self.read_text(from_text)
 
-    def read_text(self, char* filename):
+    def read_text(self, bytes filename):
         with gzip_or_text(filename) as f:
             for line in f:
                 self.sent_index.append(len(self.links))
@@ -60,14 +63,18 @@ cdef class Alignment:
                     self.links.append(self.link(i, j))
             self.sent_index.append(len(self.links))
 
-    def read_binary(self, char* filename):
+    def read_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "r")
         self.links.read_handle(f)
         self.sent_index.read_handle(f)
         fclose(f)
 
-    def write_text(self, char* filename):
+    def read_mmaped(self, MemoryMap buf):
+        self.links.read_mmaped(buf)
+        self.sent_index.read_mmaped(buf)
+
+    def write_text(self, bytes filename):
         with open(filename, "w") as f:
             sent_num = 0
             for i, link in enumerate(self.links):
@@ -77,14 +84,14 @@ cdef class Alignment:
                 f.write("%d-%d " % self.unlink(link))
             f.write("\n")
 
-    def write_binary(self, char* filename):
+    def write_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "w")
         self.links.write_handle(f)
         self.sent_index.write_handle(f)
         fclose(f)
 
-    def write_enhanced(self, char* filename):
+    def write_enhanced(self, bytes filename):
         with open(filename, "w") as f:
             sent_num = 1
             for link in self.links:
diff --git a/python/src/sa/bilex.pxi b/python/src/sa/bilex.pxi
index 44bc0ce6..5e2fcd82 100644
--- a/python/src/sa/bilex.pxi
+++ b/python/src/sa/bilex.pxi
@@ -43,26 +43,26 @@ cdef int* get_val(_node* n, int key):
             return &(n.bigger.val)
         return get_val(n.bigger, key)
 
+cdef int NULL_WORD = 0
 
 cdef class BiLex:
-    cdef FloatList col1
-    cdef FloatList col2
-    cdef IntList f_index
-    cdef IntList e_index
-    cdef id2eword, id2fword, eword2id, fword2id
+    cdef FloatList col1, col2
+    cdef IntList f_index, e_index
+    cdef Vocabulary f_voc, e_voc
 
     def __cinit__(self, from_text=None, from_data=False, from_binary=None, 
-            earray=None, fsarray=None, alignment=None):
-        self.id2eword = []
-        self.id2fword = []
-        self.eword2id = {}
-        self.fword2id = {}
+            earray=None, fsarray=None, alignment=None, mmaped=False):
+        self.f_voc = Vocabulary()
+        self.e_voc = Vocabulary()
         self.e_index = IntList()
         self.f_index = IntList()
         self.col1 = FloatList()
         self.col2 = FloatList()
         if from_binary:
-            self.read_binary(from_binary)
+            if mmaped:
+                self.read_mmaped(MemoryMap(from_binary))
+            else:
+                self.read_binary(from_binary)
         elif from_data:
             self.compute_from_data(fsarray, earray, alignment)
         else:
@@ -74,25 +74,15 @@ cdef class BiLex:
         cdef int *fsent, *esent, *alignment, *links, *ealigned, *faligned
         cdef _node** dict
         cdef int *fmargin, *emargin, *count
-        cdef int null_word
 
-        null_word = 0
-        for word in fsa.darray.id2word: # I miss list comprehensions
-            self.id2fword.append(word)
-        self.id2fword[null_word] = "NULL"
-        for id, word in enumerate(self.id2fword):
-            self.fword2id[word] = id
-
-        for word in eda.id2word:
-            self.id2eword.append(word)
-        self.id2eword[null_word] = "NULL"
-        for id, word in enumerate(self.id2eword):
-            self.eword2id[word] = id
+        self.f_voc.extend(fsa.darray.voc)
+        self.e_voc.extend(eda.voc)
+        assert(self.f_voc['NULL'] == self.e_voc['NULL'] == NULL_WORD)
 
         num_pairs = 0
 
-        V_E = len(eda.id2word)
-        V_F = len(fsa.darray.id2word)
+        V_E = len(eda.voc)
+        V_F = len(fsa.darray.voc)
         fmargin = <int*> malloc(V_F*sizeof(int))
         emargin = <int*> malloc(V_E*sizeof(int))
         memset(fmargin, 0, V_F*sizeof(int))
@@ -141,27 +131,27 @@ cdef class BiLex:
                 if faligned[i] == 0:
                     f_i = fsent[i]
                     fmargin[f_i] = fmargin[f_i] + 1
-                    emargin[null_word] = emargin[null_word] + 1
+                    emargin[NULL_WORD] = emargin[NULL_WORD] + 1
                     if dict[f_i] == NULL:
-                        dict[f_i] = new_node(null_word)
+                        dict[f_i] = new_node(NULL_WORD)
                         dict[f_i].val = 1
                         num_pairs = num_pairs + 1
                     else:
-                        count = get_val(dict[f_i], null_word)
+                        count = get_val(dict[f_i], NULL_WORD)
                         if count[0] == 0:
                             num_pairs = num_pairs + 1
                         count[0] = count[0] + 1
             for j from 0 <= j < J:
                 if ealigned[j] == 0:
                     e_j = esent[j]
-                    fmargin[null_word] = fmargin[null_word] + 1
+                    fmargin[NULL_WORD] = fmargin[NULL_WORD] + 1
                     emargin[e_j] = emargin[e_j] + 1
-                    if dict[null_word] == NULL:
-                        dict[null_word] = new_node(e_j)
-                        dict[null_word].val = 1
+                    if dict[NULL_WORD] == NULL:
+                        dict[NULL_WORD] = new_node(e_j)
+                        dict[NULL_WORD].val = 1
                         num_pairs = num_pairs + 1
                     else:
-                        count = get_val(dict[null_word], e_j)
+                        count = get_val(dict[NULL_WORD], e_j)
                         if count[0] == 0:
                             num_pairs = num_pairs + 1
                         count[0] = count[0] + 1
@@ -199,73 +189,43 @@ cdef class BiLex:
             self._add_node(n.bigger, num_pairs, fmargin, emargin)
 
 
-    def write_binary(self, char* filename):
+    def write_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "w")
         self.f_index.write_handle(f)
         self.e_index.write_handle(f)
         self.col1.write_handle(f)
         self.col2.write_handle(f)
-        self.write_wordlist(self.id2fword, f)
-        self.write_wordlist(self.id2eword, f)
+        self.f_voc.write_handle(f)
+        self.e_voc.write_handle(f)
         fclose(f)
 
-
-    cdef write_wordlist(self, wordlist, FILE* f):
-        cdef int word_len
-        cdef int num_words
-
-        num_words = len(wordlist)
-        fwrite(&(num_words), sizeof(int), 1, f)
-        for word in wordlist:
-            word_len = len(word) + 1
-            fwrite(&(word_len), sizeof(int), 1, f)
-            fwrite(<char *>word, sizeof(char), word_len, f)
-
-
-    cdef read_wordlist(self, word2id, id2word, FILE* f):
-        cdef int num_words
-        cdef int word_len
-        cdef char* word
-
-        fread(&(num_words), sizeof(int), 1, f)
-        for i from 0 <= i < num_words:
-            fread(&(word_len), sizeof(int), 1, f)
-            word = <char*> malloc (word_len * sizeof(char))
-            fread(word, sizeof(char), word_len, f)
-            word2id[word] = len(id2word)
-            id2word.append(word)
-            free(word)
-
-    def read_binary(self, char* filename):
+    def read_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "r")
         self.f_index.read_handle(f)
         self.e_index.read_handle(f)
         self.col1.read_handle(f)
         self.col2.read_handle(f)
-        self.read_wordlist(self.fword2id, self.id2fword, f)
-        self.read_wordlist(self.eword2id, self.id2eword, f)
+        self.f_voc.read_handle(f)
+        self.e_voc.read_handle(f)
         fclose(f)
 
+    def read_mmaped(self, MemoryMap buf):
+        self.f_index.read_mmaped(buf)
+        self.e_index.read_mmaped(buf)
+        self.col1.read_mmaped(buf)
+        self.col2.read_mmaped(buf)
+        self.f_voc.read_mmaped(buf)
+        self.e_voc.read_mmaped(buf)
 
     def get_e_id(self, eword):
-        if eword not in self.eword2id:
-            e_id = len(self.id2eword)
-            self.id2eword.append(eword)
-            self.eword2id[eword] = e_id
-        return self.eword2id[eword]
-
+        return self.e_voc[eword]
 
     def get_f_id(self, fword):
-        if fword not in self.fword2id:
-            f_id = len(self.id2fword)
-            self.id2fword.append(fword)
-            self.fword2id[fword] = f_id
-        return self.fword2id[fword]
+        return self.f_voc[fword]
 
-
-    def read_text(self, char* filename):
+    def read_text(self, bytes filename):
         cdef i, j, w, e_id, f_id, n_f, n_e, N
         cdef IntList fcount 
 
@@ -309,7 +269,7 @@ cdef class BiLex:
         for b from 0 <= b < n_f:
             i = self.f_index.arr[b]
             j = self.f_index.arr[b+1]
-            self.qsort(i,j, "")
+            self.qsort(i, j)
 
 
     cdef swap(self, int i, int j):
@@ -332,7 +292,7 @@ cdef class BiLex:
         self.col2.arr[j] = ftmp
 
 
-    cdef qsort(self, int i, int j, pad):
+    cdef qsort(self, int i, int j):
         cdef int pval, p
 
         if i > j:
@@ -351,11 +311,11 @@ cdef class BiLex:
                 self.swap(p+1, k)
                 self.swap(p, p+1)
                 p = p + 1
-        self.qsort(i,p, pad+"    ")
-        self.qsort(p+1,j, pad+"    ")
+        self.qsort(i, p)
+        self.qsort(p+1, j)
 
 
-    def write_enhanced(self, char* filename):
+    def write_enhanced(self, bytes filename):
         with open(filename, "w") as f:
             for i in self.f_index:
                 f.write("%d " % i)
@@ -363,10 +323,10 @@ cdef class BiLex:
             for i, s1, s2 in zip(self.e_index, self.col1, self.col2):
                 f.write("%d %f %f " % (i, s1, s2))
             f.write("\n")
-            for i, w in enumerate(self.id2fword):
+            for i, w in enumerate(self.f_voc.id2word):
                 f.write("%d %s " % (i, w))
             f.write("\n")
-            for i, w in enumerate(self.id2eword):
+            for i, w in enumerate(self.f_voc.id2word):
                 f.write("%d %s " % (i, w))
             f.write("\n")
 
@@ -374,12 +334,10 @@ cdef class BiLex:
     def get_score(self, fword, eword, col):
         cdef e_id, f_id, low, high, midpoint, val
 
-        if eword not in self.eword2id:
-            return None
-        if fword not in self.fword2id:
-            return None
-        f_id = self.fword2id[fword]
-        e_id = self.eword2id[eword]
+        f_id = self.f_voc.get(fword, None)
+        e_id = self.e_voc.get(eword, None)
+        if f_id is None or e_id is None: return None
+
         low = self.f_index.arr[f_id]
         high = self.f_index.arr[f_id+1]
         while high - low > 0:
@@ -397,7 +355,7 @@ cdef class BiLex:
         return None
 
 
-    def write_text(self, char* filename):
+    def write_text(self, bytes filename):
         """Note: does not guarantee writing the dictionary in the original order"""
         cdef i, N, e_id, f_id
         
@@ -410,4 +368,4 @@ cdef class BiLex:
                 e_id = self.e_index.arr[i]
                 score1 = self.col1.arr[i]
                 score2 = self.col2.arr[i]
-                f.write("%s %s %.6f %.6f\n" % (self.id2fword[f_id], self.id2eword[e_id], score1, score2))
+                f.write("%s %s %.6f %.6f\n" % (self.f_voc.id2word[f_id], self.e_voc.id2word[e_id], score1, score2))
diff --git a/python/src/sa/data_array.pxi b/python/src/sa/data_array.pxi
index 2a8ea921..3a54d784 100644
--- a/python/src/sa/data_array.pxi
+++ b/python/src/sa/data_array.pxi
@@ -6,23 +6,29 @@ from libc.stdio cimport FILE, fopen, fread, fwrite, fclose
 from libc.stdlib cimport malloc, realloc, free
 from libc.string cimport memset, strcpy
 
+# kept for compatibility
+INIT_VOCABULARY = ('NULL', 'END_OF_LINE')
+
 cdef class DataArray:
-    cdef public word2id
-    cdef public id2word
+    cdef public Vocabulary voc
     cdef public IntList data
     cdef public IntList sent_id
     cdef public IntList sent_index
     cdef bint use_sent_id
 
-    def __cinit__(self, from_binary=None, from_text=None, side=None, bint use_sent_id=False):
-        self.word2id = {"END_OF_FILE":0, "END_OF_LINE":1}
-        self.id2word = ["END_OF_FILE", "END_OF_LINE"]
+    def __cinit__(self, from_binary=None, from_text=None, side=None,
+            bint use_sent_id=False, mmaped=False):
+        self.voc = Vocabulary()
+        self.voc.extend(INIT_VOCABULARY)
         self.data = IntList(1000,1000)
         self.sent_id = IntList(1000,1000)
         self.sent_index = IntList(1000,1000)
         self.use_sent_id = use_sent_id
         if from_binary:
-            self.read_binary(from_binary)
+            if mmaped:
+                self.read_mmaped(MemoryMap(from_binary))
+            else:
+                self.read_binary(from_binary)
         elif from_text:
             if side:
                 self.read_bitext(from_text, (0 if side == 'source' else 1))
@@ -37,27 +43,21 @@ cdef class DataArray:
 
     def get_sentence(self, i):
         cdef int j, start, stop
-        sent = []
         start = self.sent_index.arr[i]
         stop = self.sent_index.arr[i+1]
-        for i from start <= i < stop:
-            sent.append(self.id2word[self.data.arr[i]])
-        return sent
+        sent = [self.voc.id2word[self.data.arr[j]] for j in range(start, stop)]
 
     def get_id(self, word):
-        if not word in self.word2id:
-            self.word2id[word] = len(self.id2word)
-            self.id2word.append(word)
-        return self.word2id[word]
+        return self.voc[word]
 
     def __getitem__(self, loc):
-        return self.id2word[self.data.arr[loc]]
+        return self.voc.id2word[self.data.arr[loc]]
 
     def get_sentence_bounds(self, loc):
         cdef int sid = self.sent_id.arr[loc]
         return (self.sent_index.arr[sid], self.sent_index.arr[sid+1])
 
-    def write_text(self, char* filename):
+    def write_text(self, bytes filename):
         with open(filename, "w") as f:
             for w_id in self.data:
                 if w_id > 1:
@@ -65,11 +65,11 @@ cdef class DataArray:
                 if w_id == 1:
                     f.write("\n")
 
-    def read_text(self, char* filename):
+    def read_text(self, bytes filename):
         with gzip_or_text(filename) as fp:
             self.read_text_data(fp)
 
-    def read_bitext(self, char* filename, int side):
+    def read_bitext(self, bytes filename, int side):
         with gzip_or_text(filename) as fp:
             data = (line.split(' ||| ')[side] for line in fp)
             self.read_text_data(data)
@@ -90,49 +90,33 @@ cdef class DataArray:
         self.data.append(0)
         self.sent_index.append(word_count)
 
-
-    def read_binary(self, char* filename):
+    def read_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "r")
         self.read_handle(f)
         fclose(f)
 
-    cdef void read_handle(self, FILE* f):
-        cdef int num_words, word_len
-        cdef unsigned i
-        cdef char* word
+    cdef void read_mmaped(self, MemoryMap buf):
+        self.data.read_mmaped(buf)
+        self.sent_index.read_mmaped(buf)
+        self.sent_id.read_mmaped(buf)
+        self.voc.read_mmaped(buf)
+        self.use_sent_id = (len(self.sent_id) > 0)
 
+    cdef void read_handle(self, FILE* f):
         self.data.read_handle(f)
         self.sent_index.read_handle(f)
         self.sent_id.read_handle(f)
-        fread(&(num_words), sizeof(int), 1, f)
-        for i in range(num_words):
-            fread(&(word_len), sizeof(int), 1, f)
-            word = <char*> malloc (word_len * sizeof(char))
-            fread(word, sizeof(char), word_len, f)
-            self.word2id[word] = len(self.id2word)
-            self.id2word.append(word)
-            free(word)
-        if len(self.sent_id) == 0:
-            self.use_sent_id = False
-        else:
-            self.use_sent_id = True
+        self.voc.read_handle(f)
+        self.use_sent_id = (len(self.sent_id) > 0)
 
     cdef void write_handle(self, FILE* f):
-        cdef int word_len
-        cdef int num_words
-
         self.data.write_handle(f)
         self.sent_index.write_handle(f)
         self.sent_id.write_handle(f)
-        num_words = len(self.id2word) - 2
-        fwrite(&(num_words), sizeof(int), 1, f)
-        for word in self.id2word[2:]:
-            word_len = len(word) + 1
-            fwrite(&(word_len), sizeof(int), 1, f)
-            fwrite(<char *>word, sizeof(char), word_len, f)
-
-    def write_binary(self, char* filename):
+        self.voc.write_handle(f, len(INIT_VOCABULARY))
+
+    def write_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "w")
         self.write_handle(f)
@@ -148,10 +132,10 @@ cdef class DataArray:
         for i in self.sent_id:
             f.write("%d " %i)
         f.write("\n")
-        for word in self.id2word:
-            f.write("%s %d " % (word, self.word2id[word]))
+        for w, word in enumerate(self.voc.id2word):
+            f.write("%s %d " % (word, w))
         f.write("\n")
 
-    def write_enhanced(self, char* filename):
+    def write_enhanced(self, bytes filename):
         with open(filename, "w") as f:
             self.write_enhanced_handle(self, f)
diff --git a/python/src/sa/float_list.pxi b/python/src/sa/float_list.pxi
index b98e444f..adc136be 100644
--- a/python/src/sa/float_list.pxi
+++ b/python/src/sa/float_list.pxi
@@ -16,9 +16,11 @@ cdef class FloatList:
         self.len = initial_len
         self.arr = <float*> malloc(size*sizeof(float))
         memset(self.arr, 0, initial_len*sizeof(float))
+        self.memory = self
 
     def __dealloc__(self):
-        free(self.arr)
+        if self.memory is self:
+            free(self.arr)
 
     def __getitem__(self, i):
         j = i
@@ -50,24 +52,18 @@ cdef class FloatList:
         self.len = self.len + 1
 
     cdef void write_handle(self, FILE* f):
-        fwrite(&(self.len), sizeof(float), 1, f)
+        fwrite(&(self.len), sizeof(int), 1, f)
         fwrite(self.arr, sizeof(float), self.len, f)
 
-    def write(self, char* filename):
-        cdef FILE* f
-        f = fopen(filename, "w")
-        self.write_handle(f)
-        fclose(f)
-
     cdef void read_handle(self, FILE* f):
         free(self.arr)
-        fread(&(self.len), sizeof(float), 1, f)
+        fread(&(self.len), sizeof(int), 1, f)
         self.arr = <float*> malloc(self.len * sizeof(float))
         self.size = self.len
         fread(self.arr, sizeof(float), self.len, f)
 
-    def read(self, char* filename):
-        cdef FILE* f
-        f = fopen(filename, "r")
-        self.read_handle(f)
-        fclose(f)
+    cdef void read_mmaped(self, MemoryMap buf):
+        free(self.arr)
+        self.size = self.len = buf.read_int()
+        self.arr = buf.read_float_array(self.len)
+        self.memory = buf
diff --git a/python/src/sa/int_list.pxi b/python/src/sa/int_list.pxi
index 55f5d174..8ccf7686 100644
--- a/python/src/sa/int_list.pxi
+++ b/python/src/sa/int_list.pxi
@@ -16,67 +16,24 @@ cdef class IntList:
         self.len = initial_len
         self.arr = <int*> malloc(size*sizeof(int))
         memset(self.arr, 0, initial_len*sizeof(int))
+        self.memory = self
 
-    def __str__(self):
-        cdef unsigned i
-        ret = "IntList["
-        for idx in range(self.size):
-            if idx>0:
-                ret += ","
-            ret += str(self.arr[idx])
-        ret += "]"
-        ret += "len="
-        ret += self.len
-        return ret
+    def __repr__(self):
+        return 'IntList(%s)' % list(self)
 
     def index(self, val):
         cdef unsigned i
         for i in range(self.len):
             if self.arr[i] == val:
                 return i
-        return IndexError
-
-    def partition(self,start,end):
-        pivot = self.arr[end]
-        bottom = start-1
-        top = end
-        done = 0
-        while not done:
-            while not done:
-                bottom += 1
-                if bottom == top:
-                    done = 1
-                    break
-                if self.arr[bottom] > pivot:
-                    self.arr[top] = self.arr[bottom]
-                    break
-            while not done:
-                top -= 1
-                if top == bottom:
-                    done = 1
-                    break
-                if self.arr[top] < pivot:
-                    self.arr[bottom] = self.arr[top]
-                    break
-        self.arr[top] = pivot
-        return top
-
-    def _doquicksort(self,start,end):
-        if start < end:
-            split = self.partition(start,end)
-            self._doquicksort(start,split-1)
-            self._doquicksort(split+1,end)
-        else:
-            return
-
-    def sort(self):
-        self._doquicksort(0,self.len-1)
+        raise ValueError('%s not in list' % val)
 
     def reset(self):
         self.len = 0
 
     def __dealloc__(self):
-        free(self.arr)
+        if self.memory is self:
+            free(self.arr)
 
     def __iter__(self):
         cdef int i
@@ -122,9 +79,6 @@ cdef class IntList:
     def __len__(self):
         return self.len
 
-    def get_size(self):
-        return self.size
-
     def append(self, int val):
         self._append(val)
 
@@ -135,10 +89,7 @@ cdef class IntList:
         self.arr[self.len] = val
         self.len = self.len + 1
 
-    def extend(self, other):
-        self._extend(other)
-
-    cdef void _extend(self, IntList other):
+    def extend(self, IntList other):
         self._extend_arr(other.arr, other.len)
 
     cdef void _extend_arr(self, int* other, int other_len):
@@ -158,21 +109,15 @@ cdef class IntList:
         fwrite(&(self.len), sizeof(int), 1, f)
         fwrite(self.arr, sizeof(int), self.len, f)
 
-    def write(self, char* filename):
-        cdef FILE* f
-        f = fopen(filename, "w")
-        self.write_handle(f)
-        fclose(f)
-
     cdef void read_handle(self, FILE* f):
-        (self.arr)
+        free(self.arr)
         fread(&(self.len), sizeof(int), 1, f)
         self.arr = <int*> malloc(self.len * sizeof(int))
         self.size = self.len
         fread(self.arr, sizeof(int), self.len, f)
 
-    def read(self, char* filename):
-        cdef FILE* f
-        f = fopen(filename, "r")
-        self.read_handle(f)
-        fclose(f)
+    cdef void read_mmaped(self, MemoryMap buf):
+        free(self.arr)
+        self.size = self.len = buf.read_int()
+        self.arr = buf.read_int_array(self.len)
+        self.memory = buf
diff --git a/python/src/sa/mmap.pxi b/python/src/sa/mmap.pxi
new file mode 100644
index 00000000..6b65b779
--- /dev/null
+++ b/python/src/sa/mmap.pxi
@@ -0,0 +1,53 @@
+cimport posix.fcntl
+cimport posix.unistd
+from posix.unistd cimport off_t
+
+cdef extern from "sys/mman.h":
+    void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+    int munmap(void *addr, size_t len)
+    enum:
+        PROT_READ
+    enum:
+        MAP_FILE
+        MAP_SHARED
+
+cdef extern from "sys/stat.h":
+    cdef struct stat:
+        off_t st_size
+    int fstat(int fildes, stat *buf)
+
+cdef class MemoryMap:
+    def __init__(self, filename):
+        self.fd = posix.fcntl.open(filename, posix.fcntl.O_RDONLY)
+        assert self.fd >= 0
+        # Get file size
+        cdef stat statbuf
+        fstat(self.fd, &statbuf) 
+        self.fs = statbuf.st_size
+        # Memory map file
+        self.map_start = mmap(NULL, self.fs, PROT_READ, MAP_FILE|MAP_SHARED, self.fd, 0)
+        self.map_ptr = self.map_start
+
+    def __dealloc__(self):
+        posix.unistd.close(self.fd)
+        munmap(self.map_start, self.fs)
+
+    cdef int read_int(self):
+        cdef int v = (<int*> self.map_ptr)[0]
+        self.map_ptr = &(<int*> self.map_ptr)[1]
+        return v
+
+    cdef int* read_int_array(self, int size):
+        cdef int* v = <int*> self.map_ptr
+        self.map_ptr = &(<int*> self.map_ptr)[size]
+        return v
+
+    cdef char* read_char_array(self, int size):
+        cdef char* v = <char*> self.map_ptr
+        self.map_ptr = &(<char*> self.map_ptr)[size]
+        return v
+
+    cdef float* read_float_array(self, int size):
+        cdef float* v = <float*> self.map_ptr
+        self.map_ptr = &(<float*> self.map_ptr)[size]
+        return v
diff --git a/python/src/sa/precomputation.pxi b/python/src/sa/precomputation.pxi
index a3527f47..272aa56e 100644
--- a/python/src/sa/precomputation.pxi
+++ b/python/src/sa/precomputation.pxi
@@ -73,7 +73,6 @@ cdef trie_node_data_extend(_Trie_Node* node, int* vals, int num_vals):
     memcpy(node.arr + node.arr_len, vals, num_vals*sizeof(int))
     node.arr_len = new_len
 
-
 cdef _Trie_Node* trie_insert(_Trie_Node* node, int val):
     cdef _Trie_Edge** cur
     cur = &node.root
@@ -116,7 +115,6 @@ cdef class TrieMap:
         self.root = <_Trie_Node**> malloc(self.V * sizeof(_Trie_Node*))
         memset(self.root, 0, self.V * sizeof(_Trie_Node*))
 
-
     def __dealloc__(self):
         cdef int i
         for i from 0 <= i < self.V:
@@ -124,7 +122,6 @@ cdef class TrieMap:
                 free_trie_node(self.root[i])
         free(self.root)
 
-
     def insert(self, pattern):
         cdef int* p
         cdef int i, l
@@ -135,7 +132,6 @@ cdef class TrieMap:
         self._insert(p,l)
         free(p)
 
-
     cdef _Trie_Node* _insert(self, int* pattern, int pattern_len):
         cdef int i
         cdef _Trie_Node* node
@@ -184,7 +180,6 @@ cdef class TrieMap:
                 trie_node_to_map(self.root[i], result, (i,), include_zeros)
         return result
 
-
 cdef class Precomputation:
     cdef int precompute_rank
     cdef int precompute_secondary_rank
@@ -194,10 +189,8 @@ cdef class Precomputation:
     cdef int train_min_gap_size
     cdef precomputed_index
     cdef precomputed_collocations
-    cdef read_map(self, FILE* f)
-    cdef write_map(self, m, FILE* f)
 
-    def __cinit__(self, fsarray=None, from_stats=None, from_binary=None,
+    def __cinit__(self, fsarray=None, from_stats=None, from_binary=None, mmaped=False,
             precompute_rank=1000, precompute_secondary_rank=20,
             max_length=5, max_nonterminals=2,
             train_max_initial_size=10, train_min_gap_size=2):
@@ -208,12 +201,14 @@ cdef class Precomputation:
         self.train_max_initial_size = train_max_initial_size
         self.train_min_gap_size = train_min_gap_size
         if from_binary:
-            self.read_binary(from_binary)
+            if mmaped:
+                self.read_mmaped(MemoryMap(from_binary))
+            else:
+                self.read_binary(from_binary)
         elif from_stats:
             self.precompute(from_stats, fsarray)
 
-
-    def read_binary(self, char* filename):
+    def read_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "r")
         fread(&(self.precompute_rank), sizeof(int), 1, f)
@@ -226,8 +221,17 @@ cdef class Precomputation:
         self.precomputed_collocations = self.read_map(f)
         fclose(f)
 
-
-    def write_binary(self, char* filename):
+    def read_mmaped(self, MemoryMap buf):
+        self.precompute_rank = buf.read_int()
+        self.precompute_secondary_rank = buf.read_int()
+        self.max_length = buf.read_int()
+        self.max_nonterminals = buf.read_int()
+        self.train_max_initial_size = buf.read_int()
+        self.train_min_gap_size = buf.read_int()
+        self.precomputed_index = self.read_mmaped_map(buf)
+        self.precomputed_collocations = self.read_mmaped_map(buf)
+
+    def write_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "w")
         fwrite(&(self.precompute_rank), sizeof(int), 1, f)
@@ -240,7 +244,6 @@ cdef class Precomputation:
         self.write_map(self.precomputed_collocations, f)
         fclose(f)
 
-
     cdef write_map(self, m, FILE* f):
         cdef int i, N
         cdef IntList arr
@@ -256,7 +259,6 @@ cdef class Precomputation:
             arr = val
             arr.write_handle(f)
 
-
     cdef read_map(self, FILE* f):
         cdef int i, j, k, word_id, N
         cdef IntList arr
@@ -274,6 +276,21 @@ cdef class Precomputation:
             m[key] = arr
         return m
 
+    cdef read_mmaped_map(self, MemoryMap buf):
+        cdef int i, j, k, word_id, N
+        cdef IntList arr
+
+        m = {}
+        N = buf.read_int()
+        for j in range(N):
+            key_size = buf.read_int()
+            key = []
+            for k in range(key_size):
+                key.append(buf.read_int())
+            arr = IntList()
+            arr.read_mmaped(buf)
+            m[tuple(key)] = arr
+        return m
 
     def precompute(self, stats, SuffixArray sarray):
         cdef int i, l, N, max_pattern_len, i1, l1, i2, l2, i3, l3, ptr1, ptr2, ptr3, is_super, sent_count, max_rank
@@ -284,9 +301,9 @@ cdef class Precomputation:
 
         data = darray.data
 
-        frequent_patterns = TrieMap(len(darray.id2word))
-        super_frequent_patterns = TrieMap(len(darray.id2word))
-        collocations = TrieMap(len(darray.id2word))
+        frequent_patterns = TrieMap(len(darray.voc.id2word))
+        super_frequent_patterns = TrieMap(len(darray.voc.id2word))
+        collocations = TrieMap(len(darray.voc.id2word))
 
         I_set = set()
         J_set = set()
@@ -419,7 +436,7 @@ cdef class Precomputation:
                     if word_id == -1:
                         s = s + "X "
                     else:
-                        s = s + darray.id2word[word_id] + " "
+                        s = s + darray.voc.id2word[word_id] + " "
                 logger.warn("ERROR: unexpected pattern %s in set of precomputed collocations", s)
             else:
                 chunk = ()
diff --git a/python/src/sa/rulefactory.pxi b/python/src/sa/rulefactory.pxi
index 5006a838..45b16656 100644
--- a/python/src/sa/rulefactory.pxi
+++ b/python/src/sa/rulefactory.pxi
@@ -389,10 +389,10 @@ cdef class HieroCachingRuleFactory:
         cdef int word_id, new_word_id, N
         cdef IntList idmap
         
-        N = len(darray.id2word)
+        N = len(darray.voc)
         idmap = IntList(initial_len=N)
         for word_id from 0 <= word_id < N:
-            new_word_id = sym_fromstring(darray.id2word[word_id], True)
+            new_word_id = sym_fromstring(darray.voc.id2word[word_id], True)
             idmap.arr[word_id] = new_word_id
         return idmap
 
@@ -406,7 +406,7 @@ cdef class HieroCachingRuleFactory:
                 arity = arity + 1
                 new_id = sym_setindex(self.category, arity)
             else:
-                new_id = sym_fromstring(self.fda.id2word[word_id], True)
+                new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
             result = result + (new_id,)
         return Phrase(result)
 
@@ -421,7 +421,7 @@ cdef class HieroCachingRuleFactory:
                 arity = arity + 1
                 new_id = sym_setindex(self.category, arity)
             else:
-                new_id = sym_fromstring(self.fda.id2word[word_id], True)
+                new_id = sym_fromstring(self.fda.voc.id2word[word_id], True)
             result = result + (new_id,)
         patterns.append(Phrase(result))
         patterns.append(Phrase(result + (sym_setindex(self.category, 1),)))
diff --git a/python/src/sa/suffix_array.pxi b/python/src/sa/suffix_array.pxi
index de4adcd9..4df61acd 100644
--- a/python/src/sa/suffix_array.pxi
+++ b/python/src/sa/suffix_array.pxi
@@ -8,12 +8,15 @@ cdef class SuffixArray:
     cdef IntList sa
     cdef IntList ha
 
-    def __cinit__(self, from_binary=None, from_text=None, side=None):
+    def __cinit__(self, from_binary=None, from_text=None, mmaped=False, side=None):
         self.darray = DataArray()
         self.sa = IntList()
         self.ha = IntList()
         if from_binary:
-            self.read_binary(from_binary)
+            if mmaped:
+                self.read_mmaped(MemoryMap(from_binary))
+            else:
+                self.read_binary(from_binary)
         elif from_text:
             self.read_text(from_text, side)
 
@@ -28,7 +31,7 @@ cdef class SuffixArray:
 
         self.darray = DataArray(from_text=filename, side=side, use_sent_id=True)
         N = len(self.darray)
-        V = len(self.darray.id2word)
+        V = len(self.darray.voc)
 
         self.sa = IntList(initial_len=N)
         self.ha = IntList(initial_len=V+1)
@@ -166,10 +169,10 @@ cdef class SuffixArray:
         self.q3sort(ptail+1, j, h, isa, pad+"    ")
 
 
-    def write_text(self, char* filename):
+    def write_text(self, bytes filename):
         self.darray.write_text(filename)
 
-    def read_binary(self, char* filename):
+    def read_binary(self, bytes filename):
         cdef FILE *f
         f = fopen(filename, "r")
         self.darray.read_handle(f)
@@ -177,7 +180,12 @@ cdef class SuffixArray:
         self.ha.read_handle(f)
         fclose(f)
 
-    def write_binary(self, char* filename):
+    def read_mmaped(self, MemoryMap buf):
+        self.darray.read_mmaped(buf)
+        self.sa.read_mmaped(buf)
+        self.ha.read_mmaped(buf)
+
+    def write_binary(self, bytes filename):
         cdef FILE* f
         f = fopen(filename, "w")
         self.darray.write_handle(f)
@@ -185,7 +193,7 @@ cdef class SuffixArray:
         self.ha.write_handle(f)
         fclose(f)
 
-    def write_enhanced(self, char* filename):
+    def write_enhanced(self, bytes filename):
         with open(filename, "w") as f:
             self.darray.write_enhanced_handle(f)
             for a_i in self.sa:
@@ -243,8 +251,8 @@ cdef class SuffixArray:
             low = 0
         if high == -1:
             high = len(self.sa)
-        if word in self.darray.word2id:
-            word_id = self.darray.word2id[word]
+        word_id = self.darray.voc.get(word, -1)
+        if word_id != -1:
             return self.__lookup_helper(word_id, offset, low, high)
         else:
             return None
diff --git a/python/src/sa/vocabulary.pxi b/python/src/sa/vocabulary.pxi
new file mode 100644
index 00000000..9e816db5
--- /dev/null
+++ b/python/src/sa/vocabulary.pxi
@@ -0,0 +1,64 @@
+cdef class Vocabulary:
+    cdef object id2word, word2id
+
+    def __init__(self, from_vocabulary=None):
+        self.id2word = []
+        self.word2id = {}
+
+    def extend(self, vocabulary):
+        for word in vocabulary:
+            self[word]
+
+    def __iter__(self):
+        return iter(self.id2word)
+
+    def __getitem__(self, word):
+        v = self.word2id.get(word, -1)
+        if v == -1:
+            v = len(self.id2word)
+            self.id2word.append(word)
+            self.word2id[word] = v
+        return v
+
+    def get(self, word, default):
+        return self.word2id.get(word, default)
+
+    def __len__(self):
+        return len(self.id2word)
+
+    cdef void write_handle(self, FILE* f, int offset=0):
+        cdef int word_len
+        cdef int num_words
+
+        num_words = len(self.id2word) - offset
+        fwrite(&(num_words), sizeof(int), 1, f)
+        for word in self.id2word[offset:]:
+            word_len = len(word) + 1
+            fwrite(&(word_len), sizeof(int), 1, f)
+            fwrite(<char *>word, sizeof(char), word_len, f)
+
+    cdef void read_handle(self, FILE* f):
+        cdef int num_words, word_len
+        cdef char* word
+        cdef unsigned i
+
+        fread(&(num_words), sizeof(int), 1, f)
+        for i in range(num_words):
+            fread(&(word_len), sizeof(int), 1, f)
+            word = <char*> malloc (word_len * sizeof(char))
+            fread(word, sizeof(char), word_len, f)
+            self.word2id[word] = len(self.id2word)
+            self.id2word.append(word)
+            free(word)
+
+    cdef void read_mmaped(self, MemoryMap buf):
+        cdef int num_words, word_len
+        cdef char* word
+        cdef unsigned i
+
+        num_words = buf.read_int()
+        for i in range(num_words):
+            word_len = buf.read_int()
+            word = buf.read_char_array(word_len)
+            self.word2id[word] = len(self.id2word)
+            self.id2word.append(word)
-- 
cgit v1.2.3