Generated by Cython 0.25.2

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

Raw output: pa_string_distance.c

 001: # Uncomment one # to activate deeper profiling:
 002: # # cython: profile=True
 003: 
 004: """
 005: Rough todolist:
 006:  - continue optimizing by profiling
 007:  - investigate migrating everyting to "str" instead of "unicode" (we unidecode anyway)
 008: """
 009: 
 010: from __future__ import division
+011: from unidecode import unidecode
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_n_s_unidecode);
  __Pyx_GIVEREF(__pyx_n_s_unidecode);
  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_n_s_unidecode);
  __pyx_t_2 = __Pyx_Import(__pyx_n_s_unidecode, __pyx_t_1, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_unidecode); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_unidecode, __pyx_t_1) < 0) __PYX_ERR(0, 11, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+012: import re2
  __pyx_t_2 = __Pyx_Import(__pyx_n_s_re2, 0, -1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 12, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_re2, __pyx_t_2) < 0) __PYX_ERR(0, 12, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 013: 
+014: RE_SPLIT = re2.compile(r"(?:[^\w]|[_])+")
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_re2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RE_SPLIT, __pyx_t_2) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
/* … */
  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_kp_s_w); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 14, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__4);
  __Pyx_GIVEREF(__pyx_tuple__4);
+015: RE_ISNUM = re2.compile(r"[0-9]")
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_re2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RE_ISNUM, __pyx_t_2) < 0) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
/* … */
  __pyx_tuple__5 = PyTuple_Pack(1, __pyx_kp_s_0_9); if (unlikely(!__pyx_tuple__5)) __PYX_ERR(0, 15, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__5);
  __Pyx_GIVEREF(__pyx_tuple__5);
+016: RE_UNICODE_PRECLEAN = re2.compile(r"""
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_re2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_compile); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
/* … */
  __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple__6, __pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RE_UNICODE_PRECLEAN, __pyx_t_4) < 0) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
/* … */
  __pyx_tuple__6 = PyTuple_Pack(1, __pyx_kp_s_xd8_s_0_9_Diameter_character); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 16, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__6);
  __Pyx_GIVEREF(__pyx_tuple__6);
 017:   (\xd8(?=\s*[0-9]))    # Diameter character
+018: """, flags=re2.VERBOSE)
  __pyx_t_2 = PyDict_New(); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_re2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_VERBOSE); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_flags, __pyx_t_4) < 0) __PYX_ERR(0, 18, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 019: 
+020: cdef bint DEBUG = 0
  __pyx_v_18pa_string_distance_DEBUG = 0;
 021: 
+022: cdef float jaro_winkler_ratio(unicode s1, unicode s2):
static float __pyx_f_18pa_string_distance_jaro_winkler_ratio(PyObject *__pyx_v_s1, PyObject *__pyx_v_s2) {
  float __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("jaro_winkler_ratio", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("pa_string_distance.jaro_winkler_ratio", __pyx_clineno, __pyx_lineno, __pyx_filename, 0, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+023:   return jaro_winkler(s1, len(s1), s2, len(s2), 0)
  __pyx_t_1 = __Pyx_PyUnicode_AsUnicode(__pyx_v_s1); if (unlikely((!__pyx_t_1) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error)
  if (unlikely(__pyx_v_s1 == Py_None)) {
    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
    __PYX_ERR(0, 23, __pyx_L1_error)
  }
  __pyx_t_2 = __Pyx_PyUnicode_GET_LENGTH(__pyx_v_s1); if (unlikely(__pyx_t_2 == -1)) __PYX_ERR(0, 23, __pyx_L1_error)
  __pyx_t_3 = __Pyx_PyUnicode_AsUnicode(__pyx_v_s2); if (unlikely((!__pyx_t_3) && PyErr_Occurred())) __PYX_ERR(0, 23, __pyx_L1_error)
  if (unlikely(__pyx_v_s2 == Py_None)) {
    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
    __PYX_ERR(0, 23, __pyx_L1_error)
  }
  __pyx_t_4 = __Pyx_PyUnicode_GET_LENGTH(__pyx_v_s2); if (unlikely(__pyx_t_4 == -1)) __PYX_ERR(0, 23, __pyx_L1_error)
  __pyx_r = jaro_winkler(__pyx_t_1, __pyx_t_2, __pyx_t_3, __pyx_t_4, 0);
  goto __pyx_L0;
 024: 
 025: 
+026: cdef float norm(float flt, float from1, float to1, float from2, float to2):
static float __pyx_f_18pa_string_distance_norm(float __pyx_v_flt, float __pyx_v_from1, float __pyx_v_to1, float __pyx_v_from2, float __pyx_v_to2) {
  float __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("norm", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_WriteUnraisable("pa_string_distance.norm", __pyx_clineno, __pyx_lineno, __pyx_filename, 0, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+027:   return ((flt - from1) / (to1 - from1)) * (to2 - from2) + from2
  __pyx_t_1 = (__pyx_v_flt - __pyx_v_from1);
  __pyx_t_2 = (__pyx_v_to1 - __pyx_v_from1);
  if (unlikely(__pyx_t_2 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 27, __pyx_L1_error)
  }
  __pyx_r = (((__pyx_t_1 / __pyx_t_2) * (__pyx_v_to2 - __pyx_v_from2)) + __pyx_v_from2);
  goto __pyx_L0;
 028: 
 029: 
 030: # Resampled because we don't care about really different strings
+031: cdef float jaro(unicode s1, unicode s2):
static float __pyx_f_18pa_string_distance_jaro(PyObject *__pyx_v_s1, PyObject *__pyx_v_s2) {
  PyObject *__pyx_v_j = NULL;
  float __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("jaro", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_WriteUnraisable("pa_string_distance.jaro", __pyx_clineno, __pyx_lineno, __pyx_filename, 0, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_j);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+032:   j = jaro_winkler_ratio(s1, s2)
  __pyx_t_1 = PyFloat_FromDouble(__pyx_f_18pa_string_distance_jaro_winkler_ratio(__pyx_v_s1, __pyx_v_s2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_j = __pyx_t_1;
  __pyx_t_1 = 0;
 033: 
+034:   if j < 0.75:
  __pyx_t_1 = PyObject_RichCompare(__pyx_v_j, __pyx_float_0_75, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error)
  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 34, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_2) {
/* … */
  }
+035:     return 0
    __pyx_r = 0.0;
    goto __pyx_L0;
+036:   elif j < 0.85:
  __pyx_t_1 = PyObject_RichCompare(__pyx_v_j, __pyx_float_0_85, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 36, __pyx_L1_error)
  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 36, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_2) {
/* … */
  }
+037:     return norm(j, 0, 0.85, 0, 0.01)
    __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_v_j); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 37, __pyx_L1_error)
    __pyx_r = __pyx_f_18pa_string_distance_norm(__pyx_t_3, 0.0, 0.85, 0.0, 0.01);
    goto __pyx_L0;
 038:   else:
+039:     return norm(j, 0.85, 1, 0.01, 1)
  /*else*/ {
    __pyx_t_3 = __pyx_PyFloat_AsFloat(__pyx_v_j); if (unlikely((__pyx_t_3 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L1_error)
    __pyx_r = __pyx_f_18pa_string_distance_norm(__pyx_t_3, 0.85, 1.0, 0.01, 1.0);
    goto __pyx_L0;
  }
 040: 
 041: 
+042: cdef tokenize(s):
static PyObject *__pyx_f_18pa_string_distance_tokenize(PyObject *__pyx_v_s) {
  PyObject *__pyx_v_u = 0;
  PyObject *__pyx_v_x = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("tokenize", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_AddTraceback("pa_string_distance.tokenize", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_u);
  __Pyx_XDECREF(__pyx_v_x);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 043:   cdef unicode u
+044:   if type(s) == unicode:
  __pyx_t_1 = PyObject_RichCompare(((PyObject *)Py_TYPE(__pyx_v_s)), ((PyObject *)(&PyUnicode_Type)), Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 44, __pyx_L1_error)
  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 44, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_2) {
/* … */
    goto __pyx_L3;
  }
+045:     u = unicode(unidecode(RE_UNICODE_PRECLEAN.sub(" ", s)))
    __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_unidecode); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 45, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_RE_UNICODE_PRECLEAN); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 45, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_sub); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 45, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_5 = NULL;
    __pyx_t_7 = 0;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_6);
      if (likely(__pyx_t_5)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
        __Pyx_INCREF(__pyx_t_5);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_6, function);
        __pyx_t_7 = 1;
      }
    }
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_6)) {
      PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_kp_s_, __pyx_v_s};
      __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 45, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {
      PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_kp_s_, __pyx_v_s};
      __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 45, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    {
      __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 45, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      if (__pyx_t_5) {
        __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_5); __pyx_t_5 = NULL;
      }
      __Pyx_INCREF(__pyx_kp_s_);
      __Pyx_GIVEREF(__pyx_kp_s_);
      PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_kp_s_);
      __Pyx_INCREF(__pyx_v_s);
      __Pyx_GIVEREF(__pyx_v_s);
      PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, __pyx_v_s);
      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 45, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_6 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_3);
      if (likely(__pyx_t_6)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_6);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_3, function);
      }
    }
    if (!__pyx_t_6) {
      __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_GOTREF(__pyx_t_1);
    } else {
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_4};
        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
        PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_4};
        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      } else
      #endif
      {
        __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 45, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
        __Pyx_GIVEREF(__pyx_t_4);
        PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_4);
        __pyx_t_4 = 0;
        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      }
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 45, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1);
    __pyx_t_1 = 0;
    __pyx_t_1 = __Pyx_PyObject_Call(((PyObject *)(&PyUnicode_Type)), __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 45, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_u = ((PyObject*)__pyx_t_1);
    __pyx_t_1 = 0;
 046:   else:
+047:     u = unicode(s)
  /*else*/ {
    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 47, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_INCREF(__pyx_v_s);
    __Pyx_GIVEREF(__pyx_v_s);
    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_s);
    __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)(&PyUnicode_Type)), __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 47, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_u = ((PyObject*)__pyx_t_3);
    __pyx_t_3 = 0;
  }
  __pyx_L3:;
+048:   return [x for x in RE_SPLIT.split(u.lower()) if x]
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 48, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_GetModuleGlobalName(__pyx_n_s_RE_SPLIT); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 48, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_split); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 48, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_v_u, __pyx_n_s_lower); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 48, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_6);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_6, function);
    }
  }
  if (__pyx_t_5) {
    __pyx_t_8 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_5); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 48, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else {
    __pyx_t_8 = __Pyx_PyObject_CallNoArg(__pyx_t_6); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 48, __pyx_L1_error)
  }
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_6)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  if (!__pyx_t_6) {
    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_8};
      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_6, __pyx_t_8};
      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    } else
    #endif
    {
      __pyx_t_5 = PyTuple_New(1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 48, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_6); __pyx_t_6 = NULL;
      __Pyx_GIVEREF(__pyx_t_8);
      PyTuple_SET_ITEM(__pyx_t_5, 0+1, __pyx_t_8);
      __pyx_t_8 = 0;
      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_4 = __pyx_t_1; __Pyx_INCREF(__pyx_t_4); __pyx_t_9 = 0;
    __pyx_t_10 = NULL;
  } else {
    __pyx_t_9 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 48, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_10 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 48, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_10)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_9 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_9); __Pyx_INCREF(__pyx_t_1); __pyx_t_9++; if (unlikely(0 < 0)) __PYX_ERR(0, 48, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_9); __pyx_t_9++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      } else {
        if (__pyx_t_9 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_9); __Pyx_INCREF(__pyx_t_1); __pyx_t_9++; if (unlikely(0 < 0)) __PYX_ERR(0, 48, __pyx_L1_error)
        #else
        __pyx_t_1 = PySequence_ITEM(__pyx_t_4, __pyx_t_9); __pyx_t_9++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 48, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        #endif
      }
    } else {
      __pyx_t_1 = __pyx_t_10(__pyx_t_4);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 48, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_XDECREF_SET(__pyx_v_x, __pyx_t_1);
    __pyx_t_1 = 0;
    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_x); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 48, __pyx_L1_error)
    if (__pyx_t_2) {
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_v_x))) __PYX_ERR(0, 48, __pyx_L1_error)
    }
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;
 049: 
 050: 
+051: cdef float w(tokens, weights):
static float __pyx_f_18pa_string_distance_w(PyObject *__pyx_v_tokens, PyObject *__pyx_v_weights) {
  float __pyx_v_s;
  PyObject *__pyx_v_t = NULL;
  float __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("w", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_WriteUnraisable("pa_string_distance.w", __pyx_clineno, __pyx_lineno, __pyx_filename, 0, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_t);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 052:   """ Returns the weight of a list of tokens """
+053:   cdef float s = 0.0
  __pyx_v_s = 0.0;
+054:   for t in tokens:
  if (likely(PyList_CheckExact(__pyx_v_tokens)) || PyTuple_CheckExact(__pyx_v_tokens)) {
    __pyx_t_1 = __pyx_v_tokens; __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_tokens); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 54, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_3)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __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_ERR(0, 54, __pyx_L1_error)
        #else
        __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
      } else {
        if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __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_ERR(0, 54, __pyx_L1_error)
        #else
        __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
      }
    } else {
      __pyx_t_4 = __pyx_t_3(__pyx_t_1);
      if (unlikely(!__pyx_t_4)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 54, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4);
    __pyx_t_4 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+055:     s += weights[t]
    __pyx_t_4 = PyFloat_FromDouble(__pyx_v_s); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 55, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = PyObject_GetItem(__pyx_v_weights, __pyx_v_t); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 55, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = PyNumber_InPlaceAdd(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 55, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_7 = __pyx_PyFloat_AsFloat(__pyx_t_6); if (unlikely((__pyx_t_7 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 55, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_s = __pyx_t_7;
+056:   return s
  __pyx_r = __pyx_v_s;
  goto __pyx_L0;
 057: 
 058: 
+059: cdef unicode reassemble(joiner, tokens, whitelist):
static PyObject *__pyx_f_18pa_string_distance_reassemble(PyObject *__pyx_v_joiner, PyObject *__pyx_v_tokens, PyObject *__pyx_v_whitelist) {
  PyObject *__pyx_v_t = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("reassemble", 0);
/* … */
  /* function exit code */
  __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_7);
  __Pyx_AddTraceback("pa_string_distance.reassemble", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_t);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+060:   return joiner.join([t for t in tokens if t in whitelist])
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_joiner, __pyx_n_s_join); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 60, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if (likely(PyList_CheckExact(__pyx_v_tokens)) || PyTuple_CheckExact(__pyx_v_tokens)) {
    __pyx_t_4 = __pyx_v_tokens; __Pyx_INCREF(__pyx_t_4); __pyx_t_5 = 0;
    __pyx_t_6 = NULL;
  } else {
    __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_tokens); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 60, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 60, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_6)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 60, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 60, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      } else {
        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 60, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 60, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      }
    } else {
      __pyx_t_7 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_7)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 60, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_7);
    __pyx_t_7 = 0;
    __pyx_t_8 = (__Pyx_PySequence_ContainsTF(__pyx_v_t, __pyx_v_whitelist, Py_EQ)); if (unlikely(__pyx_t_8 < 0)) __PYX_ERR(0, 60, __pyx_L1_error)
    __pyx_t_9 = (__pyx_t_8 != 0);
    if (__pyx_t_9) {
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_3, (PyObject*)__pyx_v_t))) __PYX_ERR(0, 60, __pyx_L1_error)
    }
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_4)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  if (!__pyx_t_4) {
    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_GOTREF(__pyx_t_1);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_2)) {
      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else
    #endif
    {
      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 60, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_4); __pyx_t_4 = NULL;
      __Pyx_GIVEREF(__pyx_t_3);
      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_t_3);
      __pyx_t_3 = 0;
      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (!(likely(PyUnicode_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 60, __pyx_L1_error)
  __pyx_r = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
  goto __pyx_L0;
 061: 
 062: 
+063: def pa_string_distance(str1, str2):
/* Python wrapper */
static PyObject *__pyx_pw_18pa_string_distance_1pa_string_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_18pa_string_distance_1pa_string_distance = {"pa_string_distance", (PyCFunction)__pyx_pw_18pa_string_distance_1pa_string_distance, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_18pa_string_distance_1pa_string_distance(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_str1 = 0;
  PyObject *__pyx_v_str2 = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("pa_string_distance (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_str1,&__pyx_n_s_str2,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_str1)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        case  1:
        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_str2)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("pa_string_distance", 1, 2, 2, 1); __PYX_ERR(0, 63, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "pa_string_distance") < 0)) __PYX_ERR(0, 63, __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_str1 = values[0];
    __pyx_v_str2 = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("pa_string_distance", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 63, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("pa_string_distance.pa_string_distance", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_18pa_string_distance_pa_string_distance(__pyx_self, __pyx_v_str1, __pyx_v_str2);

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_18pa_string_distance_pa_string_distance(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_str1, PyObject *__pyx_v_str2) {
  PyObject *__pyx_v_tokens1 = NULL;
  PyObject *__pyx_v_tokens2 = NULL;
  PyObject *__pyx_v_weights = NULL;
  float __pyx_v_weight1;
  float __pyx_v_weight2;
  PyObject *__pyx_v_t = NULL;
  PyObject *__pyx_v_tokens1_set = NULL;
  PyObject *__pyx_v_tokens2_set = NULL;
  float __pyx_v_max_distance;
  float __pyx_v_distance;
  PyObject *__pyx_v_diff1 = NULL;
  PyObject *__pyx_v_diff1_num = NULL;
  PyObject *__pyx_v_diff2 = NULL;
  PyObject *__pyx_v_diff2_num = NULL;
  float __pyx_v_diff1_weight;
  float __pyx_v_diff2_weight;
  float __pyx_v_diff1_num_weight;
  float __pyx_v_diff2_num_weight;
  float __pyx_v_jaro1;
  float __pyx_v_jaro2;
  float __pyx_v_distance_crossproduct;
  PyObject *__pyx_v_original1 = 0;
  PyObject *__pyx_v_original2 = 0;
  float __pyx_v_weight_originalorder;
  float __pyx_v_distance_originalorder;
  PyObject *__pyx_v_originalnum1 = 0;
  PyObject *__pyx_v_originalnum2 = 0;
  float __pyx_v_coef;
  float __pyx_v_weight_originalorderwithnum;
  float __pyx_v_distance_originalorderwithnum;
  PyObject *__pyx_v_t1 = NULL;
  PyObject *__pyx_v_t2 = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("pa_string_distance", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_AddTraceback("pa_string_distance.pa_string_distance", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_tokens1);
  __Pyx_XDECREF(__pyx_v_tokens2);
  __Pyx_XDECREF(__pyx_v_weights);
  __Pyx_XDECREF(__pyx_v_t);
  __Pyx_XDECREF(__pyx_v_tokens1_set);
  __Pyx_XDECREF(__pyx_v_tokens2_set);
  __Pyx_XDECREF(__pyx_v_diff1);
  __Pyx_XDECREF(__pyx_v_diff1_num);
  __Pyx_XDECREF(__pyx_v_diff2);
  __Pyx_XDECREF(__pyx_v_diff2_num);
  __Pyx_XDECREF(__pyx_v_original1);
  __Pyx_XDECREF(__pyx_v_original2);
  __Pyx_XDECREF(__pyx_v_originalnum1);
  __Pyx_XDECREF(__pyx_v_originalnum2);
  __Pyx_XDECREF(__pyx_v_t1);
  __Pyx_XDECREF(__pyx_v_t2);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__7 = PyTuple_Pack(34, __pyx_n_s_str1, __pyx_n_s_str2, __pyx_n_s_tokens1, __pyx_n_s_tokens2, __pyx_n_s_weights, __pyx_n_s_weight1, __pyx_n_s_weight2, __pyx_n_s_t, __pyx_n_s_tokens1_set, __pyx_n_s_tokens2_set, __pyx_n_s_max_distance, __pyx_n_s_distance, __pyx_n_s_diff1, __pyx_n_s_diff1_num, __pyx_n_s_diff2, __pyx_n_s_diff2_num, __pyx_n_s_diff1_weight, __pyx_n_s_diff2_weight, __pyx_n_s_diff1_num_weight, __pyx_n_s_diff2_num_weight, __pyx_n_s_jaro1, __pyx_n_s_jaro2, __pyx_n_s_distance_crossproduct, __pyx_n_s_original1, __pyx_n_s_original2, __pyx_n_s_weight_originalorder, __pyx_n_s_distance_originalorder, __pyx_n_s_originalnum1, __pyx_n_s_originalnum2, __pyx_n_s_coef, __pyx_n_s_weight_originalorderwithnum, __pyx_n_s_distance_originalorderwithnum, __pyx_n_s_t1, __pyx_n_s_t2); if (unlikely(!__pyx_tuple__7)) __PYX_ERR(0, 63, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__7);
  __Pyx_GIVEREF(__pyx_tuple__7);
/* … */
  __pyx_t_4 = PyCFunction_NewEx(&__pyx_mdef_18pa_string_distance_1pa_string_distance, NULL, __pyx_n_s_pa_string_distance); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 63, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_pa_string_distance, __pyx_t_4) < 0) __PYX_ERR(0, 63, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 064: 
+065:   if not str1 or not str2:
  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_str1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 65, __pyx_L1_error)
  __pyx_t_3 = ((!__pyx_t_2) != 0);
  if (!__pyx_t_3) {
  } else {
    __pyx_t_1 = __pyx_t_3;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_str2); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 65, __pyx_L1_error)
  __pyx_t_2 = ((!__pyx_t_3) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
+066:     return 1.0
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(__pyx_float_1_0);
    __pyx_r = __pyx_float_1_0;
    goto __pyx_L0;
 067: 
+068:   tokens1 = tokenize(str1)
  __pyx_t_4 = __pyx_f_18pa_string_distance_tokenize(__pyx_v_str1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_tokens1 = __pyx_t_4;
  __pyx_t_4 = 0;
+069:   tokens2 = tokenize(str2)
  __pyx_t_4 = __pyx_f_18pa_string_distance_tokenize(__pyx_v_str2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 69, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_tokens2 = __pyx_t_4;
  __pyx_t_4 = 0;
 070: 
+071:   if len(tokens1) == 0 or len(tokens2) == 0:
  __pyx_t_5 = PyObject_Length(__pyx_v_tokens1); if (unlikely(__pyx_t_5 == -1)) __PYX_ERR(0, 71, __pyx_L1_error)
  __pyx_t_2 = ((__pyx_t_5 == 0) != 0);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L7_bool_binop_done;
  }
  __pyx_t_5 = PyObject_Length(__pyx_v_tokens2); if (unlikely(__pyx_t_5 == -1)) __PYX_ERR(0, 71, __pyx_L1_error)
  __pyx_t_2 = ((__pyx_t_5 == 0) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L7_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
+072:     return 1.0
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(__pyx_float_1_0);
    __pyx_r = __pyx_float_1_0;
    goto __pyx_L0;
 073: 
+074:   weights = {}
  __pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_weights = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
+075:   cdef float weight1 = 0.0
  __pyx_v_weight1 = 0.0;
+076:   cdef float weight2 = 0.0
  __pyx_v_weight2 = 0.0;
 077: 
+078:   for t in tokens1:
  if (likely(PyList_CheckExact(__pyx_v_tokens1)) || PyTuple_CheckExact(__pyx_v_tokens1)) {
    __pyx_t_4 = __pyx_v_tokens1; __Pyx_INCREF(__pyx_t_4); __pyx_t_5 = 0;
    __pyx_t_6 = NULL;
  } else {
    __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_tokens1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 78, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 78, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_6)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 78, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 78, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      } else {
        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 78, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 78, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      }
    } else {
      __pyx_t_7 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_7)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 78, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_7);
    __pyx_t_7 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+079:     weight1 += len(t)
    __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 79, __pyx_L1_error)
    __pyx_v_weight1 = (__pyx_v_weight1 + __pyx_t_8);
+080:     if t in weights:
    __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_t, __pyx_v_weights, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 80, __pyx_L1_error)
    __pyx_t_2 = (__pyx_t_1 != 0);
    if (__pyx_t_2) {
/* … */
      goto __pyx_L11;
    }
+081:       weights[t] += len(t)
      __Pyx_INCREF(__pyx_v_t);
      __pyx_t_7 = __pyx_v_t;
      __pyx_t_9 = __Pyx_PyDict_GetItem(__pyx_v_weights, __pyx_t_7); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 81, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 81, __pyx_L1_error)
      __pyx_t_10 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 81, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_11 = PyNumber_InPlaceAdd(__pyx_t_9, __pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 81, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      if (unlikely(PyDict_SetItem(__pyx_v_weights, __pyx_t_7, __pyx_t_11) < 0)) __PYX_ERR(0, 81, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 082:     else:
+083:       weights[t] = len(t)
    /*else*/ {
      __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 83, __pyx_L1_error)
      __pyx_t_7 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 83, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (unlikely(PyDict_SetItem(__pyx_v_weights, __pyx_v_t, __pyx_t_7) < 0)) __PYX_ERR(0, 83, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    }
    __pyx_L11:;
 084: 
+085:   for t in tokens2:
  if (likely(PyList_CheckExact(__pyx_v_tokens2)) || PyTuple_CheckExact(__pyx_v_tokens2)) {
    __pyx_t_4 = __pyx_v_tokens2; __Pyx_INCREF(__pyx_t_4); __pyx_t_5 = 0;
    __pyx_t_6 = NULL;
  } else {
    __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_tokens2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 85, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 85, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_6)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 85, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 85, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      } else {
        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 85, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 85, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      }
    } else {
      __pyx_t_7 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_7)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 85, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_7);
    __pyx_t_7 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+086:     weight2 += len(t)
    __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 86, __pyx_L1_error)
    __pyx_v_weight2 = (__pyx_v_weight2 + __pyx_t_8);
+087:     if t in weights:
    __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_t, __pyx_v_weights, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 87, __pyx_L1_error)
    __pyx_t_1 = (__pyx_t_2 != 0);
    if (__pyx_t_1) {
/* … */
      goto __pyx_L14;
    }
+088:       weights[t] += len(t)
      __Pyx_INCREF(__pyx_v_t);
      __pyx_t_7 = __pyx_v_t;
      __pyx_t_11 = __Pyx_PyDict_GetItem(__pyx_v_weights, __pyx_t_7); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 88, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 88, __pyx_L1_error)
      __pyx_t_10 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 88, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_9 = PyNumber_InPlaceAdd(__pyx_t_11, __pyx_t_10); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 88, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      if (unlikely(PyDict_SetItem(__pyx_v_weights, __pyx_t_7, __pyx_t_9) < 0)) __PYX_ERR(0, 88, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
 089:     else:
+090:       weights[t] = len(t)
    /*else*/ {
      __pyx_t_8 = PyObject_Length(__pyx_v_t); if (unlikely(__pyx_t_8 == -1)) __PYX_ERR(0, 90, __pyx_L1_error)
      __pyx_t_7 = PyInt_FromSsize_t(__pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 90, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (unlikely(PyDict_SetItem(__pyx_v_weights, __pyx_v_t, __pyx_t_7) < 0)) __PYX_ERR(0, 90, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    }
    __pyx_L14:;
 091: 
+092:   tokens1_set = set(tokens1)
  __pyx_t_4 = PySet_New(__pyx_v_tokens1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 92, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_tokens1_set = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
+093:   tokens2_set = set(tokens2)
  __pyx_t_4 = PySet_New(__pyx_v_tokens2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 93, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_tokens2_set = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
 094: 
 095:   # print tokens1_set, tokens2_set
 096: 
+097:   cdef float max_distance = weight1 + weight2
  __pyx_v_max_distance = (__pyx_v_weight1 + __pyx_v_weight2);
+098:   cdef float distance = 0.0
  __pyx_v_distance = 0.0;
 099: 
+100:   diff1 = set()
  __pyx_t_4 = PySet_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 100, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_diff1 = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
+101:   diff1_num = set()
  __pyx_t_4 = PySet_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 101, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_diff1_num = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
 102: 
+103:   diff2 = set()
  __pyx_t_4 = PySet_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 103, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_diff2 = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
+104:   diff2_num = set()
  __pyx_t_4 = PySet_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 104, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_diff2_num = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
 105: 
+106:   for t in tokens1_set.difference(tokens2_set):
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_tokens1_set, __pyx_n_s_difference); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 106, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_9 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    if (likely(__pyx_t_9)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_7, function);
    }
  }
  if (!__pyx_t_9) {
    __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_tokens2_set); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_7)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens2_set};
      __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens2_set};
      __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    {
      __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 106, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_9); __pyx_t_9 = NULL;
      __Pyx_INCREF(__pyx_v_tokens2_set);
      __Pyx_GIVEREF(__pyx_v_tokens2_set);
      PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_v_tokens2_set);
      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_10, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) {
    __pyx_t_7 = __pyx_t_4; __Pyx_INCREF(__pyx_t_7); __pyx_t_5 = 0;
    __pyx_t_6 = NULL;
  } else {
    __pyx_t_5 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 106, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_6 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 106, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  for (;;) {
    if (likely(!__pyx_t_6)) {
      if (likely(PyList_CheckExact(__pyx_t_7))) {
        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_7)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_4 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_4); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 106, __pyx_L1_error)
        #else
        __pyx_t_4 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
      } else {
        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_4); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 106, __pyx_L1_error)
        #else
        __pyx_t_4 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 106, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        #endif
      }
    } else {
      __pyx_t_4 = __pyx_t_6(__pyx_t_7);
      if (unlikely(!__pyx_t_4)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 106, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_4);
    __pyx_t_4 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+107:     if RE_ISNUM.search(t):
    __pyx_t_10 = __Pyx_GetModuleGlobalName(__pyx_n_s_RE_ISNUM); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 107, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_search); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 107, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __pyx_t_10 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
      __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_9);
      if (likely(__pyx_t_10)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_10);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_9, function);
      }
    }
    if (!__pyx_t_10) {
      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_v_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    } else {
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[2] = {__pyx_t_10, __pyx_v_t};
        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
        __Pyx_GOTREF(__pyx_t_4);
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[2] = {__pyx_t_10, __pyx_v_t};
        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
        __Pyx_GOTREF(__pyx_t_4);
      } else
      #endif
      {
        __pyx_t_11 = PyTuple_New(1+1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 107, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_11);
        __Pyx_GIVEREF(__pyx_t_10); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_10); __pyx_t_10 = NULL;
        __Pyx_INCREF(__pyx_v_t);
        __Pyx_GIVEREF(__pyx_v_t);
        PyTuple_SET_ITEM(__pyx_t_11, 0+1, __pyx_v_t);
        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_11, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      }
    }
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 107, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (__pyx_t_1) {
/* … */
      goto __pyx_L17;
    }
+108:       diff1_num.add(t)
      __pyx_t_12 = PySet_Add(__pyx_v_diff1_num, __pyx_v_t); if (unlikely(__pyx_t_12 == -1)) __PYX_ERR(0, 108, __pyx_L1_error)
 109:     else:
+110:       diff1.add(t)
    /*else*/ {
      __pyx_t_12 = PySet_Add(__pyx_v_diff1, __pyx_v_t); if (unlikely(__pyx_t_12 == -1)) __PYX_ERR(0, 110, __pyx_L1_error)
    }
    __pyx_L17:;
 111: 
+112:   for t in tokens2_set.difference(tokens1_set):
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_tokens2_set, __pyx_n_s_difference); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 112, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_9 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_9)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  if (!__pyx_t_9) {
    __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_tokens1_set); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens1_set};
      __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_7);
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens1_set};
      __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_7);
    } else
    #endif
    {
      __pyx_t_11 = PyTuple_New(1+1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 112, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL;
      __Pyx_INCREF(__pyx_v_tokens1_set);
      __Pyx_GIVEREF(__pyx_v_tokens1_set);
      PyTuple_SET_ITEM(__pyx_t_11, 0+1, __pyx_v_tokens1_set);
      __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_11, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (likely(PyList_CheckExact(__pyx_t_7)) || PyTuple_CheckExact(__pyx_t_7)) {
    __pyx_t_4 = __pyx_t_7; __Pyx_INCREF(__pyx_t_4); __pyx_t_5 = 0;
    __pyx_t_6 = NULL;
  } else {
    __pyx_t_5 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 112, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 112, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  for (;;) {
    if (likely(!__pyx_t_6)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 112, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      } else {
        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_7 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_5); __Pyx_INCREF(__pyx_t_7); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 112, __pyx_L1_error)
        #else
        __pyx_t_7 = PySequence_ITEM(__pyx_t_4, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 112, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        #endif
      }
    } else {
      __pyx_t_7 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_7)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 112, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_7);
    __pyx_t_7 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+113:     if RE_ISNUM.search(t):
    __pyx_t_11 = __Pyx_GetModuleGlobalName(__pyx_n_s_RE_ISNUM); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 113, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_search); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 113, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __pyx_t_11 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_9))) {
      __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_9);
      if (likely(__pyx_t_11)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_11);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_9, function);
      }
    }
    if (!__pyx_t_11) {
      __pyx_t_7 = __Pyx_PyObject_CallOneArg(__pyx_t_9, __pyx_v_t); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 113, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    } else {
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[2] = {__pyx_t_11, __pyx_v_t};
        __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_9, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 113, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
        __Pyx_GOTREF(__pyx_t_7);
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_9)) {
        PyObject *__pyx_temp[2] = {__pyx_t_11, __pyx_v_t};
        __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_9, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 113, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
        __Pyx_GOTREF(__pyx_t_7);
      } else
      #endif
      {
        __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 113, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_GIVEREF(__pyx_t_11); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_11); __pyx_t_11 = NULL;
        __Pyx_INCREF(__pyx_v_t);
        __Pyx_GIVEREF(__pyx_v_t);
        PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_v_t);
        __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_9, __pyx_t_10, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 113, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      }
    }
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 113, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (__pyx_t_1) {
/* … */
      goto __pyx_L20;
    }
+114:       diff2_num.add(t)
      __pyx_t_12 = PySet_Add(__pyx_v_diff2_num, __pyx_v_t); if (unlikely(__pyx_t_12 == -1)) __PYX_ERR(0, 114, __pyx_L1_error)
 115:     else:
+116:       diff2.add(t)
    /*else*/ {
      __pyx_t_12 = PySet_Add(__pyx_v_diff2, __pyx_v_t); if (unlikely(__pyx_t_12 == -1)) __PYX_ERR(0, 116, __pyx_L1_error)
    }
    __pyx_L20:;
 117: 
+118:   cdef float diff1_weight = w(diff1, weights)
  __pyx_v_diff1_weight = __pyx_f_18pa_string_distance_w(__pyx_v_diff1, __pyx_v_weights);
+119:   cdef float diff2_weight = w(diff2, weights)
  __pyx_v_diff2_weight = __pyx_f_18pa_string_distance_w(__pyx_v_diff2, __pyx_v_weights);
+120:   cdef float diff1_num_weight = w(diff1_num, weights)
  __pyx_v_diff1_num_weight = __pyx_f_18pa_string_distance_w(__pyx_v_diff1_num, __pyx_v_weights);
+121:   cdef float diff2_num_weight = w(diff2_num, weights)
  __pyx_v_diff2_num_weight = __pyx_f_18pa_string_distance_w(__pyx_v_diff2_num, __pyx_v_weights);
 122: 
+123:   if DEBUG:
  __pyx_t_1 = (__pyx_v_18pa_string_distance_DEBUG != 0);
  if (__pyx_t_1) {
/* … */
  }
+124:     print "intersection tokens ", tokens1_set.intersection(tokens2_set)
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_tokens1_set, __pyx_n_s_intersection); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 124, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_9 = NULL;
    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
      if (likely(__pyx_t_9)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
        __Pyx_INCREF(__pyx_t_9);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_7, function);
      }
    }
    if (!__pyx_t_9) {
      __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_tokens2_set); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 124, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    } else {
      #if CYTHON_FAST_PYCALL
      if (PyFunction_Check(__pyx_t_7)) {
        PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens2_set};
        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 124, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        __Pyx_GOTREF(__pyx_t_4);
      } else
      #endif
      #if CYTHON_FAST_PYCCALL
      if (__Pyx_PyFastCFunction_Check(__pyx_t_7)) {
        PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_tokens2_set};
        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_7, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 124, __pyx_L1_error)
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        __Pyx_GOTREF(__pyx_t_4);
      } else
      #endif
      {
        __pyx_t_10 = PyTuple_New(1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 124, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_10);
        __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_9); __pyx_t_9 = NULL;
        __Pyx_INCREF(__pyx_v_tokens2_set);
        __Pyx_GIVEREF(__pyx_v_tokens2_set);
        PyTuple_SET_ITEM(__pyx_t_10, 0+1, __pyx_v_tokens2_set);
        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_10, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 124, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      }
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 124, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_INCREF(__pyx_kp_s_intersection_tokens);
    __Pyx_GIVEREF(__pyx_kp_s_intersection_tokens);
    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_kp_s_intersection_tokens);
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_4);
    __pyx_t_4 = 0;
    if (__Pyx_Print(0, __pyx_t_7, 1) < 0) __PYX_ERR(0, 124, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+125:     print "diff tokens1", diff1, diff1_num
    __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 125, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_INCREF(__pyx_kp_s_diff_tokens1);
    __Pyx_GIVEREF(__pyx_kp_s_diff_tokens1);
    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_kp_s_diff_tokens1);
    __Pyx_INCREF(__pyx_v_diff1);
    __Pyx_GIVEREF(__pyx_v_diff1);
    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_diff1);
    __Pyx_INCREF(__pyx_v_diff1_num);
    __Pyx_GIVEREF(__pyx_v_diff1_num);
    PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_diff1_num);
    if (__Pyx_Print(0, __pyx_t_7, 1) < 0) __PYX_ERR(0, 125, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+126:     print "diff tokens2",  diff2, diff2_num
    __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 126, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_INCREF(__pyx_kp_s_diff_tokens2);
    __Pyx_GIVEREF(__pyx_kp_s_diff_tokens2);
    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_kp_s_diff_tokens2);
    __Pyx_INCREF(__pyx_v_diff2);
    __Pyx_GIVEREF(__pyx_v_diff2);
    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_diff2);
    __Pyx_INCREF(__pyx_v_diff2_num);
    __Pyx_GIVEREF(__pyx_v_diff2_num);
    PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_diff2_num);
    if (__Pyx_Print(0, __pyx_t_7, 1) < 0) __PYX_ERR(0, 126, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+127:     print "max diff / max distance", diff1_weight + diff2_weight + diff1_num_weight + diff2_num_weight, "/", max_distance
    __pyx_t_7 = PyFloat_FromDouble((((__pyx_v_diff1_weight + __pyx_v_diff2_weight) + __pyx_v_diff1_num_weight) + __pyx_v_diff2_num_weight)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 127, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_4 = PyFloat_FromDouble(__pyx_v_max_distance); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 127, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_10 = PyTuple_New(4); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 127, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_INCREF(__pyx_kp_s_max_diff_max_distance);
    __Pyx_GIVEREF(__pyx_kp_s_max_diff_max_distance);
    PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_kp_s_max_diff_max_distance);
    __Pyx_GIVEREF(__pyx_t_7);
    PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_7);
    __Pyx_INCREF(__pyx_kp_s__2);
    __Pyx_GIVEREF(__pyx_kp_s__2);
    PyTuple_SET_ITEM(__pyx_t_10, 2, __pyx_kp_s__2);
    __Pyx_GIVEREF(__pyx_t_4);
    PyTuple_SET_ITEM(__pyx_t_10, 3, __pyx_t_4);
    __pyx_t_7 = 0;
    __pyx_t_4 = 0;
    if (__Pyx_Print(0, __pyx_t_10, 1) < 0) __PYX_ERR(0, 127, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+128:     print "token weights", weights
    __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 128, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_INCREF(__pyx_kp_s_token_weights);
    __Pyx_GIVEREF(__pyx_kp_s_token_weights);
    PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_kp_s_token_weights);
    __Pyx_INCREF(__pyx_v_weights);
    __Pyx_GIVEREF(__pyx_v_weights);
    PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_v_weights);
    if (__Pyx_Print(0, __pyx_t_10, 1) < 0) __PYX_ERR(0, 128, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
 129: 
+130:   distance += diff1_num_weight + diff2_num_weight
  __pyx_v_distance = (__pyx_v_distance + (__pyx_v_diff1_num_weight + __pyx_v_diff2_num_weight));
 131: 
+132:   if len(diff1) == 0 and len(diff2) == 0:
  __pyx_t_5 = PySet_GET_SIZE(__pyx_v_diff1); if (unlikely(__pyx_t_5 == -1)) __PYX_ERR(0, 132, __pyx_L1_error)
  __pyx_t_2 = ((__pyx_t_5 == 0) != 0);
  if (__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L23_bool_binop_done;
  }
  __pyx_t_5 = PySet_GET_SIZE(__pyx_v_diff2); if (unlikely(__pyx_t_5 == -1)) __PYX_ERR(0, 132, __pyx_L1_error)
  __pyx_t_2 = ((__pyx_t_5 == 0) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L23_bool_binop_done:;
  if (__pyx_t_1) {
/* … */
  }
+133:     return distance / max_distance
    __Pyx_XDECREF(__pyx_r);
    if (unlikely(__pyx_v_max_distance == 0)) {
      PyErr_SetString(PyExc_ZeroDivisionError, "float division");
      __PYX_ERR(0, 133, __pyx_L1_error)
    }
    __pyx_t_10 = PyFloat_FromDouble((__pyx_v_distance / __pyx_v_max_distance)); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 133, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_r = __pyx_t_10;
    __pyx_t_10 = 0;
    goto __pyx_L0;
 134: 
 135:   #
 136:   # By now, we have eliminated all the simple cases.
 137:   # Compare the remainders with a few different methods and pick the lowest distance.
 138:   #
 139: 
 140:   # 1: smallest jaro distance in all the tokens of the other string
+141:   cdef float jaro1 = sum([min([1 - jaro(t1, t2) for t2 in tokens2_set]) * weights[t1] for t1 in diff1])
  __pyx_t_10 = PyList_New(0); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 141, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_4 = PyObject_GetIter(__pyx_v_diff1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 141, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 141, __pyx_L1_error)
  for (;;) {
    {
      __pyx_t_7 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_7)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 141, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_7);
    __pyx_t_7 = 0;
    __pyx_t_7 = PyList_New(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_9 = PyObject_GetIter(__pyx_v_tokens2_set); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_13 = Py_TYPE(__pyx_t_9)->tp_iternext; if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 141, __pyx_L1_error)
    for (;;) {
      {
        __pyx_t_11 = __pyx_t_13(__pyx_t_9);
        if (unlikely(!__pyx_t_11)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 141, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_11);
      }
      __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_11);
      __pyx_t_11 = 0;
      if (!(likely(PyUnicode_CheckExact(__pyx_v_t1))||((__pyx_v_t1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_t1)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error)
      if (!(likely(PyUnicode_CheckExact(__pyx_v_t2))||((__pyx_v_t2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_t2)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error)
      __pyx_t_11 = PyFloat_FromDouble((1.0 - __pyx_f_18pa_string_distance_jaro(((PyObject*)__pyx_v_t1), ((PyObject*)__pyx_v_t2)))); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 141, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_7, (PyObject*)__pyx_t_11))) __PYX_ERR(0, 141, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    }
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_GIVEREF(__pyx_t_7);
    PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7);
    __pyx_t_7 = 0;
    __pyx_t_7 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_9, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_9 = __Pyx_PyDict_GetItem(__pyx_v_weights, __pyx_v_t1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_11 = PyNumber_Multiply(__pyx_t_7, __pyx_t_9); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(__Pyx_ListComp_Append(__pyx_t_10, (PyObject*)__pyx_t_11))) __PYX_ERR(0, 141, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 141, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_10);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_10);
  __pyx_t_10 = 0;
  __pyx_t_10 = __Pyx_PyObject_Call(__pyx_builtin_sum, __pyx_t_4, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 141, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_14 = __pyx_PyFloat_AsFloat(__pyx_t_10); if (unlikely((__pyx_t_14 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 141, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_v_jaro1 = __pyx_t_14;
+142:   cdef float jaro2 = sum([min([1 - jaro(t1, t2) for t1 in tokens1_set]) * weights[t2] for t2 in diff2])
  __pyx_t_10 = PyList_New(0); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 142, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_4 = PyObject_GetIter(__pyx_v_diff2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 142, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 142, __pyx_L1_error)
  for (;;) {
    {
      __pyx_t_11 = __pyx_t_6(__pyx_t_4);
      if (unlikely(!__pyx_t_11)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 142, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_11);
    }
    __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_11);
    __pyx_t_11 = 0;
    __pyx_t_11 = PyList_New(0); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_9 = PyObject_GetIter(__pyx_v_tokens1_set); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_13 = Py_TYPE(__pyx_t_9)->tp_iternext; if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 142, __pyx_L1_error)
    for (;;) {
      {
        __pyx_t_7 = __pyx_t_13(__pyx_t_9);
        if (unlikely(!__pyx_t_7)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 142, __pyx_L1_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_7);
      }
      __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_7);
      __pyx_t_7 = 0;
      if (!(likely(PyUnicode_CheckExact(__pyx_v_t1))||((__pyx_v_t1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_t1)->tp_name), 0))) __PYX_ERR(0, 142, __pyx_L1_error)
      if (!(likely(PyUnicode_CheckExact(__pyx_v_t2))||((__pyx_v_t2) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "unicode", Py_TYPE(__pyx_v_t2)->tp_name), 0))) __PYX_ERR(0, 142, __pyx_L1_error)
      __pyx_t_7 = PyFloat_FromDouble((1.0 - __pyx_f_18pa_string_distance_jaro(((PyObject*)__pyx_v_t1), ((PyObject*)__pyx_v_t2)))); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 142, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_11, (PyObject*)__pyx_t_7))) __PYX_ERR(0, 142, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    }
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_9 = PyTuple_New(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_GIVEREF(__pyx_t_11);
    PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_11);
    __pyx_t_11 = 0;
    __pyx_t_11 = __Pyx_PyObject_Call(__pyx_builtin_min, __pyx_t_9, NULL); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_9 = __Pyx_PyDict_GetItem(__pyx_v_weights, __pyx_v_t2); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_7 = PyNumber_Multiply(__pyx_t_11, __pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(__Pyx_ListComp_Append(__pyx_t_10, (PyObject*)__pyx_t_7))) __PYX_ERR(0, 142, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 142, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_10);
  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_10);
  __pyx_t_10 = 0;
  __pyx_t_10 = __Pyx_PyObject_Call(__pyx_builtin_sum, __pyx_t_4, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 142, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_14 = __pyx_PyFloat_AsFloat(__pyx_t_10); if (unlikely((__pyx_t_14 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 142, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_v_jaro2 = __pyx_t_14;
 143: 
+144:   cdef float distance_crossproduct = (distance + jaro1 + jaro2)
  __pyx_v_distance_crossproduct = ((__pyx_v_distance + __pyx_v_jaro1) + __pyx_v_jaro2);
 145: 
 146:   # for t1 in diff1:
 147:   #   print [(t1, t2, jaro(t1, t2)) for t2 in tokens2_set if jaro(t1, t2)]
 148:   # for t2 in diff2:
 149:   #   print [(t1, t2, jaro(t1, t2)) for t1 in tokens1_set if jaro(t1, t2)]
 150: 
 151: 
 152:   # 2: original order diffs
+153:   cdef unicode original1 = reassemble(u" ", tokens1, diff1)
  __pyx_t_10 = __pyx_f_18pa_string_distance_reassemble(__pyx_kp_u_, __pyx_v_tokens1, __pyx_v_diff1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 153, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_v_original1 = ((PyObject*)__pyx_t_10);
  __pyx_t_10 = 0;
+154:   cdef unicode original2 = reassemble(u" ", tokens2, diff2)
  __pyx_t_10 = __pyx_f_18pa_string_distance_reassemble(__pyx_kp_u_, __pyx_v_tokens2, __pyx_v_diff2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 154, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_v_original2 = ((PyObject*)__pyx_t_10);
  __pyx_t_10 = 0;
 155: 
+156:   cdef float weight_originalorder = (1 - jaro(original1, original2)) * (diff1_weight + diff2_weight)
  __pyx_v_weight_originalorder = ((1.0 - __pyx_f_18pa_string_distance_jaro(__pyx_v_original1, __pyx_v_original2)) * (__pyx_v_diff1_weight + __pyx_v_diff2_weight));
+157:   cdef float distance_originalorder = (distance + weight_originalorder)
  __pyx_v_distance_originalorder = (__pyx_v_distance + __pyx_v_weight_originalorder);
 158: 
 159:   # 2: original order diffs, with numerics
+160:   cdef unicode originalnum1 = reassemble(u"", tokens1, diff1.union(diff1_num))
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_diff1, __pyx_n_s_union); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_7)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  if (!__pyx_t_7) {
    __pyx_t_10 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_diff1_num); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 160, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_diff1_num};
      __pyx_t_10 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 160, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_GOTREF(__pyx_t_10);
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {
      PyObject *__pyx_temp[2] = {__pyx_t_7, __pyx_v_diff1_num};
      __pyx_t_10 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 160, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_GOTREF(__pyx_t_10);
    } else
    #endif
    {
      __pyx_t_9 = PyTuple_New(1+1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 160, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_GIVEREF(__pyx_t_7); PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_t_7); __pyx_t_7 = NULL;
      __Pyx_INCREF(__pyx_v_diff1_num);
      __Pyx_GIVEREF(__pyx_v_diff1_num);
      PyTuple_SET_ITEM(__pyx_t_9, 0+1, __pyx_v_diff1_num);
      __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_9, NULL); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 160, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __pyx_f_18pa_string_distance_reassemble(__pyx_kp_u__3, __pyx_v_tokens1, __pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_v_originalnum1 = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;
+161:   cdef unicode originalnum2 = reassemble(u"", tokens2, diff2.union(diff2_num))
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_v_diff2, __pyx_n_s_union); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 161, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_9 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_10))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_10);
    if (likely(__pyx_t_9)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_10);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_10, function);
    }
  }
  if (!__pyx_t_9) {
    __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_t_10, __pyx_v_diff2_num); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 161, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  } else {
    #if CYTHON_FAST_PYCALL
    if (PyFunction_Check(__pyx_t_10)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_diff2_num};
      __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_10, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 161, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    #if CYTHON_FAST_PYCCALL
    if (__Pyx_PyFastCFunction_Check(__pyx_t_10)) {
      PyObject *__pyx_temp[2] = {__pyx_t_9, __pyx_v_diff2_num};
      __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_10, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 161, __pyx_L1_error)
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_GOTREF(__pyx_t_4);
    } else
    #endif
    {
      __pyx_t_7 = PyTuple_New(1+1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 161, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_9); __pyx_t_9 = NULL;
      __Pyx_INCREF(__pyx_v_diff2_num);
      __Pyx_GIVEREF(__pyx_v_diff2_num);
      PyTuple_SET_ITEM(__pyx_t_7, 0+1, __pyx_v_diff2_num);
      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_10, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 161, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = __pyx_f_18pa_string_distance_reassemble(__pyx_kp_u__3, __pyx_v_tokens2, __pyx_t_4); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 161, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_originalnum2 = ((PyObject*)__pyx_t_10);
  __pyx_t_10 = 0;
 162: 
+163:   cdef float coef = (diff1_weight + diff2_weight + diff1_num_weight + diff2_num_weight)
  __pyx_v_coef = (((__pyx_v_diff1_weight + __pyx_v_diff2_weight) + __pyx_v_diff1_num_weight) + __pyx_v_diff2_num_weight);
+164:   cdef float weight_originalorderwithnum = (1 - jaro(originalnum1, originalnum2)) * coef
  __pyx_v_weight_originalorderwithnum = ((1.0 - __pyx_f_18pa_string_distance_jaro(__pyx_v_originalnum1, __pyx_v_originalnum2)) * __pyx_v_coef);
+165:   cdef float distance_originalorderwithnum = min(weight_originalorderwithnum + 0.01, coef)  # Add an additional fixed distance here to differentiate cases.
  __pyx_t_14 = __pyx_v_coef;
  __pyx_t_15 = (__pyx_v_weight_originalorderwithnum + 0.01);
  if (((__pyx_t_14 < __pyx_t_15) != 0)) {
    __pyx_t_16 = __pyx_t_14;
  } else {
    __pyx_t_16 = __pyx_t_15;
  }
  __pyx_v_distance_originalorderwithnum = __pyx_t_16;
 166: 
+167:   if DEBUG:
  __pyx_t_1 = (__pyx_v_18pa_string_distance_DEBUG != 0);
  if (__pyx_t_1) {
/* … */
  }
+168:     print "distance_crossproduct: %s" % distance_crossproduct
    __pyx_t_10 = PyFloat_FromDouble(__pyx_v_distance_crossproduct); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 168, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_distance_crossproduct_s, __pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 168, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (__Pyx_PrintOne(0, __pyx_t_4) < 0) __PYX_ERR(0, 168, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+169:     print "distance_originalorder: %s" % distance_originalorder
    __pyx_t_4 = PyFloat_FromDouble(__pyx_v_distance_originalorder); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 169, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_10 = __Pyx_PyString_Format(__pyx_kp_s_distance_originalorder_s, __pyx_t_4); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 169, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (__Pyx_PrintOne(0, __pyx_t_10) < 0) __PYX_ERR(0, 169, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+170:     print "distance_originalorderwithnum: %s" % distance_originalorderwithnum
    __pyx_t_10 = PyFloat_FromDouble(__pyx_v_distance_originalorderwithnum); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 170, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_4 = __Pyx_PyString_Format(__pyx_kp_s_distance_originalorderwithnum_s, __pyx_t_10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 170, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (__Pyx_PrintOne(0, __pyx_t_4) < 0) __PYX_ERR(0, 170, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 171: 
+172:   return min([distance_crossproduct, distance_originalorder, distance_originalorderwithnum]) / max_distance
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_14 = __pyx_v_distance_originalorder;
  __pyx_t_17 = __pyx_v_distance_originalorderwithnum;
  __pyx_t_18 = __pyx_v_distance_crossproduct;
  if (((__pyx_t_14 < __pyx_t_18) != 0)) {
    __pyx_t_19 = __pyx_t_14;
  } else {
    __pyx_t_19 = __pyx_t_18;
  }
  __pyx_t_18 = __pyx_t_19;
  if (((__pyx_t_17 < __pyx_t_18) != 0)) {
    __pyx_t_19 = __pyx_t_17;
  } else {
    __pyx_t_19 = __pyx_t_18;
  }
  __pyx_t_14 = __pyx_t_19;
  if (unlikely(__pyx_v_max_distance == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 172, __pyx_L1_error)
  }
  __pyx_t_4 = PyFloat_FromDouble((__pyx_t_14 / __pyx_v_max_distance)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 172, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_r = __pyx_t_4;
  __pyx_t_4 = 0;
  goto __pyx_L0;