/* Generated by Cython 3.2.4 */

/* BEGIN: Cython Metadata
{
    "distutils": {
        "define_macros": [
            [
                "NPY_NO_DEPRECATED_API",
                "NPY_1_7_API_VERSION"
            ]
        ],
        "depends": [
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayobject.h",
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include/numpy/arrayscalars.h",
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarrayobject.h",
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include/numpy/ndarraytypes.h",
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include/numpy/ufuncobject.h",
            "src/pygeoprocessing/extensions/FastFileIterator.h",
            "src/pygeoprocessing/extensions/LRUCache.h",
            "src/pygeoprocessing/extensions/ManagedRaster.h"
        ],
        "extra_compile_args": [
            "-I/home/runner/micromamba/envs/env/include",
            "-std=c++20"
        ],
        "extra_link_args": [
            "-std=c++20"
        ],
        "include_dirs": [
            "src/pygeoprocessing",
            "/tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/_core/include",
            "src/pygeoprocessing/routing",
            "src/pygeoprocessing/extensions"
        ],
        "language": "c++",
        "libraries": [
            "gdal"
        ],
        "library_dirs": [
            "/home/runner/micromamba/envs/env/lib"
        ],
        "name": "pygeoprocessing.routing.routing",
        "sources": [
            "src/pygeoprocessing/routing/routing.pyx"
        ]
    },
    "module_name": "pygeoprocessing.routing.routing"
}
END: Cython Metadata */

#ifndef PY_SSIZE_T_CLEAN
#define PY_SSIZE_T_CLEAN
#endif /* PY_SSIZE_T_CLEAN */
/* InitLimitedAPI */
#if defined(Py_LIMITED_API)
  #if !defined(CYTHON_LIMITED_API)
  #define CYTHON_LIMITED_API 1
  #endif
#elif defined(CYTHON_LIMITED_API)
  #ifdef _MSC_VER
  #pragma message ("Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead.")
  #else
  #warning Limited API usage is enabled with 'CYTHON_LIMITED_API' but 'Py_LIMITED_API' does not define a Python target version. Consider setting 'Py_LIMITED_API' instead.
  #endif
#endif

#include "Python.h"
#ifndef Py_PYTHON_H
    #error Python headers needed to compile C extensions, please install development version of Python.
#elif PY_VERSION_HEX < 0x03080000
    #error Cython requires Python 3.8+.
#else
#define __PYX_ABI_VERSION "3_2_4"
#define CYTHON_HEX_VERSION 0x030204F0
#define CYTHON_FUTURE_DIVISION 1
/* CModulePreamble */
#include <stddef.h>
#ifndef offsetof
  #define offsetof(type, member) ( (size_t) & ((type*)0) -> member )
#endif
#if !defined(_WIN32) && !defined(WIN32) && !defined(MS_WINDOWS)
  #ifndef __stdcall
    #define __stdcall
  #endif
  #ifndef __cdecl
    #define __cdecl
  #endif
  #ifndef __fastcall
    #define __fastcall
  #endif
#endif
#ifndef DL_IMPORT
  #define DL_IMPORT(t) t
#endif
#ifndef DL_EXPORT
  #define DL_EXPORT(t) t
#endif
#define __PYX_COMMA ,
#ifndef PY_LONG_LONG
  #define PY_LONG_LONG LONG_LONG
#endif
#ifndef Py_HUGE_VAL
  #define Py_HUGE_VAL HUGE_VAL
#endif
#define __PYX_LIMITED_VERSION_HEX PY_VERSION_HEX
#if defined(GRAALVM_PYTHON)
  /* For very preliminary testing purposes. Most variables are set the same as PyPy.
     The existence of this section does not imply that anything works or is even tested */
  #define CYTHON_COMPILING_IN_PYPY 0
  #define CYTHON_COMPILING_IN_CPYTHON 0
  #define CYTHON_COMPILING_IN_LIMITED_API 0
  #define CYTHON_COMPILING_IN_GRAAL 1
  #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0
  #undef CYTHON_USE_TYPE_SLOTS
  #define CYTHON_USE_TYPE_SLOTS 0
  #undef CYTHON_USE_TYPE_SPECS
  #define CYTHON_USE_TYPE_SPECS 0
  #undef CYTHON_USE_PYTYPE_LOOKUP
  #define CYTHON_USE_PYTYPE_LOOKUP 0
  #undef CYTHON_USE_PYLIST_INTERNALS
  #define CYTHON_USE_PYLIST_INTERNALS 0
  #undef CYTHON_USE_UNICODE_INTERNALS
  #define CYTHON_USE_UNICODE_INTERNALS 0
  #undef CYTHON_USE_UNICODE_WRITER
  #define CYTHON_USE_UNICODE_WRITER 0
  #undef CYTHON_USE_PYLONG_INTERNALS
  #define CYTHON_USE_PYLONG_INTERNALS 0
  #undef CYTHON_AVOID_BORROWED_REFS
  #define CYTHON_AVOID_BORROWED_REFS 1
  #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
  #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0
  #undef CYTHON_ASSUME_SAFE_MACROS
  #define CYTHON_ASSUME_SAFE_MACROS 0
  #undef CYTHON_ASSUME_SAFE_SIZE
  #define CYTHON_ASSUME_SAFE_SIZE 0
  #undef CYTHON_UNPACK_METHODS
  #define CYTHON_UNPACK_METHODS 0
  #undef CYTHON_FAST_THREAD_STATE
  #define CYTHON_FAST_THREAD_STATE 0
  #undef CYTHON_FAST_GIL
  #define CYTHON_FAST_GIL 0
  #undef CYTHON_METH_FASTCALL
  #define CYTHON_METH_FASTCALL 0
  #undef CYTHON_FAST_PYCALL
  #define CYTHON_FAST_PYCALL 0
  #ifndef CYTHON_PEP487_INIT_SUBCLASS
    #define CYTHON_PEP487_INIT_SUBCLASS 1
  #endif
  #undef CYTHON_PEP489_MULTI_PHASE_INIT
  #define CYTHON_PEP489_MULTI_PHASE_INIT 1
  #undef CYTHON_USE_MODULE_STATE
  #define CYTHON_USE_MODULE_STATE 0
  #undef CYTHON_USE_SYS_MONITORING
  #define CYTHON_USE_SYS_MONITORING 0
  #undef CYTHON_USE_TP_FINALIZE
  #define CYTHON_USE_TP_FINALIZE 0
  #undef CYTHON_USE_AM_SEND
  #define CYTHON_USE_AM_SEND 0
  #undef CYTHON_USE_DICT_VERSIONS
  #define CYTHON_USE_DICT_VERSIONS 0
  #undef CYTHON_USE_EXC_INFO_STACK
  #define CYTHON_USE_EXC_INFO_STACK 1
  #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
    #define CYTHON_UPDATE_DESCRIPTOR_DOC 0
  #endif
  #undef CYTHON_USE_FREELISTS
  #define CYTHON_USE_FREELISTS 0
  #undef CYTHON_IMMORTAL_CONSTANTS
  #define CYTHON_IMMORTAL_CONSTANTS 0
#elif defined(PYPY_VERSION)
  #define CYTHON_COMPILING_IN_PYPY 1
  #define CYTHON_COMPILING_IN_CPYTHON 0
  #define CYTHON_COMPILING_IN_LIMITED_API 0
  #define CYTHON_COMPILING_IN_GRAAL 0
  #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0
  #undef CYTHON_USE_TYPE_SLOTS
  #define CYTHON_USE_TYPE_SLOTS 1
  #ifndef CYTHON_USE_TYPE_SPECS
    #define CYTHON_USE_TYPE_SPECS 0
  #endif
  #undef CYTHON_USE_PYTYPE_LOOKUP
  #define CYTHON_USE_PYTYPE_LOOKUP 0
  #undef CYTHON_USE_PYLIST_INTERNALS
  #define CYTHON_USE_PYLIST_INTERNALS 0
  #undef CYTHON_USE_UNICODE_INTERNALS
  #define CYTHON_USE_UNICODE_INTERNALS 0
  #undef CYTHON_USE_UNICODE_WRITER
  #define CYTHON_USE_UNICODE_WRITER 0
  #undef CYTHON_USE_PYLONG_INTERNALS
  #define CYTHON_USE_PYLONG_INTERNALS 0
  #undef CYTHON_AVOID_BORROWED_REFS
  #define CYTHON_AVOID_BORROWED_REFS 1
  #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
  #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1
  #undef CYTHON_ASSUME_SAFE_MACROS
  #define CYTHON_ASSUME_SAFE_MACROS 0
  #ifndef CYTHON_ASSUME_SAFE_SIZE
    #define CYTHON_ASSUME_SAFE_SIZE 1
  #endif
  #undef CYTHON_UNPACK_METHODS
  #define CYTHON_UNPACK_METHODS 0
  #undef CYTHON_FAST_THREAD_STATE
  #define CYTHON_FAST_THREAD_STATE 0
  #undef CYTHON_FAST_GIL
  #define CYTHON_FAST_GIL 0
  #undef CYTHON_METH_FASTCALL
  #define CYTHON_METH_FASTCALL 0
  #undef CYTHON_FAST_PYCALL
  #define CYTHON_FAST_PYCALL 0
  #ifndef CYTHON_PEP487_INIT_SUBCLASS
    #define CYTHON_PEP487_INIT_SUBCLASS 1
  #endif
  #if PY_VERSION_HEX < 0x03090000
    #undef CYTHON_PEP489_MULTI_PHASE_INIT
    #define CYTHON_PEP489_MULTI_PHASE_INIT 0
  #elif !defined(CYTHON_PEP489_MULTI_PHASE_INIT)
    #define CYTHON_PEP489_MULTI_PHASE_INIT 1
  #endif
  #undef CYTHON_USE_MODULE_STATE
  #define CYTHON_USE_MODULE_STATE 0
  #undef CYTHON_USE_SYS_MONITORING
  #define CYTHON_USE_SYS_MONITORING 0
  #ifndef CYTHON_USE_TP_FINALIZE
    #define CYTHON_USE_TP_FINALIZE (PYPY_VERSION_NUM >= 0x07030C00)
  #endif
  #undef CYTHON_USE_AM_SEND
  #define CYTHON_USE_AM_SEND 0
  #undef CYTHON_USE_DICT_VERSIONS
  #define CYTHON_USE_DICT_VERSIONS 0
  #undef CYTHON_USE_EXC_INFO_STACK
  #define CYTHON_USE_EXC_INFO_STACK 0
  #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
    #define CYTHON_UPDATE_DESCRIPTOR_DOC (PYPY_VERSION_NUM >= 0x07031100)
  #endif
  #undef CYTHON_USE_FREELISTS
  #define CYTHON_USE_FREELISTS 0
  #undef CYTHON_IMMORTAL_CONSTANTS
  #define CYTHON_IMMORTAL_CONSTANTS 0
#elif defined(CYTHON_LIMITED_API)
  #ifdef Py_LIMITED_API
    #undef __PYX_LIMITED_VERSION_HEX
    #define __PYX_LIMITED_VERSION_HEX Py_LIMITED_API
  #endif
  #define CYTHON_COMPILING_IN_PYPY 0
  #define CYTHON_COMPILING_IN_CPYTHON 0
  #define CYTHON_COMPILING_IN_LIMITED_API 1
  #define CYTHON_COMPILING_IN_GRAAL 0
  #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0
  #undef CYTHON_USE_TYPE_SLOTS
  #define CYTHON_USE_TYPE_SLOTS 0
  #undef CYTHON_USE_TYPE_SPECS
  #define CYTHON_USE_TYPE_SPECS 1
  #undef CYTHON_USE_PYTYPE_LOOKUP
  #define CYTHON_USE_PYTYPE_LOOKUP 0
  #undef CYTHON_USE_PYLIST_INTERNALS
  #define CYTHON_USE_PYLIST_INTERNALS 0
  #undef CYTHON_USE_UNICODE_INTERNALS
  #define CYTHON_USE_UNICODE_INTERNALS 0
  #ifndef CYTHON_USE_UNICODE_WRITER
    #define CYTHON_USE_UNICODE_WRITER 0
  #endif
  #undef CYTHON_USE_PYLONG_INTERNALS
  #define CYTHON_USE_PYLONG_INTERNALS 0
  #ifndef CYTHON_AVOID_BORROWED_REFS
    #define CYTHON_AVOID_BORROWED_REFS 0
  #endif
  #ifndef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
    #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0
  #endif
  #undef CYTHON_ASSUME_SAFE_MACROS
  #define CYTHON_ASSUME_SAFE_MACROS 0
  #undef CYTHON_ASSUME_SAFE_SIZE
  #define CYTHON_ASSUME_SAFE_SIZE 0
  #undef CYTHON_UNPACK_METHODS
  #define CYTHON_UNPACK_METHODS 0
  #undef CYTHON_FAST_THREAD_STATE
  #define CYTHON_FAST_THREAD_STATE 0
  #undef CYTHON_FAST_GIL
  #define CYTHON_FAST_GIL 0
  #undef CYTHON_METH_FASTCALL
  #define CYTHON_METH_FASTCALL (__PYX_LIMITED_VERSION_HEX >= 0x030C0000)
  #undef CYTHON_FAST_PYCALL
  #define CYTHON_FAST_PYCALL 0
  #ifndef CYTHON_PEP487_INIT_SUBCLASS
    #define CYTHON_PEP487_INIT_SUBCLASS 1
  #endif
  #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
    #define CYTHON_PEP489_MULTI_PHASE_INIT 1
  #endif
  #ifndef CYTHON_USE_MODULE_STATE
    #define CYTHON_USE_MODULE_STATE 0
  #endif
  #undef CYTHON_USE_SYS_MONITORING
  #define CYTHON_USE_SYS_MONITORING 0
  #ifndef CYTHON_USE_TP_FINALIZE
    #define CYTHON_USE_TP_FINALIZE 0
  #endif
  #ifndef CYTHON_USE_AM_SEND
    #define CYTHON_USE_AM_SEND (__PYX_LIMITED_VERSION_HEX >= 0x030A0000)
  #endif
  #undef CYTHON_USE_DICT_VERSIONS
  #define CYTHON_USE_DICT_VERSIONS 0
  #undef CYTHON_USE_EXC_INFO_STACK
  #define CYTHON_USE_EXC_INFO_STACK 0
  #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
    #define CYTHON_UPDATE_DESCRIPTOR_DOC 0
  #endif
  #ifndef CYTHON_USE_FREELISTS
  #define CYTHON_USE_FREELISTS 1
  #endif
  #undef CYTHON_IMMORTAL_CONSTANTS
  #define CYTHON_IMMORTAL_CONSTANTS 0
#else
  #define CYTHON_COMPILING_IN_PYPY 0
  #define CYTHON_COMPILING_IN_CPYTHON 1
  #define CYTHON_COMPILING_IN_LIMITED_API 0
  #define CYTHON_COMPILING_IN_GRAAL 0
  #ifdef Py_GIL_DISABLED
    #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 1
  #else
    #define CYTHON_COMPILING_IN_CPYTHON_FREETHREADING 0
  #endif
  #if PY_VERSION_HEX < 0x030A0000
    #undef CYTHON_USE_TYPE_SLOTS
    #define CYTHON_USE_TYPE_SLOTS 1
  #elif !defined(CYTHON_USE_TYPE_SLOTS)
    #define CYTHON_USE_TYPE_SLOTS 1
  #endif
  #ifndef CYTHON_USE_TYPE_SPECS
    #define CYTHON_USE_TYPE_SPECS 0
  #endif
  #ifndef CYTHON_USE_PYTYPE_LOOKUP
    #define CYTHON_USE_PYTYPE_LOOKUP 1
  #endif
  #ifndef CYTHON_USE_PYLONG_INTERNALS
    #define CYTHON_USE_PYLONG_INTERNALS 1
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    #undef CYTHON_USE_PYLIST_INTERNALS
    #define CYTHON_USE_PYLIST_INTERNALS 0
  #elif !defined(CYTHON_USE_PYLIST_INTERNALS)
    #define CYTHON_USE_PYLIST_INTERNALS 1
  #endif
  #ifndef CYTHON_USE_UNICODE_INTERNALS
    #define CYTHON_USE_UNICODE_INTERNALS 1
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING || PY_VERSION_HEX >= 0x030B00A2
    #undef CYTHON_USE_UNICODE_WRITER
    #define CYTHON_USE_UNICODE_WRITER 0
  #elif !defined(CYTHON_USE_UNICODE_WRITER)
    #define CYTHON_USE_UNICODE_WRITER 1
  #endif
  #ifndef CYTHON_AVOID_BORROWED_REFS
    #define CYTHON_AVOID_BORROWED_REFS 0
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    #undef CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
    #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 1
  #elif !defined(CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS)
    #define CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS 0
  #endif
  #ifndef CYTHON_ASSUME_SAFE_MACROS
    #define CYTHON_ASSUME_SAFE_MACROS 1
  #endif
  #ifndef CYTHON_ASSUME_SAFE_SIZE
    #define CYTHON_ASSUME_SAFE_SIZE 1
  #endif
  #ifndef CYTHON_UNPACK_METHODS
    #define CYTHON_UNPACK_METHODS 1
  #endif
  #ifndef CYTHON_FAST_THREAD_STATE
    #define CYTHON_FAST_THREAD_STATE 1
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    #undef CYTHON_FAST_GIL
    #define CYTHON_FAST_GIL 0
  #elif !defined(CYTHON_FAST_GIL)
    #define CYTHON_FAST_GIL (PY_VERSION_HEX < 0x030C00A6)
  #endif
  #ifndef CYTHON_METH_FASTCALL
    #define CYTHON_METH_FASTCALL 1
  #endif
  #ifndef CYTHON_FAST_PYCALL
    #define CYTHON_FAST_PYCALL 1
  #endif
  #ifndef CYTHON_PEP487_INIT_SUBCLASS
    #define CYTHON_PEP487_INIT_SUBCLASS 1
  #endif
  #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
    #define CYTHON_PEP489_MULTI_PHASE_INIT 1
  #endif
  #ifndef CYTHON_USE_MODULE_STATE
    #define CYTHON_USE_MODULE_STATE 0
  #endif
  #ifndef CYTHON_USE_SYS_MONITORING
    #define CYTHON_USE_SYS_MONITORING (PY_VERSION_HEX >= 0x030d00B1)
  #endif
  #ifndef CYTHON_USE_TP_FINALIZE
    #define CYTHON_USE_TP_FINALIZE 1
  #endif
  #ifndef CYTHON_USE_AM_SEND
    #define CYTHON_USE_AM_SEND 1
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    #undef CYTHON_USE_DICT_VERSIONS
    #define CYTHON_USE_DICT_VERSIONS 0
  #elif !defined(CYTHON_USE_DICT_VERSIONS)
    #define CYTHON_USE_DICT_VERSIONS  (PY_VERSION_HEX < 0x030C00A5 && !CYTHON_USE_MODULE_STATE)
  #endif
  #ifndef CYTHON_USE_EXC_INFO_STACK
    #define CYTHON_USE_EXC_INFO_STACK 1
  #endif
  #ifndef CYTHON_UPDATE_DESCRIPTOR_DOC
    #define CYTHON_UPDATE_DESCRIPTOR_DOC 1
  #endif
  #ifndef CYTHON_USE_FREELISTS
    #define CYTHON_USE_FREELISTS (!CYTHON_COMPILING_IN_CPYTHON_FREETHREADING)
  #endif
  #if defined(CYTHON_IMMORTAL_CONSTANTS) && PY_VERSION_HEX < 0x030C0000
    #undef CYTHON_IMMORTAL_CONSTANTS
    #define CYTHON_IMMORTAL_CONSTANTS 0  // definitely won't work
  #elif !defined(CYTHON_IMMORTAL_CONSTANTS)
    #define CYTHON_IMMORTAL_CONSTANTS (PY_VERSION_HEX >= 0x030C0000 && !CYTHON_USE_MODULE_STATE && CYTHON_COMPILING_IN_CPYTHON_FREETHREADING)
  #endif
#endif
#ifndef CYTHON_COMPRESS_STRINGS
  #define CYTHON_COMPRESS_STRINGS 1
#endif
#ifndef CYTHON_FAST_PYCCALL
#define CYTHON_FAST_PYCCALL  CYTHON_FAST_PYCALL
#endif
#ifndef CYTHON_VECTORCALL
#if CYTHON_COMPILING_IN_LIMITED_API
#define CYTHON_VECTORCALL  (__PYX_LIMITED_VERSION_HEX >= 0x030C0000)
#else
#define CYTHON_VECTORCALL  (CYTHON_FAST_PYCCALL)
#endif
#endif
#if CYTHON_USE_PYLONG_INTERNALS
  #undef SHIFT
  #undef BASE
  #undef MASK
  #ifdef SIZEOF_VOID_P
    enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) };
  #endif
#endif
#ifndef __has_attribute
  #define __has_attribute(x) 0
#endif
#ifndef __has_cpp_attribute
  #define __has_cpp_attribute(x) 0
#endif
#ifndef CYTHON_RESTRICT
  #if defined(__GNUC__)
    #define CYTHON_RESTRICT __restrict__
  #elif defined(_MSC_VER) && _MSC_VER >= 1400
    #define CYTHON_RESTRICT __restrict
  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    #define CYTHON_RESTRICT restrict
  #else
    #define CYTHON_RESTRICT
  #endif
#endif
#ifndef CYTHON_UNUSED
  #if defined(__cplusplus)
    /* for clang __has_cpp_attribute(maybe_unused) is true even before C++17
     * but leads to warnings with -pedantic, since it is a C++17 feature */
    #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
      #if __has_cpp_attribute(maybe_unused)
        #define CYTHON_UNUSED [[maybe_unused]]
      #endif
    #endif
  #endif
#endif
#ifndef CYTHON_UNUSED
# if defined(__GNUC__)
#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
#     define CYTHON_UNUSED __attribute__ ((__unused__))
#   else
#     define CYTHON_UNUSED
#   endif
# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER))
#   define CYTHON_UNUSED __attribute__ ((__unused__))
# else
#   define CYTHON_UNUSED
# endif
#endif
#ifndef CYTHON_UNUSED_VAR
#  if defined(__cplusplus)
     template<class T> void CYTHON_UNUSED_VAR( const T& ) { }
#  else
#    define CYTHON_UNUSED_VAR(x) (void)(x)
#  endif
#endif
#ifndef CYTHON_MAYBE_UNUSED_VAR
  #define CYTHON_MAYBE_UNUSED_VAR(x) CYTHON_UNUSED_VAR(x)
#endif
#ifndef CYTHON_NCP_UNUSED
# if CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
#  define CYTHON_NCP_UNUSED
# else
#  define CYTHON_NCP_UNUSED CYTHON_UNUSED
# endif
#endif
#ifndef CYTHON_USE_CPP_STD_MOVE
  #if defined(__cplusplus) && (\
    __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600))
    #define CYTHON_USE_CPP_STD_MOVE 1
  #else
    #define CYTHON_USE_CPP_STD_MOVE 0
  #endif
#endif
#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None)
#include <stdint.h>
typedef uintptr_t  __pyx_uintptr_t;
#ifndef CYTHON_FALLTHROUGH
  #if defined(__cplusplus)
    /* for clang __has_cpp_attribute(fallthrough) is true even before C++17
     * but leads to warnings with -pedantic, since it is a C++17 feature */
    #if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
      #if __has_cpp_attribute(fallthrough)
        #define CYTHON_FALLTHROUGH [[fallthrough]]
      #endif
    #endif
    #ifndef CYTHON_FALLTHROUGH
      #if __has_cpp_attribute(clang::fallthrough)
        #define CYTHON_FALLTHROUGH [[clang::fallthrough]]
      #elif __has_cpp_attribute(gnu::fallthrough)
        #define CYTHON_FALLTHROUGH [[gnu::fallthrough]]
      #endif
    #endif
  #endif
  #ifndef CYTHON_FALLTHROUGH
    #if __has_attribute(fallthrough)
      #define CYTHON_FALLTHROUGH __attribute__((fallthrough))
    #else
      #define CYTHON_FALLTHROUGH
    #endif
  #endif
  #if defined(__clang__) && defined(__apple_build_version__)
    #if __apple_build_version__ < 7000000
      #undef  CYTHON_FALLTHROUGH
      #define CYTHON_FALLTHROUGH
    #endif
  #endif
#endif
#ifndef Py_UNREACHABLE
  #define Py_UNREACHABLE()  assert(0); abort()
#endif
#ifdef __cplusplus
  template <typename T>
  struct __PYX_IS_UNSIGNED_IMPL {static const bool value = T(0) < T(-1);};
  #define __PYX_IS_UNSIGNED(type) (__PYX_IS_UNSIGNED_IMPL<type>::value)
#else
  #define __PYX_IS_UNSIGNED(type) (((type)-1) > 0)
#endif
#if CYTHON_COMPILING_IN_PYPY == 1
  #define __PYX_NEED_TP_PRINT_SLOT  (PY_VERSION_HEX < 0x030A0000)
#else
  #define __PYX_NEED_TP_PRINT_SLOT  (PY_VERSION_HEX < 0x03090000)
#endif
#define __PYX_REINTERPRET_FUNCION(func_pointer, other_pointer) ((func_pointer)(void(*)(void))(other_pointer))

/* CppInitCode */
#ifndef __cplusplus
  #error "Cython files generated with the C++ option must be compiled with a C++ compiler."
#endif
#ifndef CYTHON_INLINE
  #if defined(__clang__)
    #define CYTHON_INLINE __inline__ __attribute__ ((__unused__))
  #else
    #define CYTHON_INLINE inline
  #endif
#endif
template<typename T>
void __Pyx_call_destructor(T& x) {
    x.~T();
}
template<typename T>
class __Pyx_FakeReference {
  public:
    __Pyx_FakeReference() : ptr(NULL) { }
    __Pyx_FakeReference(const T& ref) : ptr(const_cast<T*>(&ref)) { }
    T *operator->() { return ptr; }
    T *operator&() { return ptr; }
    operator T&() { return *ptr; }
    template<typename U> bool operator ==(const U& other) const { return *ptr == other; }
    template<typename U> bool operator !=(const U& other) const { return *ptr != other; }
    template<typename U> bool operator==(const __Pyx_FakeReference<U>& other) const { return *ptr == *other.ptr; }
    template<typename U> bool operator!=(const __Pyx_FakeReference<U>& other) const { return *ptr != *other.ptr; }
  private:
    T *ptr;
};

/* PythonCompatibility */
#define __PYX_BUILD_PY_SSIZE_T "n"
#define CYTHON_FORMAT_SSIZE_T "z"
#define __Pyx_BUILTIN_MODULE_NAME "builtins"
#define __Pyx_DefaultClassType PyType_Type
#if CYTHON_COMPILING_IN_LIMITED_API
    #ifndef CO_OPTIMIZED
    static int CO_OPTIMIZED;
    #endif
    #ifndef CO_NEWLOCALS
    static int CO_NEWLOCALS;
    #endif
    #ifndef CO_VARARGS
    static int CO_VARARGS;
    #endif
    #ifndef CO_VARKEYWORDS
    static int CO_VARKEYWORDS;
    #endif
    #ifndef CO_ASYNC_GENERATOR
    static int CO_ASYNC_GENERATOR;
    #endif
    #ifndef CO_GENERATOR
    static int CO_GENERATOR;
    #endif
    #ifndef CO_COROUTINE
    static int CO_COROUTINE;
    #endif
#else
    #ifndef CO_COROUTINE
      #define CO_COROUTINE 0x80
    #endif
    #ifndef CO_ASYNC_GENERATOR
      #define CO_ASYNC_GENERATOR 0x200
    #endif
#endif
static int __Pyx_init_co_variables(void);
#if PY_VERSION_HEX >= 0x030900A4 || defined(Py_IS_TYPE)
  #define __Pyx_IS_TYPE(ob, type) Py_IS_TYPE(ob, type)
#else
  #define __Pyx_IS_TYPE(ob, type) (((const PyObject*)ob)->ob_type == (type))
#endif
#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_Is)
  #define __Pyx_Py_Is(x, y)  Py_Is(x, y)
#else
  #define __Pyx_Py_Is(x, y) ((x) == (y))
#endif
#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsNone)
  #define __Pyx_Py_IsNone(ob) Py_IsNone(ob)
#else
  #define __Pyx_Py_IsNone(ob) __Pyx_Py_Is((ob), Py_None)
#endif
#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsTrue)
  #define __Pyx_Py_IsTrue(ob) Py_IsTrue(ob)
#else
  #define __Pyx_Py_IsTrue(ob) __Pyx_Py_Is((ob), Py_True)
#endif
#if PY_VERSION_HEX >= 0x030A00B1 || defined(Py_IsFalse)
  #define __Pyx_Py_IsFalse(ob) Py_IsFalse(ob)
#else
  #define __Pyx_Py_IsFalse(ob) __Pyx_Py_Is((ob), Py_False)
#endif
#define __Pyx_NoneAsNull(obj)  (__Pyx_Py_IsNone(obj) ? NULL : (obj))
#if PY_VERSION_HEX >= 0x030900F0 && !CYTHON_COMPILING_IN_PYPY
  #define __Pyx_PyObject_GC_IsFinalized(o) PyObject_GC_IsFinalized(o)
#else
  #define __Pyx_PyObject_GC_IsFinalized(o) _PyGC_FINALIZED(o)
#endif
#ifndef Py_TPFLAGS_CHECKTYPES
  #define Py_TPFLAGS_CHECKTYPES 0
#endif
#ifndef Py_TPFLAGS_HAVE_INDEX
  #define Py_TPFLAGS_HAVE_INDEX 0
#endif
#ifndef Py_TPFLAGS_HAVE_NEWBUFFER
  #define Py_TPFLAGS_HAVE_NEWBUFFER 0
#endif
#ifndef Py_TPFLAGS_HAVE_FINALIZE
  #define Py_TPFLAGS_HAVE_FINALIZE 0
#endif
#ifndef Py_TPFLAGS_SEQUENCE
  #define Py_TPFLAGS_SEQUENCE 0
#endif
#ifndef Py_TPFLAGS_MAPPING
  #define Py_TPFLAGS_MAPPING 0
#endif
#ifndef Py_TPFLAGS_IMMUTABLETYPE
  #define Py_TPFLAGS_IMMUTABLETYPE (1UL << 8)
#endif
#ifndef Py_TPFLAGS_DISALLOW_INSTANTIATION
  #define Py_TPFLAGS_DISALLOW_INSTANTIATION (1UL << 7)
#endif
#ifndef METH_STACKLESS
  #define METH_STACKLESS 0
#endif
#ifndef METH_FASTCALL
  #ifndef METH_FASTCALL
     #define METH_FASTCALL 0x80
  #endif
  typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs);
  typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args,
                                                          Py_ssize_t nargs, PyObject *kwnames);
#else
  #if PY_VERSION_HEX >= 0x030d00A4
  #  define __Pyx_PyCFunctionFast PyCFunctionFast
  #  define __Pyx_PyCFunctionFastWithKeywords PyCFunctionFastWithKeywords
  #else
  #  define __Pyx_PyCFunctionFast _PyCFunctionFast
  #  define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords
  #endif
#endif
#if CYTHON_METH_FASTCALL
  #define __Pyx_METH_FASTCALL METH_FASTCALL
  #define __Pyx_PyCFunction_FastCall __Pyx_PyCFunctionFast
  #define __Pyx_PyCFunction_FastCallWithKeywords __Pyx_PyCFunctionFastWithKeywords
#else
  #define __Pyx_METH_FASTCALL METH_VARARGS
  #define __Pyx_PyCFunction_FastCall PyCFunction
  #define __Pyx_PyCFunction_FastCallWithKeywords PyCFunctionWithKeywords
#endif
#if CYTHON_VECTORCALL
  #define __pyx_vectorcallfunc vectorcallfunc
  #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET  PY_VECTORCALL_ARGUMENTS_OFFSET
  #define __Pyx_PyVectorcall_NARGS(n)  PyVectorcall_NARGS((size_t)(n))
#else
  #define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET  0
  #define __Pyx_PyVectorcall_NARGS(n)  ((Py_ssize_t)(n))
#endif
#if PY_VERSION_HEX >= 0x030900B1
#define __Pyx_PyCFunction_CheckExact(func)  PyCFunction_CheckExact(func)
#else
#define __Pyx_PyCFunction_CheckExact(func)  PyCFunction_Check(func)
#endif
#define __Pyx_CyOrPyCFunction_Check(func)  PyCFunction_Check(func)
#if CYTHON_COMPILING_IN_CPYTHON
#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func)  (((PyCFunctionObject*)(func))->m_ml->ml_meth)
#elif !CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_CyOrPyCFunction_GET_FUNCTION(func)  PyCFunction_GET_FUNCTION(func)
#endif
#if CYTHON_COMPILING_IN_CPYTHON
#define __Pyx_CyOrPyCFunction_GET_FLAGS(func)  (((PyCFunctionObject*)(func))->m_ml->ml_flags)
static CYTHON_INLINE PyObject* __Pyx_CyOrPyCFunction_GET_SELF(PyObject *func) {
    return (__Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_STATIC) ? NULL : ((PyCFunctionObject*)func)->m_self;
}
#endif
static CYTHON_INLINE int __Pyx__IsSameCFunction(PyObject *func, void (*cfunc)(void)) {
#if CYTHON_COMPILING_IN_LIMITED_API
    return PyCFunction_Check(func) && PyCFunction_GetFunction(func) == (PyCFunction) cfunc;
#else
    return PyCFunction_Check(func) && PyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc;
#endif
}
#define __Pyx_IsSameCFunction(func, cfunc)   __Pyx__IsSameCFunction(func, cfunc)
#if PY_VERSION_HEX < 0x03090000 || (CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000)
  #define __Pyx_PyType_FromModuleAndSpec(m, s, b)  ((void)m, PyType_FromSpecWithBases(s, b))
  typedef PyObject *(*__Pyx_PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *, size_t, PyObject *);
#else
  #define __Pyx_PyType_FromModuleAndSpec(m, s, b)  PyType_FromModuleAndSpec(m, s, b)
  #define __Pyx_PyCMethod  PyCMethod
#endif
#ifndef METH_METHOD
  #define METH_METHOD 0x200
#endif
#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc)
  #define PyObject_Malloc(s)   PyMem_Malloc(s)
  #define PyObject_Free(p)     PyMem_Free(p)
  #define PyObject_Realloc(p)  PyMem_Realloc(p)
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
  #define __Pyx_PyFrame_SetLineNumber(frame, lineno)
#elif CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000
  #define __Pyx_PyCode_HasFreeVars(co)  (PyCode_GetNumFree(co) > 0)
  #define __Pyx_PyFrame_SetLineNumber(frame, lineno) GraalPyFrame_SetLineNumber((frame), (lineno))
#elif CYTHON_COMPILING_IN_GRAAL
  #define __Pyx_PyCode_HasFreeVars(co)  (PyCode_GetNumFree(co) > 0)
  #define __Pyx_PyFrame_SetLineNumber(frame, lineno) _PyFrame_SetLineNumber((frame), (lineno))
#else
  #define __Pyx_PyCode_HasFreeVars(co)  (PyCode_GetNumFree(co) > 0)
  #define __Pyx_PyFrame_SetLineNumber(frame, lineno)  (frame)->f_lineno = (lineno)
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
  #define __Pyx_PyThreadState_Current PyThreadState_Get()
#elif !CYTHON_FAST_THREAD_STATE
  #define __Pyx_PyThreadState_Current PyThreadState_GET()
#elif PY_VERSION_HEX >= 0x030d00A1
  #define __Pyx_PyThreadState_Current PyThreadState_GetUnchecked()
#else
  #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet()
#endif
#if CYTHON_USE_MODULE_STATE
static CYTHON_INLINE void *__Pyx__PyModule_GetState(PyObject *op)
{
    void *result;
    result = PyModule_GetState(op);
    if (!result)
        Py_FatalError("Couldn't find the module state");
    return result;
}
#define __Pyx_PyModule_GetState(o) (__pyx_mstatetype *)__Pyx__PyModule_GetState(o)
#else
#define __Pyx_PyModule_GetState(op) ((void)op,__pyx_mstate_global)
#endif
#define __Pyx_PyObject_GetSlot(obj, name, func_ctype)  __Pyx_PyType_GetSlot(Py_TYPE((PyObject *) obj), name, func_ctype)
#define __Pyx_PyObject_TryGetSlot(obj, name, func_ctype) __Pyx_PyType_TryGetSlot(Py_TYPE(obj), name, func_ctype)
#define __Pyx_PyObject_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(Py_TYPE(obj), sub, name, func_ctype)
#define __Pyx_PyObject_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSubSlot(Py_TYPE(obj), sub, name, func_ctype)
#if CYTHON_USE_TYPE_SLOTS
  #define __Pyx_PyType_GetSlot(type, name, func_ctype)  ((type)->name)
  #define __Pyx_PyType_TryGetSlot(type, name, func_ctype) __Pyx_PyType_GetSlot(type, name, func_ctype)
  #define __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype) (((type)->sub) ? ((type)->sub->name) : NULL)
  #define __Pyx_PyType_TryGetSubSlot(type, sub, name, func_ctype) __Pyx_PyType_GetSubSlot(type, sub, name, func_ctype)
#else
  #define __Pyx_PyType_GetSlot(type, name, func_ctype)  ((func_ctype) PyType_GetSlot((type), Py_##name))
  #define __Pyx_PyType_TryGetSlot(type, name, func_ctype)\
    ((__PYX_LIMITED_VERSION_HEX >= 0x030A0000 ||\
     (PyType_GetFlags(type) & Py_TPFLAGS_HEAPTYPE) || __Pyx_get_runtime_version() >= 0x030A0000) ?\
     __Pyx_PyType_GetSlot(type, name, func_ctype) : NULL)
  #define __Pyx_PyType_GetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_GetSlot(obj, name, func_ctype)
  #define __Pyx_PyType_TryGetSubSlot(obj, sub, name, func_ctype) __Pyx_PyType_TryGetSlot(obj, name, func_ctype)
#endif
#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized)
#define __Pyx_PyDict_NewPresized(n)  ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n))
#else
#define __Pyx_PyDict_NewPresized(n)  PyDict_New()
#endif
#define __Pyx_PyNumber_Divide(x,y)         PyNumber_TrueDivide(x,y)
#define __Pyx_PyNumber_InPlaceDivide(x,y)  PyNumber_InPlaceTrueDivide(x,y)
#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_UNICODE_INTERNALS
#define __Pyx_PyDict_GetItemStrWithError(dict, name)  _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash)
static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStr(PyObject *dict, PyObject *name) {
    PyObject *res = __Pyx_PyDict_GetItemStrWithError(dict, name);
    if (res == NULL) PyErr_Clear();
    return res;
}
#elif !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07020000
#define __Pyx_PyDict_GetItemStrWithError  PyDict_GetItemWithError
#define __Pyx_PyDict_GetItemStr           PyDict_GetItem
#else
static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict, PyObject *name) {
#if CYTHON_COMPILING_IN_PYPY
    return PyDict_GetItem(dict, name);
#else
    PyDictEntry *ep;
    PyDictObject *mp = (PyDictObject*) dict;
    long hash = ((PyStringObject *) name)->ob_shash;
    assert(hash != -1);
    ep = (mp->ma_lookup)(mp, name, hash);
    if (ep == NULL) {
        return NULL;
    }
    return ep->me_value;
#endif
}
#define __Pyx_PyDict_GetItemStr           PyDict_GetItem
#endif
#if CYTHON_USE_TYPE_SLOTS
  #define __Pyx_PyType_GetFlags(tp)   (((PyTypeObject *)tp)->tp_flags)
  #define __Pyx_PyType_HasFeature(type, feature)  ((__Pyx_PyType_GetFlags(type) & (feature)) != 0)
#else
  #define __Pyx_PyType_GetFlags(tp)   (PyType_GetFlags((PyTypeObject *)tp))
  #define __Pyx_PyType_HasFeature(type, feature)  PyType_HasFeature(type, feature)
#endif
#define __Pyx_PyObject_GetIterNextFunc(iterator)  __Pyx_PyObject_GetSlot(iterator, tp_iternext, iternextfunc)
#if CYTHON_USE_TYPE_SPECS
#define __Pyx_PyHeapTypeObject_GC_Del(obj)  {\
    PyTypeObject *type = Py_TYPE((PyObject*)obj);\
    assert(__Pyx_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE));\
    PyObject_GC_Del(obj);\
    Py_DECREF(type);\
}
#else
#define __Pyx_PyHeapTypeObject_GC_Del(obj)  PyObject_GC_Del(obj)
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
  #define __Pyx_PyUnicode_READY(op)       (0)
  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_ReadChar(u, i)
  #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u)   ((void)u, 1114111U)
  #define __Pyx_PyUnicode_KIND(u)         ((void)u, (0))
  #define __Pyx_PyUnicode_DATA(u)         ((void*)u)
  #define __Pyx_PyUnicode_READ(k, d, i)   ((void)k, PyUnicode_ReadChar((PyObject*)(d), i))
  #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != PyUnicode_GetLength(u))
#else
  #if PY_VERSION_HEX >= 0x030C0000
    #define __Pyx_PyUnicode_READY(op)       (0)
  #else
    #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ?\
                                                0 : _PyUnicode_Ready((PyObject *)(op)))
  #endif
  #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
  #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u)   PyUnicode_MAX_CHAR_VALUE(u)
  #define __Pyx_PyUnicode_KIND(u)         ((int)PyUnicode_KIND(u))
  #define __Pyx_PyUnicode_DATA(u)         PyUnicode_DATA(u)
  #define __Pyx_PyUnicode_READ(k, d, i)   PyUnicode_READ(k, d, i)
  #define __Pyx_PyUnicode_WRITE(k, d, i, ch)  PyUnicode_WRITE(k, d, i, (Py_UCS4) ch)
  #if PY_VERSION_HEX >= 0x030C0000
    #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != PyUnicode_GET_LENGTH(u))
  #else
    #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000
    #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length))
    #else
    #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u)))
    #endif
  #endif
#endif
#if CYTHON_COMPILING_IN_PYPY
  #define __Pyx_PyUnicode_Concat(a, b)      PyNumber_Add(a, b)
  #define __Pyx_PyUnicode_ConcatSafe(a, b)  PyNumber_Add(a, b)
#else
  #define __Pyx_PyUnicode_Concat(a, b)      PyUnicode_Concat(a, b)
  #define __Pyx_PyUnicode_ConcatSafe(a, b)  ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\
      PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b))
#endif
#if CYTHON_COMPILING_IN_PYPY
  #if !defined(PyUnicode_DecodeUnicodeEscape)
    #define PyUnicode_DecodeUnicodeEscape(s, size, errors)  PyUnicode_Decode(s, size, "unicode_escape", errors)
  #endif
  #if !defined(PyUnicode_Contains)
    #define PyUnicode_Contains(u, s)  PySequence_Contains(u, s)
  #endif
  #if !defined(PyByteArray_Check)
    #define PyByteArray_Check(obj)  PyObject_TypeCheck(obj, &PyByteArray_Type)
  #endif
  #if !defined(PyObject_Format)
    #define PyObject_Format(obj, fmt)  PyObject_CallMethod(obj, "__format__", "O", fmt)
  #endif
#endif
#define __Pyx_PyUnicode_FormatSafe(a, b)  ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b))
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  #define __Pyx_PySequence_ListKeepNew(obj)\
    (likely(PyList_CheckExact(obj) && PyUnstable_Object_IsUniquelyReferenced(obj)) ? __Pyx_NewRef(obj) : PySequence_List(obj))
#elif CYTHON_COMPILING_IN_CPYTHON
  #define __Pyx_PySequence_ListKeepNew(obj)\
    (likely(PyList_CheckExact(obj) && Py_REFCNT(obj) == 1) ? __Pyx_NewRef(obj) : PySequence_List(obj))
#else
  #define __Pyx_PySequence_ListKeepNew(obj)  PySequence_List(obj)
#endif
#ifndef PySet_CheckExact
  #define PySet_CheckExact(obj)        __Pyx_IS_TYPE(obj, &PySet_Type)
#endif
#if PY_VERSION_HEX >= 0x030900A4
  #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt)
  #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size)
#else
  #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
  #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size)
#endif
enum __Pyx_ReferenceSharing {
  __Pyx_ReferenceSharing_DefinitelyUnique, // We created it so we know it's unshared - no need to check
  __Pyx_ReferenceSharing_OwnStrongReference,
  __Pyx_ReferenceSharing_FunctionArgument,
  __Pyx_ReferenceSharing_SharedReference, // Never trust it to be unshared because it's a global or similar
};
#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && PY_VERSION_HEX >= 0x030E0000
#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing)\
    (sharing == __Pyx_ReferenceSharing_DefinitelyUnique ? 1 :\
      (sharing == __Pyx_ReferenceSharing_FunctionArgument ? PyUnstable_Object_IsUniqueReferencedTemporary(o) :\
      (sharing == __Pyx_ReferenceSharing_OwnStrongReference ? PyUnstable_Object_IsUniquelyReferenced(o) : 0)))
#elif (CYTHON_COMPILING_IN_CPYTHON && !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING) || CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)sharing), Py_REFCNT(o) == 1)
#else
#define __Pyx_IS_UNIQUELY_REFERENCED(o, sharing) (((void)o), ((void)sharing), 0)
#endif
#if CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
  #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
    #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i)
  #elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS
    #define __Pyx_PyList_GetItemRef(o, i) (likely((i) >= 0) ? PySequence_GetItem(o, i) : (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL))
  #else
    #define __Pyx_PyList_GetItemRef(o, i) PySequence_ITEM(o, i)
  #endif
#elif CYTHON_COMPILING_IN_LIMITED_API || !CYTHON_ASSUME_SAFE_MACROS
  #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
    #define __Pyx_PyList_GetItemRef(o, i) PyList_GetItemRef(o, i)
  #else
    #define __Pyx_PyList_GetItemRef(o, i) __Pyx_XNewRef(PyList_GetItem(o, i))
  #endif
#else
  #define __Pyx_PyList_GetItemRef(o, i) __Pyx_NewRef(PyList_GET_ITEM(o, i))
#endif
#if CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS && !CYTHON_COMPILING_IN_LIMITED_API && CYTHON_ASSUME_SAFE_MACROS
  #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) (__Pyx_IS_UNIQUELY_REFERENCED(o, unsafe_shared) ?\
    __Pyx_NewRef(PyList_GET_ITEM(o, i)) : __Pyx_PyList_GetItemRef(o, i))
#else
  #define __Pyx_PyList_GetItemRefFast(o, i, unsafe_shared) __Pyx_PyList_GetItemRef(o, i)
#endif
#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
#define __Pyx_PyDict_GetItemRef(dict, key, result) PyDict_GetItemRef(dict, key, result)
#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) {
  *result = PyObject_GetItem(dict, key);
  if (*result == NULL) {
    if (PyErr_ExceptionMatches(PyExc_KeyError)) {
      PyErr_Clear();
      return 0;
    }
    return -1;
  }
  return 1;
}
#else
static CYTHON_INLINE int __Pyx_PyDict_GetItemRef(PyObject *dict, PyObject *key, PyObject **result) {
  *result = PyDict_GetItemWithError(dict, key);
  if (*result == NULL) {
    return PyErr_Occurred() ? -1 : 0;
  }
  Py_INCREF(*result);
  return 1;
}
#endif
#if defined(CYTHON_DEBUG_VISIT_CONST) && CYTHON_DEBUG_VISIT_CONST
  #define __Pyx_VISIT_CONST(obj)  Py_VISIT(obj)
#else
  #define __Pyx_VISIT_CONST(obj)
#endif
#if CYTHON_ASSUME_SAFE_MACROS
  #define __Pyx_PySequence_ITEM(o, i) PySequence_ITEM(o, i)
  #define __Pyx_PySequence_SIZE(seq)  Py_SIZE(seq)
  #define __Pyx_PyTuple_SET_ITEM(o, i, v) (PyTuple_SET_ITEM(o, i, v), (0))
  #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GET_ITEM(o, i)
  #define __Pyx_PyList_SET_ITEM(o, i, v) (PyList_SET_ITEM(o, i, v), (0))
  #define __Pyx_PyList_GET_ITEM(o, i) PyList_GET_ITEM(o, i)
#else
  #define __Pyx_PySequence_ITEM(o, i) PySequence_GetItem(o, i)
  #define __Pyx_PySequence_SIZE(seq)  PySequence_Size(seq)
  #define __Pyx_PyTuple_SET_ITEM(o, i, v) PyTuple_SetItem(o, i, v)
  #define __Pyx_PyTuple_GET_ITEM(o, i) PyTuple_GetItem(o, i)
  #define __Pyx_PyList_SET_ITEM(o, i, v) PyList_SetItem(o, i, v)
  #define __Pyx_PyList_GET_ITEM(o, i) PyList_GetItem(o, i)
#endif
#if CYTHON_ASSUME_SAFE_SIZE
  #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_GET_SIZE(o)
  #define __Pyx_PyList_GET_SIZE(o) PyList_GET_SIZE(o)
  #define __Pyx_PySet_GET_SIZE(o) PySet_GET_SIZE(o)
  #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_GET_SIZE(o)
  #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_GET_SIZE(o)
  #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GET_LENGTH(o)
#else
  #define __Pyx_PyTuple_GET_SIZE(o) PyTuple_Size(o)
  #define __Pyx_PyList_GET_SIZE(o) PyList_Size(o)
  #define __Pyx_PySet_GET_SIZE(o) PySet_Size(o)
  #define __Pyx_PyBytes_GET_SIZE(o) PyBytes_Size(o)
  #define __Pyx_PyByteArray_GET_SIZE(o) PyByteArray_Size(o)
  #define __Pyx_PyUnicode_GET_LENGTH(o) PyUnicode_GetLength(o)
#endif
#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_InternFromString)
  #define PyUnicode_InternFromString(s) PyUnicode_FromString(s)
#endif
#define __Pyx_PyLong_FromHash_t PyLong_FromSsize_t
#define __Pyx_PyLong_AsHash_t   __Pyx_PyIndex_AsSsize_t
#if __PYX_LIMITED_VERSION_HEX >= 0x030A0000
    #define __Pyx_PySendResult PySendResult
#else
    typedef enum {
        PYGEN_RETURN = 0,
        PYGEN_ERROR = -1,
        PYGEN_NEXT = 1,
    } __Pyx_PySendResult;
#endif
#if CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX < 0x030A00A3
  typedef __Pyx_PySendResult (*__Pyx_pyiter_sendfunc)(PyObject *iter, PyObject *value, PyObject **result);
#else
  #define __Pyx_pyiter_sendfunc sendfunc
#endif
#if !CYTHON_USE_AM_SEND
#define __PYX_HAS_PY_AM_SEND 0
#elif __PYX_LIMITED_VERSION_HEX >= 0x030A0000
#define __PYX_HAS_PY_AM_SEND 1
#else
#define __PYX_HAS_PY_AM_SEND 2  // our own backported implementation
#endif
#if __PYX_HAS_PY_AM_SEND < 2
    #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods
#else
    typedef struct {
        unaryfunc am_await;
        unaryfunc am_aiter;
        unaryfunc am_anext;
        __Pyx_pyiter_sendfunc am_send;
    } __Pyx_PyAsyncMethodsStruct;
    #define __Pyx_SlotTpAsAsync(s) ((PyAsyncMethods*)(s))
#endif
#if CYTHON_USE_AM_SEND && PY_VERSION_HEX < 0x030A00F0
    #define __Pyx_TPFLAGS_HAVE_AM_SEND (1UL << 21)
#else
    #define __Pyx_TPFLAGS_HAVE_AM_SEND (0)
#endif
#if PY_VERSION_HEX >= 0x03090000
#define __Pyx_PyInterpreterState_Get() PyInterpreterState_Get()
#else
#define __Pyx_PyInterpreterState_Get() PyThreadState_Get()->interp
#endif
#if CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030A0000
#ifdef __cplusplus
extern "C"
#endif
PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize);
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
static int __Pyx_init_co_variable(PyObject *inspect, const char* name, int *write_to) {
    int value;
    PyObject *py_value = PyObject_GetAttrString(inspect, name);
    if (!py_value) return 0;
    value = (int) PyLong_AsLong(py_value);
    Py_DECREF(py_value);
    *write_to = value;
    return value != -1 || !PyErr_Occurred();
}
static int __Pyx_init_co_variables(void) {
    PyObject *inspect;
    int result;
    inspect = PyImport_ImportModule("inspect");
    result =
#if !defined(CO_OPTIMIZED)
        __Pyx_init_co_variable(inspect, "CO_OPTIMIZED", &CO_OPTIMIZED) &&
#endif
#if !defined(CO_NEWLOCALS)
        __Pyx_init_co_variable(inspect, "CO_NEWLOCALS", &CO_NEWLOCALS) &&
#endif
#if !defined(CO_VARARGS)
        __Pyx_init_co_variable(inspect, "CO_VARARGS", &CO_VARARGS) &&
#endif
#if !defined(CO_VARKEYWORDS)
        __Pyx_init_co_variable(inspect, "CO_VARKEYWORDS", &CO_VARKEYWORDS) &&
#endif
#if !defined(CO_ASYNC_GENERATOR)
        __Pyx_init_co_variable(inspect, "CO_ASYNC_GENERATOR", &CO_ASYNC_GENERATOR) &&
#endif
#if !defined(CO_GENERATOR)
        __Pyx_init_co_variable(inspect, "CO_GENERATOR", &CO_GENERATOR) &&
#endif
#if !defined(CO_COROUTINE)
        __Pyx_init_co_variable(inspect, "CO_COROUTINE", &CO_COROUTINE) &&
#endif
        1;
    Py_DECREF(inspect);
    return result ? 0 : -1;
}
#else
static int __Pyx_init_co_variables(void) {
    return 0;  // It's a limited API-only feature
}
#endif

/* MathInitCode */
#if defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)
  #ifndef _USE_MATH_DEFINES
    #define _USE_MATH_DEFINES
  #endif
#endif
#include <math.h>
#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL)
#define __Pyx_truncl trunc
#else
#define __Pyx_truncl truncl
#endif

#ifndef CYTHON_CLINE_IN_TRACEBACK_RUNTIME
#define CYTHON_CLINE_IN_TRACEBACK_RUNTIME 0
#endif
#ifndef CYTHON_CLINE_IN_TRACEBACK
#define CYTHON_CLINE_IN_TRACEBACK CYTHON_CLINE_IN_TRACEBACK_RUNTIME
#endif
#if CYTHON_CLINE_IN_TRACEBACK
#define __PYX_MARK_ERR_POS(f_index, lineno)  { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; __pyx_clineno = __LINE__; (void) __pyx_clineno; }
#else
#define __PYX_MARK_ERR_POS(f_index, lineno)  { __pyx_filename = __pyx_f[f_index]; (void) __pyx_filename; __pyx_lineno = lineno; (void) __pyx_lineno; (void) __pyx_clineno; }
#endif
#define __PYX_ERR(f_index, lineno, Ln_error) \
    { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; }

#ifdef CYTHON_EXTERN_C
    #undef __PYX_EXTERN_C
    #define __PYX_EXTERN_C CYTHON_EXTERN_C
#elif defined(__PYX_EXTERN_C)
    #ifdef _MSC_VER
    #pragma message ("Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.")
    #else
    #warning Please do not define the '__PYX_EXTERN_C' macro externally. Use 'CYTHON_EXTERN_C' instead.
    #endif
#else
    #define __PYX_EXTERN_C extern "C++"
#endif

#define __PYX_HAVE__pygeoprocessing__routing__routing
#define __PYX_HAVE_API__pygeoprocessing__routing__routing
/* Early includes */
#include <string.h>
#include <stdio.h>

    /* Using NumPy API declarations from "numpy/__init__.cython-30.pxd" */
    
#include "numpy/arrayobject.h"
#include "numpy/ndarrayobject.h"
#include "numpy/ndarraytypes.h"
#include "numpy/arrayscalars.h"
#include "numpy/ufuncobject.h"
#include <stddef.h>
#include <time.h>
#include <math.h>
#include "ios"
#include "new"
#include "stdexcept"
#include "typeinfo"
#include <deque>
#include <list>
#include <utility>

    #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
    // move should be defined for these versions of MSVC, but __cplusplus isn't set usefully
    #include <type_traits>

    namespace cython_std {
    template <typename T> typename std::remove_reference<T>::type&& move(T& t) noexcept { return std::move(t); }
    template <typename T> typename std::remove_reference<T>::type&& move(T&& t) noexcept { return std::move(t); }
    }

    #endif
    
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <string_view>
#include <string>
#include "extensions/FastFileIterator.h"
#include "extensions/LRUCache.h"
#include "extensions/ManagedRaster.h"
#ifdef _OPENMP
#include <omp.h>
#endif /* _OPENMP */

#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS)
#define CYTHON_WITHOUT_ASSERTIONS
#endif

#ifdef CYTHON_FREETHREADING_COMPATIBLE
#if CYTHON_FREETHREADING_COMPATIBLE
#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_NOT_USED
#else
#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_USED
#endif
#else
#define __Pyx_FREETHREADING_COMPATIBLE Py_MOD_GIL_USED
#endif
#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0
#define __PYX_DEFAULT_STRING_ENCODING ""
#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
#define __Pyx_uchar_cast(c) ((unsigned char)c)
#define __Pyx_long_cast(x) ((long)x)
#define __Pyx_fits_Py_ssize_t(v, type, is_signed)  (\
    (sizeof(type) < sizeof(Py_ssize_t))  ||\
    (sizeof(type) > sizeof(Py_ssize_t) &&\
          likely(v < (type)PY_SSIZE_T_MAX ||\
                 v == (type)PY_SSIZE_T_MAX)  &&\
          (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\
                                v == (type)PY_SSIZE_T_MIN)))  ||\
    (sizeof(type) == sizeof(Py_ssize_t) &&\
          (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\
                               v == (type)PY_SSIZE_T_MAX)))  )
static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) {
    return (size_t) i < (size_t) limit;
}
#if defined (__cplusplus) && __cplusplus >= 201103L
    #include <cstdlib>
    #define __Pyx_sst_abs(value) std::abs(value)
#elif SIZEOF_INT >= SIZEOF_SIZE_T
    #define __Pyx_sst_abs(value) abs(value)
#elif SIZEOF_LONG >= SIZEOF_SIZE_T
    #define __Pyx_sst_abs(value) labs(value)
#elif defined (_MSC_VER)
    #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value))
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    #define __Pyx_sst_abs(value) llabs(value)
#elif defined (__GNUC__)
    #define __Pyx_sst_abs(value) __builtin_llabs(value)
#else
    #define __Pyx_sst_abs(value) ((value<0) ? -value : value)
#endif
static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s);
static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*);
static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char*);
#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l)
#define __Pyx_PyBytes_FromString        PyBytes_FromString
#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*);
#if CYTHON_ASSUME_SAFE_MACROS
    #define __Pyx_PyBytes_AsWritableString(s)     ((char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyBytes_AsWritableSString(s)    ((signed char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyBytes_AsWritableUString(s)    ((unsigned char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyBytes_AsString(s)     ((const char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyBytes_AsSString(s)    ((const signed char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyBytes_AsUString(s)    ((const unsigned char*) PyBytes_AS_STRING(s))
    #define __Pyx_PyByteArray_AsString(s) PyByteArray_AS_STRING(s)
#else
    #define __Pyx_PyBytes_AsWritableString(s)     ((char*) PyBytes_AsString(s))
    #define __Pyx_PyBytes_AsWritableSString(s)    ((signed char*) PyBytes_AsString(s))
    #define __Pyx_PyBytes_AsWritableUString(s)    ((unsigned char*) PyBytes_AsString(s))
    #define __Pyx_PyBytes_AsString(s)     ((const char*) PyBytes_AsString(s))
    #define __Pyx_PyBytes_AsSString(s)    ((const signed char*) PyBytes_AsString(s))
    #define __Pyx_PyBytes_AsUString(s)    ((const unsigned char*) PyBytes_AsString(s))
    #define __Pyx_PyByteArray_AsString(s) PyByteArray_AsString(s)
#endif
#define __Pyx_PyObject_AsWritableString(s)    ((char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsWritableSString(s)    ((signed char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsWritableUString(s)    ((unsigned char*)(__pyx_uintptr_t) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsSString(s)    ((const signed char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_AsUString(s)    ((const unsigned char*) __Pyx_PyObject_AsString(s))
#define __Pyx_PyObject_FromCString(s)  __Pyx_PyObject_FromString((const char*)s)
#define __Pyx_PyBytes_FromCString(s)   __Pyx_PyBytes_FromString((const char*)s)
#define __Pyx_PyByteArray_FromCString(s)   __Pyx_PyByteArray_FromString((const char*)s)
#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s)
#define __Pyx_PyUnicode_FromOrdinal(o)       PyUnicode_FromOrdinal((int)o)
#define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
static CYTHON_INLINE PyObject *__Pyx_NewRef(PyObject *obj) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_NewRef)
    return Py_NewRef(obj);
#else
    Py_INCREF(obj);
    return obj;
#endif
}
static CYTHON_INLINE PyObject *__Pyx_XNewRef(PyObject *obj) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030a0000 || defined(Py_XNewRef)
    return Py_XNewRef(obj);
#else
    Py_XINCREF(obj);
    return obj;
#endif
}
static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b);
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b);
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*);
static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x);
#define __Pyx_PySequence_Tuple(obj)\
    (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj))
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t);
static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
#if CYTHON_ASSUME_SAFE_MACROS
#define __Pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AS_DOUBLE(x)
#else
#define __Pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
#define __Pyx_PyFloat_AS_DOUBLE(x) PyFloat_AsDouble(x)
#endif
#define __Pyx_PyFloat_AsFloat(x) ((float) __Pyx_PyFloat_AsDouble(x))
#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x))
#if CYTHON_USE_PYLONG_INTERNALS
  #if PY_VERSION_HEX >= 0x030C00A7
  #ifndef _PyLong_SIGN_MASK
    #define _PyLong_SIGN_MASK 3
  #endif
  #ifndef _PyLong_NON_SIZE_BITS
    #define _PyLong_NON_SIZE_BITS 3
  #endif
  #define __Pyx_PyLong_Sign(x)  (((PyLongObject*)x)->long_value.lv_tag & _PyLong_SIGN_MASK)
  #define __Pyx_PyLong_IsNeg(x)  ((__Pyx_PyLong_Sign(x) & 2) != 0)
  #define __Pyx_PyLong_IsNonNeg(x)  (!__Pyx_PyLong_IsNeg(x))
  #define __Pyx_PyLong_IsZero(x)  (__Pyx_PyLong_Sign(x) & 1)
  #define __Pyx_PyLong_IsPos(x)  (__Pyx_PyLong_Sign(x) == 0)
  #define __Pyx_PyLong_CompactValueUnsigned(x)  (__Pyx_PyLong_Digits(x)[0])
  #define __Pyx_PyLong_DigitCount(x)  ((Py_ssize_t) (((PyLongObject*)x)->long_value.lv_tag >> _PyLong_NON_SIZE_BITS))
  #define __Pyx_PyLong_SignedDigitCount(x)\
        ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * __Pyx_PyLong_DigitCount(x))
  #if defined(PyUnstable_Long_IsCompact) && defined(PyUnstable_Long_CompactValue)
    #define __Pyx_PyLong_IsCompact(x)     PyUnstable_Long_IsCompact((PyLongObject*) x)
    #define __Pyx_PyLong_CompactValue(x)  PyUnstable_Long_CompactValue((PyLongObject*) x)
  #else
    #define __Pyx_PyLong_IsCompact(x)     (((PyLongObject*)x)->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS))
    #define __Pyx_PyLong_CompactValue(x)  ((1 - (Py_ssize_t) __Pyx_PyLong_Sign(x)) * (Py_ssize_t) __Pyx_PyLong_Digits(x)[0])
  #endif
  typedef Py_ssize_t  __Pyx_compact_pylong;
  typedef size_t  __Pyx_compact_upylong;
  #else
  #define __Pyx_PyLong_IsNeg(x)  (Py_SIZE(x) < 0)
  #define __Pyx_PyLong_IsNonNeg(x)  (Py_SIZE(x) >= 0)
  #define __Pyx_PyLong_IsZero(x)  (Py_SIZE(x) == 0)
  #define __Pyx_PyLong_IsPos(x)  (Py_SIZE(x) > 0)
  #define __Pyx_PyLong_CompactValueUnsigned(x)  ((Py_SIZE(x) == 0) ? 0 : __Pyx_PyLong_Digits(x)[0])
  #define __Pyx_PyLong_DigitCount(x)  __Pyx_sst_abs(Py_SIZE(x))
  #define __Pyx_PyLong_SignedDigitCount(x)  Py_SIZE(x)
  #define __Pyx_PyLong_IsCompact(x)  (Py_SIZE(x) == 0 || Py_SIZE(x) == 1 || Py_SIZE(x) == -1)
  #define __Pyx_PyLong_CompactValue(x)\
        ((Py_SIZE(x) == 0) ? (sdigit) 0 : ((Py_SIZE(x) < 0) ? -(sdigit)__Pyx_PyLong_Digits(x)[0] : (sdigit)__Pyx_PyLong_Digits(x)[0]))
  typedef sdigit  __Pyx_compact_pylong;
  typedef digit  __Pyx_compact_upylong;
  #endif
  #if PY_VERSION_HEX >= 0x030C00A5
  #define __Pyx_PyLong_Digits(x)  (((PyLongObject*)x)->long_value.ob_digit)
  #else
  #define __Pyx_PyLong_Digits(x)  (((PyLongObject*)x)->ob_digit)
  #endif
#endif
#if __PYX_DEFAULT_STRING_ENCODING_IS_UTF8
  #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
#elif __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
  #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeASCII(c_str, size, NULL)
#else
  #define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
#endif


/* Test for GCC > 2.95 */
#if defined(__GNUC__)     && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)))
  #define likely(x)   __builtin_expect(!!(x), 1)
  #define unlikely(x) __builtin_expect(!!(x), 0)
#else /* !__GNUC__ or GCC < 2.95 */
  #define likely(x)   (x)
  #define unlikely(x) (x)
#endif /* __GNUC__ */
/* PretendToInitialize */
#ifdef __cplusplus
#if __cplusplus > 201103L
#include <type_traits>
#endif
template <typename T>
static void __Pyx_pretend_to_initialize(T* ptr) {
#if __cplusplus > 201103L
    if ((std::is_trivially_default_constructible<T>::value))
#endif
        *ptr = T();
    (void)ptr;
}
#else
static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; }
#endif


#if !CYTHON_USE_MODULE_STATE
static PyObject *__pyx_m = NULL;
#endif
static int __pyx_lineno;
static int __pyx_clineno = 0;
static const char * const __pyx_cfilenm = __FILE__;
static const char *__pyx_filename;

/* Header.proto */
#if !defined(CYTHON_CCOMPLEX)
  #if defined(__cplusplus)
    #define CYTHON_CCOMPLEX 1
  #elif (defined(_Complex_I) && !defined(_MSC_VER)) || ((defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_COMPLEX__) && !defined(_MSC_VER))
    #define CYTHON_CCOMPLEX 1
  #else
    #define CYTHON_CCOMPLEX 0
  #endif
#endif
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    #include <complex>
  #else
    #include <complex.h>
  #endif
#endif
#if CYTHON_CCOMPLEX && !defined(__cplusplus) && defined(__sun__) && defined(__GNUC__)
  #undef _Complex_I
  #define _Complex_I 1.0fj
#endif

/* #### Code section: filename_table ### */

static const char* const __pyx_f[] = {
  "src/pygeoprocessing/routing/routing.pyx",
  "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd",
  "cpython/type.pxd",
};
/* #### Code section: utility_code_proto_before_types ### */
/* Atomics.proto (used by UnpackUnboundCMethod) */
#include <pythread.h>
#ifndef CYTHON_ATOMICS
    #define CYTHON_ATOMICS 1
#endif
#define __PYX_CYTHON_ATOMICS_ENABLED() CYTHON_ATOMICS
#define __PYX_GET_CYTHON_COMPILING_IN_CPYTHON_FREETHREADING() CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
#define __pyx_atomic_int_type int
#define __pyx_nonatomic_int_type int
#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\
                        (__STDC_VERSION__ >= 201112L) &&\
                        !defined(__STDC_NO_ATOMICS__))
    #include <stdatomic.h>
#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\
                    (__cplusplus >= 201103L) ||\
                    (defined(_MSC_VER) && _MSC_VER >= 1700)))
    #include <atomic>
#endif
#if CYTHON_ATOMICS && (defined(__STDC_VERSION__) &&\
                        (__STDC_VERSION__ >= 201112L) &&\
                        !defined(__STDC_NO_ATOMICS__) &&\
                       ATOMIC_INT_LOCK_FREE == 2)
    #undef __pyx_atomic_int_type
    #define __pyx_atomic_int_type atomic_int
    #define __pyx_atomic_ptr_type atomic_uintptr_t
    #define __pyx_nonatomic_ptr_type uintptr_t
    #define __pyx_atomic_incr_relaxed(value) atomic_fetch_add_explicit(value, 1, memory_order_relaxed)
    #define __pyx_atomic_incr_acq_rel(value) atomic_fetch_add_explicit(value, 1, memory_order_acq_rel)
    #define __pyx_atomic_decr_acq_rel(value) atomic_fetch_sub_explicit(value, 1, memory_order_acq_rel)
    #define __pyx_atomic_sub(value, arg) atomic_fetch_sub(value, arg)
    #define __pyx_atomic_int_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired)
    #define __pyx_atomic_load(value) atomic_load(value)
    #define __pyx_atomic_store(value, new_value) atomic_store(value, new_value)
    #define __pyx_atomic_pointer_load_relaxed(value) atomic_load_explicit(value, memory_order_relaxed)
    #define __pyx_atomic_pointer_load_acquire(value) atomic_load_explicit(value, memory_order_acquire)
    #define __pyx_atomic_pointer_exchange(value, new_value) atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value)
    #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) atomic_compare_exchange_strong(value, expected, desired)
    #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER)
        #pragma message ("Using standard C atomics")
    #elif defined(__PYX_DEBUG_ATOMICS)
        #warning "Using standard C atomics"
    #endif
#elif CYTHON_ATOMICS && (defined(__cplusplus) && (\
                    (__cplusplus >= 201103L) ||\
\
                    (defined(_MSC_VER) && _MSC_VER >= 1700)) &&\
                    ATOMIC_INT_LOCK_FREE == 2)
    #undef __pyx_atomic_int_type
    #define __pyx_atomic_int_type std::atomic_int
    #define __pyx_atomic_ptr_type std::atomic_uintptr_t
    #define __pyx_nonatomic_ptr_type uintptr_t
    #define __pyx_atomic_incr_relaxed(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_relaxed)
    #define __pyx_atomic_incr_acq_rel(value) std::atomic_fetch_add_explicit(value, 1, std::memory_order_acq_rel)
    #define __pyx_atomic_decr_acq_rel(value) std::atomic_fetch_sub_explicit(value, 1, std::memory_order_acq_rel)
    #define __pyx_atomic_sub(value, arg) std::atomic_fetch_sub(value, arg)
    #define __pyx_atomic_int_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired)
    #define __pyx_atomic_load(value) std::atomic_load(value)
    #define __pyx_atomic_store(value, new_value) std::atomic_store(value, new_value)
    #define __pyx_atomic_pointer_load_relaxed(value) std::atomic_load_explicit(value, std::memory_order_relaxed)
    #define __pyx_atomic_pointer_load_acquire(value) std::atomic_load_explicit(value, std::memory_order_acquire)
    #define __pyx_atomic_pointer_exchange(value, new_value) std::atomic_exchange(value, (__pyx_nonatomic_ptr_type)new_value)
    #define __pyx_atomic_pointer_cmp_exchange(value, expected, desired) std::atomic_compare_exchange_strong(value, expected, desired)
    #if defined(__PYX_DEBUG_ATOMICS) && defined(_MSC_VER)
        #pragma message ("Using standard C++ atomics")
    #elif defined(__PYX_DEBUG_ATOMICS)
        #warning "Using standard C++ atomics"
    #endif
#elif CYTHON_ATOMICS && (__GNUC__ >= 5 || (__GNUC__ == 4 &&\
                    (__GNUC_MINOR__ > 1 ||\
                    (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 2))))
    #define __pyx_atomic_ptr_type void*
    #define __pyx_nonatomic_ptr_type void*
    #define __pyx_atomic_incr_relaxed(value) __sync_fetch_and_add(value, 1)
    #define __pyx_atomic_incr_acq_rel(value) __sync_fetch_and_add(value, 1)
    #define __pyx_atomic_decr_acq_rel(value) __sync_fetch_and_sub(value, 1)
    #define __pyx_atomic_sub(value, arg) __sync_fetch_and_sub(value, arg)
    static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) {
        __pyx_nonatomic_int_type old = __sync_val_compare_and_swap(value, *expected, desired);
        int result = old == *expected;
        *expected = old;
        return result;
    }
    #define __pyx_atomic_load(value) __sync_fetch_and_add(value, 0)
    #define __pyx_atomic_store(value, new_value) __sync_lock_test_and_set(value, new_value)
    #define __pyx_atomic_pointer_load_relaxed(value) __sync_fetch_and_add(value, 0)
    #define __pyx_atomic_pointer_load_acquire(value) __sync_fetch_and_add(value, 0)
    #define __pyx_atomic_pointer_exchange(value, new_value) __sync_lock_test_and_set(value, (__pyx_atomic_ptr_type)new_value)
    static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) {
        __pyx_nonatomic_ptr_type old = __sync_val_compare_and_swap(value, *expected, desired);
        int result = old == *expected;
        *expected = old;
        return result;
    }
    #ifdef __PYX_DEBUG_ATOMICS
        #warning "Using GNU atomics"
    #endif
#elif CYTHON_ATOMICS && defined(_MSC_VER)
    #include <intrin.h>
    #undef __pyx_atomic_int_type
    #define __pyx_atomic_int_type long
    #define __pyx_atomic_ptr_type void*
    #undef __pyx_nonatomic_int_type
    #define __pyx_nonatomic_int_type long
    #define __pyx_nonatomic_ptr_type void*
    #pragma intrinsic (_InterlockedExchangeAdd, _InterlockedExchange, _InterlockedCompareExchange, _InterlockedCompareExchangePointer, _InterlockedExchangePointer)
    #define __pyx_atomic_incr_relaxed(value) _InterlockedExchangeAdd(value, 1)
    #define __pyx_atomic_incr_acq_rel(value) _InterlockedExchangeAdd(value, 1)
    #define __pyx_atomic_decr_acq_rel(value) _InterlockedExchangeAdd(value, -1)
    #define __pyx_atomic_sub(value, arg) _InterlockedExchangeAdd(value, -arg)
    static CYTHON_INLINE int __pyx_atomic_int_cmp_exchange(__pyx_atomic_int_type* value, __pyx_nonatomic_int_type* expected, __pyx_nonatomic_int_type desired) {
        __pyx_nonatomic_int_type old = _InterlockedCompareExchange(value, desired, *expected);
        int result = old == *expected;
        *expected = old;
        return result;
    }
    #define __pyx_atomic_load(value) _InterlockedExchangeAdd(value, 0)
    #define __pyx_atomic_store(value, new_value) _InterlockedExchange(value, new_value)
    #define __pyx_atomic_pointer_load_relaxed(value) *(void * volatile *)value
    #define __pyx_atomic_pointer_load_acquire(value) _InterlockedCompareExchangePointer(value, 0, 0)
    #define __pyx_atomic_pointer_exchange(value, new_value) _InterlockedExchangePointer(value, (__pyx_atomic_ptr_type)new_value)
    static CYTHON_INLINE int __pyx_atomic_pointer_cmp_exchange(__pyx_atomic_ptr_type* value, __pyx_nonatomic_ptr_type* expected, __pyx_nonatomic_ptr_type desired) {
        __pyx_atomic_ptr_type old = _InterlockedCompareExchangePointer(value, desired, *expected);
        int result = old == *expected;
        *expected = old;
        return result;
    }
    #ifdef __PYX_DEBUG_ATOMICS
        #pragma message ("Using MSVC atomics")
    #endif
#else
    #undef CYTHON_ATOMICS
    #define CYTHON_ATOMICS 0
    #ifdef __PYX_DEBUG_ATOMICS
        #warning "Not using atomics"
    #endif
#endif

/* CriticalSectionsDefinition.proto (used by CriticalSections) */
#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
#define __Pyx_PyCriticalSection void*
#define __Pyx_PyCriticalSection2 void*
#define __Pyx_PyCriticalSection_End(cs)
#define __Pyx_PyCriticalSection2_End(cs)
#else
#define __Pyx_PyCriticalSection PyCriticalSection
#define __Pyx_PyCriticalSection2 PyCriticalSection2
#define __Pyx_PyCriticalSection_End PyCriticalSection_End
#define __Pyx_PyCriticalSection2_End PyCriticalSection2_End
#endif

/* CriticalSections.proto (used by ParseKeywordsImpl) */
#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
#define __Pyx_PyCriticalSection_Begin(cs, arg) (void)(cs)
#define __Pyx_PyCriticalSection2_Begin(cs, arg1, arg2) (void)(cs)
#else
#define __Pyx_PyCriticalSection_Begin PyCriticalSection_Begin
#define __Pyx_PyCriticalSection2_Begin PyCriticalSection2_Begin
#endif
#if PY_VERSION_HEX < 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_BEGIN_CRITICAL_SECTION(o) {
#define __Pyx_END_CRITICAL_SECTION() }
#else
#define __Pyx_BEGIN_CRITICAL_SECTION Py_BEGIN_CRITICAL_SECTION
#define __Pyx_END_CRITICAL_SECTION Py_END_CRITICAL_SECTION
#endif

/* BufferFormatStructs.proto (used by BufferFormatCheck) */
struct __Pyx_StructField_;
#define __PYX_BUF_FLAGS_PACKED_STRUCT (1 << 0)
typedef struct {
  const char* name;
  const struct __Pyx_StructField_* fields;
  size_t size;
  size_t arraysize[8];
  int ndim;
  char typegroup;
  char is_unsigned;
  int flags;
} __Pyx_TypeInfo;
typedef struct __Pyx_StructField_ {
  const __Pyx_TypeInfo* type;
  const char* name;
  size_t offset;
} __Pyx_StructField;
typedef struct {
  const __Pyx_StructField* field;
  size_t parent_offset;
} __Pyx_BufFmt_StackElem;
typedef struct {
  __Pyx_StructField root;
  __Pyx_BufFmt_StackElem* head;
  size_t fmt_offset;
  size_t new_count, enc_count;
  size_t struct_alignment;
  int is_complex;
  char enc_type;
  char new_packmode;
  char enc_packmode;
  char is_valid_array;
} __Pyx_BufFmt_Context;

/* IncludeStructmemberH.proto (used by FixUpExtensionType) */
#include <structmember.h>

/* #### Code section: numeric_typedefs ### */

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":744
 * # in Cython to enable them only on the right systems.
 * 
 * ctypedef npy_int8       int8_t             # <<<<<<<<<<<<<<
 * ctypedef npy_int16      int16_t
 * ctypedef npy_int32      int32_t
*/
typedef npy_int8 __pyx_t_5numpy_int8_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":745
 * 
 * ctypedef npy_int8       int8_t
 * ctypedef npy_int16      int16_t             # <<<<<<<<<<<<<<
 * ctypedef npy_int32      int32_t
 * ctypedef npy_int64      int64_t
*/
typedef npy_int16 __pyx_t_5numpy_int16_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":746
 * ctypedef npy_int8       int8_t
 * ctypedef npy_int16      int16_t
 * ctypedef npy_int32      int32_t             # <<<<<<<<<<<<<<
 * ctypedef npy_int64      int64_t
 * 
*/
typedef npy_int32 __pyx_t_5numpy_int32_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":747
 * ctypedef npy_int16      int16_t
 * ctypedef npy_int32      int32_t
 * ctypedef npy_int64      int64_t             # <<<<<<<<<<<<<<
 * 
 * ctypedef npy_uint8      uint8_t
*/
typedef npy_int64 __pyx_t_5numpy_int64_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":749
 * ctypedef npy_int64      int64_t
 * 
 * ctypedef npy_uint8      uint8_t             # <<<<<<<<<<<<<<
 * ctypedef npy_uint16     uint16_t
 * ctypedef npy_uint32     uint32_t
*/
typedef npy_uint8 __pyx_t_5numpy_uint8_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":750
 * 
 * ctypedef npy_uint8      uint8_t
 * ctypedef npy_uint16     uint16_t             # <<<<<<<<<<<<<<
 * ctypedef npy_uint32     uint32_t
 * ctypedef npy_uint64     uint64_t
*/
typedef npy_uint16 __pyx_t_5numpy_uint16_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":751
 * ctypedef npy_uint8      uint8_t
 * ctypedef npy_uint16     uint16_t
 * ctypedef npy_uint32     uint32_t             # <<<<<<<<<<<<<<
 * ctypedef npy_uint64     uint64_t
 * 
*/
typedef npy_uint32 __pyx_t_5numpy_uint32_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":752
 * ctypedef npy_uint16     uint16_t
 * ctypedef npy_uint32     uint32_t
 * ctypedef npy_uint64     uint64_t             # <<<<<<<<<<<<<<
 * 
 * ctypedef npy_float32    float32_t
*/
typedef npy_uint64 __pyx_t_5numpy_uint64_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":754
 * ctypedef npy_uint64     uint64_t
 * 
 * ctypedef npy_float32    float32_t             # <<<<<<<<<<<<<<
 * ctypedef npy_float64    float64_t
 * #ctypedef npy_float80    float80_t
*/
typedef npy_float32 __pyx_t_5numpy_float32_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":755
 * 
 * ctypedef npy_float32    float32_t
 * ctypedef npy_float64    float64_t             # <<<<<<<<<<<<<<
 * #ctypedef npy_float80    float80_t
 * #ctypedef npy_float128   float128_t
*/
typedef npy_float64 __pyx_t_5numpy_float64_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":762
 * ctypedef double complex complex128_t
 * 
 * ctypedef npy_longlong   longlong_t             # <<<<<<<<<<<<<<
 * ctypedef npy_ulonglong  ulonglong_t
 * 
*/
typedef npy_longlong __pyx_t_5numpy_longlong_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":763
 * 
 * ctypedef npy_longlong   longlong_t
 * ctypedef npy_ulonglong  ulonglong_t             # <<<<<<<<<<<<<<
 * 
 * ctypedef npy_intp       intp_t
*/
typedef npy_ulonglong __pyx_t_5numpy_ulonglong_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":765
 * ctypedef npy_ulonglong  ulonglong_t
 * 
 * ctypedef npy_intp       intp_t             # <<<<<<<<<<<<<<
 * ctypedef npy_uintp      uintp_t
 * 
*/
typedef npy_intp __pyx_t_5numpy_intp_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":766
 * 
 * ctypedef npy_intp       intp_t
 * ctypedef npy_uintp      uintp_t             # <<<<<<<<<<<<<<
 * 
 * ctypedef npy_double     float_t
*/
typedef npy_uintp __pyx_t_5numpy_uintp_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":768
 * ctypedef npy_uintp      uintp_t
 * 
 * ctypedef npy_double     float_t             # <<<<<<<<<<<<<<
 * ctypedef npy_double     double_t
 * ctypedef npy_longdouble longdouble_t
*/
typedef npy_double __pyx_t_5numpy_float_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":769
 * 
 * ctypedef npy_double     float_t
 * ctypedef npy_double     double_t             # <<<<<<<<<<<<<<
 * ctypedef npy_longdouble longdouble_t
 * 
*/
typedef npy_double __pyx_t_5numpy_double_t;

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":770
 * ctypedef npy_double     float_t
 * ctypedef npy_double     double_t
 * ctypedef npy_longdouble longdouble_t             # <<<<<<<<<<<<<<
 * 
 * ctypedef float complex       cfloat_t
*/
typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
/* #### Code section: complex_type_declarations ### */
/* Declarations.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #ifdef __cplusplus
    typedef ::std::complex< float > __pyx_t_float_complex;
  #else
    typedef float _Complex __pyx_t_float_complex;
  #endif
#else
    typedef struct { float real, imag; } __pyx_t_float_complex;
#endif
static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float, float);

/* Declarations.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #ifdef __cplusplus
    typedef ::std::complex< double > __pyx_t_double_complex;
  #else
    typedef double _Complex __pyx_t_double_complex;
  #endif
#else
    typedef struct { double real, imag; } __pyx_t_double_complex;
#endif
static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double, double);

/* Declarations.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #ifdef __cplusplus
    typedef ::std::complex< long double > __pyx_t_long_double_complex;
  #else
    typedef long double _Complex __pyx_t_long_double_complex;
  #endif
#else
    typedef struct { long double real, imag; } __pyx_t_long_double_complex;
#endif
static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double, long double);

/* #### Code section: type_declarations ### */

/*--- Type declarations ---*/
struct __pyx_defaults;
struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_FlowPixelType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue;
struct __pyx_t_15pygeoprocessing_7routing_7routing_WeightedFlowPixelType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_MFDFlowPixelType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_StreamConnectivityPoint;
struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_FinishType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_GreaterPixel;

/* "pygeoprocessing/routing/routing.pyx":97
 * 
 * # this is the class type that'll get stored in the priority queue
 * cdef struct PixelType:             # <<<<<<<<<<<<<<
 *     double value  # pixel value
 *     unsigned int xi  # pixel x coordinate in the raster
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType {
  double value;
  unsigned int xi;
  unsigned int yi;
  int priority;
};

/* "pygeoprocessing/routing/routing.pyx":105
 * # this struct is used to record an intermediate flow pixel's last calculated
 * # direction and the flow accumulation value so far
 * cdef struct FlowPixelType:             # <<<<<<<<<<<<<<
 *     unsigned int xi
 *     unsigned int yi
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_FlowPixelType {
  unsigned int xi;
  unsigned int yi;
  int last_flow_dir;
  double value;
};

/* "pygeoprocessing/routing/routing.pyx":114
 * # ``decayed_value`` updated in-place as we walk the flow graph until the value
 * # is less than the ``min_value``.
 * cdef struct DecayingValue:             # <<<<<<<<<<<<<<
 *     double decayed_value  # The value, which will be progressively updated as it decays
 *     double min_value  # The minimum value before the Decaying Value should be ignored.
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue {
  double decayed_value;
  double min_value;
};

/* "pygeoprocessing/routing/routing.pyx":123
 * # Additionally, we track all of the decaying values from upstream that
 * # influence the load on this pixel.  Used during decaying flow accumulation.
 * cdef struct WeightedFlowPixelType:             # <<<<<<<<<<<<<<
 *     unsigned int xi  # The pixel's x coordinate in pixel space
 *     unsigned int yi  # The pixel's y coordinate in pixel space
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_WeightedFlowPixelType {
  unsigned int xi;
  unsigned int yi;
  int last_flow_dir;
  double value;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue>  decaying_values;
};

/* "pygeoprocessing/routing/routing.pyx":132
 * # this struct is used in distance_to_channel_mfd to add up each pixel's
 * # weighted distances and flow weights
 * cdef struct MFDFlowPixelType:             # <<<<<<<<<<<<<<
 *     unsigned int xi
 *     unsigned int yi
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_MFDFlowPixelType {
  unsigned int xi;
  unsigned int yi;
  int last_flow_dir;
  double sum_of_weighted_distances;
  double sum_of_weights;
};

/* "pygeoprocessing/routing/routing.pyx":143
 * # d8 flow direction to walk and the source_id indicates the source stream it
 * # spawned from
 * cdef struct StreamConnectivityPoint:             # <<<<<<<<<<<<<<
 *     unsigned int xi
 *     unsigned int yi
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_StreamConnectivityPoint {
  unsigned int xi;
  unsigned int yi;
  int upstream_d8_dir;
  unsigned int source_id;
};

/* "pygeoprocessing/routing/routing.pyx":150
 * 
 * # used to record x/y locations as needed
 * cdef struct CoordinateType:             # <<<<<<<<<<<<<<
 *     unsigned int xi
 *     unsigned int yi
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType {
  unsigned int xi;
  unsigned int yi;
};

/* "pygeoprocessing/routing/routing.pyx":155
 * 
 * 
 * cdef struct FinishType:             # <<<<<<<<<<<<<<
 *     unsigned int xi
 *     unsigned int yi
*/
struct __pyx_t_15pygeoprocessing_7routing_7routing_FinishType {
  unsigned int xi;
  unsigned int yi;
  unsigned int n_pushed;
};

/* "pygeoprocessing/routing/routing.pyx":161
 * 
 * # this type is used to create a priority queue on the custom Pixel tpye
 * ctypedef priority_queue[             # <<<<<<<<<<<<<<
 *     PixelType, deque[PixelType], GreaterPixel] PitPriorityQueueType
 * 
*/
typedef std::priority_queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType,std::deque<struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType> ,__pyx_t_15pygeoprocessing_7routing_7routing_GreaterPixel>  __pyx_t_15pygeoprocessing_7routing_7routing_PitPriorityQueueType;

/* "pygeoprocessing/routing/routing.pyx":165
 * 
 * # this queue is used to record flow directions
 * ctypedef queue[int] IntQueueType             # <<<<<<<<<<<<<<
 * 
 * # type used to store x/y coordinates and a queue to put them in
*/
typedef std::queue<int>  __pyx_t_15pygeoprocessing_7routing_7routing_IntQueueType;

/* "pygeoprocessing/routing/routing.pyx":168
 * 
 * # type used to store x/y coordinates and a queue to put them in
 * ctypedef queue[CoordinateType] CoordinateQueueType             # <<<<<<<<<<<<<<
 * 
 * # functor for priority queue of pixels
*/
typedef std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType;
struct __pyx_t_15pygeoprocessing_7routing_7routing_GreaterPixel {
  virtual int operator()(struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType &, struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType &);
  virtual ~__pyx_t_15pygeoprocessing_7routing_7routing_GreaterPixel() {

    /* "pygeoprocessing/routing/routing.pyx":171
 * 
 * # functor for priority queue of pixels
 * cdef cppclass GreaterPixel nogil:             # <<<<<<<<<<<<<<
 *     bint get "operator()"(PixelType& lhs, PixelType& rhs):
 *         # lhs is > than rhs if its value is greater or if it's equal if
*/
  }
};

/* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/
struct __pyx_defaults {
  PyObject_HEAD
  PyObject *arg0;
};

/* #### Code section: utility_code_proto ### */

/* --- Runtime support code (head) --- */
/* Refnanny.proto */
#ifndef CYTHON_REFNANNY
  #define CYTHON_REFNANNY 0
#endif
#if CYTHON_REFNANNY
  typedef struct {
    void (*INCREF)(void*, PyObject*, Py_ssize_t);
    void (*DECREF)(void*, PyObject*, Py_ssize_t);
    void (*GOTREF)(void*, PyObject*, Py_ssize_t);
    void (*GIVEREF)(void*, PyObject*, Py_ssize_t);
    void* (*SetupContext)(const char*, Py_ssize_t, const char*);
    void (*FinishContext)(void**);
  } __Pyx_RefNannyAPIStruct;
  static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
  static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname);
  #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
  #define __Pyx_RefNannySetupContext(name, acquire_gil)\
          if (acquire_gil) {\
              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\
              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\
              PyGILState_Release(__pyx_gilstate_save);\
          } else {\
              __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), (__LINE__), (__FILE__));\
          }
  #define __Pyx_RefNannyFinishContextNogil() {\
              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\
              __Pyx_RefNannyFinishContext();\
              PyGILState_Release(__pyx_gilstate_save);\
          }
  #define __Pyx_RefNannyFinishContextNogil() {\
              PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\
              __Pyx_RefNannyFinishContext();\
              PyGILState_Release(__pyx_gilstate_save);\
          }
  #define __Pyx_RefNannyFinishContext()\
          __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
  #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), (__LINE__))
  #define __Pyx_XINCREF(r)  do { if((r) == NULL); else {__Pyx_INCREF(r); }} while(0)
  #define __Pyx_XDECREF(r)  do { if((r) == NULL); else {__Pyx_DECREF(r); }} while(0)
  #define __Pyx_XGOTREF(r)  do { if((r) == NULL); else {__Pyx_GOTREF(r); }} while(0)
  #define __Pyx_XGIVEREF(r) do { if((r) == NULL); else {__Pyx_GIVEREF(r);}} while(0)
#else
  #define __Pyx_RefNannyDeclarations
  #define __Pyx_RefNannySetupContext(name, acquire_gil)
  #define __Pyx_RefNannyFinishContextNogil()
  #define __Pyx_RefNannyFinishContext()
  #define __Pyx_INCREF(r) Py_INCREF(r)
  #define __Pyx_DECREF(r) Py_DECREF(r)
  #define __Pyx_GOTREF(r)
  #define __Pyx_GIVEREF(r)
  #define __Pyx_XINCREF(r) Py_XINCREF(r)
  #define __Pyx_XDECREF(r) Py_XDECREF(r)
  #define __Pyx_XGOTREF(r)
  #define __Pyx_XGIVEREF(r)
#endif
#define __Pyx_Py_XDECREF_SET(r, v) do {\
        PyObject *tmp = (PyObject *) r;\
        r = v; Py_XDECREF(tmp);\
    } while (0)
#define __Pyx_XDECREF_SET(r, v) do {\
        PyObject *tmp = (PyObject *) r;\
        r = v; __Pyx_XDECREF(tmp);\
    } while (0)
#define __Pyx_DECREF_SET(r, v) do {\
        PyObject *tmp = (PyObject *) r;\
        r = v; __Pyx_DECREF(tmp);\
    } while (0)
#define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
#define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)

/* PyErrExceptionMatches.proto (used by PyObjectGetAttrStrNoError) */
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyErr_ExceptionMatches(err) __Pyx_PyErr_ExceptionMatchesInState(__pyx_tstate, err)
static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err);
#else
#define __Pyx_PyErr_ExceptionMatches(err)  PyErr_ExceptionMatches(err)
#endif

/* PyThreadStateGet.proto (used by PyErrFetchRestore) */
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyThreadState_declare  PyThreadState *__pyx_tstate;
#define __Pyx_PyThreadState_assign  __pyx_tstate = __Pyx_PyThreadState_Current;
#if PY_VERSION_HEX >= 0x030C00A6
#define __Pyx_PyErr_Occurred()  (__pyx_tstate->current_exception != NULL)
#define __Pyx_PyErr_CurrentExceptionType()  (__pyx_tstate->current_exception ? (PyObject*) Py_TYPE(__pyx_tstate->current_exception) : (PyObject*) NULL)
#else
#define __Pyx_PyErr_Occurred()  (__pyx_tstate->curexc_type != NULL)
#define __Pyx_PyErr_CurrentExceptionType()  (__pyx_tstate->curexc_type)
#endif
#else
#define __Pyx_PyThreadState_declare
#define __Pyx_PyThreadState_assign
#define __Pyx_PyErr_Occurred()  (PyErr_Occurred() != NULL)
#define __Pyx_PyErr_CurrentExceptionType()  PyErr_Occurred()
#endif

/* PyErrFetchRestore.proto (used by PyObjectGetAttrStrNoError) */
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL)
#define __Pyx_ErrRestoreWithState(type, value, tb)  __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb)
#define __Pyx_ErrFetchWithState(type, value, tb)    __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb)
#define __Pyx_ErrRestore(type, value, tb)  __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb)
#define __Pyx_ErrFetch(type, value, tb)    __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb)
static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb);
static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A6
#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL))
#else
#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc)
#endif
#else
#define __Pyx_PyErr_Clear() PyErr_Clear()
#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc)
#define __Pyx_ErrRestoreWithState(type, value, tb)  PyErr_Restore(type, value, tb)
#define __Pyx_ErrFetchWithState(type, value, tb)  PyErr_Fetch(type, value, tb)
#define __Pyx_ErrRestoreInState(tstate, type, value, tb)  PyErr_Restore(type, value, tb)
#define __Pyx_ErrFetchInState(tstate, type, value, tb)  PyErr_Fetch(type, value, tb)
#define __Pyx_ErrRestore(type, value, tb)  PyErr_Restore(type, value, tb)
#define __Pyx_ErrFetch(type, value, tb)  PyErr_Fetch(type, value, tb)
#endif

/* PyObjectGetAttrStr.proto (used by PyObjectGetAttrStrNoError) */
#if CYTHON_USE_TYPE_SLOTS
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name);
#else
#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
#endif

/* PyObjectGetAttrStrNoError.proto (used by GetBuiltinName) */
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name);

/* GetBuiltinName.proto */
static PyObject *__Pyx_GetBuiltinName(PyObject *name);

/* GetTopmostException.proto (used by SaveResetException) */
#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
static _PyErr_StackItem * __Pyx_PyErr_GetTopmostException(PyThreadState *tstate);
#endif

/* SaveResetException.proto */
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_ExceptionSave(type, value, tb)  __Pyx__ExceptionSave(__pyx_tstate, type, value, tb)
static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
#define __Pyx_ExceptionReset(type, value, tb)  __Pyx__ExceptionReset(__pyx_tstate, type, value, tb)
static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb);
#else
#define __Pyx_ExceptionSave(type, value, tb)   PyErr_GetExcInfo(type, value, tb)
#define __Pyx_ExceptionReset(type, value, tb)  PyErr_SetExcInfo(type, value, tb)
#endif

/* GetException.proto */
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_GetException(type, value, tb)  __Pyx__GetException(__pyx_tstate, type, value, tb)
static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb);
#else
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb);
#endif

/* PyImportError_Check.proto */
#define __Pyx_PyExc_ImportError_Check(obj)  __Pyx_TypeCheck(obj, PyExc_ImportError)

/* PyObjectCall.proto (used by PyObjectFastCall) */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw);
#else
#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw)
#endif

/* PyObjectCallMethO.proto (used by PyObjectFastCall) */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg);
#endif

/* PyObjectFastCall.proto */
#define __Pyx_PyObject_FastCall(func, args, nargs)  __Pyx_PyObject_FastCallDict(func, args, (size_t)(nargs), NULL)
static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs);

/* RaiseException.export */
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause);

/* TupleAndListFromArray.proto (used by fastcall) */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n);
#endif
#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_METH_FASTCALL
static CYTHON_INLINE PyObject* __Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n);
#endif

/* IncludeStringH.proto (used by BytesEquals) */
#include <string.h>

/* BytesEquals.proto (used by UnicodeEquals) */
static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals);

/* UnicodeEquals.proto (used by fastcall) */
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals);

/* fastcall.proto */
#if CYTHON_AVOID_BORROWED_REFS
    #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_PySequence_ITEM(args, i)
#elif CYTHON_ASSUME_SAFE_MACROS
    #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_NewRef(__Pyx_PyTuple_GET_ITEM(args, i))
#else
    #define __Pyx_ArgRef_VARARGS(args, i) __Pyx_XNewRef(PyTuple_GetItem(args, i))
#endif
#define __Pyx_NumKwargs_VARARGS(kwds) PyDict_Size(kwds)
#define __Pyx_KwValues_VARARGS(args, nargs) NULL
#define __Pyx_GetKwValue_VARARGS(kw, kwvalues, s) __Pyx_PyDict_GetItemStrWithError(kw, s)
#define __Pyx_KwargsAsDict_VARARGS(kw, kwvalues) PyDict_Copy(kw)
#if CYTHON_METH_FASTCALL
    #define __Pyx_ArgRef_FASTCALL(args, i) __Pyx_NewRef(args[i])
    #define __Pyx_NumKwargs_FASTCALL(kwds) __Pyx_PyTuple_GET_SIZE(kwds)
    #define __Pyx_KwValues_FASTCALL(args, nargs) ((args) + (nargs))
    static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API
    CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues);
  #else
    #define __Pyx_KwargsAsDict_FASTCALL(kw, kwvalues) _PyStack_AsDict(kwvalues, kw)
  #endif
#else
    #define __Pyx_ArgRef_FASTCALL __Pyx_ArgRef_VARARGS
    #define __Pyx_NumKwargs_FASTCALL __Pyx_NumKwargs_VARARGS
    #define __Pyx_KwValues_FASTCALL __Pyx_KwValues_VARARGS
    #define __Pyx_GetKwValue_FASTCALL __Pyx_GetKwValue_VARARGS
    #define __Pyx_KwargsAsDict_FASTCALL __Pyx_KwargsAsDict_VARARGS
#endif
#define __Pyx_ArgsSlice_VARARGS(args, start, stop) PyTuple_GetSlice(args, start, stop)
#if CYTHON_METH_FASTCALL || (CYTHON_COMPILING_IN_CPYTHON && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) __Pyx_PyTuple_FromArray(args + start, stop - start)
#else
#define __Pyx_ArgsSlice_FASTCALL(args, start, stop) PyTuple_GetSlice(args, start, stop)
#endif

/* py_dict_items.proto (used by OwnedDictNext) */
static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d);

/* CallCFunction.proto (used by CallUnboundCMethod0) */
#define __Pyx_CallCFunction(cfunc, self, args)\
    ((PyCFunction)(void(*)(void))(cfunc)->func)(self, args)
#define __Pyx_CallCFunctionWithKeywords(cfunc, self, args, kwargs)\
    ((PyCFunctionWithKeywords)(void(*)(void))(cfunc)->func)(self, args, kwargs)
#define __Pyx_CallCFunctionFast(cfunc, self, args, nargs)\
    ((__Pyx_PyCFunctionFast)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs)
#define __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, nargs, kwnames)\
    ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))(PyCFunction)(cfunc)->func)(self, args, nargs, kwnames)

/* PyObjectCallOneArg.proto (used by CallUnboundCMethod0) */
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg);

/* UnpackUnboundCMethod.proto (used by CallUnboundCMethod0) */
typedef struct {
    PyObject *type;
    PyObject **method_name;
#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && CYTHON_ATOMICS
    __pyx_atomic_int_type initialized;
#endif
    PyCFunction func;
    PyObject *method;
    int flag;
} __Pyx_CachedCFunction;
#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
static CYTHON_INLINE int __Pyx_CachedCFunction_GetAndSetInitializing(__Pyx_CachedCFunction *cfunc) {
#if !CYTHON_ATOMICS
    return 1;
#else
    __pyx_nonatomic_int_type expected = 0;
    if (__pyx_atomic_int_cmp_exchange(&cfunc->initialized, &expected, 1)) {
        return 0;
    }
    return expected;
#endif
}
static CYTHON_INLINE void __Pyx_CachedCFunction_SetFinishedInitializing(__Pyx_CachedCFunction *cfunc) {
#if CYTHON_ATOMICS
    __pyx_atomic_store(&cfunc->initialized, 2);
#endif
}
#else
#define __Pyx_CachedCFunction_GetAndSetInitializing(cfunc) 2
#define __Pyx_CachedCFunction_SetFinishedInitializing(cfunc)
#endif

/* CallUnboundCMethod0.proto */
CYTHON_UNUSED
static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self);
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self);
#else
#define __Pyx_CallUnboundCMethod0(cfunc, self)  __Pyx__CallUnboundCMethod0(cfunc, self)
#endif

/* py_dict_values.proto (used by OwnedDictNext) */
static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d);

/* OwnedDictNext.proto (used by ParseKeywordsImpl) */
#if CYTHON_AVOID_BORROWED_REFS
static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue);
#else
CYTHON_INLINE
static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue);
#endif

/* RaiseDoubleKeywords.proto (used by ParseKeywordsImpl) */
static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name);

/* ParseKeywordsImpl.export */
static int __Pyx_ParseKeywordsTuple(
    PyObject *kwds,
    PyObject * const *kwvalues,
    PyObject ** const argnames[],
    PyObject *kwds2,
    PyObject *values[],
    Py_ssize_t num_pos_args,
    Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs
);
static int __Pyx_ParseKeywordDictToDict(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject *kwds2,
    PyObject *values[],
    Py_ssize_t num_pos_args,
    const char* function_name
);
static int __Pyx_ParseKeywordDict(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject *values[],
    Py_ssize_t num_pos_args,
    Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs
);

/* CallUnboundCMethod2.proto */
CYTHON_UNUSED
static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2);
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2);
#else
#define __Pyx_CallUnboundCMethod2(cfunc, self, arg1, arg2)  __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2)
#endif

/* ParseKeywords.proto */
static CYTHON_INLINE int __Pyx_ParseKeywords(
    PyObject *kwds, PyObject *const *kwvalues, PyObject ** const argnames[],
    PyObject *kwds2, PyObject *values[],
    Py_ssize_t num_pos_args, Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs
);

/* RaiseArgTupleInvalid.proto */
static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
    Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found);

/* PyObjectFastCallMethod.proto */
#if CYTHON_VECTORCALL && PY_VERSION_HEX >= 0x03090000
#define __Pyx_PyObject_FastCallMethod(name, args, nargsf) PyObject_VectorcallMethod(name, args, nargsf, NULL)
#else
static PyObject *__Pyx_PyObject_FastCallMethod(PyObject *name, PyObject *const *args, size_t nargsf);
#endif

/* DictGetItem.proto */
#if !CYTHON_COMPILING_IN_PYPY
static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key);
#define __Pyx_PyObject_Dict_GetItem(obj, name)\
    (likely(PyDict_CheckExact(obj)) ?\
     __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name))
#else
#define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key)
#define __Pyx_PyObject_Dict_GetItem(obj, name)  PyObject_GetItem(obj, name)
#endif

/* PyLongBinop.proto */
#if !CYTHON_COMPILING_IN_PYPY
static CYTHON_INLINE PyObject* __Pyx_PyLong_SubtractObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check);
#else
#define __Pyx_PyLong_SubtractObjC(op1, op2, intval, inplace, zerodivision_check)\
    (inplace ? PyNumber_InPlaceSubtract(op1, op2) : PyNumber_Subtract(op1, op2))
#endif

/* PyLongBinop.proto */
#if !CYTHON_COMPILING_IN_PYPY
static CYTHON_INLINE PyObject* __Pyx_PyLong_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check);
#else
#define __Pyx_PyLong_AddObjC(op1, op2, intval, inplace, zerodivision_check)\
    (inplace ? PyNumber_InPlaceAdd(op1, op2) : PyNumber_Add(op1, op2))
#endif

/* RaiseTooManyValuesToUnpack.proto */
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected);

/* RaiseNeedMoreValuesToUnpack.proto */
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index);

/* IterFinish.proto */
static CYTHON_INLINE int __Pyx_IterFinish(void);

/* UnpackItemEndCheck.proto */
static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected);

/* PyDictVersioning.proto (used by GetModuleGlobalName) */
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
#define __PYX_DICT_VERSION_INIT  ((PY_UINT64_T) -1)
#define __PYX_GET_DICT_VERSION(dict)  (((PyDictObject*)(dict))->ma_version_tag)
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\
    (version_var) = __PYX_GET_DICT_VERSION(dict);\
    (cache_var) = (value);
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\
    static PY_UINT64_T __pyx_dict_version = 0;\
    static PyObject *__pyx_dict_cached_value = NULL;\
    if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\
        (VAR) = __Pyx_XNewRef(__pyx_dict_cached_value);\
    } else {\
        (VAR) = __pyx_dict_cached_value = (LOOKUP);\
        __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\
    }\
}
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj);
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj);
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version);
#else
#define __PYX_GET_DICT_VERSION(dict)  (0)
#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)
#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP)  (VAR) = (LOOKUP);
#endif

/* GetModuleGlobalName.proto */
#if CYTHON_USE_DICT_VERSIONS
#define __Pyx_GetModuleGlobalName(var, name)  do {\
    static PY_UINT64_T __pyx_dict_version = 0;\
    static PyObject *__pyx_dict_cached_value = NULL;\
    (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_mstate_global->__pyx_d))) ?\
        (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\
        __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\
} while(0)
#define __Pyx_GetModuleGlobalNameUncached(var, name)  do {\
    PY_UINT64_T __pyx_dict_version;\
    PyObject *__pyx_dict_cached_value;\
    (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\
} while(0)
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value);
#else
#define __Pyx_GetModuleGlobalName(var, name)  (var) = __Pyx__GetModuleGlobalName(name)
#define __Pyx_GetModuleGlobalNameUncached(var, name)  (var) = __Pyx__GetModuleGlobalName(name)
static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name);
#endif

/* GetItemInt.proto */
#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\
    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
    __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck, unsafe_shared) :\
    (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\
               __Pyx_GetItemInt_Generic(o, to_py_func(i))))
#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\
    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
    __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck, unsafe_shared) :\
    (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
                                                              int wraparound, int boundscheck, int unsafe_shared);
#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck, has_gil, unsafe_shared)\
    (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\
    __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck, unsafe_shared) :\
    (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL))
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
                                                              int wraparound, int boundscheck, int unsafe_shared);
static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j);
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
                                                     int is_list, int wraparound, int boundscheck, int unsafe_shared);

/* ObjectGetItem.proto */
#if CYTHON_USE_TYPE_SLOTS
static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key);
#else
#define __Pyx_PyObject_GetItem(obj, key)  PyObject_GetItem(obj, key)
#endif

/* PyOSError_Check.proto */
#define __Pyx_PyExc_OSError_Check(obj)  __Pyx_TypeCheck(obj, PyExc_OSError)

/* PyObjectVectorCallKwBuilder.proto */
CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n);
#if CYTHON_VECTORCALL
#if PY_VERSION_HEX >= 0x03090000
#define __Pyx_Object_Vectorcall_CallFromBuilder PyObject_Vectorcall
#else
#define __Pyx_Object_Vectorcall_CallFromBuilder _PyObject_Vectorcall
#endif
#define __Pyx_MakeVectorcallBuilderKwds(n) PyTuple_New(n)
static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n);
static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n);
#else
#define __Pyx_Object_Vectorcall_CallFromBuilder __Pyx_PyObject_FastCallDict
#define __Pyx_MakeVectorcallBuilderKwds(n) __Pyx_PyDict_NewPresized(n)
#define __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n) PyDict_SetItem(builder, key, value)
#define __Pyx_VectorcallBuilder_AddArgStr(key, value, builder, args, n) PyDict_SetItemString(builder, key, value)
#endif

/* MoveIfSupported.proto */
#if CYTHON_USE_CPP_STD_MOVE
  #include <utility>
  #define __PYX_STD_MOVE_IF_SUPPORTED(x) std::move(x)
#else
  #define __PYX_STD_MOVE_IF_SUPPORTED(x) x
#endif

/* PyObjectVectorCallMethodKwBuilder.proto */
#if CYTHON_VECTORCALL && PY_VERSION_HEX >= 0x03090000
#define __Pyx_Object_VectorcallMethod_CallFromBuilder PyObject_VectorcallMethod
#else
static PyObject *__Pyx_Object_VectorcallMethod_CallFromBuilder(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames);
#endif

/* BuildPyUnicode.proto (used by COrdinalToPyUnicode) */
static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, const char* chars, int clength,
                                                int prepend_sign, char padding_char);

/* COrdinalToPyUnicode.proto (used by CIntToPyUnicode) */
static CYTHON_INLINE int __Pyx_CheckUnicodeValue(int value);
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromOrdinal_Padded(int value, Py_ssize_t width, char padding_char);

/* GCCDiagnostics.proto (used by CIntToPyUnicode) */
#if !defined(__INTEL_COMPILER) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define __Pyx_HAS_GCC_DIAGNOSTIC
#endif

/* IncludeStdlibH.proto (used by CIntToPyUnicode) */
#include <stdlib.h>

/* CIntToPyUnicode.proto */
#define __Pyx_PyUnicode_From_unsigned_long(value, width, padding_char, format_char) (\
    ((format_char) == ('c')) ?\
        __Pyx_uchar___Pyx_PyUnicode_From_unsigned_long(value, width, padding_char) :\
        __Pyx____Pyx_PyUnicode_From_unsigned_long(value, width, padding_char, format_char)\
    )
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_unsigned_long(unsigned long value, Py_ssize_t width, char padding_char);
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_unsigned_long(unsigned long value, Py_ssize_t width, char padding_char, char format_char);

/* CIntToPyUnicode.proto */
#define __Pyx_PyUnicode_From_unsigned_int(value, width, padding_char, format_char) (\
    ((format_char) == ('c')) ?\
        __Pyx_uchar___Pyx_PyUnicode_From_unsigned_int(value, width, padding_char) :\
        __Pyx____Pyx_PyUnicode_From_unsigned_int(value, width, padding_char, format_char)\
    )
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_unsigned_int(unsigned int value, Py_ssize_t width, char padding_char);
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_unsigned_int(unsigned int value, Py_ssize_t width, char padding_char, char format_char);

/* JoinPyUnicode.export */
static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength,
                                      Py_UCS4 max_char);

/* PyLongCompare.proto */
static CYTHON_INLINE int __Pyx_PyLong_BoolNeObjC(PyObject *op1, PyObject *op2, long intval, long inplace);

/* ExtTypeTest.proto */
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type);

/* IsLittleEndian.proto (used by BufferFormatCheck) */
static CYTHON_INLINE int __Pyx_Is_Little_Endian(void);

/* BufferFormatCheck.proto (used by BufferGetAndValidate) */
static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts);
static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                              __Pyx_BufFmt_StackElem* stack,
                              const __Pyx_TypeInfo* type);

/* BufferGetAndValidate.proto */
#define __Pyx_GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack)\
    ((obj == Py_None || obj == NULL) ?\
    (__Pyx_ZeroBuffer(buf), 0) :\
    __Pyx__GetBufferAndValidate(buf, obj, dtype, flags, nd, cast, stack))
static int  __Pyx__GetBufferAndValidate(Py_buffer* buf, PyObject* obj,
  const __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
static void __Pyx_ZeroBuffer(Py_buffer* buf);
static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
static Py_ssize_t __Pyx_minusones[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
static Py_ssize_t __Pyx_zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };

/* BufferFallbackError.proto */
static void __Pyx_RaiseBufferFallbackError(void);

/* BufferIndexError.proto */
static void __Pyx_RaiseBufferIndexError(int axis);

#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
/* PyValueError_Check.proto */
#define __Pyx_PyExc_ValueError_Check(obj)  __Pyx_TypeCheck(obj, PyExc_ValueError)

/* pybytes_as_double.proto (used by pyunicode_as_double) */
static double __Pyx_SlowPyString_AsDouble(PyObject *obj);
static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length);
static CYTHON_INLINE double __Pyx_PyBytes_AsDouble(PyObject *obj) {
    char* as_c_string;
    Py_ssize_t size;
#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
    as_c_string = PyBytes_AS_STRING(obj);
    size = PyBytes_GET_SIZE(obj);
#else
    if (PyBytes_AsStringAndSize(obj, &as_c_string, &size) < 0) {
        return (double)-1;
    }
#endif
    return __Pyx__PyBytes_AsDouble(obj, as_c_string, size);
}
static CYTHON_INLINE double __Pyx_PyByteArray_AsDouble(PyObject *obj) {
    char* as_c_string;
    Py_ssize_t size;
#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
    as_c_string = PyByteArray_AS_STRING(obj);
    size = PyByteArray_GET_SIZE(obj);
#else
    as_c_string = PyByteArray_AsString(obj);
    if (as_c_string == NULL) {
        return (double)-1;
    }
    size = PyByteArray_Size(obj);
#endif
    return __Pyx__PyBytes_AsDouble(obj, as_c_string, size);
}

/* pyunicode_as_double.proto */
#if !CYTHON_COMPILING_IN_PYPY && CYTHON_ASSUME_SAFE_MACROS
static const char* __Pyx__PyUnicode_AsDouble_Copy(const void* data, const int kind, char* buffer, Py_ssize_t start, Py_ssize_t end) {
    int last_was_punctuation;
    Py_ssize_t i;
    last_was_punctuation = 1;
    for (i=start; i <= end; i++) {
        Py_UCS4 chr = PyUnicode_READ(kind, data, i);
        int is_punctuation = (chr == '_') | (chr == '.');
        *buffer = (char)chr;
        buffer += (chr != '_');
        if (unlikely(chr > 127)) goto parse_failure;
        if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure;
        last_was_punctuation = is_punctuation;
    }
    if (unlikely(last_was_punctuation)) goto parse_failure;
    *buffer = '\0';
    return buffer;
parse_failure:
    return NULL;
}
static double __Pyx__PyUnicode_AsDouble_inf_nan(const void* data, int kind, Py_ssize_t start, Py_ssize_t length) {
    int matches = 1;
    Py_UCS4 chr;
    Py_UCS4 sign = PyUnicode_READ(kind, data, start);
    int is_signed = (sign == '-') | (sign == '+');
    start += is_signed;
    length -= is_signed;
    switch (PyUnicode_READ(kind, data, start)) {
        #ifdef Py_NAN
        case 'n':
        case 'N':
            if (unlikely(length != 3)) goto parse_failure;
            chr = PyUnicode_READ(kind, data, start+1);
            matches &= (chr == 'a') | (chr == 'A');
            chr = PyUnicode_READ(kind, data, start+2);
            matches &= (chr == 'n') | (chr == 'N');
            if (unlikely(!matches)) goto parse_failure;
            return (sign == '-') ? -Py_NAN : Py_NAN;
        #endif
        case 'i':
        case 'I':
            if (unlikely(length < 3)) goto parse_failure;
            chr = PyUnicode_READ(kind, data, start+1);
            matches &= (chr == 'n') | (chr == 'N');
            chr = PyUnicode_READ(kind, data, start+2);
            matches &= (chr == 'f') | (chr == 'F');
            if (likely(length == 3 && matches))
                return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
            if (unlikely(length != 8)) goto parse_failure;
            chr = PyUnicode_READ(kind, data, start+3);
            matches &= (chr == 'i') | (chr == 'I');
            chr = PyUnicode_READ(kind, data, start+4);
            matches &= (chr == 'n') | (chr == 'N');
            chr = PyUnicode_READ(kind, data, start+5);
            matches &= (chr == 'i') | (chr == 'I');
            chr = PyUnicode_READ(kind, data, start+6);
            matches &= (chr == 't') | (chr == 'T');
            chr = PyUnicode_READ(kind, data, start+7);
            matches &= (chr == 'y') | (chr == 'Y');
            if (unlikely(!matches)) goto parse_failure;
            return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
        case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
            break;
        default:
            goto parse_failure;
    }
    return 0.0;
parse_failure:
    return -1.0;
}
static double __Pyx_PyUnicode_AsDouble_WithSpaces(PyObject *obj) {
    double value;
    const char *last;
    char *end;
    Py_ssize_t start, length = PyUnicode_GET_LENGTH(obj);
    const int kind = PyUnicode_KIND(obj);
    const void* data = PyUnicode_DATA(obj);
    start = 0;
    while (Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, start)))
        start++;
    while (start < length - 1 && Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, length - 1)))
        length--;
    length -= start;
    if (unlikely(length <= 0)) goto fallback;
    value = __Pyx__PyUnicode_AsDouble_inf_nan(data, kind, start, length);
    if (unlikely(value == -1.0)) goto fallback;
    if (value != 0.0) return value;
    if (length < 40) {
        char number[40];
        last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
        if (unlikely(!last)) goto fallback;
        value = PyOS_string_to_double(number, &end, NULL);
    } else {
        char *number = (char*) PyMem_Malloc((length + 1) * sizeof(char));
        if (unlikely(!number)) goto fallback;
        last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
        if (unlikely(!last)) {
            PyMem_Free(number);
            goto fallback;
        }
        value = PyOS_string_to_double(number, &end, NULL);
        PyMem_Free(number);
    }
    if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
        return value;
    }
fallback:
    return __Pyx_SlowPyString_AsDouble(obj);
}
#endif
static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj) {
#if !CYTHON_COMPILING_IN_PYPY && CYTHON_ASSUME_SAFE_MACROS
    if (unlikely(__Pyx_PyUnicode_READY(obj) == -1))
        return (double)-1;
    if (likely(PyUnicode_IS_ASCII(obj))) {
        const char *s;
        Py_ssize_t length;
        s = PyUnicode_AsUTF8AndSize(obj, &length);
        return __Pyx__PyBytes_AsDouble(obj, s, length);
    }
    return __Pyx_PyUnicode_AsDouble_WithSpaces(obj);
#else
    return __Pyx_SlowPyString_AsDouble(obj);
#endif
}

/* FloatExceptionCheck.proto */
#define __PYX_CHECK_FLOAT_EXCEPTION(value, error_value)\
    ((error_value) == (error_value) ?\
     (value) == (error_value) :\
     (value) != (value))

/* ModInt[long].proto */
static CYTHON_INLINE long __Pyx_mod_long(long, long, int b_is_constant);

/* PyLongCompare.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_EqObjC(PyObject *op1, PyObject *op2, long intval, long inplace);

/* CIntToPyUnicode.proto */
#define __Pyx_PyUnicode_From_long(value, width, padding_char, format_char) (\
    ((format_char) == ('c')) ?\
        __Pyx_uchar___Pyx_PyUnicode_From_long(value, width, padding_char) :\
        __Pyx____Pyx_PyUnicode_From_long(value, width, padding_char, format_char)\
    )
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_long(long value, Py_ssize_t width, char padding_char);
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_long(long value, Py_ssize_t width, char padding_char, char format_char);

/* ListAppend.proto (used by append) */
#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS
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) & likely(len > (L->allocated >> 1))) {
        Py_INCREF(x);
        #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000
        L->ob_item[len] = x;
        #else
        PyList_SET_ITEM(list, len, x);
        #endif
        __Pyx_SET_SIZE(list, len + 1);
        return 0;
    }
    return PyList_Append(list, x);
}
#else
#define __Pyx_PyList_Append(L,x) PyList_Append(L,x)
#endif

/* PyObjectCall2Args.proto (used by PyObjectCallMethod1) */
static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2);

/* PyObjectGetMethod.proto (used by PyObjectCallMethod1) */
#if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method);
#endif

/* PyObjectCallMethod1.proto (used by append) */
static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg);

/* append.proto */
static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x);

/* PyObjectFormatSimple.proto */
#if CYTHON_COMPILING_IN_PYPY
    #define __Pyx_PyObject_FormatSimple(s, f) (\
        likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\
        PyObject_Format(s, f))
#elif CYTHON_USE_TYPE_SLOTS
    #define __Pyx_PyObject_FormatSimple(s, f) (\
        likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\
        likely(PyLong_CheckExact(s)) ? PyLong_Type.tp_repr(s) :\
        likely(PyFloat_CheckExact(s)) ? PyFloat_Type.tp_repr(s) :\
        PyObject_Format(s, f))
#else
    #define __Pyx_PyObject_FormatSimple(s, f) (\
        likely(PyUnicode_CheckExact(s)) ? (Py_INCREF(s), s) :\
        PyObject_Format(s, f))
#endif

/* CIntToPyUnicode.proto */
#define __Pyx_PyUnicode_From_int(value, width, padding_char, format_char) (\
    ((format_char) == ('c')) ?\
        __Pyx_uchar___Pyx_PyUnicode_From_int(value, width, padding_char) :\
        __Pyx____Pyx_PyUnicode_From_int(value, width, padding_char, format_char)\
    )
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char);
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char, char format_char);

/* ListCompAppend.proto */
#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS
static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) {
    PyListObject* L = (PyListObject*) list;
    Py_ssize_t len = Py_SIZE(list);
    if (likely(L->allocated > len)) {
        Py_INCREF(x);
        #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000
        L->ob_item[len] = x;
        #else
        PyList_SET_ITEM(list, len, x);
        #endif
        __Pyx_SET_SIZE(list, len + 1);
        return 0;
    }
    return PyList_Append(list, x);
}
#else
#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x)
#endif

/* pop_index.proto */
static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix);
static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix);
#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix);
#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
    (likely(PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed))) ?\
        __Pyx__PyList_PopIndex(L, py_ix, ix) : (\
        (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
            __Pyx__PyObject_PopIndex(L, py_ix)))
#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
    __Pyx_fits_Py_ssize_t(ix, type, is_signed) ?\
        __Pyx__PyList_PopIndex(L, py_ix, ix) : (\
        (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
            __Pyx__PyObject_PopIndex(L, py_ix)))
#else
#define __Pyx_PyList_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)\
    __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func)
#define __Pyx_PyObject_PopIndex(L, py_ix, ix, is_signed, type, to_py_func) (\
    (unlikely((py_ix) == Py_None)) ? __Pyx__PyObject_PopNewIndex(L, to_py_func(ix)) :\
        __Pyx__PyObject_PopIndex(L, py_ix))
#endif

/* PyDictContains.proto */
static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) {
    int result = PyDict_Contains(dict, item);
    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
}

/* CIntToPyUnicode.proto */
#define __Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char, format_char) (\
    ((format_char) == ('c')) ?\
        __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char) :\
        __Pyx____Pyx_PyUnicode_From_Py_ssize_t(value, width, padding_char, format_char)\
    )
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char);
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char, char format_char);

/* PyObjectCallNoArg.proto (used by PyObjectCallMethod0) */
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func);

/* PyObjectCallMethod0.proto (used by pop) */
static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name);

/* pop.proto */
static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L);
#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L);
#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ?\
    __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L))
#else
#define __Pyx_PyList_Pop(L)  __Pyx__PyObject_Pop(L)
#define __Pyx_PyObject_Pop(L)  __Pyx__PyObject_Pop(L)
#endif

/* ListExtend.proto */
static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) {
#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00a2
    return PyList_Extend(L, v);
#elif CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030d0000
    PyObject* none = _PyList_Extend((PyListObject*)L, v);
    if (unlikely(!none))
        return -1;
    Py_DECREF(none);
    return 0;
#else
    return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v);
#endif
}

/* PyRange_Check.proto */
#if CYTHON_COMPILING_IN_PYPY && !defined(PyRange_Check)
  #define PyRange_Check(obj)  __Pyx_TypeCheck((obj), &PyRange_Type)
#endif

/* PySequenceContains.proto */
static CYTHON_INLINE int __Pyx_PySequence_ContainsTF(PyObject* item, PyObject* seq, int eq) {
    int result = PySequence_Contains(seq, item);
    return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
}

/* RaiseNoneIterError.proto (used by UnpackTupleError) */
static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);

/* UnpackTupleError.proto (used by UnpackTuple2) */
static void __Pyx_UnpackTupleError(PyObject *, Py_ssize_t index);

/* UnpackTuple2.proto (used by dict_iter) */
static CYTHON_INLINE int __Pyx_unpack_tuple2(
    PyObject* tuple, PyObject** value1, PyObject** value2, int is_tuple, int has_known_size, int decref_tuple);
static CYTHON_INLINE int __Pyx_unpack_tuple2_exact(
    PyObject* tuple, PyObject** value1, PyObject** value2, int decref_tuple);
static int __Pyx_unpack_tuple2_generic(
    PyObject* tuple, PyObject** value1, PyObject** value2, int has_known_size, int decref_tuple);

/* dict_iter.proto */
static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, PyObject* method_name,
                                                   Py_ssize_t* p_orig_length, int* p_is_dict);
static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos,
                                              PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict);

/* PyObjectFormat.proto */
#if CYTHON_USE_UNICODE_WRITER
static PyObject* __Pyx_PyObject_Format(PyObject* s, PyObject* f);
#else
#define __Pyx_PyObject_Format(s, f) PyObject_Format(s, f)
#endif

/* UnicodeConcatInPlace.proto */
# if CYTHON_COMPILING_IN_CPYTHON
    #if CYTHON_REFNANNY
        #define __Pyx_PyUnicode_ConcatInPlace(left, right, unsafe_shared) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right, unsafe_shared, __pyx_refnanny)
    #else
        #define __Pyx_PyUnicode_ConcatInPlace(left, right, unsafe_shared) __Pyx_PyUnicode_ConcatInPlaceImpl(&left, right, unsafe_shared)
    #endif
    #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_DefinitelyUnique)
    #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_OwnStrongReference)
    #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_DefinitelyUnique)
    #define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlace(left, right) __Pyx_PyUnicode_ConcatInPlace(left, right, __Pyx_ReferenceSharing_SharedReference)
    static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right, int unsafe_shared
        #if CYTHON_REFNANNY
        , void* __pyx_refnanny
        #endif
    );
#else
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlace __Pyx_PyUnicode_Concat
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace __Pyx_PyUnicode_Concat
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace __Pyx_PyUnicode_Concat
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlace __Pyx_PyUnicode_Concat
#endif
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlaceSafe(left, right)\
    ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ?\
    PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_DefinitelyUniqueInPlace(left, right))
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlaceSafe(left, right)\
    ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ?\
    PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(left, right))
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlaceSafe(left, right)\
    ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ?\
    PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_FunctionArgumentInPlace(left, right))
#define __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlaceSafe(left, right)\
    ((unlikely((left) == Py_None) || unlikely((right) == Py_None)) ?\
    PyNumber_InPlaceAdd(left, right) : __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_SharedReferenceInPlace(left, right))

/* pyfrozenset_new.proto (used by PySetContains) */
static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it);

/* PySetContains.proto */
static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq);

/* PyLongCompare.proto */
static CYTHON_INLINE int __Pyx_PyLong_BoolEqObjC(PyObject *op1, PyObject *op2, long intval, long inplace);

/* PyLongBinop.proto */
#if !CYTHON_COMPILING_IN_PYPY
static CYTHON_INLINE PyObject* __Pyx_PyLong_MultiplyObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check);
#else
#define __Pyx_PyLong_MultiplyObjC(op1, op2, intval, inplace, zerodivision_check)\
    (inplace ? PyNumber_InPlaceMultiply(op1, op2) : PyNumber_Multiply(op1, op2))
#endif

/* PyRuntimeError_Check.proto */
#define __Pyx_PyExc_RuntimeError_Check(obj)  __Pyx_TypeCheck(obj, PyExc_RuntimeError)

/* PyObjectLookupSpecial.proto */
#if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
#define __Pyx_PyObject_LookupSpecialNoError(obj, attr_name)  __Pyx__PyObject_LookupSpecial(obj, attr_name, 0)
#define __Pyx_PyObject_LookupSpecial(obj, attr_name)  __Pyx__PyObject_LookupSpecial(obj, attr_name, 1)
static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error);
#else
#define __Pyx_PyObject_LookupSpecialNoError(o,n) __Pyx_PyObject_GetAttrStrNoError(o,n)
#define __Pyx_PyObject_LookupSpecial(o,n) __Pyx_PyObject_GetAttrStr(o,n)
#endif

/* AllocateExtensionType.proto */
static PyObject *__Pyx_AllocateExtensionType(PyTypeObject *t, int is_final);

/* CallTypeTraverse.proto */
#if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000)
#define __Pyx_call_type_traverse(o, always_call, visit, arg) 0
#else
static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg);
#endif

/* LimitedApiGetTypeDict.proto (used by SetItemOnTypeDict) */
#if CYTHON_COMPILING_IN_LIMITED_API
static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp);
#endif

/* SetItemOnTypeDict.proto (used by FixUpExtensionType) */
static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v);
#define __Pyx_SetItemOnTypeDict(tp, k, v) __Pyx__SetItemOnTypeDict((PyTypeObject*)tp, k, v)

/* FixUpExtensionType.proto */
static CYTHON_INLINE int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type);

/* ValidateBasesTuple.proto (used by PyType_Ready) */
#if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases);
#endif

/* PyType_Ready.proto */
CYTHON_UNUSED static int __Pyx_PyType_Ready(PyTypeObject *t);

/* TypeImport.proto */
#ifndef __PYX_HAVE_RT_ImportType_proto_3_2_4
#define __PYX_HAVE_RT_ImportType_proto_3_2_4
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#include <stdalign.h>
#endif
#if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || __cplusplus >= 201103L
#define __PYX_GET_STRUCT_ALIGNMENT_3_2_4(s) alignof(s)
#else
#define __PYX_GET_STRUCT_ALIGNMENT_3_2_4(s) sizeof(void*)
#endif
enum __Pyx_ImportType_CheckSize_3_2_4 {
   __Pyx_ImportType_CheckSize_Error_3_2_4 = 0,
   __Pyx_ImportType_CheckSize_Warn_3_2_4 = 1,
   __Pyx_ImportType_CheckSize_Ignore_3_2_4 = 2
};
static PyTypeObject *__Pyx_ImportType_3_2_4(PyObject* module, const char *module_name, const char *class_name, size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_4 check_size);
#endif

/* HasAttr.proto (used by ImportImpl) */
#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
#define __Pyx_HasAttr(o, n)  PyObject_HasAttrWithError(o, n)
#else
static CYTHON_INLINE int __Pyx_HasAttr(PyObject *, PyObject *);
#endif

/* ImportImpl.export */
static PyObject *__Pyx__Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, PyObject *moddict, int level);

/* Import.proto */
static CYTHON_INLINE PyObject *__Pyx_Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, int level);

/* ImportFrom.proto */
static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name);

/* dict_setdefault.proto (used by FetchCommonType) */
static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value);

/* AddModuleRef.proto (used by FetchSharedCythonModule) */
#if ((CYTHON_COMPILING_IN_CPYTHON_FREETHREADING ) ||\
     __PYX_LIMITED_VERSION_HEX < 0x030d0000)
  static PyObject *__Pyx_PyImport_AddModuleRef(const char *name);
#else
  #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name)
#endif

/* FetchSharedCythonModule.proto (used by FetchCommonType) */
static PyObject *__Pyx_FetchSharedCythonABIModule(void);

/* FetchCommonType.proto (used by CommonTypesMetaclass) */
static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases);

/* CommonTypesMetaclass.proto (used by CythonFunctionShared) */
static int __pyx_CommonTypesMetaclass_init(PyObject *module);
#define __Pyx_CommonTypesMetaclass_USED

/* PyMethodNew.proto (used by CythonFunctionShared) */
static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ);

/* PyVectorcallFastCallDict.proto (used by CythonFunctionShared) */
#if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL
static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw);
#endif

/* CythonFunctionShared.proto (used by CythonFunction) */
#define __Pyx_CyFunction_USED
#define __Pyx_CYFUNCTION_STATICMETHOD  0x01
#define __Pyx_CYFUNCTION_CLASSMETHOD   0x02
#define __Pyx_CYFUNCTION_CCLASS        0x04
#define __Pyx_CYFUNCTION_COROUTINE     0x08
#define __Pyx_CyFunction_GetClosure(f)\
    (((__pyx_CyFunctionObject *) (f))->func_closure)
#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
  #define __Pyx_CyFunction_GetClassObj(f)\
      (((__pyx_CyFunctionObject *) (f))->func_classobj)
#else
  #define __Pyx_CyFunction_GetClassObj(f)\
      ((PyObject*) ((PyCMethodObject *) (f))->mm_class)
#endif
#define __Pyx_CyFunction_SetClassObj(f, classobj)\
    __Pyx__CyFunction_SetClassObj((__pyx_CyFunctionObject *) (f), (classobj))
#define __Pyx_CyFunction_Defaults(type, f)\
    ((type *)(((__pyx_CyFunctionObject *) (f))->defaults))
#define __Pyx_CyFunction_SetDefaultsGetter(f, g)\
    ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g)
typedef struct {
#if CYTHON_COMPILING_IN_LIMITED_API
    PyObject_HEAD
    PyObject *func;
#elif PY_VERSION_HEX < 0x030900B1
    PyCFunctionObject func;
#else
    PyCMethodObject func;
#endif
#if CYTHON_COMPILING_IN_LIMITED_API && CYTHON_METH_FASTCALL
    __pyx_vectorcallfunc func_vectorcall;
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
    PyObject *func_weakreflist;
#endif
#if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API
    PyObject *func_dict;
#endif
    PyObject *func_name;
    PyObject *func_qualname;
    PyObject *func_doc;
    PyObject *func_globals;
    PyObject *func_code;
    PyObject *func_closure;
#if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
    PyObject *func_classobj;
#endif
    PyObject *defaults;
    int flags;
    PyObject *defaults_tuple;
    PyObject *defaults_kwdict;
    PyObject *(*defaults_getter)(PyObject *);
    PyObject *func_annotations;
    PyObject *func_is_coroutine;
} __pyx_CyFunctionObject;
#undef __Pyx_CyOrPyCFunction_Check
#define __Pyx_CyFunction_Check(obj)  __Pyx_TypeCheck(obj, __pyx_mstate_global->__pyx_CyFunctionType)
#define __Pyx_CyOrPyCFunction_Check(obj)  __Pyx_TypeCheck2(obj, __pyx_mstate_global->__pyx_CyFunctionType, &PyCFunction_Type)
#define __Pyx_CyFunction_CheckExact(obj)  __Pyx_IS_TYPE(obj, __pyx_mstate_global->__pyx_CyFunctionType)
static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void));
#undef __Pyx_IsSameCFunction
#define __Pyx_IsSameCFunction(func, cfunc)   __Pyx__IsSameCyOrCFunction(func, cfunc)
static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml,
                                      int flags, PyObject* qualname,
                                      PyObject *closure,
                                      PyObject *module, PyObject *globals,
                                      PyObject* code);
static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj);
static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func,
                                                         PyTypeObject *defaults_type);
static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m,
                                                            PyObject *tuple);
static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m,
                                                             PyObject *dict);
static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m,
                                                              PyObject *dict);
static int __pyx_CyFunction_init(PyObject *module);
#if CYTHON_METH_FASTCALL
static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
#if CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_CyFunction_func_vectorcall(f) (((__pyx_CyFunctionObject*)f)->func_vectorcall)
#else
#define __Pyx_CyFunction_func_vectorcall(f) (((PyCFunctionObject*)f)->vectorcall)
#endif
#endif

/* CythonFunction.proto */
static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml,
                                      int flags, PyObject* qualname,
                                      PyObject *closure,
                                      PyObject *module, PyObject *globals,
                                      PyObject* code);

/* CLineInTraceback.proto (used by AddTraceback) */
#if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME
static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);
#else
#define __Pyx_CLineForTraceback(tstate, c_line)  (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0)
#endif

/* CodeObjectCache.proto (used by AddTraceback) */
#if CYTHON_COMPILING_IN_LIMITED_API
typedef PyObject __Pyx_CachedCodeObjectType;
#else
typedef PyCodeObject __Pyx_CachedCodeObjectType;
#endif
typedef struct {
    __Pyx_CachedCodeObjectType* code_object;
    int code_line;
} __Pyx_CodeObjectCacheEntry;
struct __Pyx_CodeObjectCache {
    int count;
    int max_count;
    __Pyx_CodeObjectCacheEntry* entries;
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    __pyx_atomic_int_type accessor_count;
  #endif
};
static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line);
static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line);
static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object);

/* AddTraceback.proto */
static void __Pyx_AddTraceback(const char *funcname, int c_line,
                               int py_line, const char *filename);

/* BufferStructDeclare.proto */
typedef struct {
  Py_ssize_t shape, strides, suboffsets;
} __Pyx_Buf_DimInfo;
typedef struct {
  size_t refcount;
  Py_buffer pybuffer;
} __Pyx_Buffer;
typedef struct {
  __Pyx_Buffer *rcbuffer;
  char *data;
  __Pyx_Buf_DimInfo diminfo[8];
} __Pyx_LocalBuf_ND;

/* CppExceptionConversion.proto */
#ifndef __Pyx_CppExn2PyErr
#include <new>
#include <typeinfo>
#include <stdexcept>
#include <ios>
static void __Pyx_CppExn2PyErr() {
  try {
    if (PyErr_Occurred())
      ; // let the latest Python exn pass through and ignore the current one
    else
      throw;
  } catch (const std::bad_alloc& exn) {
    PyErr_SetString(PyExc_MemoryError, exn.what());
  } catch (const std::bad_cast& exn) {
    PyErr_SetString(PyExc_TypeError, exn.what());
  } catch (const std::bad_typeid& exn) {
    PyErr_SetString(PyExc_TypeError, exn.what());
  } catch (const std::domain_error& exn) {
    PyErr_SetString(PyExc_ValueError, exn.what());
  } catch (const std::invalid_argument& exn) {
    PyErr_SetString(PyExc_ValueError, exn.what());
  } catch (const std::ios_base::failure& exn) {
    PyErr_SetString(PyExc_IOError, exn.what());
  } catch (const std::out_of_range& exn) {
    PyErr_SetString(PyExc_IndexError, exn.what());
  } catch (const std::overflow_error& exn) {
    PyErr_SetString(PyExc_OverflowError, exn.what());
  } catch (const std::range_error& exn) {
    PyErr_SetString(PyExc_ArithmeticError, exn.what());
  } catch (const std::underflow_error& exn) {
    PyErr_SetString(PyExc_ArithmeticError, exn.what());
  } catch (const std::exception& exn) {
    PyErr_SetString(PyExc_RuntimeError, exn.what());
  }
  catch (...)
  {
    PyErr_SetString(PyExc_RuntimeError, "Unknown exception");
  }
}
#endif

/* RealImag.proto */
#if CYTHON_CCOMPLEX
  #ifdef __cplusplus
    #define __Pyx_CREAL(z) ((z).real())
    #define __Pyx_CIMAG(z) ((z).imag())
  #else
    #define __Pyx_CREAL(z) (__real__(z))
    #define __Pyx_CIMAG(z) (__imag__(z))
  #endif
#else
    #define __Pyx_CREAL(z) ((z).real)
    #define __Pyx_CIMAG(z) ((z).imag)
#endif
#if defined(__cplusplus) && CYTHON_CCOMPLEX\
        && (defined(_WIN32) || defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 5 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 )) || __cplusplus >= 201103)
    #define __Pyx_SET_CREAL(z,x) ((z).real(x))
    #define __Pyx_SET_CIMAG(z,y) ((z).imag(y))
#else
    #define __Pyx_SET_CREAL(z,x) __Pyx_CREAL(z) = (x)
    #define __Pyx_SET_CIMAG(z,y) __Pyx_CIMAG(z) = (y)
#endif

/* Arithmetic.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #define __Pyx_c_eq_float(a, b)   ((a)==(b))
    #define __Pyx_c_sum_float(a, b)  ((a)+(b))
    #define __Pyx_c_diff_float(a, b) ((a)-(b))
    #define __Pyx_c_prod_float(a, b) ((a)*(b))
    #define __Pyx_c_quot_float(a, b) ((a)/(b))
    #define __Pyx_c_neg_float(a)     (-(a))
  #ifdef __cplusplus
    #define __Pyx_c_is_zero_float(z) ((z)==(float)0)
    #define __Pyx_c_conj_float(z)    (::std::conj(z))
    #if 1
        #define __Pyx_c_abs_float(z)     (::std::abs(z))
        #define __Pyx_c_pow_float(a, b)  (::std::pow(a, b))
    #endif
  #else
    #define __Pyx_c_is_zero_float(z) ((z)==0)
    #define __Pyx_c_conj_float(z)    (conjf(z))
    #if 1
        #define __Pyx_c_abs_float(z)     (cabsf(z))
        #define __Pyx_c_pow_float(a, b)  (cpowf(a, b))
    #endif
 #endif
#else
    static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex, __pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex, __pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex, __pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex, __pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex, __pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex);
    static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex);
    static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex);
    #if 1
        static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex);
        static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex, __pyx_t_float_complex);
    #endif
#endif

/* Arithmetic.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #define __Pyx_c_eq_double(a, b)   ((a)==(b))
    #define __Pyx_c_sum_double(a, b)  ((a)+(b))
    #define __Pyx_c_diff_double(a, b) ((a)-(b))
    #define __Pyx_c_prod_double(a, b) ((a)*(b))
    #define __Pyx_c_quot_double(a, b) ((a)/(b))
    #define __Pyx_c_neg_double(a)     (-(a))
  #ifdef __cplusplus
    #define __Pyx_c_is_zero_double(z) ((z)==(double)0)
    #define __Pyx_c_conj_double(z)    (::std::conj(z))
    #if 1
        #define __Pyx_c_abs_double(z)     (::std::abs(z))
        #define __Pyx_c_pow_double(a, b)  (::std::pow(a, b))
    #endif
  #else
    #define __Pyx_c_is_zero_double(z) ((z)==0)
    #define __Pyx_c_conj_double(z)    (conj(z))
    #if 1
        #define __Pyx_c_abs_double(z)     (cabs(z))
        #define __Pyx_c_pow_double(a, b)  (cpow(a, b))
    #endif
 #endif
#else
    static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex, __pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex, __pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex, __pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex, __pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex, __pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex);
    static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex);
    static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex);
    #if 1
        static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex);
        static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex, __pyx_t_double_complex);
    #endif
#endif

/* Arithmetic.proto */
#if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #define __Pyx_c_eq_long__double(a, b)   ((a)==(b))
    #define __Pyx_c_sum_long__double(a, b)  ((a)+(b))
    #define __Pyx_c_diff_long__double(a, b) ((a)-(b))
    #define __Pyx_c_prod_long__double(a, b) ((a)*(b))
    #define __Pyx_c_quot_long__double(a, b) ((a)/(b))
    #define __Pyx_c_neg_long__double(a)     (-(a))
  #ifdef __cplusplus
    #define __Pyx_c_is_zero_long__double(z) ((z)==(long double)0)
    #define __Pyx_c_conj_long__double(z)    (::std::conj(z))
    #if 1
        #define __Pyx_c_abs_long__double(z)     (::std::abs(z))
        #define __Pyx_c_pow_long__double(a, b)  (::std::pow(a, b))
    #endif
  #else
    #define __Pyx_c_is_zero_long__double(z) ((z)==0)
    #define __Pyx_c_conj_long__double(z)    (conjl(z))
    #if 1
        #define __Pyx_c_abs_long__double(z)     (cabsl(z))
        #define __Pyx_c_pow_long__double(a, b)  (cpowl(a, b))
    #endif
 #endif
#else
    static CYTHON_INLINE int __Pyx_c_eq_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_sum_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_diff_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_prod_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_neg_long__double(__pyx_t_long_double_complex);
    static CYTHON_INLINE int __Pyx_c_is_zero_long__double(__pyx_t_long_double_complex);
    static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_conj_long__double(__pyx_t_long_double_complex);
    #if 1
        static CYTHON_INLINE long double __Pyx_c_abs_long__double(__pyx_t_long_double_complex);
        static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_pow_long__double(__pyx_t_long_double_complex, __pyx_t_long_double_complex);
    #endif
#endif

/* CIntFromPy.proto */
static CYTHON_INLINE PY_LONG_LONG __Pyx_PyLong_As_PY_LONG_LONG(PyObject *);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_PY_LONG_LONG(PY_LONG_LONG value);

/* CIntFromPy.proto */
static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *);

/* CIntFromPy.proto */
static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_int(int value);

/* CIntFromPy.proto */
static CYTHON_INLINE unsigned int __Pyx_PyLong_As_unsigned_int(PyObject *);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_int(unsigned int value);

/* CIntFromPy.proto */
static CYTHON_INLINE unsigned long __Pyx_PyLong_As_unsigned_long(PyObject *);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_long(unsigned long value);

/* CIntFromPy.proto */
static CYTHON_INLINE size_t __Pyx_PyLong_As_size_t(PyObject *);

/* CIntToPy.proto */
static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value);

/* FormatTypeName.proto */
#if CYTHON_COMPILING_IN_LIMITED_API
typedef PyObject *__Pyx_TypeName;
#define __Pyx_FMT_TYPENAME "%U"
#define __Pyx_DECREF_TypeName(obj) Py_XDECREF(obj)
#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
#define __Pyx_PyType_GetFullyQualifiedName PyType_GetFullyQualifiedName
#else
static __Pyx_TypeName __Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp);
#endif
#else  // !LIMITED_API
typedef const char *__Pyx_TypeName;
#define __Pyx_FMT_TYPENAME "%.200s"
#define __Pyx_PyType_GetFullyQualifiedName(tp) ((tp)->tp_name)
#define __Pyx_DECREF_TypeName(obj)
#endif

/* FastTypeChecks.proto */
#if CYTHON_COMPILING_IN_CPYTHON
#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type)
#define __Pyx_TypeCheck2(obj, type1, type2) __Pyx_IsAnySubtype2(Py_TYPE(obj), (PyTypeObject *)type1, (PyTypeObject *)type2)
static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b);
static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b);
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type);
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2);
#else
#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#define __Pyx_TypeCheck2(obj, type1, type2) (PyObject_TypeCheck(obj, (PyTypeObject *)type1) || PyObject_TypeCheck(obj, (PyTypeObject *)type2))
#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type)
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2) {
    return PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2);
}
#endif
#define __Pyx_PyErr_ExceptionMatches2(err1, err2)  __Pyx_PyErr_GivenExceptionMatches2(__Pyx_PyErr_CurrentExceptionType(), err1, err2)
#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception)
#ifdef PyExceptionInstance_Check
  #define __Pyx_PyBaseException_Check(obj) PyExceptionInstance_Check(obj)
#else
  #define __Pyx_PyBaseException_Check(obj) __Pyx_TypeCheck(obj, PyExc_BaseException)
#endif

/* GetRuntimeVersion.proto */
#if __PYX_LIMITED_VERSION_HEX < 0x030b0000
static unsigned long __Pyx_cached_runtime_version = 0;
static void __Pyx_init_runtime_version(void);
#else
#define __Pyx_init_runtime_version()
#endif
static unsigned long __Pyx_get_runtime_version(void);

/* CheckBinaryVersion.proto */
static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer);

/* DecompressString.proto */
static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo);

/* MultiPhaseInitModuleState.proto */
#if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE
static PyObject *__Pyx_State_FindModule(void*);
static int __Pyx_State_AddModule(PyObject* module, void*);
static int __Pyx_State_RemoveModule(void*);
#elif CYTHON_USE_MODULE_STATE
#define __Pyx_State_FindModule PyState_FindModule
#define __Pyx_State_AddModule PyState_AddModule
#define __Pyx_State_RemoveModule PyState_RemoveModule
#endif

/* #### Code section: module_declarations ### */
/* CythonABIVersion.proto */
#if CYTHON_COMPILING_IN_LIMITED_API
    #if CYTHON_METH_FASTCALL
        #define __PYX_FASTCALL_ABI_SUFFIX  "_fastcall"
    #else
        #define __PYX_FASTCALL_ABI_SUFFIX
    #endif
    #define __PYX_LIMITED_ABI_SUFFIX "limited" __PYX_FASTCALL_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX
#else
    #define __PYX_LIMITED_ABI_SUFFIX
#endif
#if __PYX_HAS_PY_AM_SEND == 1
    #define __PYX_AM_SEND_ABI_SUFFIX
#elif __PYX_HAS_PY_AM_SEND == 2
    #define __PYX_AM_SEND_ABI_SUFFIX "amsendbackport"
#else
    #define __PYX_AM_SEND_ABI_SUFFIX "noamsend"
#endif
#ifndef __PYX_MONITORING_ABI_SUFFIX
    #define __PYX_MONITORING_ABI_SUFFIX
#endif
#if CYTHON_USE_TP_FINALIZE
    #define __PYX_TP_FINALIZE_ABI_SUFFIX
#else
    #define __PYX_TP_FINALIZE_ABI_SUFFIX "nofinalize"
#endif
#if CYTHON_USE_FREELISTS || !defined(__Pyx_AsyncGen_USED)
    #define __PYX_FREELISTS_ABI_SUFFIX
#else
    #define __PYX_FREELISTS_ABI_SUFFIX "nofreelists"
#endif
#define CYTHON_ABI  __PYX_ABI_VERSION __PYX_LIMITED_ABI_SUFFIX __PYX_MONITORING_ABI_SUFFIX __PYX_TP_FINALIZE_ABI_SUFFIX __PYX_FREELISTS_ABI_SUFFIX __PYX_AM_SEND_ABI_SUFFIX
#define __PYX_ABI_MODULE_NAME "_cython_" CYTHON_ABI
#define __PYX_TYPE_MODULE_PREFIX __PYX_ABI_MODULE_NAME "."

static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarray(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr *__pyx_v_self); /* proto*/
static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiIterObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject *__pyx_v_self); /* proto*/
static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__pyx_v_self); /* proto*/

/* Module declarations from "cython" */

/* Module declarations from "libc.string" */

/* Module declarations from "libc.stdio" */

/* Module declarations from "__builtin__" */

/* Module declarations from "cpython.type" */

/* Module declarations from "cpython" */

/* Module declarations from "cpython.object" */

/* Module declarations from "cpython.ref" */

/* Module declarations from "numpy" */

/* Module declarations from "numpy" */
static CYTHON_INLINE int __pyx_f_5numpy_import_array(void); /*proto*/

/* Module declarations from "cpython.mem" */

/* Module declarations from "libc.stddef" */

/* Module declarations from "libc.time" */

/* Module declarations from "libc.math" */

/* Module declarations from "libcpp.deque" */

/* Module declarations from "libcpp.list" */

/* Module declarations from "libcpp.utility" */

/* Module declarations from "libcpp.pair" */

/* Module declarations from "libcpp.queue" */

/* Module declarations from "libcpp.set" */

/* Module declarations from "libcpp.stack" */

/* Module declarations from "libcpp.vector" */

/* Module declarations from "libcpp.string_view" */

/* Module declarations from "libcpp.string" */

/* Module declarations from "pygeoprocessing.extensions" */

/* Module declarations from "pygeoprocessing.routing.routing" */
static float __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD;
static double __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
static double __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2;
static double __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV;
static void __pyx_f_15pygeoprocessing_7routing_7routing__diagonal_fill_step(int, int, int, long, long, ManagedRaster, long, PyObject *); /*proto*/
static int __pyx_f_15pygeoprocessing_7routing_7routing__in_watershed(int, int, int, int, int, int, int, ManagedRaster, long); /*proto*/
static PyObject *__pyx_f_15pygeoprocessing_7routing_7routing__calculate_stream_geometry(int, int, int, PyObject *, int, int, ManagedRaster, ManagedRaster, int, int, PyObject *); /*proto*/
/* #### Code section: typeinfo ### */
static const __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t = { "float64_t", NULL, sizeof(__pyx_t_5numpy_float64_t), { 0 }, 0, 'R', 0, 0 };
static const __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t = { "uint8_t", NULL, sizeof(__pyx_t_5numpy_uint8_t), { 0 }, 0, __PYX_IS_UNSIGNED(__pyx_t_5numpy_uint8_t) ? 'U' : 'I', __PYX_IS_UNSIGNED(__pyx_t_5numpy_uint8_t), 0 };
static const __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t = { "int32_t", NULL, sizeof(__pyx_t_5numpy_int32_t), { 0 }, 0, __PYX_IS_UNSIGNED(__pyx_t_5numpy_int32_t) ? 'U' : 'I', __PYX_IS_UNSIGNED(__pyx_t_5numpy_int32_t), 0 };
static const __Pyx_TypeInfo __Pyx_TypeInfo_nn_npy_int32 = { "npy_int32", NULL, sizeof(npy_int32), { 0 }, 0, __PYX_IS_UNSIGNED(npy_int32) ? 'U' : 'I', __PYX_IS_UNSIGNED(npy_int32), 0 };
/* #### Code section: before_global_var ### */
#define __Pyx_MODULE_NAME "pygeoprocessing.routing.routing"
extern int __pyx_module_is_main_pygeoprocessing__routing__routing;
int __pyx_module_is_main_pygeoprocessing__routing__routing = 0;

/* Implementation of "pygeoprocessing.routing.routing" */
/* #### Code section: global_var ### */
static PyObject *__pyx_builtin_enumerate;
static PyObject *__pyx_builtin_min;
static PyObject *__pyx_builtin_max;
static PyObject *__pyx_builtin_sorted;
/* #### Code section: string_decls ### */
static const char __pyx_k_Provides_PyGeprocessing_Routing[] = "\nProvides PyGeprocessing Routing functionality.\n\nUnless otherwise specified, all internal computation of rasters are done in\na float64 space. The only possible loss of precision could occur when an\nincoming DEM type is an int64 type and values in that dem exceed 2^52 but GDAL\ndoes not support int64 rasters so no precision loss is possible with a\nfloat64.\n\nD8 flow direction conventions encode the flow direction as::\n\n     3 2 1\n     4 x 0\n     5 6 7\n\nThis is slightly different from how TauDEM encodes flow direction, which is as::\n    4 3 2\n    5 x 1\n    6 7 8\n\nTo convert a TauDEM flow direction raster to a pygeoprocessing-compatible flow\ndirection raster, the following ``raster_map`` call may be used::\n\n    taudem_flow_dir_path = 'taudem_d8_flow_dir.tif'\n    pygeoprocessing.raster_map(\n        lambda d: d+1, [taudem_flow_dir_path],\n        'pygeoprocessing_d8_flow_dir.tif')\n";
/* #### Code section: decls ### */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing__generate_read_bounds(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_offset_dict, PyObject *__pyx_v_raster_x_size, PyObject *__pyx_v_raster_y_size); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_32__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_2fill_pits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_filled_dem_raster_path, PyObject *__pyx_v_working_dir, PY_LONG_LONG __pyx_v_max_pixel_fill_count, PyObject *__pyx_v_single_outlet_tuple, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_34__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_4flow_dir_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_flow_dir_path, PyObject *__pyx_v_working_dir, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_36__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_6flow_accumulation_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_raster_path_band, PyObject *__pyx_v_target_flow_accum_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_custom_decay_factor, double __pyx_v_min_decay_proportion, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_38__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_8flow_dir_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_flow_dir_path, PyObject *__pyx_v_working_dir, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_40__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_10flow_accumulation_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_mfd_raster_path_band, PyObject *__pyx_v_target_flow_accum_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_42__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_12distance_to_channel_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_channel_raster_path_band, PyObject *__pyx_v_target_distance_to_channel_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_44__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_14distance_to_channel_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_mfd_raster_path_band, PyObject *__pyx_v_channel_raster_path_band, PyObject *__pyx_v_target_distance_to_channel_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_46__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_16extract_streams_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_accum_raster_path_band, PyObject *__pyx_v_flow_dir_mfd_path_band, double __pyx_v_flow_threshold, PyObject *__pyx_v_target_stream_raster_path, double __pyx_v_trace_threshold_proportion, PyObject *__pyx_v_raster_driver_creation_tuple); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_18_is_raster_path_band_formatted(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_raster_path_band); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_48__defaults__(CYTHON_UNUSED PyObject *__pyx_self); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_20extract_strahler_streams_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_flow_accum_raster_path_band, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_stream_vector_path, long __pyx_v_min_flow_accum_threshold, int __pyx_v_river_order, float __pyx_v_min_p_val, PyObject *__pyx_v_autotune_flow_accumulation, PyObject *__pyx_v_osr_axis_mapping_strategy); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_22_build_discovery_finish_rasters(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_target_discovery_raster_path, PyObject *__pyx_v_target_finish_raster_path); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_24calculate_subwatershed_boundary(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_d8_flow_dir_raster_path_band, PyObject *__pyx_v_strahler_stream_vector_path, PyObject *__pyx_v_target_watershed_boundary_vector_path, PyObject *__pyx_v_max_steps_per_watershed, PyObject *__pyx_v_outlet_at_confluence); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_26detect_lowest_drain_and_sink(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_28detect_outlets(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_raster_path_band, PyObject *__pyx_v_flow_dir_type, PyObject *__pyx_v_target_outlet_vector_path); /* proto */
static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_30_delete_feature(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_stream_feature, PyObject *__pyx_v_stream_layer, PyObject *__pyx_v_upstream_to_downstream_id, PyObject *__pyx_v_downstream_to_upstream_ids); /* proto */
static PyObject *__pyx_tp_new_15pygeoprocessing_7routing_7routing___pyx_defaults(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
/* #### Code section: late_includes ### */
/* #### Code section: module_state ### */
/* SmallCodeConfig */
#ifndef CYTHON_SMALL_CODE
#if defined(__clang__)
    #define CYTHON_SMALL_CODE
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
    #define CYTHON_SMALL_CODE __attribute__((cold))
#else
    #define CYTHON_SMALL_CODE
#endif
#endif

typedef struct {
  PyObject *__pyx_d;
  PyObject *__pyx_b;
  PyObject *__pyx_cython_runtime;
  PyObject *__pyx_empty_tuple;
  PyObject *__pyx_empty_bytes;
  PyObject *__pyx_empty_unicode;
  PyTypeObject *__pyx_ptype_7cpython_4type_type;
  PyTypeObject *__pyx_ptype_5numpy_dtype;
  PyTypeObject *__pyx_ptype_5numpy_flatiter;
  PyTypeObject *__pyx_ptype_5numpy_broadcast;
  PyTypeObject *__pyx_ptype_5numpy_ndarray;
  PyTypeObject *__pyx_ptype_5numpy_generic;
  PyTypeObject *__pyx_ptype_5numpy_number;
  PyTypeObject *__pyx_ptype_5numpy_integer;
  PyTypeObject *__pyx_ptype_5numpy_signedinteger;
  PyTypeObject *__pyx_ptype_5numpy_unsignedinteger;
  PyTypeObject *__pyx_ptype_5numpy_inexact;
  PyTypeObject *__pyx_ptype_5numpy_floating;
  PyTypeObject *__pyx_ptype_5numpy_complexfloating;
  PyTypeObject *__pyx_ptype_5numpy_flexible;
  PyTypeObject *__pyx_ptype_5numpy_character;
  PyTypeObject *__pyx_ptype_5numpy_ufunc;
  PyObject *__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults;
  PyTypeObject *__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults;
  __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_items;
  __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_pop;
  __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_values;
  __Pyx_CachedCFunction __pyx_umethod_PyList_Type_pop;
  PyObject *__pyx_slice[1];
  PyObject *__pyx_tuple[14];
  PyObject *__pyx_codeobj_tab[16];
  PyObject *__pyx_string_tab[687];
  PyObject *__pyx_number_tab[8];
/* #### Code section: module_state_contents ### */
/* CommonTypesMetaclass.module_state_decls */
PyTypeObject *__pyx_CommonTypesMetaclassType;

/* CachedMethodType.module_state_decls */
#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *__Pyx_CachedMethodType;
#endif

/* CythonFunctionShared.module_state_decls */
PyTypeObject *__pyx_CyFunctionType;

/* CodeObjectCache.module_state_decls */
struct __Pyx_CodeObjectCache __pyx_code_cache;

/* #### Code section: module_state_end ### */
} __pyx_mstatetype;

#if CYTHON_USE_MODULE_STATE
#ifdef __cplusplus
namespace {
extern struct PyModuleDef __pyx_moduledef;
} /* anonymous namespace */
#else
static struct PyModuleDef __pyx_moduledef;
#endif

#define __pyx_mstate_global (__Pyx_PyModule_GetState(__Pyx_State_FindModule(&__pyx_moduledef)))

#define __pyx_m (__Pyx_State_FindModule(&__pyx_moduledef))
#else
static __pyx_mstatetype __pyx_mstate_global_static =
#ifdef __cplusplus
    {};
#else
    {0};
#endif
static __pyx_mstatetype * const __pyx_mstate_global = &__pyx_mstate_global_static;
#endif
/* #### Code section: constant_name_defines ### */
#define __pyx_kp_u_ __pyx_string_tab[0]
#define __pyx_kp_u_1f __pyx_string_tab[1]
#define __pyx_kp_u_1f_complete __pyx_string_tab[2]
#define __pyx_kp_u_Dist_to_channel_D8_1f_complete __pyx_string_tab[3]
#define __pyx_kp_u_Dist_to_channel_MFD_1f_complete __pyx_string_tab[4]
#define __pyx_kp_u_Extract_streams_MFD_100_0_comple __pyx_string_tab[5]
#define __pyx_kp_u_Extract_streams_MFD_1f_complete __pyx_string_tab[6]
#define __pyx_kp_u_Extract_streams_MFD_filter_out_i __pyx_string_tab[7]
#define __pyx_kp_u_Flow_accum_MFD_1f_complete __pyx_string_tab[8]
#define __pyx_kp_u_Flow_accumulation_D8_1f_complete __pyx_string_tab[9]
#define __pyx_kp_u_Flow_dir_MFD_1f_complete __pyx_string_tab[10]
#define __pyx_kp_u_Y_m_d__H__M__S __pyx_string_tab[11]
#define __pyx_kp_u__2 __pyx_string_tab[12]
#define __pyx_kp_u__3 __pyx_string_tab[13]
#define __pyx_kp_u_bak_tif __pyx_string_tab[14]
#define __pyx_kp_u_calculate_subwatershed_boundary_2 __pyx_string_tab[15]
#define __pyx_kp_u_calculate_subwatershed_boundary_3 __pyx_string_tab[16]
#define __pyx_kp_u_compatable_dem_tif __pyx_string_tab[17]
#define __pyx_kp_u_compatible_dem_complete __pyx_string_tab[18]
#define __pyx_kp_u_complete __pyx_string_tab[19]
#define __pyx_kp_u_complete_2 __pyx_string_tab[20]
#define __pyx_kp_u_couldn_t_remove_temp_dir __pyx_string_tab[21]
#define __pyx_kp_u_creating_target_flow_accum_raste __pyx_string_tab[22]
#define __pyx_kp_u_creating_visited_raster_layer __pyx_string_tab[23]
#define __pyx_kp_u_dem_is_not_a_power_of_2_creating __pyx_string_tab[24]
#define __pyx_kp_u_disable __pyx_string_tab[25]
#define __pyx_kp_u_discovery_tif __pyx_string_tab[26]
#define __pyx_kp_u_discovery_time_processing __pyx_string_tab[27]
#define __pyx_kp_u_enable __pyx_string_tab[28]
#define __pyx_kp_u_exceeded_max_pixel_fill_count_wh __pyx_string_tab[29]
#define __pyx_kp_u_exceeded_max_pixel_fill_count_wh_2 __pyx_string_tab[30]
#define __pyx_kp_u_exists_removing_before_creating __pyx_string_tab[31]
#define __pyx_kp_u_expected_flow_dir_type_of_either __pyx_string_tab[32]
#define __pyx_kp_u_extract_strahler_streams_d8_all __pyx_string_tab[33]
#define __pyx_kp_u_extract_strahler_streams_d8_com __pyx_string_tab[34]
#define __pyx_kp_u_extract_strahler_streams_d8_det __pyx_string_tab[35]
#define __pyx_kp_u_extract_strahler_streams_d8_det_2 __pyx_string_tab[36]
#define __pyx_kp_u_extract_strahler_streams_d8_dra __pyx_string_tab[37]
#define __pyx_kp_u_extract_strahler_streams_d8_dra_2 __pyx_string_tab[38]
#define __pyx_kp_u_extract_strahler_streams_d8_fin __pyx_string_tab[39]
#define __pyx_kp_u_extract_strahler_streams_d8_fin_2 __pyx_string_tab[40]
#define __pyx_kp_u_extract_strahler_streams_d8_fin_3 __pyx_string_tab[41]
#define __pyx_kp_u_extract_strahler_streams_d8_flo __pyx_string_tab[42]
#define __pyx_kp_u_extract_strahler_streams_d8_flo_2 __pyx_string_tab[43]
#define __pyx_kp_u_extract_strahler_streams_d8_see __pyx_string_tab[44]
#define __pyx_kp_u_extract_strahler_streams_d8_sta __pyx_string_tab[45]
#define __pyx_kp_u_extract_strahler_streams_d8_str __pyx_string_tab[46]
#define __pyx_kp_u_extract_strahler_streams_d8_str_2 __pyx_string_tab[47]
#define __pyx_kp_u_extract_strahler_streams_d8_str_3 __pyx_string_tab[48]
#define __pyx_kp_u_extract_strahler_streams_d8_str_4 __pyx_string_tab[49]
#define __pyx_kp_u_fill_pits __pyx_string_tab[50]
#define __pyx_kp_u_fill_pits__s __pyx_string_tab[51]
#define __pyx_kp_u_fill_pits_complete __pyx_string_tab[52]
#define __pyx_kp_u_finish_tif __pyx_string_tab[53]
#define __pyx_kp_u_flat_region_mask_tif __pyx_string_tab[54]
#define __pyx_kp_u_flow_dir_d8 __pyx_string_tab[55]
#define __pyx_kp_u_flow_dir_d8__s __pyx_string_tab[56]
#define __pyx_kp_u_flow_dir_d8_complete __pyx_string_tab[57]
#define __pyx_kp_u_flow_dir_multiple_flow_dir__s __pyx_string_tab[58]
#define __pyx_kp_u_gc __pyx_string_tab[59]
#define __pyx_kp_u_infer_sinks __pyx_string_tab[60]
#define __pyx_kp_u_isenabled __pyx_string_tab[61]
#define __pyx_kp_u_no_geometry_for_source_point_at __pyx_string_tab[62]
#define __pyx_kp_u_numpy__core_multiarray_failed_to __pyx_string_tab[63]
#define __pyx_kp_u_numpy__core_umath_failed_to_impo __pyx_string_tab[64]
#define __pyx_kp_u_of __pyx_string_tab[65]
#define __pyx_kp_u_order_1 __pyx_string_tab[66]
#define __pyx_kp_u_out_of_bounds_for __pyx_string_tab[67]
#define __pyx_kp_u_outlet_1 __pyx_string_tab[68]
#define __pyx_kp_u_outlet_detection __pyx_string_tab[69]
#define __pyx_kp_u_outlet_detection_0_complete __pyx_string_tab[70]
#define __pyx_kp_u_outlet_detection_100_complete_co __pyx_string_tab[71]
#define __pyx_kp_u_outlet_detection_done __pyx_string_tab[72]
#define __pyx_kp_u_outlets_complete __pyx_string_tab[73]
#define __pyx_kp_u_pit_mask_tif __pyx_string_tab[74]
#define __pyx_kp_u_pixels_complete __pyx_string_tab[75]
#define __pyx_kp_u_plateau_distance_tif __pyx_string_tab[76]
#define __pyx_kp_u_plateu_drain_mask_tif __pyx_string_tab[77]
#define __pyx_kp_u_pygeoprocessing_geoprocessing_co __pyx_string_tab[78]
#define __pyx_kp_u_pygeoprocessing_utils __pyx_string_tab[79]
#define __pyx_kp_u_quitting_too_many_steps __pyx_string_tab[80]
#define __pyx_kp_u_raster __pyx_string_tab[81]
#define __pyx_kp_u_s_is_supposed_to_be_a_raster_ba __pyx_string_tab[82]
#define __pyx_kp_u_segments_complete __pyx_string_tab[83]
#define __pyx_kp_u_source_points_complete __pyx_string_tab[84]
#define __pyx_kp_u_src_pygeoprocessing_routing_rout __pyx_string_tab[85]
#define __pyx_kp_u_starting_search __pyx_string_tab[86]
#define __pyx_kp_u_stream_fragments_complete __pyx_string_tab[87]
#define __pyx_kp_u_trace_threshold_proportion_shoul __pyx_string_tab[88]
#define __pyx_kp_u_upstream_direction __pyx_string_tab[89]
#define __pyx_kp_u_utf_8 __pyx_string_tab[90]
#define __pyx_kp_u_visited_tif __pyx_string_tab[91]
#define __pyx_n_u_AddGeometry __pyx_string_tab[92]
#define __pyx_n_u_AddPoint __pyx_string_tab[93]
#define __pyx_n_u_ApplyGeoTransform __pyx_string_tab[94]
#define __pyx_n_u_BLOCK_BITS __pyx_string_tab[95]
#define __pyx_n_u_CommitTransaction __pyx_string_tab[96]
#define __pyx_n_u_Create __pyx_string_tab[97]
#define __pyx_n_u_CreateCopy __pyx_string_tab[98]
#define __pyx_n_u_CreateFeature __pyx_string_tab[99]
#define __pyx_n_u_CreateField __pyx_string_tab[100]
#define __pyx_n_u_CreateGeometryFromWkb __pyx_string_tab[101]
#define __pyx_n_u_CreateLayer __pyx_string_tab[102]
#define __pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT __pyx_string_tab[103]
#define __pyx_n_u_DEFAULT_OSR_AXIS_MAPPING_STRATEG __pyx_string_tab[104]
#define __pyx_n_u_DeleteFeature __pyx_string_tab[105]
#define __pyx_n_u_DeleteField __pyx_string_tab[106]
#define __pyx_n_u_ExportToWkb __pyx_string_tab[107]
#define __pyx_n_u_Feature __pyx_string_tab[108]
#define __pyx_n_u_FieldDefn __pyx_string_tab[109]
#define __pyx_n_u_FindFieldIndex __pyx_string_tab[110]
#define __pyx_n_u_FlushCache __pyx_string_tab[111]
#define __pyx_n_u_GA_Update __pyx_string_tab[112]
#define __pyx_n_u_GDALUseExceptions __pyx_string_tab[113]
#define __pyx_n_u_GDT_Byte __pyx_string_tab[114]
#define __pyx_n_u_GDT_Float64 __pyx_string_tab[115]
#define __pyx_n_u_GDT_Int32 __pyx_string_tab[116]
#define __pyx_n_u_GDT_Unknown __pyx_string_tab[117]
#define __pyx_n_u_GPKG __pyx_string_tab[118]
#define __pyx_n_u_GTiff __pyx_string_tab[119]
#define __pyx_n_u_Geometry __pyx_string_tab[120]
#define __pyx_n_u_GetDriverByName __pyx_string_tab[121]
#define __pyx_n_u_GetFID __pyx_string_tab[122]
#define __pyx_n_u_GetFeature __pyx_string_tab[123]
#define __pyx_n_u_GetField __pyx_string_tab[124]
#define __pyx_n_u_GetGeometryRef __pyx_string_tab[125]
#define __pyx_n_u_GetLayer __pyx_string_tab[126]
#define __pyx_n_u_GetLayerDefn __pyx_string_tab[127]
#define __pyx_n_u_GetRasterBand __pyx_string_tab[128]
#define __pyx_n_u_ID __pyx_string_tab[129]
#define __pyx_n_u_ImportFromWkt __pyx_string_tab[130]
#define __pyx_n_u_LOGGER __pyx_string_tab[131]
#define __pyx_n_u_OFTInteger __pyx_string_tab[132]
#define __pyx_n_u_OFTInteger64 __pyx_string_tab[133]
#define __pyx_n_u_OFTReal __pyx_string_tab[134]
#define __pyx_n_u_OF_RASTER __pyx_string_tab[135]
#define __pyx_n_u_OF_VECTOR __pyx_string_tab[136]
#define __pyx_n_u_OpenEx __pyx_string_tab[137]
#define __pyx_n_u_Pyx_PyDict_NextRef __pyx_string_tab[138]
#define __pyx_n_u_ReadAsArray __pyx_string_tab[139]
#define __pyx_n_u_ResetReading __pyx_string_tab[140]
#define __pyx_n_u_SPARSE_CREATION_OPTIONS __pyx_string_tab[141]
#define __pyx_n_u_SetAttributeFilter __pyx_string_tab[142]
#define __pyx_n_u_SetAxisMappingStrategy __pyx_string_tab[143]
#define __pyx_n_u_SetFeature __pyx_string_tab[144]
#define __pyx_n_u_SetField __pyx_string_tab[145]
#define __pyx_n_u_SetGeometry __pyx_string_tab[146]
#define __pyx_n_u_SpatialReference __pyx_string_tab[147]
#define __pyx_n_u_StartTransaction __pyx_string_tab[148]
#define __pyx_n_u_Union __pyx_string_tab[149]
#define __pyx_n_u_WriteArray __pyx_string_tab[150]
#define __pyx_n_u__4 __pyx_string_tab[151]
#define __pyx_n_u_all_defined __pyx_string_tab[152]
#define __pyx_n_u_append __pyx_string_tab[153]
#define __pyx_n_u_astype __pyx_string_tab[154]
#define __pyx_n_u_asyncio_coroutines __pyx_string_tab[155]
#define __pyx_n_u_autotune_flow_accumulation __pyx_string_tab[156]
#define __pyx_n_u_backtrace_set __pyx_string_tab[157]
#define __pyx_n_u_base_datatype __pyx_string_tab[158]
#define __pyx_n_u_base_feature_count __pyx_string_tab[159]
#define __pyx_n_u_base_nodata __pyx_string_tab[160]
#define __pyx_n_u_basename __pyx_string_tab[161]
#define __pyx_n_u_block_array __pyx_string_tab[162]
#define __pyx_n_u_block_offsets __pyx_string_tab[163]
#define __pyx_n_u_block_offsets_list __pyx_string_tab[164]
#define __pyx_n_u_block_size __pyx_string_tab[165]
#define __pyx_n_u_boundary_list __pyx_string_tab[166]
#define __pyx_n_u_boundary_x __pyx_string_tab[167]
#define __pyx_n_u_boundary_y __pyx_string_tab[168]
#define __pyx_n_u_build_discovery_finish_rasters __pyx_string_tab[169]
#define __pyx_n_u_calculate_subwatershed_boundary __pyx_string_tab[170]
#define __pyx_n_u_calculate_subwatershed_boundary_4 __pyx_string_tab[171]
#define __pyx_n_u_cell_to_test __pyx_string_tab[172]
#define __pyx_n_u_center_val __pyx_string_tab[173]
#define __pyx_n_u_channel_band __pyx_string_tab[174]
#define __pyx_n_u_channel_buffer_array __pyx_string_tab[175]
#define __pyx_n_u_channel_managed_raster __pyx_string_tab[176]
#define __pyx_n_u_channel_raster __pyx_string_tab[177]
#define __pyx_n_u_channel_raster_path_band __pyx_string_tab[178]
#define __pyx_n_u_class_getitem __pyx_string_tab[179]
#define __pyx_n_u_cline_in_traceback __pyx_string_tab[180]
#define __pyx_n_u_collections __pyx_string_tab[181]
#define __pyx_n_u_compatable_dem_raster_path_band __pyx_string_tab[182]
#define __pyx_n_u_compressed_integer_slopes __pyx_string_tab[183]
#define __pyx_n_u_compressed_upstream_flow_dir __pyx_string_tab[184]
#define __pyx_n_u_connected_fid __pyx_string_tab[185]
#define __pyx_n_u_connected_fids __pyx_string_tab[186]
#define __pyx_n_u_connected_upstream_fids __pyx_string_tab[187]
#define __pyx_n_u_coord_to_stream_ids __pyx_string_tab[188]
#define __pyx_n_u_copy __pyx_string_tab[189]
#define __pyx_n_u_copyfile __pyx_string_tab[190]
#define __pyx_n_u_current_pixel __pyx_string_tab[191]
#define __pyx_n_u_custom_decay_factor __pyx_string_tab[192]
#define __pyx_n_u_d __pyx_string_tab[193]
#define __pyx_n_u_d8 __pyx_string_tab[194]
#define __pyx_n_u_d8_flow_dir_managed_raster __pyx_string_tab[195]
#define __pyx_n_u_d8_flow_dir_mode __pyx_string_tab[196]
#define __pyx_n_u_d8_flow_dir_raster_path_band __pyx_string_tab[197]
#define __pyx_n_u_d_n __pyx_string_tab[198]
#define __pyx_n_u_datatype __pyx_string_tab[199]
#define __pyx_n_u_debug __pyx_string_tab[200]
#define __pyx_n_u_decay_factor __pyx_string_tab[201]
#define __pyx_n_u_decay_factor_managed_raster __pyx_string_tab[202]
#define __pyx_n_u_decay_factor_nodata __pyx_string_tab[203]
#define __pyx_n_u_decay_from_upstream __pyx_string_tab[204]
#define __pyx_n_u_decayed_value __pyx_string_tab[205]
#define __pyx_n_u_decaying_values __pyx_string_tab[206]
#define __pyx_n_u_defaultdict __pyx_string_tab[207]
#define __pyx_n_u_delete_feature __pyx_string_tab[208]
#define __pyx_n_u_deleted_set __pyx_string_tab[209]
#define __pyx_n_u_delta_x __pyx_string_tab[210]
#define __pyx_n_u_delta_y __pyx_string_tab[211]
#define __pyx_n_u_dem_band __pyx_string_tab[212]
#define __pyx_n_u_dem_block_xsize __pyx_string_tab[213]
#define __pyx_n_u_dem_block_ysize __pyx_string_tab[214]
#define __pyx_n_u_dem_buffer_array __pyx_string_tab[215]
#define __pyx_n_u_dem_managed_raster __pyx_string_tab[216]
#define __pyx_n_u_dem_nodata __pyx_string_tab[217]
#define __pyx_n_u_dem_raster __pyx_string_tab[218]
#define __pyx_n_u_dem_raster_info __pyx_string_tab[219]
#define __pyx_n_u_dem_raster_path_band __pyx_string_tab[220]
#define __pyx_n_u_detect_lowest_drain_and_sink __pyx_string_tab[221]
#define __pyx_n_u_detect_outlets __pyx_string_tab[222]
#define __pyx_n_u_diagonal_nodata __pyx_string_tab[223]
#define __pyx_n_u_dir __pyx_string_tab[224]
#define __pyx_n_u_direction_drain_queue __pyx_string_tab[225]
#define __pyx_n_u_dirname __pyx_string_tab[226]
#define __pyx_n_u_discovery __pyx_string_tab[227]
#define __pyx_n_u_discovery_count __pyx_string_tab[228]
#define __pyx_n_u_discovery_info __pyx_string_tab[229]
#define __pyx_n_u_discovery_managed_raster __pyx_string_tab[230]
#define __pyx_n_u_discovery_nodata __pyx_string_tab[231]
#define __pyx_n_u_discovery_srs __pyx_string_tab[232]
#define __pyx_n_u_discovery_stack __pyx_string_tab[233]
#define __pyx_n_u_discovery_time_raster_path __pyx_string_tab[234]
#define __pyx_n_u_dist_to_channel_mfd_work_dir __pyx_string_tab[235]
#define __pyx_n_u_distance_drain_queue __pyx_string_tab[236]
#define __pyx_n_u_distance_nodata __pyx_string_tab[237]
#define __pyx_n_u_distance_to_channel_d8 __pyx_string_tab[238]
#define __pyx_n_u_distance_to_channel_managed_rast __pyx_string_tab[239]
#define __pyx_n_u_distance_to_channel_mfd __pyx_string_tab[240]
#define __pyx_n_u_distance_to_channel_stack __pyx_string_tab[241]
#define __pyx_n_u_do_decayed_accumulation __pyx_string_tab[242]
#define __pyx_n_u_downhill_neighbor __pyx_string_tab[243]
#define __pyx_n_u_downhill_slope_array __pyx_string_tab[244]
#define __pyx_n_u_downstream_dem __pyx_string_tab[245]
#define __pyx_n_u_downstream_feature __pyx_string_tab[246]
#define __pyx_n_u_downstream_fid __pyx_string_tab[247]
#define __pyx_n_u_downstream_geom __pyx_string_tab[248]
#define __pyx_n_u_downstream_order __pyx_string_tab[249]
#define __pyx_n_u_downstream_to_upstream_ids __pyx_string_tab[250]
#define __pyx_n_u_drain_distance __pyx_string_tab[251]
#define __pyx_n_u_drain_pixel __pyx_string_tab[252]
#define __pyx_n_u_drain_queue __pyx_string_tab[253]
#define __pyx_n_u_drain_search_queue __pyx_string_tab[254]
#define __pyx_n_u_drop_distance __pyx_string_tab[255]
#define __pyx_n_u_drop_distance_collection __pyx_string_tab[256]
#define __pyx_n_u_ds_fa __pyx_string_tab[257]
#define __pyx_n_u_ds_x __pyx_string_tab[258]
#define __pyx_n_u_ds_x_1 __pyx_string_tab[259]
#define __pyx_n_u_ds_y __pyx_string_tab[260]
#define __pyx_n_u_ds_y_1 __pyx_string_tab[261]
#define __pyx_n_u_dtype __pyx_string_tab[262]
#define __pyx_n_u_edge_dir __pyx_string_tab[263]
#define __pyx_n_u_edge_side __pyx_string_tab[264]
#define __pyx_n_u_empty __pyx_string_tab[265]
#define __pyx_n_u_encode __pyx_string_tab[266]
#define __pyx_n_u_enter __pyx_string_tab[267]
#define __pyx_n_u_enumerate __pyx_string_tab[268]
#define __pyx_n_u_equal_var __pyx_string_tab[269]
#define __pyx_n_u_exception __pyx_string_tab[270]
#define __pyx_n_u_exists __pyx_string_tab[271]
#define __pyx_n_u_exit __pyx_string_tab[272]
#define __pyx_n_u_extract_strahler_streams_d8 __pyx_string_tab[273]
#define __pyx_n_u_extract_streams_mfd __pyx_string_tab[274]
#define __pyx_n_u_feature_id __pyx_string_tab[275]
#define __pyx_n_u_fid __pyx_string_tab[276]
#define __pyx_n_u_fid_to_order __pyx_string_tab[277]
#define __pyx_n_u_fill_height __pyx_string_tab[278]
#define __pyx_n_u_fill_pits_2 __pyx_string_tab[279]
#define __pyx_n_u_fill_queue __pyx_string_tab[280]
#define __pyx_n_u_fill_value_list __pyx_string_tab[281]
#define __pyx_n_u_filled_dem_band __pyx_string_tab[282]
#define __pyx_n_u_filled_dem_managed_raster __pyx_string_tab[283]
#define __pyx_n_u_filled_dem_raster __pyx_string_tab[284]
#define __pyx_n_u_finish __pyx_string_tab[285]
#define __pyx_n_u_finish_coordinate __pyx_string_tab[286]
#define __pyx_n_u_finish_managed_raster __pyx_string_tab[287]
#define __pyx_n_u_finish_stack __pyx_string_tab[288]
#define __pyx_n_u_finish_time_raster_path __pyx_string_tab[289]
#define __pyx_n_u_flat_region_mask_managed_raster __pyx_string_tab[290]
#define __pyx_n_u_flat_region_mask_path __pyx_string_tab[291]
#define __pyx_n_u_float64 __pyx_string_tab[292]
#define __pyx_n_u_flow_accum __pyx_string_tab[293]
#define __pyx_n_u_flow_accum_info __pyx_string_tab[294]
#define __pyx_n_u_flow_accum_managed_raster __pyx_string_tab[295]
#define __pyx_n_u_flow_accum_mr __pyx_string_tab[296]
#define __pyx_n_u_flow_accum_nodata __pyx_string_tab[297]
#define __pyx_n_u_flow_accum_raster_path_band __pyx_string_tab[298]
#define __pyx_n_u_flow_accumulation_d8 __pyx_string_tab[299]
#define __pyx_n_u_flow_accumulation_mfd __pyx_string_tab[300]
#define __pyx_n_u_flow_dir __pyx_string_tab[301]
#define __pyx_n_u_flow_dir_band __pyx_string_tab[302]
#define __pyx_n_u_flow_dir_block __pyx_string_tab[303]
#define __pyx_n_u_flow_dir_buffer_array __pyx_string_tab[304]
#define __pyx_n_u_flow_dir_d8_2 __pyx_string_tab[305]
#define __pyx_n_u_flow_dir_d8_managed_raster __pyx_string_tab[306]
#define __pyx_n_u_flow_dir_d8_raster_path_band __pyx_string_tab[307]
#define __pyx_n_u_flow_dir_info __pyx_string_tab[308]
#define __pyx_n_u_flow_dir_managed_raster __pyx_string_tab[309]
#define __pyx_n_u_flow_dir_mfd __pyx_string_tab[310]
#define __pyx_n_u_flow_dir_mfd_band __pyx_string_tab[311]
#define __pyx_n_u_flow_dir_mfd_buffer_array __pyx_string_tab[312]
#define __pyx_n_u_flow_dir_mfd_managed_raster __pyx_string_tab[313]
#define __pyx_n_u_flow_dir_mfd_mr __pyx_string_tab[314]
#define __pyx_n_u_flow_dir_mfd_path_band __pyx_string_tab[315]
#define __pyx_n_u_flow_dir_mfd_raster __pyx_string_tab[316]
#define __pyx_n_u_flow_dir_mfd_raster_path_band __pyx_string_tab[317]
#define __pyx_n_u_flow_dir_n __pyx_string_tab[318]
#define __pyx_n_u_flow_dir_nodata __pyx_string_tab[319]
#define __pyx_n_u_flow_dir_raster __pyx_string_tab[320]
#define __pyx_n_u_flow_dir_raster_info __pyx_string_tab[321]
#define __pyx_n_u_flow_dir_raster_path_band __pyx_string_tab[322]
#define __pyx_n_u_flow_dir_srs __pyx_string_tab[323]
#define __pyx_n_u_flow_dir_type __pyx_string_tab[324]
#define __pyx_n_u_flow_dir_weight __pyx_string_tab[325]
#define __pyx_n_u_flow_nodata __pyx_string_tab[326]
#define __pyx_n_u_flow_pixel __pyx_string_tab[327]
#define __pyx_n_u_flow_threshold __pyx_string_tab[328]
#define __pyx_n_u_func __pyx_string_tab[329]
#define __pyx_n_u_g0 __pyx_string_tab[330]
#define __pyx_n_u_g1 __pyx_string_tab[331]
#define __pyx_n_u_g2 __pyx_string_tab[332]
#define __pyx_n_u_g3 __pyx_string_tab[333]
#define __pyx_n_u_g4 __pyx_string_tab[334]
#define __pyx_n_u_g5 __pyx_string_tab[335]
#define __pyx_n_u_gdal __pyx_string_tab[336]
#define __pyx_n_u_gdal_use_exceptions __pyx_string_tab[337]
#define __pyx_n_u_generate_read_bounds __pyx_string_tab[338]
#define __pyx_n_u_geoprocessing_core __pyx_string_tab[339]
#define __pyx_n_u_geotransform __pyx_string_tab[340]
#define __pyx_n_u_getLogger __pyx_string_tab[341]
#define __pyx_n_u_get_raster_info __pyx_string_tab[342]
#define __pyx_n_u_gmtime __pyx_string_tab[343]
#define __pyx_n_u_gpkg_driver __pyx_string_tab[344]
#define __pyx_n_u_i __pyx_string_tab[345]
#define __pyx_n_u_i_n __pyx_string_tab[346]
#define __pyx_n_u_i_sn __pyx_string_tab[347]
#define __pyx_n_u_i_upstream_flow __pyx_string_tab[348]
#define __pyx_n_u_index __pyx_string_tab[349]
#define __pyx_n_u_inf __pyx_string_tab[350]
#define __pyx_n_u_info __pyx_string_tab[351]
#define __pyx_n_u_int32 __pyx_string_tab[352]
#define __pyx_n_u_int8 __pyx_string_tab[353]
#define __pyx_n_u_int_max_steps_per_watershed __pyx_string_tab[354]
#define __pyx_n_u_is_a_channel __pyx_string_tab[355]
#define __pyx_n_u_is_coroutine __pyx_string_tab[356]
#define __pyx_n_u_is_drain __pyx_string_tab[357]
#define __pyx_n_u_is_outlet __pyx_string_tab[358]
#define __pyx_n_u_is_raster_path_band_formatted __pyx_string_tab[359]
#define __pyx_n_u_isnan __pyx_string_tab[360]
#define __pyx_n_u_items __pyx_string_tab[361]
#define __pyx_n_u_iterblocks __pyx_string_tab[362]
#define __pyx_n_u_j __pyx_string_tab[363]
#define __pyx_n_u_join __pyx_string_tab[364]
#define __pyx_n_u_joined_line __pyx_string_tab[365]
#define __pyx_n_u_largest_block __pyx_string_tab[366]
#define __pyx_n_u_largest_slope __pyx_string_tab[367]
#define __pyx_n_u_largest_slope_dir __pyx_string_tab[368]
#define __pyx_n_u_last_flow_dir __pyx_string_tab[369]
#define __pyx_n_u_last_log_time __pyx_string_tab[370]
#define __pyx_n_u_left __pyx_string_tab[371]
#define __pyx_n_u_left_in __pyx_string_tab[372]
#define __pyx_n_u_linemerge __pyx_string_tab[373]
#define __pyx_n_u_loads __pyx_string_tab[374]
#define __pyx_n_u_local_flow_accum __pyx_string_tab[375]
#define __pyx_n_u_logging __pyx_string_tab[376]
#define __pyx_n_u_lower __pyx_string_tab[377]
#define __pyx_n_u_lowest_drain_height __pyx_string_tab[378]
#define __pyx_n_u_lowest_sink_height __pyx_string_tab[379]
#define __pyx_n_u_main __pyx_string_tab[380]
#define __pyx_n_u_makedirs __pyx_string_tab[381]
#define __pyx_n_u_mask_nodata __pyx_string_tab[382]
#define __pyx_n_u_max __pyx_string_tab[383]
#define __pyx_n_u_max_pixel_fill_count __pyx_string_tab[384]
#define __pyx_n_u_max_steps_per_watershed __pyx_string_tab[385]
#define __pyx_n_u_max_upstream_flow_accum __pyx_string_tab[386]
#define __pyx_n_u_mfd __pyx_string_tab[387]
#define __pyx_n_u_mfd_flow_dir __pyx_string_tab[388]
#define __pyx_n_u_mfd_value __pyx_string_tab[389]
#define __pyx_n_u_min __pyx_string_tab[390]
#define __pyx_n_u_min_decay_proportion __pyx_string_tab[391]
#define __pyx_n_u_min_flow_accum_threshold __pyx_string_tab[392]
#define __pyx_n_u_min_p_val __pyx_string_tab[393]
#define __pyx_n_u_min_value __pyx_string_tab[394]
#define __pyx_n_u_mkdtemp __pyx_string_tab[395]
#define __pyx_n_u_modified_offset_dict __pyx_string_tab[396]
#define __pyx_n_u_module __pyx_string_tab[397]
#define __pyx_n_u_multi_line __pyx_string_tab[398]
#define __pyx_n_u_n_cols __pyx_string_tab[399]
#define __pyx_n_u_n_dir __pyx_string_tab[400]
#define __pyx_n_u_n_distance __pyx_string_tab[401]
#define __pyx_n_u_n_drain_distance __pyx_string_tab[402]
#define __pyx_n_u_n_height __pyx_string_tab[403]
#define __pyx_n_u_n_iterations __pyx_string_tab[404]
#define __pyx_n_u_n_pixels __pyx_string_tab[405]
#define __pyx_n_u_n_points __pyx_string_tab[406]
#define __pyx_n_u_n_processed __pyx_string_tab[407]
#define __pyx_n_u_n_pushed __pyx_string_tab[408]
#define __pyx_n_u_n_rows __pyx_string_tab[409]
#define __pyx_n_u_n_slope __pyx_string_tab[410]
#define __pyx_n_u_n_steps __pyx_string_tab[411]
#define __pyx_n_u_n_x_blocks __pyx_string_tab[412]
#define __pyx_n_u_name __pyx_string_tab[413]
#define __pyx_n_u_nan __pyx_string_tab[414]
#define __pyx_n_u_natural_drain_exists __pyx_string_tab[415]
#define __pyx_n_u_new_raster_from_base __pyx_string_tab[416]
#define __pyx_n_u_next_id __pyx_string_tab[417]
#define __pyx_n_u_nodata __pyx_string_tab[418]
#define __pyx_n_u_nodata_distance_drain_queue __pyx_string_tab[419]
#define __pyx_n_u_nodata_downhill_slope_array __pyx_string_tab[420]
#define __pyx_n_u_nodata_drain_queue __pyx_string_tab[421]
#define __pyx_n_u_nodata_flow_dir_queue __pyx_string_tab[422]
#define __pyx_n_u_nodata_neighbor __pyx_string_tab[423]
#define __pyx_n_u_numpy __pyx_string_tab[424]
#define __pyx_n_u_offset_dict __pyx_string_tab[425]
#define __pyx_n_u_offset_info __pyx_string_tab[426]
#define __pyx_n_u_offset_only __pyx_string_tab[427]
#define __pyx_n_u_ogr __pyx_string_tab[428]
#define __pyx_n_u_open_set __pyx_string_tab[429]
#define __pyx_n_u_ops __pyx_string_tab[430]
#define __pyx_n_u_options __pyx_string_tab[431]
#define __pyx_n_u_order __pyx_string_tab[432]
#define __pyx_n_u_order_count __pyx_string_tab[433]
#define __pyx_n_u_os __pyx_string_tab[434]
#define __pyx_n_u_osgeo __pyx_string_tab[435]
#define __pyx_n_u_osr __pyx_string_tab[436]
#define __pyx_n_u_osr_axis_mapping_strategy __pyx_string_tab[437]
#define __pyx_n_u_out_dir __pyx_string_tab[438]
#define __pyx_n_u_out_dir_increase __pyx_string_tab[439]
#define __pyx_n_u_outet_basename __pyx_string_tab[440]
#define __pyx_n_u_outflow_dir __pyx_string_tab[441]
#define __pyx_n_u_outlet __pyx_string_tab[442]
#define __pyx_n_u_outlet_at_confluence __pyx_string_tab[443]
#define __pyx_n_u_outlet_feature __pyx_string_tab[444]
#define __pyx_n_u_outlet_fid __pyx_string_tab[445]
#define __pyx_n_u_outlet_fid_list __pyx_string_tab[446]
#define __pyx_n_u_outlet_index __pyx_string_tab[447]
#define __pyx_n_u_outlet_layer __pyx_string_tab[448]
#define __pyx_n_u_outlet_point __pyx_string_tab[449]
#define __pyx_n_u_outlet_vector __pyx_string_tab[450]
#define __pyx_n_u_outlet_x __pyx_string_tab[451]
#define __pyx_n_u_outlet_y __pyx_string_tab[452]
#define __pyx_n_u_p_val __pyx_string_tab[453]
#define __pyx_n_u_path __pyx_string_tab[454]
#define __pyx_n_u_payload __pyx_string_tab[455]
#define __pyx_n_u_pit_mask_managed_raster __pyx_string_tab[456]
#define __pyx_n_u_pit_mask_path __pyx_string_tab[457]
#define __pyx_n_u_pit_queue __pyx_string_tab[458]
#define __pyx_n_u_pixel __pyx_string_tab[459]
#define __pyx_n_u_pixel_count __pyx_string_tab[460]
#define __pyx_n_u_pixel_drains __pyx_string_tab[461]
#define __pyx_n_u_pixel_val __pyx_string_tab[462]
#define __pyx_n_u_plateau_distance_managed_raster __pyx_string_tab[463]
#define __pyx_n_u_plateau_distance_nodata __pyx_string_tab[464]
#define __pyx_n_u_plateau_distance_path __pyx_string_tab[465]
#define __pyx_n_u_plateau_drain_mask_managed_raste __pyx_string_tab[466]
#define __pyx_n_u_plateu_drain_mask_path __pyx_string_tab[467]
#define __pyx_n_u_pop __pyx_string_tab[468]
#define __pyx_n_u_pour_point __pyx_string_tab[469]
#define __pyx_n_u_preempted __pyx_string_tab[470]
#define __pyx_n_u_prefix __pyx_string_tab[471]
#define __pyx_n_u_priority __pyx_string_tab[472]
#define __pyx_n_u_processed_nodes __pyx_string_tab[473]
#define __pyx_n_u_processed_segments __pyx_string_tab[474]
#define __pyx_n_u_proj_x __pyx_string_tab[475]
#define __pyx_n_u_proj_y __pyx_string_tab[476]
#define __pyx_n_u_projection_wkt __pyx_string_tab[477]
#define __pyx_n_u_pygeoprocessing __pyx_string_tab[478]
#define __pyx_n_u_pygeoprocessing_routing_routing __pyx_string_tab[479]
#define __pyx_n_u_qualname __pyx_string_tab[480]
#define __pyx_n_u_raster_coord __pyx_string_tab[481]
#define __pyx_n_u_raster_driver __pyx_string_tab[482]
#define __pyx_n_u_raster_driver_creation_tuple __pyx_string_tab[483]
#define __pyx_n_u_raster_info __pyx_string_tab[484]
#define __pyx_n_u_raster_path_band __pyx_string_tab[485]
#define __pyx_n_u_raster_size __pyx_string_tab[486]
#define __pyx_n_u_raster_srs __pyx_string_tab[487]
#define __pyx_n_u_raster_x_size __pyx_string_tab[488]
#define __pyx_n_u_raster_y_size __pyx_string_tab[489]
#define __pyx_n_u_raw_weight_nodata __pyx_string_tab[490]
#define __pyx_n_u_remove __pyx_string_tab[491]
#define __pyx_n_u_reverse __pyx_string_tab[492]
#define __pyx_n_u_right __pyx_string_tab[493]
#define __pyx_n_u_right_in __pyx_string_tab[494]
#define __pyx_n_u_river_id __pyx_string_tab[495]
#define __pyx_n_u_river_order __pyx_string_tab[496]
#define __pyx_n_u_rmtree __pyx_string_tab[497]
#define __pyx_n_u_root_height __pyx_string_tab[498]
#define __pyx_n_u_scipy __pyx_string_tab[499]
#define __pyx_n_u_scipy_stats __pyx_string_tab[500]
#define __pyx_n_u_search_queue __pyx_string_tab[501]
#define __pyx_n_u_search_stack __pyx_string_tab[502]
#define __pyx_n_u_search_steps __pyx_string_tab[503]
#define __pyx_n_u_segments_to_process __pyx_string_tab[504]
#define __pyx_n_u_set_name __pyx_string_tab[505]
#define __pyx_n_u_setdefault __pyx_string_tab[506]
#define __pyx_n_u_shapely __pyx_string_tab[507]
#define __pyx_n_u_shapely_ops __pyx_string_tab[508]
#define __pyx_n_u_shapely_wkb __pyx_string_tab[509]
#define __pyx_n_u_shutil __pyx_string_tab[510]
#define __pyx_n_u_single_outlet __pyx_string_tab[511]
#define __pyx_n_u_single_outlet_tuple __pyx_string_tab[512]
#define __pyx_n_u_sink_pixel __pyx_string_tab[513]
#define __pyx_n_u_sorted __pyx_string_tab[514]
#define __pyx_n_u_sorted_stream_order_list __pyx_string_tab[515]
#define __pyx_n_u_source_id __pyx_string_tab[516]
#define __pyx_n_u_source_point_stack __pyx_string_tab[517]
#define __pyx_n_u_source_stream_point __pyx_string_tab[518]
#define __pyx_n_u_splitext __pyx_string_tab[519]
#define __pyx_n_u_stats __pyx_string_tab[520]
#define __pyx_n_u_strahler_stream_vector_path __pyx_string_tab[521]
#define __pyx_n_u_stream_array __pyx_string_tab[522]
#define __pyx_n_u_stream_band __pyx_string_tab[523]
#define __pyx_n_u_stream_basename __pyx_string_tab[524]
#define __pyx_n_u_stream_feature __pyx_string_tab[525]
#define __pyx_n_u_stream_fid __pyx_string_tab[526]
#define __pyx_n_u_stream_layer __pyx_string_tab[527]
#define __pyx_n_u_stream_line __pyx_string_tab[528]
#define __pyx_n_u_stream_mr __pyx_string_tab[529]
#define __pyx_n_u_stream_nodata __pyx_string_tab[530]
#define __pyx_n_u_stream_order __pyx_string_tab[531]
#define __pyx_n_u_stream_order_list __pyx_string_tab[532]
#define __pyx_n_u_stream_raster __pyx_string_tab[533]
#define __pyx_n_u_stream_val __pyx_string_tab[534]
#define __pyx_n_u_stream_vector __pyx_string_tab[535]
#define __pyx_n_u_streams_by_order __pyx_string_tab[536]
#define __pyx_n_u_streams_to_process __pyx_string_tab[537]
#define __pyx_n_u_streams_to_retest __pyx_string_tab[538]
#define __pyx_n_u_strftime __pyx_string_tab[539]
#define __pyx_n_u_suffix __pyx_string_tab[540]
#define __pyx_n_u_sum_of_downhill_slopes __pyx_string_tab[541]
#define __pyx_n_u_sum_of_nodata_slope_weights __pyx_string_tab[542]
#define __pyx_n_u_sum_of_slope_weights __pyx_string_tab[543]
#define __pyx_n_u_sum_of_weighted_distances __pyx_string_tab[544]
#define __pyx_n_u_sum_of_weights __pyx_string_tab[545]
#define __pyx_n_u_target_discovery_raster_path __pyx_string_tab[546]
#define __pyx_n_u_target_distance_to_channel_raste __pyx_string_tab[547]
#define __pyx_n_u_target_filled_dem_raster_path __pyx_string_tab[548]
#define __pyx_n_u_target_finish_raster_path __pyx_string_tab[549]
#define __pyx_n_u_target_flow_accum_raster_path __pyx_string_tab[550]
#define __pyx_n_u_target_flow_dir_path __pyx_string_tab[551]
#define __pyx_n_u_target_offset_dict __pyx_string_tab[552]
#define __pyx_n_u_target_outlet_vector_path __pyx_string_tab[553]
#define __pyx_n_u_target_stream_raster_path __pyx_string_tab[554]
#define __pyx_n_u_target_stream_vector_path __pyx_string_tab[555]
#define __pyx_n_u_target_watershed_boundary_vector __pyx_string_tab[556]
#define __pyx_n_u_tempfile __pyx_string_tab[557]
#define __pyx_n_u_terminated_early __pyx_string_tab[558]
#define __pyx_n_u_test __pyx_string_tab[559]
#define __pyx_n_u_test_dir __pyx_string_tab[560]
#define __pyx_n_u_test_order __pyx_string_tab[561]
#define __pyx_n_u_thresh_fa __pyx_string_tab[562]
#define __pyx_n_u_time __pyx_string_tab[563]
#define __pyx_n_u_tmp_decay_factor_nodata __pyx_string_tab[564]
#define __pyx_n_u_tmp_dir __pyx_string_tab[565]
#define __pyx_n_u_tmp_dir_root __pyx_string_tab[566]
#define __pyx_n_u_tmp_flow_dir_nodata __pyx_string_tab[567]
#define __pyx_n_u_tmp_work_dir __pyx_string_tab[568]
#define __pyx_n_u_trace_flow_threshold __pyx_string_tab[569]
#define __pyx_n_u_trace_threshold_proportion __pyx_string_tab[570]
#define __pyx_n_u_ttest_ind __pyx_string_tab[571]
#define __pyx_n_u_uint8 __pyx_string_tab[572]
#define __pyx_n_u_upstream_all_defined __pyx_string_tab[573]
#define __pyx_n_u_upstream_coord __pyx_string_tab[574]
#define __pyx_n_u_upstream_count __pyx_string_tab[575]
#define __pyx_n_u_upstream_d8_dir __pyx_string_tab[576]
#define __pyx_n_u_upstream_decaying_value __pyx_string_tab[577]
#define __pyx_n_u_upstream_dem __pyx_string_tab[578]
#define __pyx_n_u_upstream_dirs __pyx_string_tab[579]
#define __pyx_n_u_upstream_feature __pyx_string_tab[580]
#define __pyx_n_u_upstream_fid __pyx_string_tab[581]
#define __pyx_n_u_upstream_fid_list __pyx_string_tab[582]
#define __pyx_n_u_upstream_fid_map __pyx_string_tab[583]
#define __pyx_n_u_upstream_fids __pyx_string_tab[584]
#define __pyx_n_u_upstream_flow_accum __pyx_string_tab[585]
#define __pyx_n_u_upstream_flow_dir __pyx_string_tab[586]
#define __pyx_n_u_upstream_flow_dir_sum __pyx_string_tab[587]
#define __pyx_n_u_upstream_flow_weight __pyx_string_tab[588]
#define __pyx_n_u_upstream_id __pyx_string_tab[589]
#define __pyx_n_u_upstream_id_list __pyx_string_tab[590]
#define __pyx_n_u_upstream_index __pyx_string_tab[591]
#define __pyx_n_u_upstream_order __pyx_string_tab[592]
#define __pyx_n_u_upstream_pixels_remain __pyx_string_tab[593]
#define __pyx_n_u_upstream_stack __pyx_string_tab[594]
#define __pyx_n_u_upstream_to_downstream_id __pyx_string_tab[595]
#define __pyx_n_u_upstream_transport_factor __pyx_string_tab[596]
#define __pyx_n_u_us_fa __pyx_string_tab[597]
#define __pyx_n_u_us_x __pyx_string_tab[598]
#define __pyx_n_u_us_y __pyx_string_tab[599]
#define __pyx_n_u_use_const_decay_factor __pyx_string_tab[600]
#define __pyx_n_u_utils __pyx_string_tab[601]
#define __pyx_n_u_value __pyx_string_tab[602]
#define __pyx_n_u_values __pyx_string_tab[603]
#define __pyx_n_u_visit_count __pyx_string_tab[604]
#define __pyx_n_u_visit_order_stack __pyx_string_tab[605]
#define __pyx_n_u_visited_managed_raster __pyx_string_tab[606]
#define __pyx_n_u_visited_raster_path __pyx_string_tab[607]
#define __pyx_n_u_warning __pyx_string_tab[608]
#define __pyx_n_u_watershed_basename __pyx_string_tab[609]
#define __pyx_n_u_watershed_boundary __pyx_string_tab[610]
#define __pyx_n_u_watershed_feature __pyx_string_tab[611]
#define __pyx_n_u_watershed_layer __pyx_string_tab[612]
#define __pyx_n_u_watershed_polygon __pyx_string_tab[613]
#define __pyx_n_u_watershed_vector __pyx_string_tab[614]
#define __pyx_n_u_weight_nodata __pyx_string_tab[615]
#define __pyx_n_u_weight_raster __pyx_string_tab[616]
#define __pyx_n_u_weight_raster_path_band __pyx_string_tab[617]
#define __pyx_n_u_weight_val __pyx_string_tab[618]
#define __pyx_n_u_win_xsize __pyx_string_tab[619]
#define __pyx_n_u_win_xsize_border __pyx_string_tab[620]
#define __pyx_n_u_win_ysize __pyx_string_tab[621]
#define __pyx_n_u_win_ysize_border __pyx_string_tab[622]
#define __pyx_n_u_wkb __pyx_string_tab[623]
#define __pyx_n_u_wkbLineString __pyx_string_tab[624]
#define __pyx_n_u_wkbLinearRing __pyx_string_tab[625]
#define __pyx_n_u_wkbPoint __pyx_string_tab[626]
#define __pyx_n_u_wkbPolygon __pyx_string_tab[627]
#define __pyx_n_u_working_dir __pyx_string_tab[628]
#define __pyx_n_u_working_dir_path __pyx_string_tab[629]
#define __pyx_n_u_working_downhill_slope_array __pyx_string_tab[630]
#define __pyx_n_u_working_downhill_slope_sum __pyx_string_tab[631]
#define __pyx_n_u_working_feature __pyx_string_tab[632]
#define __pyx_n_u_working_fid __pyx_string_tab[633]
#define __pyx_n_u_working_flow_accum_threshold __pyx_string_tab[634]
#define __pyx_n_u_working_geom __pyx_string_tab[635]
#define __pyx_n_u_working_order __pyx_string_tab[636]
#define __pyx_n_u_working_river_id __pyx_string_tab[637]
#define __pyx_n_u_working_stack __pyx_string_tab[638]
#define __pyx_n_u_workspace_dir __pyx_string_tab[639]
#define __pyx_n_u_x __pyx_string_tab[640]
#define __pyx_n_u_x_f __pyx_string_tab[641]
#define __pyx_n_u_x_l __pyx_string_tab[642]
#define __pyx_n_u_x_n __pyx_string_tab[643]
#define __pyx_n_u_x_off_border __pyx_string_tab[644]
#define __pyx_n_u_x_p __pyx_string_tab[645]
#define __pyx_n_u_x_u __pyx_string_tab[646]
#define __pyx_n_u_xa __pyx_string_tab[647]
#define __pyx_n_u_xb __pyx_string_tab[648]
#define __pyx_n_u_xi __pyx_string_tab[649]
#define __pyx_n_u_xi_bn __pyx_string_tab[650]
#define __pyx_n_u_xi_n __pyx_string_tab[651]
#define __pyx_n_u_xi_q __pyx_string_tab[652]
#define __pyx_n_u_xi_root __pyx_string_tab[653]
#define __pyx_n_u_xi_sn __pyx_string_tab[654]
#define __pyx_n_u_xoff __pyx_string_tab[655]
#define __pyx_n_u_y_f __pyx_string_tab[656]
#define __pyx_n_u_y_l __pyx_string_tab[657]
#define __pyx_n_u_y_n __pyx_string_tab[658]
#define __pyx_n_u_y_off_border __pyx_string_tab[659]
#define __pyx_n_u_y_p __pyx_string_tab[660]
#define __pyx_n_u_y_u __pyx_string_tab[661]
#define __pyx_n_u_ya __pyx_string_tab[662]
#define __pyx_n_u_yb __pyx_string_tab[663]
#define __pyx_n_u_yi __pyx_string_tab[664]
#define __pyx_n_u_yi_bn __pyx_string_tab[665]
#define __pyx_n_u_yi_n __pyx_string_tab[666]
#define __pyx_n_u_yi_q __pyx_string_tab[667]
#define __pyx_n_u_yi_root __pyx_string_tab[668]
#define __pyx_n_u_yi_sn __pyx_string_tab[669]
#define __pyx_n_u_yoff __pyx_string_tab[670]
#define __pyx_kp_b_iso88591_12_x_E_1_5_uD_B_1_A_I_q_Qa_N_1 __pyx_string_tab[671]
#define __pyx_kp_b_iso88591_45_B_E_o_5Q6J_1_1_1A_7_U_1_Q_1 __pyx_string_tab[672]
#define __pyx_kp_b_iso88591_B_A_E_t_j_EQ_t4_EQ_j_EQ_Qd_N_1 __pyx_string_tab[673]
#define __pyx_kp_b_iso88591_E_82Q_Q_a_1_82Q_Q_a_1_1HBk_r_Q __pyx_string_tab[674]
#define __pyx_kp_b_iso88591_F_O_31_AQ_AQ_s_1_N_1A_q_aq_Kwa __pyx_string_tab[675]
#define __pyx_kp_b_iso88591_H_e1_U_o_5Q_AQ_ay_G1__AYaq_Q_1 __pyx_string_tab[676]
#define __pyx_kp_b_iso88591_M_q_XV1_j_q_s_Q_1_9A_AQ_aq_d_d __pyx_string_tab[677]
#define __pyx_kp_b_iso88591_N_Bc_DBa_j_A_o_5Q_1A_O1IQ_1Baq __pyx_string_tab[678]
#define __pyx_kp_b_iso88591_O_31_AQ_I_1_Qiq_ARq_m1_ARwaq_AT __pyx_string_tab[679]
#define __pyx_kp_b_iso88591_Q_7_Q_E_o_5Q6J_1_1_1A_7_U_1_Q_1 __pyx_string_tab[680]
#define __pyx_kp_b_iso88591_V_HHA_q_Be5_e81A_5_QoQ_b_U_1_a __pyx_string_tab[681]
#define __pyx_kp_b_iso88591_X_E_o_5Q6J_1_1_1A_7_U_1_Q_1_wa __pyx_string_tab[682]
#define __pyx_kp_b_iso88591_a_P_E_t_j_EQ_t4_EQ_j_EQ_a_N_1_Q __pyx_string_tab[683]
#define __pyx_kp_b_iso88591_r_E_5_uD_B_1_A_I_q_AQ_N_1_Q_a_g __pyx_string_tab[684]
#define __pyx_kp_b_iso88591_t_Q_q_q_A_s_q_Zq_Q_q_Zq_Q_q_q __pyx_string_tab[685]
#define __pyx_kp_b_iso88591_wa_Q_2_Qa_Q_a_waq_Q_a_aq __pyx_string_tab[686]
#define __pyx_float_1_25 __pyx_number_tab[0]
#define __pyx_float_100_0 __pyx_number_tab[1]
#define __pyx_int_0 __pyx_number_tab[2]
#define __pyx_int_neg_1 __pyx_number_tab[3]
#define __pyx_int_1 __pyx_number_tab[4]
#define __pyx_int_2 __pyx_number_tab[5]
#define __pyx_int_100 __pyx_number_tab[6]
#define __pyx_int_1000000 __pyx_number_tab[7]
/* #### Code section: module_state_clear ### */
#if CYTHON_USE_MODULE_STATE
static CYTHON_SMALL_CODE int __pyx_m_clear(PyObject *m) {
  __pyx_mstatetype *clear_module_state = __Pyx_PyModule_GetState(m);
  if (!clear_module_state) return 0;
  Py_CLEAR(clear_module_state->__pyx_d);
  Py_CLEAR(clear_module_state->__pyx_b);
  Py_CLEAR(clear_module_state->__pyx_cython_runtime);
  Py_CLEAR(clear_module_state->__pyx_empty_tuple);
  Py_CLEAR(clear_module_state->__pyx_empty_bytes);
  Py_CLEAR(clear_module_state->__pyx_empty_unicode);
  #if CYTHON_PEP489_MULTI_PHASE_INIT
  __Pyx_State_RemoveModule(NULL);
  #endif
  Py_CLEAR(clear_module_state->__pyx_ptype_7cpython_4type_type);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_dtype);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_flatiter);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_broadcast);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_ndarray);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_generic);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_number);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_integer);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_signedinteger);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_unsignedinteger);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_inexact);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_floating);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_complexfloating);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_flexible);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_character);
  Py_CLEAR(clear_module_state->__pyx_ptype_5numpy_ufunc);
  Py_CLEAR(clear_module_state->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults);
  Py_CLEAR(clear_module_state->__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults);
  for (int i=0; i<1; ++i) { Py_CLEAR(clear_module_state->__pyx_slice[i]); }
  for (int i=0; i<14; ++i) { Py_CLEAR(clear_module_state->__pyx_tuple[i]); }
  for (int i=0; i<16; ++i) { Py_CLEAR(clear_module_state->__pyx_codeobj_tab[i]); }
  for (int i=0; i<687; ++i) { Py_CLEAR(clear_module_state->__pyx_string_tab[i]); }
  for (int i=0; i<8; ++i) { Py_CLEAR(clear_module_state->__pyx_number_tab[i]); }
/* #### Code section: module_state_clear_contents ### */
/* CommonTypesMetaclass.module_state_clear */
Py_CLEAR(clear_module_state->__pyx_CommonTypesMetaclassType);

/* CythonFunctionShared.module_state_clear */
Py_CLEAR(clear_module_state->__pyx_CyFunctionType);

/* #### Code section: module_state_clear_end ### */
return 0;
}
#endif
/* #### Code section: module_state_traverse ### */
#if CYTHON_USE_MODULE_STATE
static CYTHON_SMALL_CODE int __pyx_m_traverse(PyObject *m, visitproc visit, void *arg) {
  __pyx_mstatetype *traverse_module_state = __Pyx_PyModule_GetState(m);
  if (!traverse_module_state) return 0;
  Py_VISIT(traverse_module_state->__pyx_d);
  Py_VISIT(traverse_module_state->__pyx_b);
  Py_VISIT(traverse_module_state->__pyx_cython_runtime);
  __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_tuple);
  __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_bytes);
  __Pyx_VISIT_CONST(traverse_module_state->__pyx_empty_unicode);
  Py_VISIT(traverse_module_state->__pyx_ptype_7cpython_4type_type);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_dtype);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_flatiter);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_broadcast);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_ndarray);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_generic);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_number);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_integer);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_signedinteger);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_unsignedinteger);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_inexact);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_floating);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_complexfloating);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_flexible);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_character);
  Py_VISIT(traverse_module_state->__pyx_ptype_5numpy_ufunc);
  Py_VISIT(traverse_module_state->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults);
  Py_VISIT(traverse_module_state->__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults);
  for (int i=0; i<1; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_slice[i]); }
  for (int i=0; i<14; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_tuple[i]); }
  for (int i=0; i<16; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_codeobj_tab[i]); }
  for (int i=0; i<687; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_string_tab[i]); }
  for (int i=0; i<8; ++i) { __Pyx_VISIT_CONST(traverse_module_state->__pyx_number_tab[i]); }
/* #### Code section: module_state_traverse_contents ### */
/* CommonTypesMetaclass.module_state_traverse */
Py_VISIT(traverse_module_state->__pyx_CommonTypesMetaclassType);

/* CythonFunctionShared.module_state_traverse */
Py_VISIT(traverse_module_state->__pyx_CyFunctionType);

/* #### Code section: module_state_traverse_end ### */
return 0;
}
#endif
/* #### Code section: module_code ### */

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":243
 *         cdef int type_num
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp itemsize(self) noexcept nogil:
 *             return PyDataType_ELSIZE(self)
*/

static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_8itemsize_itemsize(PyArray_Descr *__pyx_v_self) {
  npy_intp __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":245
 *         @property
 *         cdef inline npy_intp itemsize(self) noexcept nogil:
 *             return PyDataType_ELSIZE(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyDataType_ELSIZE(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":243
 *         cdef int type_num
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp itemsize(self) noexcept nogil:
 *             return PyDataType_ELSIZE(self)
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":247
 *             return PyDataType_ELSIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp alignment(self) noexcept nogil:
 *             return PyDataType_ALIGNMENT(self)
*/

static CYTHON_INLINE npy_intp __pyx_f_5numpy_5dtype_9alignment_alignment(PyArray_Descr *__pyx_v_self) {
  npy_intp __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":249
 *         @property
 *         cdef inline npy_intp alignment(self) noexcept nogil:
 *             return PyDataType_ALIGNMENT(self)             # <<<<<<<<<<<<<<
 * 
 *         # Use fields/names with care as they may be NULL.  You must check
*/
  __pyx_r = PyDataType_ALIGNMENT(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":247
 *             return PyDataType_ELSIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp alignment(self) noexcept nogil:
 *             return PyDataType_ALIGNMENT(self)
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":253
 *         # Use fields/names with care as they may be NULL.  You must check
 *         # for this using PyDataType_HASFIELDS.
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline object fields(self):
 *             return <object>PyDataType_FIELDS(self)
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_6fields_fields(PyArray_Descr *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1;
  __Pyx_RefNannySetupContext("fields", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":255
 *         @property
 *         cdef inline object fields(self):
 *             return <object>PyDataType_FIELDS(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyDataType_FIELDS(__pyx_v_self);
  __Pyx_INCREF(((PyObject *)__pyx_t_1));
  __pyx_r = ((PyObject *)__pyx_t_1);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":253
 *         # Use fields/names with care as they may be NULL.  You must check
 *         # for this using PyDataType_HASFIELDS.
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline object fields(self):
 *             return <object>PyDataType_FIELDS(self)
*/

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

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":257
 *             return <object>PyDataType_FIELDS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline tuple names(self):
 *             return <tuple>PyDataType_NAMES(self)
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_5dtype_5names_names(PyArray_Descr *__pyx_v_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1;
  __Pyx_RefNannySetupContext("names", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":259
 *         @property
 *         cdef inline tuple names(self):
 *             return <tuple>PyDataType_NAMES(self)             # <<<<<<<<<<<<<<
 * 
 *         # Use PyDataType_HASSUBARRAY to test whether this field is
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyDataType_NAMES(__pyx_v_self);
  __Pyx_INCREF(((PyObject*)__pyx_t_1));
  __pyx_r = ((PyObject*)__pyx_t_1);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":257
 *             return <object>PyDataType_FIELDS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline tuple names(self):
 *             return <tuple>PyDataType_NAMES(self)
*/

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

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":264
 *         # valid (the pointer can be NULL). Most users should access
 *         # this field via the inline helper method PyDataType_SHAPE.
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil:
 *             return PyDataType_SUBARRAY(self)
*/

static CYTHON_INLINE PyArray_ArrayDescr *__pyx_f_5numpy_5dtype_8subarray_subarray(PyArray_Descr *__pyx_v_self) {
  PyArray_ArrayDescr *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":266
 *         @property
 *         cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil:
 *             return PyDataType_SUBARRAY(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyDataType_SUBARRAY(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":264
 *         # valid (the pointer can be NULL). Most users should access
 *         # this field via the inline helper method PyDataType_SHAPE.
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline PyArray_ArrayDescr* subarray(self) noexcept nogil:
 *             return PyDataType_SUBARRAY(self)
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":268
 *             return PyDataType_SUBARRAY(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_uint64 flags(self) noexcept nogil:
 *             """The data types flags."""
*/

static CYTHON_INLINE npy_uint64 __pyx_f_5numpy_5dtype_5flags_flags(PyArray_Descr *__pyx_v_self) {
  npy_uint64 __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":271
 *         cdef inline npy_uint64 flags(self) noexcept nogil:
 *             """The data types flags."""
 *             return PyDataType_FLAGS(self)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = PyDataType_FLAGS(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":268
 *             return PyDataType_SUBARRAY(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_uint64 flags(self) noexcept nogil:
 *             """The data types flags."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":280
 *     ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int numiter(self) noexcept nogil:
 *             """The number of arrays that need to be broadcast to the same shape."""
*/

static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_7numiter_numiter(PyArrayMultiIterObject *__pyx_v_self) {
  int __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":283
 *         cdef inline int numiter(self) noexcept nogil:
 *             """The number of arrays that need to be broadcast to the same shape."""
 *             return PyArray_MultiIter_NUMITER(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_MultiIter_NUMITER(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":280
 *     ctypedef class numpy.broadcast [object PyArrayMultiIterObject, check_size ignore]:
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int numiter(self) noexcept nogil:
 *             """The number of arrays that need to be broadcast to the same shape."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":285
 *             return PyArray_MultiIter_NUMITER(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp size(self) noexcept nogil:
 *             """The total broadcasted size."""
*/

static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_4size_size(PyArrayMultiIterObject *__pyx_v_self) {
  npy_intp __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":288
 *         cdef inline npy_intp size(self) noexcept nogil:
 *             """The total broadcasted size."""
 *             return PyArray_MultiIter_SIZE(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_MultiIter_SIZE(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":285
 *             return PyArray_MultiIter_NUMITER(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp size(self) noexcept nogil:
 *             """The total broadcasted size."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":290
 *             return PyArray_MultiIter_SIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp index(self) noexcept nogil:
 *             """The current (1-d) index into the broadcasted result."""
*/

static CYTHON_INLINE npy_intp __pyx_f_5numpy_9broadcast_5index_index(PyArrayMultiIterObject *__pyx_v_self) {
  npy_intp __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":293
 *         cdef inline npy_intp index(self) noexcept nogil:
 *             """The current (1-d) index into the broadcasted result."""
 *             return PyArray_MultiIter_INDEX(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_MultiIter_INDEX(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":290
 *             return PyArray_MultiIter_SIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp index(self) noexcept nogil:
 *             """The current (1-d) index into the broadcasted result."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":295
 *             return PyArray_MultiIter_INDEX(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int nd(self) noexcept nogil:
 *             """The number of dimensions in the broadcasted result."""
*/

static CYTHON_INLINE int __pyx_f_5numpy_9broadcast_2nd_nd(PyArrayMultiIterObject *__pyx_v_self) {
  int __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":298
 *         cdef inline int nd(self) noexcept nogil:
 *             """The number of dimensions in the broadcasted result."""
 *             return PyArray_MultiIter_NDIM(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_MultiIter_NDIM(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":295
 *             return PyArray_MultiIter_INDEX(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int nd(self) noexcept nogil:
 *             """The number of dimensions in the broadcasted result."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":300
 *             return PyArray_MultiIter_NDIM(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp* dimensions(self) noexcept nogil:
 *             """The shape of the broadcasted result."""
*/

static CYTHON_INLINE npy_intp *__pyx_f_5numpy_9broadcast_10dimensions_dimensions(PyArrayMultiIterObject *__pyx_v_self) {
  npy_intp *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":303
 *         cdef inline npy_intp* dimensions(self) noexcept nogil:
 *             """The shape of the broadcasted result."""
 *             return PyArray_MultiIter_DIMS(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_MultiIter_DIMS(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":300
 *             return PyArray_MultiIter_NDIM(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp* dimensions(self) noexcept nogil:
 *             """The shape of the broadcasted result."""
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":305
 *             return PyArray_MultiIter_DIMS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline void** iters(self) noexcept nogil:
 *             """An array of iterator objects that holds the iterators for the arrays to be broadcast together.
*/

static CYTHON_INLINE void **__pyx_f_5numpy_9broadcast_5iters_iters(PyArrayMultiIterObject *__pyx_v_self) {
  void **__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":309
 *             """An array of iterator objects that holds the iterators for the arrays to be broadcast together.
 *             On return, the iterators are adjusted for broadcasting."""
 *             return PyArray_MultiIter_ITERS(self)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = PyArray_MultiIter_ITERS(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":305
 *             return PyArray_MultiIter_DIMS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline void** iters(self) noexcept nogil:
 *             """An array of iterator objects that holds the iterators for the arrays to be broadcast together.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":323
 *         # Instead, we use properties that map to the corresponding C-API functions.
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline PyObject* base(self) noexcept nogil:
 *             """Returns a borrowed reference to the object owning the data/memory.
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_7ndarray_4base_base(PyArrayObject *__pyx_v_self) {
  PyObject *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":327
 *             """Returns a borrowed reference to the object owning the data/memory.
 *             """
 *             return PyArray_BASE(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_BASE(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":323
 *         # Instead, we use properties that map to the corresponding C-API functions.
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline PyObject* base(self) noexcept nogil:
 *             """Returns a borrowed reference to the object owning the data/memory.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":329
 *             return PyArray_BASE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline dtype descr(self):
 *             """Returns an owned reference to the dtype of the array.
*/

static CYTHON_INLINE PyArray_Descr *__pyx_f_5numpy_7ndarray_5descr_descr(PyArrayObject *__pyx_v_self) {
  PyArray_Descr *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyArray_Descr *__pyx_t_1;
  __Pyx_RefNannySetupContext("descr", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":333
 *             """Returns an owned reference to the dtype of the array.
 *             """
 *             return <dtype>PyArray_DESCR(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __Pyx_XDECREF((PyObject *)__pyx_r);
  __pyx_t_1 = PyArray_DESCR(__pyx_v_self);
  __Pyx_INCREF((PyObject *)((PyArray_Descr *)__pyx_t_1));
  __pyx_r = ((PyArray_Descr *)__pyx_t_1);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":329
 *             return PyArray_BASE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline dtype descr(self):
 *             """Returns an owned reference to the dtype of the array.
*/

  /* function exit code */
  __pyx_L0:;
  __Pyx_XGIVEREF((PyObject *)__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":335
 *             return <dtype>PyArray_DESCR(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int ndim(self) noexcept nogil:
 *             """Returns the number of dimensions in the array.
*/

static CYTHON_INLINE int __pyx_f_5numpy_7ndarray_4ndim_ndim(PyArrayObject *__pyx_v_self) {
  int __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":339
 *             """Returns the number of dimensions in the array.
 *             """
 *             return PyArray_NDIM(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_NDIM(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":335
 *             return <dtype>PyArray_DESCR(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline int ndim(self) noexcept nogil:
 *             """Returns the number of dimensions in the array.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":341
 *             return PyArray_NDIM(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp *shape(self) noexcept nogil:
 *             """Returns a pointer to the dimensions/shape of the array.
*/

static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_5shape_shape(PyArrayObject *__pyx_v_self) {
  npy_intp *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":347
 *             Can return NULL for 0-dimensional arrays.
 *             """
 *             return PyArray_DIMS(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_DIMS(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":341
 *             return PyArray_NDIM(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp *shape(self) noexcept nogil:
 *             """Returns a pointer to the dimensions/shape of the array.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":349
 *             return PyArray_DIMS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp *strides(self) noexcept nogil:
 *             """Returns a pointer to the strides of the array.
*/

static CYTHON_INLINE npy_intp *__pyx_f_5numpy_7ndarray_7strides_strides(PyArrayObject *__pyx_v_self) {
  npy_intp *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":354
 *             The number of elements matches the number of dimensions of the array (ndim).
 *             """
 *             return PyArray_STRIDES(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_STRIDES(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":349
 *             return PyArray_DIMS(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp *strides(self) noexcept nogil:
 *             """Returns a pointer to the strides of the array.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":356
 *             return PyArray_STRIDES(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp size(self) noexcept nogil:
 *             """Returns the total size (in number of elements) of the array.
*/

static CYTHON_INLINE npy_intp __pyx_f_5numpy_7ndarray_4size_size(PyArrayObject *__pyx_v_self) {
  npy_intp __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":360
 *             """Returns the total size (in number of elements) of the array.
 *             """
 *             return PyArray_SIZE(self)             # <<<<<<<<<<<<<<
 * 
 *         @property
*/
  __pyx_r = PyArray_SIZE(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":356
 *             return PyArray_STRIDES(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline npy_intp size(self) noexcept nogil:
 *             """Returns the total size (in number of elements) of the array.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":362
 *             return PyArray_SIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline char* data(self) noexcept nogil:
 *             """The pointer to the data buffer as a char*.
*/

static CYTHON_INLINE char *__pyx_f_5numpy_7ndarray_4data_data(PyArrayObject *__pyx_v_self) {
  char *__pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":369
 *             of `PyArray_DATA()` instead, which returns a 'void*'.
 *             """
 *             return PyArray_BYTES(self)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = PyArray_BYTES(__pyx_v_self);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":362
 *             return PyArray_SIZE(self)
 * 
 *         @property             # <<<<<<<<<<<<<<
 *         cdef inline char* data(self) noexcept nogil:
 *             """The pointer to the data buffer as a char*.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":777
 * ctypedef long double complex clongdouble_t
 * 
 * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(1, <void*>a)
 * 
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew1(PyObject *__pyx_v_a) {
  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("PyArray_MultiIterNew1", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":778
 * 
 * cdef inline object PyArray_MultiIterNew1(a):
 *     return PyArray_MultiIterNew(1, <void*>a)             # <<<<<<<<<<<<<<
 * 
 * cdef inline object PyArray_MultiIterNew2(a, b):
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyArray_MultiIterNew(1, ((void *)__pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 778, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":777
 * ctypedef long double complex clongdouble_t
 * 
 * cdef inline object PyArray_MultiIterNew1(a):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(1, <void*>a)
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew1", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":780
 *     return PyArray_MultiIterNew(1, <void*>a)
 * 
 * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
 * 
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew2(PyObject *__pyx_v_a, PyObject *__pyx_v_b) {
  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("PyArray_MultiIterNew2", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":781
 * 
 * cdef inline object PyArray_MultiIterNew2(a, b):
 *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)             # <<<<<<<<<<<<<<
 * 
 * cdef inline object PyArray_MultiIterNew3(a, b, c):
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyArray_MultiIterNew(2, ((void *)__pyx_v_a), ((void *)__pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 781, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":780
 *     return PyArray_MultiIterNew(1, <void*>a)
 * 
 * cdef inline object PyArray_MultiIterNew2(a, b):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew2", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":783
 *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
 * 
 * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
 * 
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew3(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c) {
  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("PyArray_MultiIterNew3", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":784
 * 
 * cdef inline object PyArray_MultiIterNew3(a, b, c):
 *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)             # <<<<<<<<<<<<<<
 * 
 * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyArray_MultiIterNew(3, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 784, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":783
 *     return PyArray_MultiIterNew(2, <void*>a, <void*>b)
 * 
 * cdef inline object PyArray_MultiIterNew3(a, b, c):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew3", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":786
 *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
 * 
 * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
 * 
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew4(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d) {
  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("PyArray_MultiIterNew4", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":787
 * 
 * cdef inline object PyArray_MultiIterNew4(a, b, c, d):
 *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)             # <<<<<<<<<<<<<<
 * 
 * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyArray_MultiIterNew(4, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 787, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":786
 *     return PyArray_MultiIterNew(3, <void*>a, <void*>b, <void*> c)
 * 
 * cdef inline object PyArray_MultiIterNew4(a, b, c, d):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew4", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":789
 *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
 * 
 * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
 * 
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyArray_MultiIterNew5(PyObject *__pyx_v_a, PyObject *__pyx_v_b, PyObject *__pyx_v_c, PyObject *__pyx_v_d, PyObject *__pyx_v_e) {
  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("PyArray_MultiIterNew5", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":790
 * 
 * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):
 *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)             # <<<<<<<<<<<<<<
 * 
 * cdef inline tuple PyDataType_SHAPE(dtype d):
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyArray_MultiIterNew(5, ((void *)__pyx_v_a), ((void *)__pyx_v_b), ((void *)__pyx_v_c), ((void *)__pyx_v_d), ((void *)__pyx_v_e)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 790, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":789
 *     return PyArray_MultiIterNew(4, <void*>a, <void*>b, <void*>c, <void*> d)
 * 
 * cdef inline object PyArray_MultiIterNew5(a, b, c, d, e):             # <<<<<<<<<<<<<<
 *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("numpy.PyArray_MultiIterNew5", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":792
 *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
 * 
 * cdef inline tuple PyDataType_SHAPE(dtype d):             # <<<<<<<<<<<<<<
 *     if PyDataType_HASSUBARRAY(d):
 *         return <tuple>d.subarray.shape
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr *__pyx_v_d) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  PyObject *__pyx_t_2;
  __Pyx_RefNannySetupContext("PyDataType_SHAPE", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":793
 * 
 * cdef inline tuple PyDataType_SHAPE(dtype d):
 *     if PyDataType_HASSUBARRAY(d):             # <<<<<<<<<<<<<<
 *         return <tuple>d.subarray.shape
 *     else:
*/
  __pyx_t_1 = PyDataType_HASSUBARRAY(__pyx_v_d);
  if (__pyx_t_1) {

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":794
 * cdef inline tuple PyDataType_SHAPE(dtype d):
 *     if PyDataType_HASSUBARRAY(d):
 *         return <tuple>d.subarray.shape             # <<<<<<<<<<<<<<
 *     else:
 *         return ()
*/
    __Pyx_XDECREF(__pyx_r);
    __pyx_t_2 = __pyx_f_5numpy_5dtype_8subarray_subarray(__pyx_v_d)->shape;
    __Pyx_INCREF(((PyObject*)__pyx_t_2));
    __pyx_r = ((PyObject*)__pyx_t_2);
    goto __pyx_L0;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":793
 * 
 * cdef inline tuple PyDataType_SHAPE(dtype d):
 *     if PyDataType_HASSUBARRAY(d):             # <<<<<<<<<<<<<<
 *         return <tuple>d.subarray.shape
 *     else:
*/
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":796
 *         return <tuple>d.subarray.shape
 *     else:
 *         return ()             # <<<<<<<<<<<<<<
 * 
 * 
*/
  /*else*/ {
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(__pyx_mstate_global->__pyx_empty_tuple);
    __pyx_r = __pyx_mstate_global->__pyx_empty_tuple;
    goto __pyx_L0;
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":792
 *     return PyArray_MultiIterNew(5, <void*>a, <void*>b, <void*>c, <void*> d, <void*> e)
 * 
 * cdef inline tuple PyDataType_SHAPE(dtype d):             # <<<<<<<<<<<<<<
 *     if PyDataType_HASSUBARRAY(d):
 *         return <tuple>d.subarray.shape
*/

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

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":995
 *     int _import_umath() except -1
 * 
 * cdef inline void set_array_base(ndarray arr, object base) except *:             # <<<<<<<<<<<<<<
 *     Py_INCREF(base) # important to do this before stealing the reference below!
 *     PyArray_SetBaseObject(arr, base)
*/

static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_arr, PyObject *__pyx_v_base) {
  int __pyx_t_1;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":996
 * 
 * cdef inline void set_array_base(ndarray arr, object base) except *:
 *     Py_INCREF(base) # important to do this before stealing the reference below!             # <<<<<<<<<<<<<<
 *     PyArray_SetBaseObject(arr, base)
 * 
*/
  Py_INCREF(__pyx_v_base);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":997
 * cdef inline void set_array_base(ndarray arr, object base) except *:
 *     Py_INCREF(base) # important to do this before stealing the reference below!
 *     PyArray_SetBaseObject(arr, base)             # <<<<<<<<<<<<<<
 * 
 * cdef inline object get_array_base(ndarray arr):
*/
  __pyx_t_1 = PyArray_SetBaseObject(__pyx_v_arr, __pyx_v_base); if (unlikely(__pyx_t_1 == ((int)-1))) __PYX_ERR(1, 997, __pyx_L1_error)

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":995
 *     int _import_umath() except -1
 * 
 * cdef inline void set_array_base(ndarray arr, object base) except *:             # <<<<<<<<<<<<<<
 *     Py_INCREF(base) # important to do this before stealing the reference below!
 *     PyArray_SetBaseObject(arr, base)
*/

  /* function exit code */
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_AddTraceback("numpy.set_array_base", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_L0:;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":999
 *     PyArray_SetBaseObject(arr, base)
 * 
 * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
 *     base = PyArray_BASE(arr)
 *     if base is NULL:
*/

static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__pyx_v_arr) {
  PyObject *__pyx_v_base;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  __Pyx_RefNannySetupContext("get_array_base", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1000
 * 
 * cdef inline object get_array_base(ndarray arr):
 *     base = PyArray_BASE(arr)             # <<<<<<<<<<<<<<
 *     if base is NULL:
 *         return None
*/
  __pyx_v_base = PyArray_BASE(__pyx_v_arr);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1001
 * cdef inline object get_array_base(ndarray arr):
 *     base = PyArray_BASE(arr)
 *     if base is NULL:             # <<<<<<<<<<<<<<
 *         return None
 *     return <object>base
*/
  __pyx_t_1 = (__pyx_v_base == NULL);
  if (__pyx_t_1) {

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1002
 *     base = PyArray_BASE(arr)
 *     if base is NULL:
 *         return None             # <<<<<<<<<<<<<<
 *     return <object>base
 * 
*/
    __Pyx_XDECREF(__pyx_r);
    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
    goto __pyx_L0;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1001
 * cdef inline object get_array_base(ndarray arr):
 *     base = PyArray_BASE(arr)
 *     if base is NULL:             # <<<<<<<<<<<<<<
 *         return None
 *     return <object>base
*/
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1003
 *     if base is NULL:
 *         return None
 *     return <object>base             # <<<<<<<<<<<<<<
 * 
 * # Versions of the import_* functions which are more suitable for
*/
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_base));
  __pyx_r = ((PyObject *)__pyx_v_base);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":999
 *     PyArray_SetBaseObject(arr, base)
 * 
 * cdef inline object get_array_base(ndarray arr):             # <<<<<<<<<<<<<<
 *     base = PyArray_BASE(arr)
 *     if base is NULL:
*/

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

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1007
 * # Versions of the import_* functions which are more suitable for
 * # Cython code.
 * cdef inline int import_array() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         __pyx_import_array()
*/

static CYTHON_INLINE int __pyx_f_5numpy_import_array(void) {
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  size_t __pyx_t_10;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("import_array", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1008
 * # Cython code.
 * cdef inline int import_array() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         __pyx_import_array()
 *     except Exception:
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
    __Pyx_XGOTREF(__pyx_t_1);
    __Pyx_XGOTREF(__pyx_t_2);
    __Pyx_XGOTREF(__pyx_t_3);
    /*try:*/ {

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1009
 * cdef inline int import_array() except -1:
 *     try:
 *         __pyx_import_array()             # <<<<<<<<<<<<<<
 *     except Exception:
 *         raise ImportError("numpy._core.multiarray failed to import")
*/
      __pyx_t_4 = _import_array(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1009, __pyx_L3_error)

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1008
 * # Cython code.
 * cdef inline int import_array() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         __pyx_import_array()
 *     except Exception:
*/
    }
    __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;
    goto __pyx_L8_try_end;
    __pyx_L3_error:;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1010
 *     try:
 *         __pyx_import_array()
 *     except Exception:             # <<<<<<<<<<<<<<
 *         raise ImportError("numpy._core.multiarray failed to import")
 * 
*/
    __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception))));
    if (__pyx_t_4) {
      __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename);
      if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1010, __pyx_L5_except_error)
      __Pyx_XGOTREF(__pyx_t_5);
      __Pyx_XGOTREF(__pyx_t_6);
      __Pyx_XGOTREF(__pyx_t_7);

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1011
 *         __pyx_import_array()
 *     except Exception:
 *         raise ImportError("numpy._core.multiarray failed to import")             # <<<<<<<<<<<<<<
 * 
 * cdef inline int import_umath() except -1:
*/
      __pyx_t_9 = NULL;
      __pyx_t_10 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_multiarray_failed_to};
        __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1011, __pyx_L5_except_error)
        __Pyx_GOTREF(__pyx_t_8);
      }
      __Pyx_Raise(__pyx_t_8, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __PYX_ERR(1, 1011, __pyx_L5_except_error)
    }
    goto __pyx_L5_except_error;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1008
 * # Cython code.
 * cdef inline int import_array() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         __pyx_import_array()
 *     except Exception:
*/
    __pyx_L5_except_error:;
    __Pyx_XGIVEREF(__pyx_t_1);
    __Pyx_XGIVEREF(__pyx_t_2);
    __Pyx_XGIVEREF(__pyx_t_3);
    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
    goto __pyx_L1_error;
    __pyx_L8_try_end:;
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1007
 * # Versions of the import_* functions which are more suitable for
 * # Cython code.
 * cdef inline int import_array() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         __pyx_import_array()
*/

  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("numpy.import_array", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1013
 *         raise ImportError("numpy._core.multiarray failed to import")
 * 
 * cdef inline int import_umath() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         _import_umath()
*/

static CYTHON_INLINE int __pyx_f_5numpy_import_umath(void) {
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  size_t __pyx_t_10;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("import_umath", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1014
 * 
 * cdef inline int import_umath() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
    __Pyx_XGOTREF(__pyx_t_1);
    __Pyx_XGOTREF(__pyx_t_2);
    __Pyx_XGOTREF(__pyx_t_3);
    /*try:*/ {

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1015
 * cdef inline int import_umath() except -1:
 *     try:
 *         _import_umath()             # <<<<<<<<<<<<<<
 *     except Exception:
 *         raise ImportError("numpy._core.umath failed to import")
*/
      __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1015, __pyx_L3_error)

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1014
 * 
 * cdef inline int import_umath() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
    }
    __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;
    goto __pyx_L8_try_end;
    __pyx_L3_error:;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1016
 *     try:
 *         _import_umath()
 *     except Exception:             # <<<<<<<<<<<<<<
 *         raise ImportError("numpy._core.umath failed to import")
 * 
*/
    __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception))));
    if (__pyx_t_4) {
      __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename);
      if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1016, __pyx_L5_except_error)
      __Pyx_XGOTREF(__pyx_t_5);
      __Pyx_XGOTREF(__pyx_t_6);
      __Pyx_XGOTREF(__pyx_t_7);

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1017
 *         _import_umath()
 *     except Exception:
 *         raise ImportError("numpy._core.umath failed to import")             # <<<<<<<<<<<<<<
 * 
 * cdef inline int import_ufunc() except -1:
*/
      __pyx_t_9 = NULL;
      __pyx_t_10 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_umath_failed_to_impo};
        __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1017, __pyx_L5_except_error)
        __Pyx_GOTREF(__pyx_t_8);
      }
      __Pyx_Raise(__pyx_t_8, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __PYX_ERR(1, 1017, __pyx_L5_except_error)
    }
    goto __pyx_L5_except_error;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1014
 * 
 * cdef inline int import_umath() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
    __pyx_L5_except_error:;
    __Pyx_XGIVEREF(__pyx_t_1);
    __Pyx_XGIVEREF(__pyx_t_2);
    __Pyx_XGIVEREF(__pyx_t_3);
    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
    goto __pyx_L1_error;
    __pyx_L8_try_end:;
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1013
 *         raise ImportError("numpy._core.multiarray failed to import")
 * 
 * cdef inline int import_umath() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         _import_umath()
*/

  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("numpy.import_umath", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1019
 *         raise ImportError("numpy._core.umath failed to import")
 * 
 * cdef inline int import_ufunc() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         _import_umath()
*/

static CYTHON_INLINE int __pyx_f_5numpy_import_ufunc(void) {
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  size_t __pyx_t_10;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("import_ufunc", 0);

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1020
 * 
 * cdef inline int import_ufunc() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
    __Pyx_XGOTREF(__pyx_t_1);
    __Pyx_XGOTREF(__pyx_t_2);
    __Pyx_XGOTREF(__pyx_t_3);
    /*try:*/ {

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1021
 * cdef inline int import_ufunc() except -1:
 *     try:
 *         _import_umath()             # <<<<<<<<<<<<<<
 *     except Exception:
 *         raise ImportError("numpy._core.umath failed to import")
*/
      __pyx_t_4 = _import_umath(); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(1, 1021, __pyx_L3_error)

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1020
 * 
 * cdef inline int import_ufunc() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
    }
    __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;
    goto __pyx_L8_try_end;
    __pyx_L3_error:;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1022
 *     try:
 *         _import_umath()
 *     except Exception:             # <<<<<<<<<<<<<<
 *         raise ImportError("numpy._core.umath failed to import")
 * 
*/
    __pyx_t_4 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_Exception))));
    if (__pyx_t_4) {
      __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename);
      if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(1, 1022, __pyx_L5_except_error)
      __Pyx_XGOTREF(__pyx_t_5);
      __Pyx_XGOTREF(__pyx_t_6);
      __Pyx_XGOTREF(__pyx_t_7);

      /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1023
 *         _import_umath()
 *     except Exception:
 *         raise ImportError("numpy._core.umath failed to import")             # <<<<<<<<<<<<<<
 * 
 * 
*/
      __pyx_t_9 = NULL;
      __pyx_t_10 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_numpy__core_umath_failed_to_impo};
        __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ImportError)), __pyx_callargs+__pyx_t_10, (2-__pyx_t_10) | (__pyx_t_10*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 1023, __pyx_L5_except_error)
        __Pyx_GOTREF(__pyx_t_8);
      }
      __Pyx_Raise(__pyx_t_8, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __PYX_ERR(1, 1023, __pyx_L5_except_error)
    }
    goto __pyx_L5_except_error;

    /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1020
 * 
 * cdef inline int import_ufunc() except -1:
 *     try:             # <<<<<<<<<<<<<<
 *         _import_umath()
 *     except Exception:
*/
    __pyx_L5_except_error:;
    __Pyx_XGIVEREF(__pyx_t_1);
    __Pyx_XGIVEREF(__pyx_t_2);
    __Pyx_XGIVEREF(__pyx_t_3);
    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
    goto __pyx_L1_error;
    __pyx_L8_try_end:;
  }

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1019
 *         raise ImportError("numpy._core.umath failed to import")
 * 
 * cdef inline int import_ufunc() except -1:             # <<<<<<<<<<<<<<
 *     try:
 *         _import_umath()
*/

  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_AddTraceback("numpy.import_ufunc", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1026
 * 
 * 
 * cdef inline bint is_timedelta64_object(object obj) noexcept:             # <<<<<<<<<<<<<<
 *     """
 *     Cython equivalent of `isinstance(obj, np.timedelta64)`
*/

static CYTHON_INLINE int __pyx_f_5numpy_is_timedelta64_object(PyObject *__pyx_v_obj) {
  int __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1038
 *     bool
 *     """
 *     return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyTimedeltaArrType_Type));
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1026
 * 
 * 
 * cdef inline bint is_timedelta64_object(object obj) noexcept:             # <<<<<<<<<<<<<<
 *     """
 *     Cython equivalent of `isinstance(obj, np.timedelta64)`
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1041
 * 
 * 
 * cdef inline bint is_datetime64_object(object obj) noexcept:             # <<<<<<<<<<<<<<
 *     """
 *     Cython equivalent of `isinstance(obj, np.datetime64)`
*/

static CYTHON_INLINE int __pyx_f_5numpy_is_datetime64_object(PyObject *__pyx_v_obj) {
  int __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1053
 *     bool
 *     """
 *     return PyObject_TypeCheck(obj, &PyDatetimeArrType_Type)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = PyObject_TypeCheck(__pyx_v_obj, (&PyDatetimeArrType_Type));
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1041
 * 
 * 
 * cdef inline bint is_datetime64_object(object obj) noexcept:             # <<<<<<<<<<<<<<
 *     """
 *     Cython equivalent of `isinstance(obj, np.datetime64)`
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1056
 * 
 * 
 * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the int64 value underlying scalar numpy datetime64 object
*/

static CYTHON_INLINE npy_datetime __pyx_f_5numpy_get_datetime64_value(PyObject *__pyx_v_obj) {
  npy_datetime __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1063
 *     also needed.  That can be found using `get_datetime64_unit`.
 *     """
 *     return (<PyDatetimeScalarObject*>obj).obval             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = ((PyDatetimeScalarObject *)__pyx_v_obj)->obval;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1056
 * 
 * 
 * cdef inline npy_datetime get_datetime64_value(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the int64 value underlying scalar numpy datetime64 object
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1066
 * 
 * 
 * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the int64 value underlying scalar numpy timedelta64 object
*/

static CYTHON_INLINE npy_timedelta __pyx_f_5numpy_get_timedelta64_value(PyObject *__pyx_v_obj) {
  npy_timedelta __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1070
 *     returns the int64 value underlying scalar numpy timedelta64 object
 *     """
 *     return (<PyTimedeltaScalarObject*>obj).obval             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = ((PyTimedeltaScalarObject *)__pyx_v_obj)->obval;
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1066
 * 
 * 
 * cdef inline npy_timedelta get_timedelta64_value(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the int64 value underlying scalar numpy timedelta64 object
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1073
 * 
 * 
 * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the unit part of the dtype for a numpy datetime64 object.
*/

static CYTHON_INLINE NPY_DATETIMEUNIT __pyx_f_5numpy_get_datetime64_unit(PyObject *__pyx_v_obj) {
  NPY_DATETIMEUNIT __pyx_r;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1077
 *     returns the unit part of the dtype for a numpy datetime64 object.
 *     """
 *     return <NPY_DATETIMEUNIT>(<PyDatetimeScalarObject*>obj).obmeta.base             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = ((NPY_DATETIMEUNIT)((PyDatetimeScalarObject *)__pyx_v_obj)->obmeta.base);
  goto __pyx_L0;

  /* "../../../../../tmp/build-env-t6bxskvy/lib/python3.13/site-packages/numpy/__init__.cython-30.pxd":1073
 * 
 * 
 * cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) noexcept nogil:             # <<<<<<<<<<<<<<
 *     """
 *     returns the unit part of the dtype for a numpy datetime64 object.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":172
 * # functor for priority queue of pixels
 * cdef cppclass GreaterPixel nogil:
 *     bint get "operator()"(PixelType& lhs, PixelType& rhs):             # <<<<<<<<<<<<<<
 *         # lhs is > than rhs if its value is greater or if it's equal if
 *         # the priority is >.
*/

int __pyx_t_15pygeoprocessing_7routing_7routing_GreaterPixel::operator()(struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType &__pyx_v_lhs, struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType &__pyx_v_rhs) {
  int __pyx_r;
  int __pyx_t_1;

  /* "pygeoprocessing/routing/routing.pyx":175
 *         # lhs is > than rhs if its value is greater or if it's equal if
 *         # the priority is >.
 *         if lhs.value > rhs.value:             # <<<<<<<<<<<<<<
 *             return 1
 *         if lhs.value == rhs.value:
*/
  __pyx_t_1 = (__pyx_v_lhs.value > __pyx_v_rhs.value);
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":176
 *         # the priority is >.
 *         if lhs.value > rhs.value:
 *             return 1             # <<<<<<<<<<<<<<
 *         if lhs.value == rhs.value:
 *             if lhs.priority > rhs.priority:
*/
    __pyx_r = 1;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":175
 *         # lhs is > than rhs if its value is greater or if it's equal if
 *         # the priority is >.
 *         if lhs.value > rhs.value:             # <<<<<<<<<<<<<<
 *             return 1
 *         if lhs.value == rhs.value:
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":177
 *         if lhs.value > rhs.value:
 *             return 1
 *         if lhs.value == rhs.value:             # <<<<<<<<<<<<<<
 *             if lhs.priority > rhs.priority:
 *                 return 1
*/
  __pyx_t_1 = (__pyx_v_lhs.value == __pyx_v_rhs.value);
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":178
 *             return 1
 *         if lhs.value == rhs.value:
 *             if lhs.priority > rhs.priority:             # <<<<<<<<<<<<<<
 *                 return 1
 *         return 0
*/
    __pyx_t_1 = (__pyx_v_lhs.priority > __pyx_v_rhs.priority);
    if (__pyx_t_1) {

      /* "pygeoprocessing/routing/routing.pyx":179
 *         if lhs.value == rhs.value:
 *             if lhs.priority > rhs.priority:
 *                 return 1             # <<<<<<<<<<<<<<
 *         return 0
 * 
*/
      __pyx_r = 1;
      goto __pyx_L0;

      /* "pygeoprocessing/routing/routing.pyx":178
 *             return 1
 *         if lhs.value == rhs.value:
 *             if lhs.priority > rhs.priority:             # <<<<<<<<<<<<<<
 *                 return 1
 *         return 0
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":177
 *         if lhs.value > rhs.value:
 *             return 1
 *         if lhs.value == rhs.value:             # <<<<<<<<<<<<<<
 *             if lhs.priority > rhs.priority:
 *                 return 1
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":180
 *             if lhs.priority > rhs.priority:
 *                 return 1
 *         return 0             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_r = 0;
  goto __pyx_L0;

  /* "pygeoprocessing/routing/routing.pyx":172
 * # functor for priority queue of pixels
 * cdef cppclass GreaterPixel nogil:
 *     bint get "operator()"(PixelType& lhs, PixelType& rhs):             # <<<<<<<<<<<<<<
 *         # lhs is > than rhs if its value is greater or if it's equal if
 *         # the priority is >.
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":183
 * 
 * 
 * def _generate_read_bounds(offset_dict, raster_x_size, raster_y_size):             # <<<<<<<<<<<<<<
 *     """Helper function to expand GDAL memory block read bound by 1 pixel.
 * 
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_1_generate_read_bounds(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing__generate_read_bounds, "Helper function to expand GDAL memory block read bound by 1 pixel.\n\n    This function is used in the context of reading a memory block on a GDAL\n    raster plus an additional 1 pixel boundary if it fits into an existing\n    numpy array of size (2+offset_dict['y_size'], 2+offset_dict['x_size']).\n\n    Parameters:\n        offset_dict (dict): dictionary that has values for 'win_xsize',\n            'win_ysize', 'xoff', and 'yoff' to describe the bounding box\n            to read from the raster.\n        raster_x_size, raster_y_size (int): these are the global x/y sizes\n            of the raster that's being read.\n\n    Returns:\n        (xa, xb, ya, yb) (tuple of int): bounds that can be used to slice a\n            numpy array of size\n                (2+offset_dict['y_size'], 2+offset_dict['x_size'])\n        modified_offset_dict (dict): a copy of `offset_dict` with the\n            `win_*size` keys expanded if the modified bounding box will still\n            fit on the array.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_1_generate_read_bounds = {"_generate_read_bounds", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_1_generate_read_bounds, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing__generate_read_bounds};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_1_generate_read_bounds(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_offset_dict = 0;
  PyObject *__pyx_v_raster_x_size = 0;
  PyObject *__pyx_v_raster_y_size = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[3] = {0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_generate_read_bounds (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_offset_dict,&__pyx_mstate_global->__pyx_n_u_raster_x_size,&__pyx_mstate_global->__pyx_n_u_raster_y_size,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 183, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 183, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 183, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 183, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "_generate_read_bounds", 0) < (0)) __PYX_ERR(0, 183, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("_generate_read_bounds", 1, 3, 3, i); __PYX_ERR(0, 183, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 3)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 183, __pyx_L3_error)
      values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 183, __pyx_L3_error)
      values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 183, __pyx_L3_error)
    }
    __pyx_v_offset_dict = values[0];
    __pyx_v_raster_x_size = values[1];
    __pyx_v_raster_y_size = values[2];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("_generate_read_bounds", 1, 3, 3, __pyx_nargs); __PYX_ERR(0, 183, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._generate_read_bounds", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing__generate_read_bounds(__pyx_self, __pyx_v_offset_dict, __pyx_v_raster_x_size, __pyx_v_raster_y_size);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing__generate_read_bounds(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_offset_dict, PyObject *__pyx_v_raster_x_size, PyObject *__pyx_v_raster_y_size) {
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_target_offset_dict = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  size_t __pyx_t_3;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_generate_read_bounds", 0);

  /* "pygeoprocessing/routing/routing.pyx":205
 *             fit on the array.
 *     """
 *     xa = 1             # <<<<<<<<<<<<<<
 *     xb = -1
 *     ya = 1
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_1);
  __pyx_v_xa = __pyx_mstate_global->__pyx_int_1;

  /* "pygeoprocessing/routing/routing.pyx":206
 *     """
 *     xa = 1
 *     xb = -1             # <<<<<<<<<<<<<<
 *     ya = 1
 *     yb = -1
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1);
  __pyx_v_xb = __pyx_mstate_global->__pyx_int_neg_1;

  /* "pygeoprocessing/routing/routing.pyx":207
 *     xa = 1
 *     xb = -1
 *     ya = 1             # <<<<<<<<<<<<<<
 *     yb = -1
 *     target_offset_dict = offset_dict.copy()
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_1);
  __pyx_v_ya = __pyx_mstate_global->__pyx_int_1;

  /* "pygeoprocessing/routing/routing.pyx":208
 *     xb = -1
 *     ya = 1
 *     yb = -1             # <<<<<<<<<<<<<<
 *     target_offset_dict = offset_dict.copy()
 *     if offset_dict['xoff'] > 0:
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1);
  __pyx_v_yb = __pyx_mstate_global->__pyx_int_neg_1;

  /* "pygeoprocessing/routing/routing.pyx":209
 *     ya = 1
 *     yb = -1
 *     target_offset_dict = offset_dict.copy()             # <<<<<<<<<<<<<<
 *     if offset_dict['xoff'] > 0:
 *         xa = None
*/
  __pyx_t_2 = __pyx_v_offset_dict;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_copy, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 209, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_target_offset_dict = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":210
 *     yb = -1
 *     target_offset_dict = offset_dict.copy()
 *     if offset_dict['xoff'] > 0:             # <<<<<<<<<<<<<<
 *         xa = None
 *         target_offset_dict['xoff'] -= 1
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 210, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_mstate_global->__pyx_int_0, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 210, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 210, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":211
 *     target_offset_dict = offset_dict.copy()
 *     if offset_dict['xoff'] > 0:
 *         xa = None             # <<<<<<<<<<<<<<
 *         target_offset_dict['xoff'] -= 1
 *         target_offset_dict['win_xsize'] += 1
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_xa, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":212
 *     if offset_dict['xoff'] > 0:
 *         xa = None
 *         target_offset_dict['xoff'] -= 1             # <<<<<<<<<<<<<<
 *         target_offset_dict['win_xsize'] += 1
 *     if offset_dict['yoff'] > 0:
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_xoff);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_xoff;
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyLong_SubtractObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_1) < 0))) __PYX_ERR(0, 212, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":213
 *         xa = None
 *         target_offset_dict['xoff'] -= 1
 *         target_offset_dict['win_xsize'] += 1             # <<<<<<<<<<<<<<
 *     if offset_dict['yoff'] > 0:
 *         ya = None
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_win_xsize);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_win_xsize;
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_2) < 0))) __PYX_ERR(0, 213, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":210
 *     yb = -1
 *     target_offset_dict = offset_dict.copy()
 *     if offset_dict['xoff'] > 0:             # <<<<<<<<<<<<<<
 *         xa = None
 *         target_offset_dict['xoff'] -= 1
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":214
 *         target_offset_dict['xoff'] -= 1
 *         target_offset_dict['win_xsize'] += 1
 *     if offset_dict['yoff'] > 0:             # <<<<<<<<<<<<<<
 *         ya = None
 *         target_offset_dict['yoff'] -= 1
*/
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 214, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_mstate_global->__pyx_int_0, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 214, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 214, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":215
 *         target_offset_dict['win_xsize'] += 1
 *     if offset_dict['yoff'] > 0:
 *         ya = None             # <<<<<<<<<<<<<<
 *         target_offset_dict['yoff'] -= 1
 *         target_offset_dict['win_ysize'] += 1
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_ya, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":216
 *     if offset_dict['yoff'] > 0:
 *         ya = None
 *         target_offset_dict['yoff'] -= 1             # <<<<<<<<<<<<<<
 *         target_offset_dict['win_ysize'] += 1
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_yoff);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_yoff;
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 216, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyLong_SubtractObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 216, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_2) < 0))) __PYX_ERR(0, 216, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":217
 *         ya = None
 *         target_offset_dict['yoff'] -= 1
 *         target_offset_dict['win_ysize'] += 1             # <<<<<<<<<<<<<<
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):
 *         xb = None
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_win_ysize);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_win_ysize;
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 217, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyLong_AddObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 217, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_1) < 0))) __PYX_ERR(0, 217, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":214
 *         target_offset_dict['xoff'] -= 1
 *         target_offset_dict['win_xsize'] += 1
 *     if offset_dict['yoff'] > 0:             # <<<<<<<<<<<<<<
 *         ya = None
 *         target_offset_dict['yoff'] -= 1
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":218
 *         target_offset_dict['yoff'] -= 1
 *         target_offset_dict['win_ysize'] += 1
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):             # <<<<<<<<<<<<<<
 *         xb = None
 *         target_offset_dict['win_xsize'] += 1
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_6 = PyNumber_Add(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_6, __pyx_v_raster_x_size, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 218, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":219
 *         target_offset_dict['win_ysize'] += 1
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):
 *         xb = None             # <<<<<<<<<<<<<<
 *         target_offset_dict['win_xsize'] += 1
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_xb, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":220
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):
 *         xb = None
 *         target_offset_dict['win_xsize'] += 1             # <<<<<<<<<<<<<<
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):
 *         yb = None
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_win_xsize);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_win_xsize;
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 220, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_6 = __Pyx_PyLong_AddObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 220, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_6) < 0))) __PYX_ERR(0, 220, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":218
 *         target_offset_dict['yoff'] -= 1
 *         target_offset_dict['win_ysize'] += 1
 *     if (offset_dict['xoff'] + offset_dict['win_xsize'] < raster_x_size):             # <<<<<<<<<<<<<<
 *         xb = None
 *         target_offset_dict['win_xsize'] += 1
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":221
 *         xb = None
 *         target_offset_dict['win_xsize'] += 1
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):             # <<<<<<<<<<<<<<
 *         yb = None
 *         target_offset_dict['win_ysize'] += 1
*/
  __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 221, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 221, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = PyNumber_Add(__pyx_t_6, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 221, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_v_raster_y_size, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 221, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 221, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":222
 *         target_offset_dict['win_xsize'] += 1
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):
 *         yb = None             # <<<<<<<<<<<<<<
 *         target_offset_dict['win_ysize'] += 1
 *     return (xa, xb, ya, yb), target_offset_dict
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_yb, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":223
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):
 *         yb = None
 *         target_offset_dict['win_ysize'] += 1             # <<<<<<<<<<<<<<
 *     return (xa, xb, ya, yb), target_offset_dict
 * 
*/
    __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_win_ysize);
    __pyx_t_5 = __pyx_mstate_global->__pyx_n_u_win_ysize;
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_target_offset_dict, __pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyLong_AddObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(__pyx_v_target_offset_dict, __pyx_t_5, __pyx_t_1) < 0))) __PYX_ERR(0, 223, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":221
 *         xb = None
 *         target_offset_dict['win_xsize'] += 1
 *     if (offset_dict['yoff'] + offset_dict['win_ysize'] < raster_y_size):             # <<<<<<<<<<<<<<
 *         yb = None
 *         target_offset_dict['win_ysize'] += 1
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":224
 *         yb = None
 *         target_offset_dict['win_ysize'] += 1
 *     return (xa, xb, ya, yb), target_offset_dict             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyTuple_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_v_xa);
  __Pyx_GIVEREF(__pyx_v_xa);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_xa) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_xb);
  __Pyx_GIVEREF(__pyx_v_xb);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_xb) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_ya);
  __Pyx_GIVEREF(__pyx_v_ya);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_ya) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_yb);
  __Pyx_GIVEREF(__pyx_v_yb);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_yb) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 224, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_target_offset_dict);
  __Pyx_GIVEREF(__pyx_v_target_offset_dict);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_target_offset_dict) != (0)) __PYX_ERR(0, 224, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* "pygeoprocessing/routing/routing.pyx":183
 * 
 * 
 * def _generate_read_bounds(offset_dict, raster_x_size, raster_y_size):             # <<<<<<<<<<<<<<
 *     """Helper function to expand GDAL memory block read bound by 1 pixel.
 * 
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._generate_read_bounds", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_target_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_32__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":231
 *         dem_raster_path_band, target_filled_dem_raster_path,
 *         working_dir=None,
 *         long long max_pixel_fill_count=-1,             # <<<<<<<<<<<<<<
 *         single_outlet_tuple=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
*/
  __pyx_t_1 = __Pyx_PyLong_From_PY_LONG_LONG(((PY_LONG_LONG)-1LL)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 231, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/
  __pyx_t_2 = PyTuple_New(4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, Py_None) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 2, Py_None) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 3, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, Py_None) != (0)) __PYX_ERR(0, 227, __pyx_L1_error);
  __pyx_t_2 = 0;
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_3fill_pits(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_2fill_pits, "Fill the pits in a DEM.\n\n    This function defines pits as hydrologically connected regions that do\n    not drain to the edge of the raster or a nodata pixel. After the call\n    pits are filled to the height of the lowest pour point.\n\n    Parameters:\n        dem_raster_path_band (tuple): a path, band number tuple indicating the\n            DEM calculate flow direction. Paths may use any GDAL-supported\n            scheme, including virtual file system /vsi schemes.\n        target_filled_dem_raster_path (str): path the pit filled dem,\n            that's created by a call to this function. It is functionally a\n            single band copy of ``dem_raster_path_band`` with the pit pixels\n            raised to the pour point. For runtime efficiency, this raster is\n            tiled and its blocksize is set to (``1<<BLOCK_BITS``,\n            ``1<<BLOCK_BITS``)\n            even if ``dem_raster_path_band[0]`` was not tiled or a different\n            block size.\n        working_dir (str): If not None, indicates where temporary files\n            should be created during this run. If this directory doesn't exist\n            it is created by this call. If None, a temporary directory is\n            created by tempdir.mkdtemp which is removed after the function\n            call completes successfully.\n        max_pixel_fill_count (int): maximum number of pixels to fill a pit\n            before leaving as a depression. Useful if there are natural\n            large depressions. Value of -1 fills the raster with no search\n            limit.\n        single_outlet_tuple (tuple): If not None, this is an x/y tuple in\n            raster coordinates indicating the only pixel that can be\n            considered a drain. If None then any pixel that would drain to\n            the edge of the raster or a nodata hole will be considered a\n            drain.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as th""e first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_3fill_pits = {"fill_pits", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_3fill_pits, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_2fill_pits};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_3fill_pits(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_dem_raster_path_band = 0;
  PyObject *__pyx_v_target_filled_dem_raster_path = 0;
  PyObject *__pyx_v_working_dir = 0;
  PY_LONG_LONG __pyx_v_max_pixel_fill_count;
  PyObject *__pyx_v_single_outlet_tuple = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[6] = {0,0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("fill_pits (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_dem_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_filled_dem_raster_path,&__pyx_mstate_global->__pyx_n_u_working_dir,&__pyx_mstate_global->__pyx_n_u_max_pixel_fill_count,&__pyx_mstate_global->__pyx_n_u_single_outlet_tuple,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 227, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "fill_pits", 0) < (0)) __PYX_ERR(0, 227, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":230
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
 *         working_dir=None,             # <<<<<<<<<<<<<<
 *         long long max_pixel_fill_count=-1,
 *         single_outlet_tuple=None,
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));

      /* "pygeoprocessing/routing/routing.pyx":232
 *         working_dir=None,
 *         long long max_pixel_fill_count=-1,
 *         single_outlet_tuple=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Fill the pits in a DEM.
*/
      if (!values[4]) values[4] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("fill_pits", 0, 2, 6, i); __PYX_ERR(0, 227, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 227, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 227, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 227, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }

      /* "pygeoprocessing/routing/routing.pyx":230
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
 *         working_dir=None,             # <<<<<<<<<<<<<<
 *         long long max_pixel_fill_count=-1,
 *         single_outlet_tuple=None,
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));

      /* "pygeoprocessing/routing/routing.pyx":232
 *         working_dir=None,
 *         long long max_pixel_fill_count=-1,
 *         single_outlet_tuple=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Fill the pits in a DEM.
*/
      if (!values[4]) values[4] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_dem_raster_path_band = values[0];
    __pyx_v_target_filled_dem_raster_path = values[1];
    __pyx_v_working_dir = values[2];
    if (values[3]) {
      __pyx_v_max_pixel_fill_count = __Pyx_PyLong_As_PY_LONG_LONG(values[3]); if (unlikely((__pyx_v_max_pixel_fill_count == (PY_LONG_LONG)-1) && PyErr_Occurred())) __PYX_ERR(0, 231, __pyx_L3_error)
    } else {
      __pyx_v_max_pixel_fill_count = ((PY_LONG_LONG)((PY_LONG_LONG)-1LL));
    }
    __pyx_v_single_outlet_tuple = values[4];
    __pyx_v_raster_driver_creation_tuple = values[5];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("fill_pits", 0, 2, 6, __pyx_nargs); __PYX_ERR(0, 227, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.fill_pits", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_2fill_pits(__pyx_self, __pyx_v_dem_raster_path_band, __pyx_v_target_filled_dem_raster_path, __pyx_v_working_dir, __pyx_v_max_pixel_fill_count, __pyx_v_single_outlet_tuple, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_2fill_pits(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_filled_dem_raster_path, PyObject *__pyx_v_working_dir, PY_LONG_LONG __pyx_v_max_pixel_fill_count, PyObject *__pyx_v_single_outlet_tuple, PyObject *__pyx_v_raster_driver_creation_tuple) {
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_q;
  unsigned int __pyx_v_yi_q;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  int __pyx_v_downhill_neighbor;
  int __pyx_v_nodata_neighbor;
  int __pyx_v_natural_drain_exists;
  PY_LONG_LONG __pyx_v_search_steps;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_v_search_queue;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_v_fill_queue;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType __pyx_v_pixel;
  __pyx_t_15pygeoprocessing_7routing_7routing_PitPriorityQueueType __pyx_v_pit_queue;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  unsigned int __pyx_v_n_x_blocks;
  double __pyx_v_center_val;
  double __pyx_v_dem_nodata;
  double __pyx_v_fill_height;
  int __pyx_v_feature_id;
  unsigned long __pyx_v_current_pixel;
  int __pyx_v_single_outlet;
  int __pyx_v_outlet_x;
  int __pyx_v_outlet_y;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_dem_raster_info = NULL;
  PyObject *__pyx_v_base_nodata = NULL;
  long __pyx_v_mask_nodata;
  PyObject *__pyx_v_working_dir_path = NULL;
  PyObject *__pyx_v_flat_region_mask_path = NULL;
  ManagedRaster __pyx_v_flat_region_mask_managed_raster;
  PyObject *__pyx_v_pit_mask_path = NULL;
  ManagedRaster __pyx_v_pit_mask_managed_raster;
  PyObject *__pyx_v_base_datatype = NULL;
  PyObject *__pyx_v_filled_dem_raster = NULL;
  PyObject *__pyx_v_filled_dem_band = NULL;
  PyObject *__pyx_v_offset_info = NULL;
  PyObject *__pyx_v_block_array = NULL;
  ManagedRaster __pyx_v_filled_dem_managed_raster;
  PyObject *__pyx_v_offset_dict = NULL;
  double __pyx_v_n_height;
  long __pyx_v_pour_point;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  PyObject *(*__pyx_t_5)(PyObject *);
  int __pyx_t_6;
  int __pyx_t_7;
  PyObject *__pyx_t_8 = NULL;
  size_t __pyx_t_9;
  double __pyx_t_10;
  unsigned int __pyx_t_11;
  unsigned int __pyx_t_12;
  PyObject *__pyx_t_13 = NULL;
  PyObject *__pyx_t_14 = NULL;
  PyObject *__pyx_t_15 = NULL;
  PyObject *__pyx_t_16 = NULL;
  PyObject *__pyx_t_17 = NULL;
  PyObject *__pyx_t_18 = NULL;
  PyObject *__pyx_t_19 = NULL;
  PyObject *__pyx_t_20 = NULL;
  PyObject *__pyx_t_21 = NULL;
  char *__pyx_t_22;
  ManagedRaster __pyx_t_23;
  Py_ssize_t __pyx_t_24;
  PyObject *(*__pyx_t_25)(PyObject *);
  PyObject *__pyx_t_26[5];
  unsigned int __pyx_t_27;
  unsigned int __pyx_t_28;
  unsigned int __pyx_t_29;
  unsigned int __pyx_t_30;
  int __pyx_t_31;
  unsigned int __pyx_t_32;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_t_33;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType __pyx_t_34;
  __pyx_t_15pygeoprocessing_7routing_7routing_PitPriorityQueueType __pyx_t_35;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("fill_pits", 0);

  /* "pygeoprocessing/routing/routing.pyx":327
 * 
 *     # used to handle the case for single outlet mode
 *     cdef int single_outlet=0, outlet_x=-1, outlet_y=-1             # <<<<<<<<<<<<<<
 *     if single_outlet_tuple is not None:
 *         single_outlet = 1
*/
  __pyx_v_single_outlet = 0;
  __pyx_v_outlet_x = -1;
  __pyx_v_outlet_y = -1;

  /* "pygeoprocessing/routing/routing.pyx":328
 *     # used to handle the case for single outlet mode
 *     cdef int single_outlet=0, outlet_x=-1, outlet_y=-1
 *     if single_outlet_tuple is not None:             # <<<<<<<<<<<<<<
 *         single_outlet = 1
 *         outlet_x, outlet_y = single_outlet_tuple
*/
  __pyx_t_1 = (__pyx_v_single_outlet_tuple != Py_None);
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":329
 *     cdef int single_outlet=0, outlet_x=-1, outlet_y=-1
 *     if single_outlet_tuple is not None:
 *         single_outlet = 1             # <<<<<<<<<<<<<<
 *         outlet_x, outlet_y = single_outlet_tuple
 * 
*/
    __pyx_v_single_outlet = 1;

    /* "pygeoprocessing/routing/routing.pyx":330
 *     if single_outlet_tuple is not None:
 *         single_outlet = 1
 *         outlet_x, outlet_y = single_outlet_tuple             # <<<<<<<<<<<<<<
 * 
 *     # used for time-delayed logging
*/
    if ((likely(PyTuple_CheckExact(__pyx_v_single_outlet_tuple))) || (PyList_CheckExact(__pyx_v_single_outlet_tuple))) {
      PyObject* sequence = __pyx_v_single_outlet_tuple;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 330, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_3);
      } else {
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 330, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 330, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
      }
      #else
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 330, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 330, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      #endif
    } else {
      Py_ssize_t index = -1;
      __pyx_t_4 = PyObject_GetIter(__pyx_v_single_outlet_tuple); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 330, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_5 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_4);
      index = 0; __pyx_t_2 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L4_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      index = 1; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L4_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_3);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < (0)) __PYX_ERR(0, 330, __pyx_L1_error)
      __pyx_t_5 = NULL;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      goto __pyx_L5_unpacking_done;
      __pyx_L4_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __pyx_t_5 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 330, __pyx_L1_error)
      __pyx_L5_unpacking_done:;
    }
    __pyx_t_6 = __Pyx_PyLong_As_int(__pyx_t_2); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 330, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_7 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 330, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_outlet_x = __pyx_t_6;
    __pyx_v_outlet_y = __pyx_t_7;

    /* "pygeoprocessing/routing/routing.pyx":328
 *     # used to handle the case for single outlet mode
 *     cdef int single_outlet=0, outlet_x=-1, outlet_y=-1
 *     if single_outlet_tuple is not None:             # <<<<<<<<<<<<<<
 *         single_outlet = 1
 *         outlet_x, outlet_y = single_outlet_tuple
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":334
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     # determine dem nodata in the working type, or set an improbable value
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":338
 *     # determine dem nodata in the working type, or set an improbable value
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 338, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_8);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_v_dem_raster_info = __pyx_t_3;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":339
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
*/
  __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 339, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 339, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyLong_SubtractObjC(__pyx_t_8, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 339, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_8 = __Pyx_PyObject_GetItem(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 339, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_base_nodata = __pyx_t_8;
  __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":340
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
  __pyx_t_1 = (__pyx_v_base_nodata != Py_None);
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":342
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)             # <<<<<<<<<<<<<<
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
*/
    __pyx_t_4 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 342, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 342, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_9 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_4);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_9 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_base_nodata};
      __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 342, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
    }
    __pyx_t_10 = __Pyx_PyFloat_AsDouble(__pyx_t_8); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 342, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_v_dem_nodata = __pyx_t_10;

    /* "pygeoprocessing/routing/routing.pyx":340
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
    goto __pyx_L6;
  }

  /* "pygeoprocessing/routing/routing.pyx":345
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     # these are used to determine if a sample is within the raster
*/
  /*else*/ {
    __pyx_v_dem_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
  }
  __pyx_L6:;

  /* "pygeoprocessing/routing/routing.pyx":348
 * 
 *     # these are used to determine if a sample is within the raster
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     # this is the nodata value for all the flat region and pit masks
*/
  __pyx_t_8 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 348, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) {
    PyObject* sequence = __pyx_t_8;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 348, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_4);
    } else {
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 348, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 348, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
    }
    #else
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 348, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 348, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    #endif
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_3 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 348, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_5 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3);
    index = 0; __pyx_t_2 = __pyx_t_5(__pyx_t_3); if (unlikely(!__pyx_t_2)) goto __pyx_L7_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_4 = __pyx_t_5(__pyx_t_3); if (unlikely(!__pyx_t_4)) goto __pyx_L7_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_3), 2) < (0)) __PYX_ERR(0, 348, __pyx_L1_error)
    __pyx_t_5 = NULL;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    goto __pyx_L8_unpacking_done;
    __pyx_L7_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_5 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 348, __pyx_L1_error)
    __pyx_L8_unpacking_done:;
  }
  __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 348, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_4); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 348, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_raster_x_size = __pyx_t_11;
  __pyx_v_raster_y_size = __pyx_t_12;

  /* "pygeoprocessing/routing/routing.pyx":351
 * 
 *     # this is the nodata value for all the flat region and pit masks
 *     mask_nodata = 0             # <<<<<<<<<<<<<<
 * 
 *     # set up the working dir for the mask rasters
*/
  __pyx_v_mask_nodata = 0;

  /* "pygeoprocessing/routing/routing.pyx":354
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
    __Pyx_XGOTREF(__pyx_t_13);
    __Pyx_XGOTREF(__pyx_t_14);
    __Pyx_XGOTREF(__pyx_t_15);
    /*try:*/ {

      /* "pygeoprocessing/routing/routing.pyx":355
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      __pyx_t_1 = (__pyx_v_working_dir != Py_None);
      if (__pyx_t_1) {

        /* "pygeoprocessing/routing/routing.pyx":356
 *     try:
 *         if working_dir is not None:
 *             os.makedirs(working_dir)             # <<<<<<<<<<<<<<
 *     except OSError:
 *         pass
*/
        __pyx_t_4 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 356, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_makedirs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 356, __pyx_L9_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_9 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
          assert(__pyx_t_4);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
          __Pyx_INCREF(__pyx_t_4);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
          __pyx_t_9 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_working_dir};
          __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 356, __pyx_L9_error)
          __Pyx_GOTREF(__pyx_t_8);
        }
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

        /* "pygeoprocessing/routing/routing.pyx":355
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":354
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    }
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    goto __pyx_L14_try_end;
    __pyx_L9_error:;
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;

    /* "pygeoprocessing/routing/routing.pyx":357
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
 *     except OSError:             # <<<<<<<<<<<<<<
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
*/
    __pyx_t_7 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_OSError))));
    if (__pyx_t_7) {
      __Pyx_ErrRestore(0,0,0);
      goto __pyx_L10_exception_handled;
    }
    goto __pyx_L11_except_error;

    /* "pygeoprocessing/routing/routing.pyx":354
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    __pyx_L11_except_error:;
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_XGIVEREF(__pyx_t_14);
    __Pyx_XGIVEREF(__pyx_t_15);
    __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
    goto __pyx_L1_error;
    __pyx_L10_exception_handled:;
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_XGIVEREF(__pyx_t_14);
    __Pyx_XGIVEREF(__pyx_t_15);
    __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
    __pyx_L14_try_end:;
  }

  /* "pygeoprocessing/routing/routing.pyx":359
 *     except OSError:
 *         pass
 *     working_dir_path = tempfile.mkdtemp(             # <<<<<<<<<<<<<<
 *         dir=working_dir, prefix='fill_pits_%s_' % time.strftime(
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":360
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='fill_pits_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_16 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 360, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_strftime); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 360, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":361
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='fill_pits_%s_' % time.strftime(
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))             # <<<<<<<<<<<<<<
 * 
 *     # this raster is used to keep track of what pixels have been searched for
*/
  __pyx_t_19 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_20, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 361, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __pyx_t_21 = __Pyx_PyObject_GetAttrStr(__pyx_t_20, __pyx_mstate_global->__pyx_n_u_gmtime); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 361, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_21);
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_21))) {
    __pyx_t_19 = PyMethod_GET_SELF(__pyx_t_21);
    assert(__pyx_t_19);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_21);
    __Pyx_INCREF(__pyx_t_19);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_21, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_19, NULL};
    __pyx_t_17 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_21, __pyx_callargs+__pyx_t_9, (1-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_19); __pyx_t_19 = 0;
    __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
    if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 361, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
  }
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_18))) {
    __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_18);
    assert(__pyx_t_16);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_18);
    __Pyx_INCREF(__pyx_t_16);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_18, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_16, __pyx_mstate_global->__pyx_kp_u_Y_m_d__H__M__S, __pyx_t_17};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_18, __pyx_callargs+__pyx_t_9, (3-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 360, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }

  /* "pygeoprocessing/routing/routing.pyx":360
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='fill_pits_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_18 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_fill_pits__s, __pyx_t_4); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 360, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_3, NULL};
    __pyx_t_4 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 359, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_v_working_dir, __pyx_t_4, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 359, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_t_18, __pyx_t_4, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 359, __pyx_L1_error)
    __pyx_t_8 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_9, (1-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_4);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 359, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
  }
  __pyx_v_working_dir_path = __pyx_t_8;
  __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":366
 *     # a plateau or pit. if a pixel is set, it means it is part of a locally
 *     # undrained area
 *     flat_region_mask_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'flat_region_mask.tif')
 *     n_x_blocks = raster_x_size >> BLOCK_BITS + 1
*/
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 366, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 366, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_2 = __pyx_t_18;
  __Pyx_INCREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":367
 *     # undrained area
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')             # <<<<<<<<<<<<<<
 *     n_x_blocks = raster_x_size >> BLOCK_BITS + 1
 * 
*/
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_flat_region_mask_tif};
    __pyx_t_8 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_9, (3-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
    if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 366, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
  }
  __pyx_v_flat_region_mask_path = __pyx_t_8;
  __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":368
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')
 *     n_x_blocks = raster_x_size >> BLOCK_BITS + 1             # <<<<<<<<<<<<<<
 * 
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_8 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 368, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GetModuleGlobalName(__pyx_t_18, __pyx_mstate_global->__pyx_n_u_BLOCK_BITS); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 368, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_t_18, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 368, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_t_18 = PyNumber_Rshift(__pyx_t_8, __pyx_t_2); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 368, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_18); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 368, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_v_n_x_blocks = __pyx_t_12;

  /* "pygeoprocessing/routing/routing.pyx":370
 *     n_x_blocks = raster_x_size >> BLOCK_BITS + 1
 * 
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 370, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 370, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":371
 * 
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,             # <<<<<<<<<<<<<<
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 371, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 371, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 371, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":372
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
*/
  __pyx_t_3 = __Pyx_PyLong_From_long(__pyx_v_mask_nodata); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 372, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_16 = PyList_New(1); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 372, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_GIVEREF(__pyx_t_3);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_16, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 372, __pyx_L1_error);
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":373
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)
*/
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_2, __pyx_t_8, __pyx_v_flat_region_mask_path, __pyx_t_17, __pyx_t_16};
    __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 370, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_3, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 370, __pyx_L1_error)
    __pyx_t_18 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_9, (5-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 370, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":375
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # this raster will have the value of 'feature_id' set to it if it has
*/
  __pyx_t_4 = __pyx_v_flat_region_mask_path;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_18 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 375, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __pyx_t_22 = __Pyx_PyObject_AsWritableString(__pyx_t_18); if (unlikely((!__pyx_t_22) && PyErr_Occurred())) __PYX_ERR(0, 375, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":374
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flat_region_mask_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_23 = ManagedRaster(__pyx_t_22, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 374, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_v_flat_region_mask_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_23);

  /* "pygeoprocessing/routing/routing.pyx":380
 *     # been searched as part of the search for a pour point for pit number
 *     # `feature_id`
 *     pit_mask_path = os.path.join(working_dir_path, 'pit_mask.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], pit_mask_path, gdal.GDT_Int32,
*/
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 380, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 380, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_4 = __pyx_t_16;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_pit_mask_tif};
    __pyx_t_18 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_9, (3-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 380, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __pyx_v_pit_mask_path = __pyx_t_18;
  __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":381
 *     # `feature_id`
 *     pit_mask_path = os.path.join(working_dir_path, 'pit_mask.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], pit_mask_path, gdal.GDT_Int32,
 *         [mask_nodata],
*/
  __pyx_t_16 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 381, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 381, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":382
 *     pit_mask_path = os.path.join(working_dir_path, 'pit_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], pit_mask_path, gdal.GDT_Int32,             # <<<<<<<<<<<<<<
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 382, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 382, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_GDT_Int32); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 382, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":383
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], pit_mask_path, gdal.GDT_Int32,
 *         [mask_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     pit_mask_managed_raster = ManagedRaster(
*/
  __pyx_t_17 = __Pyx_PyLong_From_long(__pyx_v_mask_nodata); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 383, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 383, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_17);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_17) != (0)) __PYX_ERR(0, 383, __pyx_L1_error);
  __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":384
 *         dem_raster_path_band[0], pit_mask_path, gdal.GDT_Int32,
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     pit_mask_managed_raster = ManagedRaster(
 *         pit_mask_path.encode('utf-8'), 1, True)
*/
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_16);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_16);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_16, __pyx_t_4, __pyx_v_pit_mask_path, __pyx_t_8, __pyx_t_2};
    __pyx_t_17 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 381, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_17, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 381, __pyx_L1_error)
    __pyx_t_18 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_9, (5-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_17);
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 381, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":386
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     pit_mask_managed_raster = ManagedRaster(
 *         pit_mask_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # copy the base DEM to the target and set up for writing
*/
  __pyx_t_3 = __pyx_v_pit_mask_path;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_18 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 386, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __pyx_t_22 = __Pyx_PyObject_AsWritableString(__pyx_t_18); if (unlikely((!__pyx_t_22) && PyErr_Occurred())) __PYX_ERR(0, 386, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":385
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     pit_mask_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         pit_mask_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_23 = ManagedRaster(__pyx_t_22, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 385, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_v_pit_mask_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_23);

  /* "pygeoprocessing/routing/routing.pyx":389
 * 
 *     # copy the base DEM to the target and set up for writing
 *     base_datatype = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0])['datatype']
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 389, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 389, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":390
 *     # copy the base DEM to the target and set up for writing
 *     base_datatype = pygeoprocessing.get_raster_info(
 *         dem_raster_path_band[0])['datatype']             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_filled_dem_raster_path,
*/
  __pyx_t_17 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 390, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_17};
    __pyx_t_18 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 389, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_t_18, __pyx_mstate_global->__pyx_n_u_datatype); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 390, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_v_base_datatype = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":391
 *     base_datatype = pygeoprocessing.get_raster_info(
 *         dem_raster_path_band[0])['datatype']
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], target_filled_dem_raster_path,
 *         base_datatype, [dem_nodata],
*/
  __pyx_t_18 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 391, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 391, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":392
 *         dem_raster_path_band[0])['datatype']
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_filled_dem_raster_path,             # <<<<<<<<<<<<<<
 *         base_datatype, [dem_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_17 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 392, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);

  /* "pygeoprocessing/routing/routing.pyx":393
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_filled_dem_raster_path,
 *         base_datatype, [dem_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     filled_dem_raster = gdal.OpenEx(
*/
  __pyx_t_8 = PyFloat_FromDouble(__pyx_v_dem_nodata); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 393, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 393, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_8);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_4, 0, __pyx_t_8) != (0)) __PYX_ERR(0, 393, __pyx_L1_error);
  __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":394
 *         dem_raster_path_band[0], target_filled_dem_raster_path,
 *         base_datatype, [dem_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     filled_dem_raster = gdal.OpenEx(
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
*/
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_18 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_18);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_18);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_18, __pyx_t_17, __pyx_v_target_filled_dem_raster_path, __pyx_v_base_datatype, __pyx_t_4};
    __pyx_t_8 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 391, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_8, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 391, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_9, (5-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_8);
    __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 391, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":395
 *         base_datatype, [dem_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     filled_dem_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 395, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 395, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":396
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     filled_dem_raster = gdal.OpenEx(
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)             # <<<<<<<<<<<<<<
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
 *     for offset_info, block_array in pygeoprocessing.iterblocks(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_GA_Update); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_8 = PyNumber_Or(__pyx_t_17, __pyx_t_18); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 396, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_v_target_filled_dem_raster_path, __pyx_t_8};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_9, (3-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 395, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_filled_dem_raster = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":397
 *     filled_dem_raster = gdal.OpenEx(
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)             # <<<<<<<<<<<<<<
 *     for offset_info, block_array in pygeoprocessing.iterblocks(
 *                 dem_raster_path_band):
*/
  __pyx_t_4 = __pyx_v_filled_dem_raster;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_int_1};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 397, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_filled_dem_band = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":398
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
 *     for offset_info, block_array in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *                 dem_raster_path_band):
 *         filled_dem_band.WriteArray(
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 398, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 398, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":399
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
 *     for offset_info, block_array in pygeoprocessing.iterblocks(
 *                 dem_raster_path_band):             # <<<<<<<<<<<<<<
 *         filled_dem_band.WriteArray(
 *             block_array, xoff=offset_info['xoff'], yoff=offset_info['yoff'])
*/
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_dem_raster_path_band};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 398, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }

  /* "pygeoprocessing/routing/routing.pyx":398
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
 *     for offset_info, block_array in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *                 dem_raster_path_band):
 *         filled_dem_band.WriteArray(
*/
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_3 = __pyx_t_2; __Pyx_INCREF(__pyx_t_3);
    __pyx_t_24 = 0;
    __pyx_t_25 = NULL;
  } else {
    __pyx_t_24 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 398, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_25 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 398, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_25)) {
      if (likely(PyList_CheckExact(__pyx_t_3))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 398, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_24, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_24;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_3);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 398, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_24));
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_3, __pyx_t_24);
        #endif
        ++__pyx_t_24;
      }
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 398, __pyx_L1_error)
    } else {
      __pyx_t_2 = __pyx_t_25(__pyx_t_3);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 398, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_2);
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 398, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_4);
        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_8);
      } else {
        __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 398, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_4);
        __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 398, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_8);
      }
      #else
      __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 398, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_8 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 398, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_18 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 398, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_18);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_5 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_18);
      index = 0; __pyx_t_4 = __pyx_t_5(__pyx_t_18); if (unlikely(!__pyx_t_4)) goto __pyx_L20_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_4);
      index = 1; __pyx_t_8 = __pyx_t_5(__pyx_t_18); if (unlikely(!__pyx_t_8)) goto __pyx_L20_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_8);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_18), 2) < (0)) __PYX_ERR(0, 398, __pyx_L1_error)
      __pyx_t_5 = NULL;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      goto __pyx_L21_unpacking_done;
      __pyx_L20_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      __pyx_t_5 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 398, __pyx_L1_error)
      __pyx_L21_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_offset_info, __pyx_t_4);
    __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_block_array, __pyx_t_8);
    __pyx_t_8 = 0;

    /* "pygeoprocessing/routing/routing.pyx":400
 *     for offset_info, block_array in pygeoprocessing.iterblocks(
 *                 dem_raster_path_band):
 *         filled_dem_band.WriteArray(             # <<<<<<<<<<<<<<
 *             block_array, xoff=offset_info['xoff'], yoff=offset_info['yoff'])
 *     filled_dem_band.FlushCache()
*/
    __pyx_t_8 = __pyx_v_filled_dem_band;
    __Pyx_INCREF(__pyx_t_8);

    /* "pygeoprocessing/routing/routing.pyx":401
 *                 dem_raster_path_band):
 *         filled_dem_band.WriteArray(
 *             block_array, xoff=offset_info['xoff'], yoff=offset_info['yoff'])             # <<<<<<<<<<<<<<
 *     filled_dem_band.FlushCache()
 *     filled_dem_raster.FlushCache()
*/
    __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_info, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 401, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_18 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_info, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 401, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
    __pyx_t_9 = 0;
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_8, __pyx_v_block_array};
      __pyx_t_17 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 400, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_xoff, __pyx_t_4, __pyx_t_17, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 400, __pyx_L1_error)
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_yoff, __pyx_t_18, __pyx_t_17, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 400, __pyx_L1_error)
      __pyx_t_2 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_WriteArray, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_17);
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 400, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":398
 *         target_filled_dem_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     filled_dem_band = filled_dem_raster.GetRasterBand(1)
 *     for offset_info, block_array in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *                 dem_raster_path_band):
 *         filled_dem_band.WriteArray(
*/
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":402
 *         filled_dem_band.WriteArray(
 *             block_array, xoff=offset_info['xoff'], yoff=offset_info['yoff'])
 *     filled_dem_band.FlushCache()             # <<<<<<<<<<<<<<
 *     filled_dem_raster.FlushCache()
 *     filled_dem_band = None
*/
  __pyx_t_2 = __pyx_v_filled_dem_band;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_FlushCache, __pyx_callargs+__pyx_t_9, (1-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 402, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":403
 *             block_array, xoff=offset_info['xoff'], yoff=offset_info['yoff'])
 *     filled_dem_band.FlushCache()
 *     filled_dem_raster.FlushCache()             # <<<<<<<<<<<<<<
 *     filled_dem_band = None
 *     filled_dem_raster = None
*/
  __pyx_t_2 = __pyx_v_filled_dem_raster;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_FlushCache, __pyx_callargs+__pyx_t_9, (1-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 403, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":404
 *     filled_dem_band.FlushCache()
 *     filled_dem_raster.FlushCache()
 *     filled_dem_band = None             # <<<<<<<<<<<<<<
 *     filled_dem_raster = None
 *     filled_dem_managed_raster = ManagedRaster(
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_filled_dem_band, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":405
 *     filled_dem_raster.FlushCache()
 *     filled_dem_band = None
 *     filled_dem_raster = None             # <<<<<<<<<<<<<<
 *     filled_dem_managed_raster = ManagedRaster(
 *         target_filled_dem_raster_path.encode('utf-8'), 1, True)
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_filled_dem_raster, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":407
 *     filled_dem_raster = None
 *     filled_dem_managed_raster = ManagedRaster(
 *         target_filled_dem_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # feature_id will start at 1 since the mask nodata is 0.
*/
  __pyx_t_2 = __pyx_v_target_filled_dem_raster_path;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 407, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_22 = __Pyx_PyObject_AsWritableString(__pyx_t_3); if (unlikely((!__pyx_t_22) && PyErr_Occurred())) __PYX_ERR(0, 407, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":406
 *     filled_dem_band = None
 *     filled_dem_raster = None
 *     filled_dem_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_filled_dem_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_23 = ManagedRaster(__pyx_t_22, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 406, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_filled_dem_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_23);

  /* "pygeoprocessing/routing/routing.pyx":410
 * 
 *     # feature_id will start at 1 since the mask nodata is 0.
 *     feature_id = 0             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for a pixel that is locally undrained
*/
  __pyx_v_feature_id = 0;

  /* "pygeoprocessing/routing/routing.pyx":413
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 413, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_18 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 413, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_18);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

  /* "pygeoprocessing/routing/routing.pyx":414
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             dem_raster_path_band, offset_only=True, largest_block=0):             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_18))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_18);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_18);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_18, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_2, __pyx_v_dem_raster_path_band};
    __pyx_t_17 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 413, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_17, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 413, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_17, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 413, __pyx_L1_error)
    __pyx_t_3 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_18, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_17);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 413, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }

  /* "pygeoprocessing/routing/routing.pyx":413
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
    __pyx_t_18 = __pyx_t_3; __Pyx_INCREF(__pyx_t_18);
    __pyx_t_24 = 0;
    __pyx_t_25 = NULL;
  } else {
    __pyx_t_24 = -1; __pyx_t_18 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 413, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
    __pyx_t_25 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_18); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 413, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  for (;;) {
    if (likely(!__pyx_t_25)) {
      if (likely(PyList_CheckExact(__pyx_t_18))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_18);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 413, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(__pyx_t_18, __pyx_t_24, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_24;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_18);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 413, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_3 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_18, __pyx_t_24));
        #else
        __pyx_t_3 = __Pyx_PySequence_ITEM(__pyx_t_18, __pyx_t_24);
        #endif
        ++__pyx_t_24;
      }
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 413, __pyx_L1_error)
    } else {
      __pyx_t_3 = __pyx_t_25(__pyx_t_18);
      if (unlikely(!__pyx_t_3)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 413, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_3);
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":415
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 415, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 415, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_xsize = __pyx_t_12;

    /* "pygeoprocessing/routing/routing.pyx":416
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 416, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 416, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_ysize = __pyx_t_12;

    /* "pygeoprocessing/routing/routing.pyx":417
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 417, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 417, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_xoff = __pyx_t_12;

    /* "pygeoprocessing/routing/routing.pyx":418
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 418, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_12 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_12 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 418, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_yoff = __pyx_t_12;

    /* "pygeoprocessing/routing/routing.pyx":420
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_1 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_1) {

      /* "pygeoprocessing/routing/routing.pyx":421
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":422
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(fill pits): '
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":423
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(fill pits): '
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '
*/
      __pyx_t_17 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 423, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 423, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":425
 *             LOGGER.info(
 *                 '(fill pits): '
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '             # <<<<<<<<<<<<<<
 *                 'pixels complete')
 * 
*/
      __pyx_t_2 = __Pyx_PyUnicode_From_unsigned_long(__pyx_v_current_pixel, 0, ' ', 'd'); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 425, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_8 = __Pyx_PyUnicode_From_unsigned_int((__pyx_v_raster_x_size * __pyx_v_raster_y_size), 0, ' ', 'd'); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 425, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_26[0] = __pyx_mstate_global->__pyx_kp_u_fill_pits;
      __pyx_t_26[1] = __pyx_t_2;
      __pyx_t_26[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_26[3] = __pyx_t_8;
      __pyx_t_26[4] = __pyx_mstate_global->__pyx_kp_u_pixels_complete;

      /* "pygeoprocessing/routing/routing.pyx":424
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
 *                 '(fill pits): '             # <<<<<<<<<<<<<<
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '
 *                 'pixels complete')
*/
      __pyx_t_16 = __Pyx_PyUnicode_Join(__pyx_t_26, 5, 13 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_8) + 16, 127);
      if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 424, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_9 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_4))) {
        __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_4);
        assert(__pyx_t_17);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
        __Pyx_INCREF(__pyx_t_17);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
        __pyx_t_9 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_17, __pyx_t_16};
        __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
        __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 423, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":420
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":429
 * 
 *         # search block for locally undrained pixels
 *         for yi in range(win_ysize):             # <<<<<<<<<<<<<<
 *             yi_root = yi+yoff
 *             for xi in range(win_xsize):
*/
    __pyx_t_12 = __pyx_v_win_ysize;
    __pyx_t_11 = __pyx_t_12;
    for (__pyx_t_27 = 0; __pyx_t_27 < __pyx_t_11; __pyx_t_27+=1) {
      __pyx_v_yi = __pyx_t_27;

      /* "pygeoprocessing/routing/routing.pyx":430
 *         # search block for locally undrained pixels
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff             # <<<<<<<<<<<<<<
 *             for xi in range(win_xsize):
 *                 xi_root = xi+xoff
*/
      __pyx_v_yi_root = (__pyx_v_yi + __pyx_v_yoff);

      /* "pygeoprocessing/routing/routing.pyx":431
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff
 *             for xi in range(win_xsize):             # <<<<<<<<<<<<<<
 *                 xi_root = xi+xoff
 *                 # this value is set in case it turns out to be the root of a
*/
      __pyx_t_28 = __pyx_v_win_xsize;
      __pyx_t_29 = __pyx_t_28;
      for (__pyx_t_30 = 0; __pyx_t_30 < __pyx_t_29; __pyx_t_30+=1) {
        __pyx_v_xi = __pyx_t_30;

        /* "pygeoprocessing/routing/routing.pyx":432
 *             yi_root = yi+yoff
 *             for xi in range(win_xsize):
 *                 xi_root = xi+xoff             # <<<<<<<<<<<<<<
 *                 # this value is set in case it turns out to be the root of a
 *                 # pit, we'll start the fill from this pixel in the last phase
*/
        __pyx_v_xi_root = (__pyx_v_xi + __pyx_v_xoff);

        /* "pygeoprocessing/routing/routing.pyx":436
 *                 # pit, we'll start the fill from this pixel in the last phase
 *                 # of the algorithm
 *                 center_val = filled_dem_managed_raster.get(xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                 if is_close(center_val, dem_nodata):
 *                     continue
*/
        __pyx_v_center_val = __pyx_v_filled_dem_managed_raster.get(__pyx_v_xi_root, __pyx_v_yi_root);

        /* "pygeoprocessing/routing/routing.pyx":437
 *                 # of the algorithm
 *                 center_val = filled_dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_1 = is_close(__pyx_v_center_val, __pyx_v_dem_nodata);
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":438
 *                 center_val = filled_dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 if flat_region_mask_managed_raster.get(
*/
          goto __pyx_L28_continue;

          /* "pygeoprocessing/routing/routing.pyx":437
 *                 # of the algorithm
 *                 center_val = filled_dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":441
 * 
 *                 if flat_region_mask_managed_raster.get(
 *                         xi_root, yi_root) != mask_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_1 = (__pyx_v_flat_region_mask_managed_raster.get(__pyx_v_xi_root, __pyx_v_yi_root) != __pyx_v_mask_nodata);

        /* "pygeoprocessing/routing/routing.pyx":440
 *                     continue
 * 
 *                 if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != mask_nodata:
 *                     continue
*/
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":442
 *                 if flat_region_mask_managed_raster.get(
 *                         xi_root, yi_root) != mask_nodata:
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # a single outlet trivially drains
*/
          goto __pyx_L28_continue;

          /* "pygeoprocessing/routing/routing.pyx":440
 *                     continue
 * 
 *                 if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != mask_nodata:
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":445
 * 
 *                 # a single outlet trivially drains
 *                 if (single_outlet and             # <<<<<<<<<<<<<<
 *                         xi_root == outlet_x and
 *                         yi_root == outlet_y):
*/
        __pyx_t_31 = (__pyx_v_single_outlet != 0);
        if (__pyx_t_31) {
        } else {
          __pyx_t_1 = __pyx_t_31;
          goto __pyx_L33_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":446
 *                 # a single outlet trivially drains
 *                 if (single_outlet and
 *                         xi_root == outlet_x and             # <<<<<<<<<<<<<<
 *                         yi_root == outlet_y):
 *                     continue
*/
        __pyx_t_31 = (__pyx_v_xi_root == __pyx_v_outlet_x);
        if (__pyx_t_31) {
        } else {
          __pyx_t_1 = __pyx_t_31;
          goto __pyx_L33_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":447
 *                 if (single_outlet and
 *                         xi_root == outlet_x and
 *                         yi_root == outlet_y):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_31 = (__pyx_v_yi_root == __pyx_v_outlet_y);
        __pyx_t_1 = __pyx_t_31;
        __pyx_L33_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":445
 * 
 *                 # a single outlet trivially drains
 *                 if (single_outlet and             # <<<<<<<<<<<<<<
 *                         xi_root == outlet_x and
 *                         yi_root == outlet_y):
*/
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":448
 *                         xi_root == outlet_x and
 *                         yi_root == outlet_y):
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # search neighbors for downhill or nodata
*/
          goto __pyx_L28_continue;

          /* "pygeoprocessing/routing/routing.pyx":445
 * 
 *                 # a single outlet trivially drains
 *                 if (single_outlet and             # <<<<<<<<<<<<<<
 *                         xi_root == outlet_x and
 *                         yi_root == outlet_y):
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":451
 * 
 *                 # search neighbors for downhill or nodata
 *                 downhill_neighbor = 0             # <<<<<<<<<<<<<<
 *                 nodata_neighbor = 0
 *                 for i_n in range(8):
*/
        __pyx_v_downhill_neighbor = 0;

        /* "pygeoprocessing/routing/routing.pyx":452
 *                 # search neighbors for downhill or nodata
 *                 downhill_neighbor = 0
 *                 nodata_neighbor = 0             # <<<<<<<<<<<<<<
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
*/
        __pyx_v_nodata_neighbor = 0;

        /* "pygeoprocessing/routing/routing.pyx":453
 *                 downhill_neighbor = 0
 *                 nodata_neighbor = 0
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
*/
        for (__pyx_t_32 = 0; __pyx_t_32 < 8; __pyx_t_32+=1) {
          __pyx_v_i_n = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":454
 *                 nodata_neighbor = 0
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
*/
          __pyx_v_xi_n = (__pyx_v_xi_root + (COL_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":455
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
*/
          __pyx_v_yi_n = (__pyx_v_yi_root + (ROW_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":457
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         if not single_outlet:
*/
          __pyx_t_31 = (__pyx_v_xi_n < 0);
          if (!__pyx_t_31) {
          } else {
            __pyx_t_1 = __pyx_t_31;
            goto __pyx_L39_bool_binop_done;
          }
          __pyx_t_31 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
          if (!__pyx_t_31) {
          } else {
            __pyx_t_1 = __pyx_t_31;
            goto __pyx_L39_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":458
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                         if not single_outlet:
 *                             # it'll drain off the edge of the raster
*/
          __pyx_t_31 = (__pyx_v_yi_n < 0);
          if (!__pyx_t_31) {
          } else {
            __pyx_t_1 = __pyx_t_31;
            goto __pyx_L39_bool_binop_done;
          }
          __pyx_t_31 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
          __pyx_t_1 = __pyx_t_31;
          __pyx_L39_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":457
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         if not single_outlet:
*/
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":459
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         if not single_outlet:             # <<<<<<<<<<<<<<
 *                             # it'll drain off the edge of the raster
 *                             nodata_neighbor = 1
*/
            __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":461
 *                         if not single_outlet:
 *                             # it'll drain off the edge of the raster
 *                             nodata_neighbor = 1             # <<<<<<<<<<<<<<
 *                             break
 *                         else:
*/
              __pyx_v_nodata_neighbor = 1;

              /* "pygeoprocessing/routing/routing.pyx":462
 *                             # it'll drain off the edge of the raster
 *                             nodata_neighbor = 1
 *                             break             # <<<<<<<<<<<<<<
 *                         else:
 *                             # continue so we don't access out of bounds
*/
              goto __pyx_L37_break;

              /* "pygeoprocessing/routing/routing.pyx":459
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         if not single_outlet:             # <<<<<<<<<<<<<<
 *                             # it'll drain off the edge of the raster
 *                             nodata_neighbor = 1
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":465
 *                         else:
 *                             # continue so we don't access out of bounds
 *                             continue             # <<<<<<<<<<<<<<
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):
*/
            /*else*/ {
              goto __pyx_L36_continue;
            }

            /* "pygeoprocessing/routing/routing.pyx":457
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         if not single_outlet:
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":466
 *                             # continue so we don't access out of bounds
 *                             continue
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                     if is_close(n_height, dem_nodata):
 *                         if not single_outlet:
*/
          __pyx_v_n_height = __pyx_v_filled_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

          /* "pygeoprocessing/routing/routing.pyx":467
 *                             continue
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         if not single_outlet:
 *                             # it'll drain to nodata
*/
          __pyx_t_1 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":468
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):
 *                         if not single_outlet:             # <<<<<<<<<<<<<<
 *                             # it'll drain to nodata
 *                             nodata_neighbor = 1
*/
            __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":470
 *                         if not single_outlet:
 *                             # it'll drain to nodata
 *                             nodata_neighbor = 1             # <<<<<<<<<<<<<<
 *                             break
 *                         else:
*/
              __pyx_v_nodata_neighbor = 1;

              /* "pygeoprocessing/routing/routing.pyx":471
 *                             # it'll drain to nodata
 *                             nodata_neighbor = 1
 *                             break             # <<<<<<<<<<<<<<
 *                         else:
 *                             # skip the rest so it doesn't drain downhill
*/
              goto __pyx_L37_break;

              /* "pygeoprocessing/routing/routing.pyx":468
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):
 *                         if not single_outlet:             # <<<<<<<<<<<<<<
 *                             # it'll drain to nodata
 *                             nodata_neighbor = 1
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":474
 *                         else:
 *                             # skip the rest so it doesn't drain downhill
 *                             continue             # <<<<<<<<<<<<<<
 *                     if n_height < center_val:
 *                         # it'll drain downhill
*/
            /*else*/ {
              goto __pyx_L36_continue;
            }

            /* "pygeoprocessing/routing/routing.pyx":467
 *                             continue
 *                     n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         if not single_outlet:
 *                             # it'll drain to nodata
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":475
 *                             # skip the rest so it doesn't drain downhill
 *                             continue
 *                     if n_height < center_val:             # <<<<<<<<<<<<<<
 *                         # it'll drain downhill
 *                         downhill_neighbor = 1
*/
          __pyx_t_1 = (__pyx_v_n_height < __pyx_v_center_val);
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":477
 *                     if n_height < center_val:
 *                         # it'll drain downhill
 *                         downhill_neighbor = 1             # <<<<<<<<<<<<<<
 *                         break
 * 
*/
            __pyx_v_downhill_neighbor = 1;

            /* "pygeoprocessing/routing/routing.pyx":478
 *                         # it'll drain downhill
 *                         downhill_neighbor = 1
 *                         break             # <<<<<<<<<<<<<<
 * 
 *                 if downhill_neighbor or nodata_neighbor:
*/
            goto __pyx_L37_break;

            /* "pygeoprocessing/routing/routing.pyx":475
 *                             # skip the rest so it doesn't drain downhill
 *                             continue
 *                     if n_height < center_val:             # <<<<<<<<<<<<<<
 *                         # it'll drain downhill
 *                         downhill_neighbor = 1
*/
          }
          __pyx_L36_continue:;
        }
        __pyx_L37_break:;

        /* "pygeoprocessing/routing/routing.pyx":480
 *                         break
 * 
 *                 if downhill_neighbor or nodata_neighbor:             # <<<<<<<<<<<<<<
 *                     # it drains, so skip
 *                     continue
*/
        __pyx_t_31 = (__pyx_v_downhill_neighbor != 0);
        if (!__pyx_t_31) {
        } else {
          __pyx_t_1 = __pyx_t_31;
          goto __pyx_L48_bool_binop_done;
        }
        __pyx_t_31 = (__pyx_v_nodata_neighbor != 0);
        __pyx_t_1 = __pyx_t_31;
        __pyx_L48_bool_binop_done:;
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":482
 *                 if downhill_neighbor or nodata_neighbor:
 *                     # it drains, so skip
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # otherwise, this pixel doesn't drain locally, search to see
*/
          goto __pyx_L28_continue;

          /* "pygeoprocessing/routing/routing.pyx":480
 *                         break
 * 
 *                 if downhill_neighbor or nodata_neighbor:             # <<<<<<<<<<<<<<
 *                     # it drains, so skip
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":486
 *                 # otherwise, this pixel doesn't drain locally, search to see
 *                 # if it's a pit or plateau
 *                 search_queue.push(CoordinateType(xi_root, yi_root))             # <<<<<<<<<<<<<<
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)
 *                 natural_drain_exists = 0
*/
        __pyx_t_33.xi = __pyx_v_xi_root;
        __pyx_t_33.yi = __pyx_v_yi_root;
        __pyx_v_search_queue.push(__pyx_t_33);

        /* "pygeoprocessing/routing/routing.pyx":487
 *                 # if it's a pit or plateau
 *                 search_queue.push(CoordinateType(xi_root, yi_root))
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 *                 natural_drain_exists = 0
 * 
*/
        __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

        /* "pygeoprocessing/routing/routing.pyx":488
 *                 search_queue.push(CoordinateType(xi_root, yi_root))
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)
 *                 natural_drain_exists = 0             # <<<<<<<<<<<<<<
 * 
 *                 # this loop does a BFS starting at this pixel to all pixels
*/
        __pyx_v_natural_drain_exists = 0;

        /* "pygeoprocessing/routing/routing.pyx":496
 *                 # it can be entirely marked as processed and not re-accessed
 *                 # on later iterations
 *                 search_steps = 0             # <<<<<<<<<<<<<<
 *                 while not search_queue.empty():
 *                     xi_q = search_queue.front().xi
*/
        __pyx_v_search_steps = 0;

        /* "pygeoprocessing/routing/routing.pyx":497
 *                 # on later iterations
 *                 search_steps = 0
 *                 while not search_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi
*/
        while (1) {
          __pyx_t_1 = (!__pyx_v_search_queue.empty());
          if (!__pyx_t_1) break;

          /* "pygeoprocessing/routing/routing.pyx":498
 *                 search_steps = 0
 *                 while not search_queue.empty():
 *                     xi_q = search_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()
*/
          __pyx_t_32 = __pyx_v_search_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":499
 *                 while not search_queue.empty():
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi             # <<<<<<<<<<<<<<
 *                     search_queue.pop()
 *                     if (max_pixel_fill_count > 0 and
*/
          __pyx_t_32 = __pyx_v_search_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":500
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()             # <<<<<<<<<<<<<<
 *                     if (max_pixel_fill_count > 0 and
 *                             search_steps > max_pixel_fill_count):
*/
          __pyx_v_search_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":501
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear the search queue and quit
*/
          __pyx_t_31 = (__pyx_v_max_pixel_fill_count > 0);
          if (__pyx_t_31) {
          } else {
            __pyx_t_1 = __pyx_t_31;
            goto __pyx_L53_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":502
 *                     search_queue.pop()
 *                     if (max_pixel_fill_count > 0 and
 *                             search_steps > max_pixel_fill_count):             # <<<<<<<<<<<<<<
 *                         # clear the search queue and quit
 *                         LOGGER.debug(
*/
          __pyx_t_31 = (__pyx_v_search_steps > __pyx_v_max_pixel_fill_count);
          __pyx_t_1 = __pyx_t_31;
          __pyx_L53_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":501
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear the search queue and quit
*/
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":504
 *                             search_steps > max_pixel_fill_count):
 *                         # clear the search queue and quit
 *                         LOGGER.debug(             # <<<<<<<<<<<<<<
 *                             'exceeded max pixel fill count when searching '
 *                             'for plateau drain')
*/
            __pyx_t_4 = NULL;
            __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 504, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_16);
            __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 504, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_17);
            __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
            __pyx_t_9 = 1;
            #if CYTHON_UNPACK_METHODS
            if (unlikely(PyMethod_Check(__pyx_t_17))) {
              __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_17);
              assert(__pyx_t_4);
              PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_17);
              __Pyx_INCREF(__pyx_t_4);
              __Pyx_INCREF(__pyx__function);
              __Pyx_DECREF_SET(__pyx_t_17, __pyx__function);
              __pyx_t_9 = 0;
            }
            #endif
            {
              PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_exceeded_max_pixel_fill_count_wh};
              __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_17, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
              __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
              __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
              if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 504, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_3);
            }
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

            /* "pygeoprocessing/routing/routing.pyx":507
 *                             'exceeded max pixel fill count when searching '
 *                             'for plateau drain')
 *                         while not search_queue.empty():             # <<<<<<<<<<<<<<
 *                             search_queue.pop()
 *                         natural_drain_exists = 1
*/
            while (1) {
              __pyx_t_1 = (!__pyx_v_search_queue.empty());
              if (!__pyx_t_1) break;

              /* "pygeoprocessing/routing/routing.pyx":508
 *                             'for plateau drain')
 *                         while not search_queue.empty():
 *                             search_queue.pop()             # <<<<<<<<<<<<<<
 *                         natural_drain_exists = 1
 *                         break
*/
              __pyx_v_search_queue.pop();
            }

            /* "pygeoprocessing/routing/routing.pyx":509
 *                         while not search_queue.empty():
 *                             search_queue.pop()
 *                         natural_drain_exists = 1             # <<<<<<<<<<<<<<
 *                         break
 *                     search_steps += 1
*/
            __pyx_v_natural_drain_exists = 1;

            /* "pygeoprocessing/routing/routing.pyx":510
 *                             search_queue.pop()
 *                         natural_drain_exists = 1
 *                         break             # <<<<<<<<<<<<<<
 *                     search_steps += 1
 * 
*/
            goto __pyx_L51_break;

            /* "pygeoprocessing/routing/routing.pyx":501
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear the search queue and quit
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":511
 *                         natural_drain_exists = 1
 *                         break
 *                     search_steps += 1             # <<<<<<<<<<<<<<
 * 
 *                     for i_n in range(8):
*/
          __pyx_v_search_steps = (__pyx_v_search_steps + 1);

          /* "pygeoprocessing/routing/routing.pyx":513
 *                     search_steps += 1
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_32 = 0; __pyx_t_32 < 8; __pyx_t_32+=1) {
            __pyx_v_i_n = __pyx_t_32;

            /* "pygeoprocessing/routing/routing.pyx":514
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":515
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":517
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:
*/
            __pyx_t_31 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L60_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L60_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":518
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1
*/
            __pyx_t_31 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L60_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_1 = __pyx_t_31;
            __pyx_L60_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":517
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":519
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 natural_drain_exists = 1
 *                             continue
*/
              __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
              if (__pyx_t_1) {

                /* "pygeoprocessing/routing/routing.pyx":520
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
                __pyx_v_natural_drain_exists = 1;

                /* "pygeoprocessing/routing/routing.pyx":519
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 natural_drain_exists = 1
 *                             continue
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":521
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         n_height = filled_dem_managed_raster.get(
*/
              goto __pyx_L57_continue;

              /* "pygeoprocessing/routing/routing.pyx":517
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             if not single_outlet:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":523
 *                             continue
 * 
 *                         n_height = filled_dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                             xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
*/
            __pyx_v_n_height = __pyx_v_filled_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":525
 *                         n_height = filled_dem_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1
*/
            __pyx_t_1 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":526
 *                             xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 natural_drain_exists = 1
 *                             continue
*/
              __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
              if (__pyx_t_1) {

                /* "pygeoprocessing/routing/routing.pyx":527
 *                         if is_close(n_height, dem_nodata):
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_height < center_val:
*/
                __pyx_v_natural_drain_exists = 1;

                /* "pygeoprocessing/routing/routing.pyx":526
 *                             xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 natural_drain_exists = 1
 *                             continue
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":528
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_height < center_val:
 *                             natural_drain_exists = 1
*/
              goto __pyx_L57_continue;

              /* "pygeoprocessing/routing/routing.pyx":525
 *                         n_height = filled_dem_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             if not single_outlet:
 *                                 natural_drain_exists = 1
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":529
 *                                 natural_drain_exists = 1
 *                             continue
 *                         if n_height < center_val:             # <<<<<<<<<<<<<<
 *                             natural_drain_exists = 1
 *                             continue
*/
            __pyx_t_1 = (__pyx_v_n_height < __pyx_v_center_val);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":530
 *                             continue
 *                         if n_height < center_val:
 *                             natural_drain_exists = 1             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
              __pyx_v_natural_drain_exists = 1;

              /* "pygeoprocessing/routing/routing.pyx":531
 *                         if n_height < center_val:
 *                             natural_drain_exists = 1
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         if flat_region_mask_managed_raster.get(
*/
              goto __pyx_L57_continue;

              /* "pygeoprocessing/routing/routing.pyx":529
 *                                 natural_drain_exists = 1
 *                             continue
 *                         if n_height < center_val:             # <<<<<<<<<<<<<<
 *                             natural_drain_exists = 1
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":534
 * 
 *                         if flat_region_mask_managed_raster.get(
 *                                 xi_n, yi_n) == 1:             # <<<<<<<<<<<<<<
 *                             # been set before on a previous iteration, skip
 *                             continue
*/
            __pyx_t_1 = (__pyx_v_flat_region_mask_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == 1.0);

            /* "pygeoprocessing/routing/routing.pyx":533
 *                             continue
 * 
 *                         if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == 1:
 *                             # been set before on a previous iteration, skip
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":536
 *                                 xi_n, yi_n) == 1:
 *                             # been set before on a previous iteration, skip
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_height == center_val:
 *                             # only grow if it's at the same level and not
*/
              goto __pyx_L57_continue;

              /* "pygeoprocessing/routing/routing.pyx":533
 *                             continue
 * 
 *                         if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == 1:
 *                             # been set before on a previous iteration, skip
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":537
 *                             # been set before on a previous iteration, skip
 *                             continue
 *                         if n_height == center_val:             # <<<<<<<<<<<<<<
 *                             # only grow if it's at the same level and not
 *                             # previously visited
*/
            __pyx_t_1 = (__pyx_v_n_height == __pyx_v_center_val);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":541
 *                             # previously visited
 *                             search_queue.push(
 *                                 CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                             flat_region_mask_managed_raster.set(
 *                                 xi_n, yi_n, 1)
*/
              __pyx_t_33.xi = __pyx_v_xi_n;
              __pyx_t_33.yi = __pyx_v_yi_n;

              /* "pygeoprocessing/routing/routing.pyx":540
 *                             # only grow if it's at the same level and not
 *                             # previously visited
 *                             search_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_n, yi_n))
 *                             flat_region_mask_managed_raster.set(
*/
              __pyx_v_search_queue.push(__pyx_t_33);

              /* "pygeoprocessing/routing/routing.pyx":542
 *                             search_queue.push(
 *                                 CoordinateType(xi_n, yi_n))
 *                             flat_region_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, 1)
 * 
*/
              __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

              /* "pygeoprocessing/routing/routing.pyx":537
 *                             # been set before on a previous iteration, skip
 *                             continue
 *                         if n_height == center_val:             # <<<<<<<<<<<<<<
 *                             # only grow if it's at the same level and not
 *                             # previously visited
*/
            }
            __pyx_L57_continue:;
          }
        }
        __pyx_L51_break:;

        /* "pygeoprocessing/routing/routing.pyx":545
 *                                 xi_n, yi_n, 1)
 * 
 *                 if not natural_drain_exists:             # <<<<<<<<<<<<<<
 *                     # this space does not naturally drain, so fill it
 *                     pixel = PixelType(
*/
        __pyx_t_1 = (!(__pyx_v_natural_drain_exists != 0));
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":548
 *                     # this space does not naturally drain, so fill it
 *                     pixel = PixelType(
 *                         center_val, xi_root, yi_root, (             # <<<<<<<<<<<<<<
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +
 *                             xi_root >> BLOCK_BITS))
*/
          __pyx_t_34.value = __pyx_v_center_val;
          __pyx_t_34.xi = __pyx_v_xi_root;
          __pyx_t_34.yi = __pyx_v_yi_root;

          /* "pygeoprocessing/routing/routing.pyx":549
 *                     pixel = PixelType(
 *                         center_val, xi_root, yi_root, (
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +             # <<<<<<<<<<<<<<
 *                             xi_root >> BLOCK_BITS))
 *                     feature_id += 1
*/
          __pyx_t_3 = __Pyx_PyLong_From_unsigned_int(__pyx_v_n_x_blocks); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_3);
          __pyx_t_17 = __Pyx_PyLong_From_unsigned_int(__pyx_v_yi_root); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_17);
          __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_BLOCK_BITS); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __pyx_t_16 = PyNumber_Rshift(__pyx_t_17, __pyx_t_4); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_16);
          __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_4 = PyNumber_Multiply(__pyx_t_3, __pyx_t_16); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

          /* "pygeoprocessing/routing/routing.pyx":550
 *                         center_val, xi_root, yi_root, (
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +
 *                             xi_root >> BLOCK_BITS))             # <<<<<<<<<<<<<<
 *                     feature_id += 1
 *                     pit_mask_managed_raster.set(
*/
          __pyx_t_16 = __Pyx_PyLong_From_unsigned_int(__pyx_v_xi_root); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 550, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_16);

          /* "pygeoprocessing/routing/routing.pyx":549
 *                     pixel = PixelType(
 *                         center_val, xi_root, yi_root, (
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +             # <<<<<<<<<<<<<<
 *                             xi_root >> BLOCK_BITS))
 *                     feature_id += 1
*/
          __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_t_16); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 549, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_3);
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

          /* "pygeoprocessing/routing/routing.pyx":550
 *                         center_val, xi_root, yi_root, (
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +
 *                             xi_root >> BLOCK_BITS))             # <<<<<<<<<<<<<<
 *                     feature_id += 1
 *                     pit_mask_managed_raster.set(
*/
          __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_BLOCK_BITS); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 550, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_16);
          __pyx_t_4 = PyNumber_Rshift(__pyx_t_3, __pyx_t_16); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 550, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
          __pyx_t_7 = __Pyx_PyLong_As_int(__pyx_t_4); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 550, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_34.priority = __pyx_t_7;
          __pyx_v_pixel = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":551
 *                             n_x_blocks * (yi_root >> BLOCK_BITS) +
 *                             xi_root >> BLOCK_BITS))
 *                     feature_id += 1             # <<<<<<<<<<<<<<
 *                     pit_mask_managed_raster.set(
 *                         xi_root, yi_root, feature_id)
*/
          __pyx_v_feature_id = (__pyx_v_feature_id + 1);

          /* "pygeoprocessing/routing/routing.pyx":552
 *                             xi_root >> BLOCK_BITS))
 *                     feature_id += 1
 *                     pit_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root, feature_id)
 *                     pit_queue.push(pixel)
*/
          __pyx_v_pit_mask_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, __pyx_v_feature_id);

          /* "pygeoprocessing/routing/routing.pyx":554
 *                     pit_mask_managed_raster.set(
 *                         xi_root, yi_root, feature_id)
 *                     pit_queue.push(pixel)             # <<<<<<<<<<<<<<
 * 
 *                 # this loop visits pixels in increasing height order, so the
*/
          __pyx_v_pit_queue.push(__pyx_v_pixel);

          /* "pygeoprocessing/routing/routing.pyx":545
 *                                 xi_n, yi_n, 1)
 * 
 *                 if not natural_drain_exists:             # <<<<<<<<<<<<<<
 *                     # this space does not naturally drain, so fill it
 *                     pixel = PixelType(
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":559
 *                 # first non-processed pixel that's < pixel.height or nodata
 *                 # will be the lowest pour point
 *                 pour_point = 0             # <<<<<<<<<<<<<<
 *                 fill_height = dem_nodata
 *                 search_steps = 0
*/
        __pyx_v_pour_point = 0;

        /* "pygeoprocessing/routing/routing.pyx":560
 *                 # will be the lowest pour point
 *                 pour_point = 0
 *                 fill_height = dem_nodata             # <<<<<<<<<<<<<<
 *                 search_steps = 0
 *                 while not pit_queue.empty():
*/
        __pyx_v_fill_height = __pyx_v_dem_nodata;

        /* "pygeoprocessing/routing/routing.pyx":561
 *                 pour_point = 0
 *                 fill_height = dem_nodata
 *                 search_steps = 0             # <<<<<<<<<<<<<<
 *                 while not pit_queue.empty():
 *                     pixel = pit_queue.top()
*/
        __pyx_v_search_steps = 0;

        /* "pygeoprocessing/routing/routing.pyx":562
 *                 fill_height = dem_nodata
 *                 search_steps = 0
 *                 while not pit_queue.empty():             # <<<<<<<<<<<<<<
 *                     pixel = pit_queue.top()
 *                     pit_queue.pop()
*/
        while (1) {
          __pyx_t_1 = (!__pyx_v_pit_queue.empty());
          if (!__pyx_t_1) break;

          /* "pygeoprocessing/routing/routing.pyx":563
 *                 search_steps = 0
 *                 while not pit_queue.empty():
 *                     pixel = pit_queue.top()             # <<<<<<<<<<<<<<
 *                     pit_queue.pop()
 *                     xi_q = pixel.xi
*/
          __pyx_v_pixel = __pyx_v_pit_queue.top();

          /* "pygeoprocessing/routing/routing.pyx":564
 *                 while not pit_queue.empty():
 *                     pixel = pit_queue.top()
 *                     pit_queue.pop()             # <<<<<<<<<<<<<<
 *                     xi_q = pixel.xi
 *                     yi_q = pixel.yi
*/
          __pyx_v_pit_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":565
 *                     pixel = pit_queue.top()
 *                     pit_queue.pop()
 *                     xi_q = pixel.xi             # <<<<<<<<<<<<<<
 *                     yi_q = pixel.yi
 * 
*/
          __pyx_t_32 = __pyx_v_pixel.xi;
          __pyx_v_xi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":566
 *                     pit_queue.pop()
 *                     xi_q = pixel.xi
 *                     yi_q = pixel.yi             # <<<<<<<<<<<<<<
 * 
 *                     # search to see if the fill has gone on too long
*/
          __pyx_t_32 = __pyx_v_pixel.yi;
          __pyx_v_yi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":569
 * 
 *                     # search to see if the fill has gone on too long
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear pit_queue and quit
*/
          __pyx_t_31 = (__pyx_v_max_pixel_fill_count > 0);
          if (__pyx_t_31) {
          } else {
            __pyx_t_1 = __pyx_t_31;
            goto __pyx_L74_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":570
 *                     # search to see if the fill has gone on too long
 *                     if (max_pixel_fill_count > 0 and
 *                             search_steps > max_pixel_fill_count):             # <<<<<<<<<<<<<<
 *                         # clear pit_queue and quit
 *                         LOGGER.debug(
*/
          __pyx_t_31 = (__pyx_v_search_steps > __pyx_v_max_pixel_fill_count);
          __pyx_t_1 = __pyx_t_31;
          __pyx_L74_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":569
 * 
 *                     # search to see if the fill has gone on too long
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear pit_queue and quit
*/
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":572
 *                             search_steps > max_pixel_fill_count):
 *                         # clear pit_queue and quit
 *                         LOGGER.debug(             # <<<<<<<<<<<<<<
 *                             'exceeded max pixel fill count when searching '
 *                             'for pour point')
*/
            __pyx_t_16 = NULL;
            __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 572, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 572, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_17);
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            __pyx_t_9 = 1;
            #if CYTHON_UNPACK_METHODS
            if (unlikely(PyMethod_Check(__pyx_t_17))) {
              __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_17);
              assert(__pyx_t_16);
              PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_17);
              __Pyx_INCREF(__pyx_t_16);
              __Pyx_INCREF(__pyx__function);
              __Pyx_DECREF_SET(__pyx_t_17, __pyx__function);
              __pyx_t_9 = 0;
            }
            #endif
            {
              PyObject *__pyx_callargs[2] = {__pyx_t_16, __pyx_mstate_global->__pyx_kp_u_exceeded_max_pixel_fill_count_wh_2};
              __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_17, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
              __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
              __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
              if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 572, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_4);
            }
            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

            /* "pygeoprocessing/routing/routing.pyx":575
 *                             'exceeded max pixel fill count when searching '
 *                             'for pour point')
 *                         pit_queue = PitPriorityQueueType()             # <<<<<<<<<<<<<<
 *                         natural_drain_exists = 1
 *                         break
*/
            try {
              __pyx_t_35 = __pyx_t_15pygeoprocessing_7routing_7routing_PitPriorityQueueType();
            } catch(...) {
              __Pyx_CppExn2PyErr();
              __PYX_ERR(0, 575, __pyx_L1_error)
            }
            __pyx_v_pit_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_35);

            /* "pygeoprocessing/routing/routing.pyx":576
 *                             'for pour point')
 *                         pit_queue = PitPriorityQueueType()
 *                         natural_drain_exists = 1             # <<<<<<<<<<<<<<
 *                         break
 *                     search_steps += 1
*/
            __pyx_v_natural_drain_exists = 1;

            /* "pygeoprocessing/routing/routing.pyx":577
 *                         pit_queue = PitPriorityQueueType()
 *                         natural_drain_exists = 1
 *                         break             # <<<<<<<<<<<<<<
 *                     search_steps += 1
 * 
*/
            goto __pyx_L72_break;

            /* "pygeoprocessing/routing/routing.pyx":569
 * 
 *                     # search to see if the fill has gone on too long
 *                     if (max_pixel_fill_count > 0 and             # <<<<<<<<<<<<<<
 *                             search_steps > max_pixel_fill_count):
 *                         # clear pit_queue and quit
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":578
 *                         natural_drain_exists = 1
 *                         break
 *                     search_steps += 1             # <<<<<<<<<<<<<<
 * 
 *                     # this is the potential fill height if pixel is pour point
*/
          __pyx_v_search_steps = (__pyx_v_search_steps + 1);

          /* "pygeoprocessing/routing/routing.pyx":581
 * 
 *                     # this is the potential fill height if pixel is pour point
 *                     fill_height = pixel.value             # <<<<<<<<<<<<<<
 * 
 *                     for i_n in range(8):
*/
          __pyx_t_10 = __pyx_v_pixel.value;
          __pyx_v_fill_height = __pyx_t_10;

          /* "pygeoprocessing/routing/routing.pyx":583
 *                     fill_height = pixel.value
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_32 = 0; __pyx_t_32 < 8; __pyx_t_32+=1) {
            __pyx_v_i_n = __pyx_t_32;

            /* "pygeoprocessing/routing/routing.pyx":584
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":585
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":587
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # drain off the edge of the raster
*/
            __pyx_t_31 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L79_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L79_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":588
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             # drain off the edge of the raster
 *                             if not single_outlet:
*/
            __pyx_t_31 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L79_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_1 = __pyx_t_31;
            __pyx_L79_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":587
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # drain off the edge of the raster
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":590
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # drain off the edge of the raster
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 pour_point = 1
 *                                 break
*/
              __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
              if (__pyx_t_1) {

                /* "pygeoprocessing/routing/routing.pyx":591
 *                             # drain off the edge of the raster
 *                             if not single_outlet:
 *                                 pour_point = 1             # <<<<<<<<<<<<<<
 *                                 break
 *                             else:
*/
                __pyx_v_pour_point = 1;

                /* "pygeoprocessing/routing/routing.pyx":592
 *                             if not single_outlet:
 *                                 pour_point = 1
 *                                 break             # <<<<<<<<<<<<<<
 *                             else:
 *                                 continue
*/
                goto __pyx_L77_break;

                /* "pygeoprocessing/routing/routing.pyx":590
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # drain off the edge of the raster
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 pour_point = 1
 *                                 break
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":594
 *                                 break
 *                             else:
 *                                 continue             # <<<<<<<<<<<<<<
 * 
 *                         if pit_mask_managed_raster.get(
*/
              /*else*/ {
                goto __pyx_L76_continue;
              }

              /* "pygeoprocessing/routing/routing.pyx":587
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # drain off the edge of the raster
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":597
 * 
 *                         if pit_mask_managed_raster.get(
 *                                 xi_n, yi_n) == feature_id:             # <<<<<<<<<<<<<<
 *                             # this cell has already been processed
 *                             continue
*/
            __pyx_t_1 = (__pyx_v_pit_mask_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == __pyx_v_feature_id);

            /* "pygeoprocessing/routing/routing.pyx":596
 *                                 continue
 * 
 *                         if pit_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == feature_id:
 *                             # this cell has already been processed
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":599
 *                                 xi_n, yi_n) == feature_id:
 *                             # this cell has already been processed
 *                             continue             # <<<<<<<<<<<<<<
 *                         # mark as visited in the search for pour point
 *                         pit_mask_managed_raster.set(xi_n, yi_n, feature_id)
*/
              goto __pyx_L76_continue;

              /* "pygeoprocessing/routing/routing.pyx":596
 *                                 continue
 * 
 *                         if pit_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == feature_id:
 *                             # this cell has already been processed
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":601
 *                             continue
 *                         # mark as visited in the search for pour point
 *                         pit_mask_managed_raster.set(xi_n, yi_n, feature_id)             # <<<<<<<<<<<<<<
 * 
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
*/
            __pyx_v_pit_mask_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, __pyx_v_feature_id);

            /* "pygeoprocessing/routing/routing.pyx":603
 *                         pit_mask_managed_raster.set(xi_n, yi_n, feature_id)
 * 
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                         if (single_outlet and xi_n == outlet_x
 *                                 and yi_n == outlet_y):
*/
            __pyx_v_n_height = __pyx_v_filled_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":604
 * 
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if (single_outlet and xi_n == outlet_x             # <<<<<<<<<<<<<<
 *                                 and yi_n == outlet_y):
 *                             fill_height = n_height
*/
            __pyx_t_31 = (__pyx_v_single_outlet != 0);
            if (__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L86_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":605
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if (single_outlet and xi_n == outlet_x
 *                                 and yi_n == outlet_y):             # <<<<<<<<<<<<<<
 *                             fill_height = n_height
 *                             pour_point = 1
*/
            __pyx_t_31 = (__pyx_v_xi_n == __pyx_v_outlet_x);
            if (__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L86_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_yi_n == __pyx_v_outlet_y);
            __pyx_t_1 = __pyx_t_31;
            __pyx_L86_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":604
 * 
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if (single_outlet and xi_n == outlet_x             # <<<<<<<<<<<<<<
 *                                 and yi_n == outlet_y):
 *                             fill_height = n_height
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":606
 *                         if (single_outlet and xi_n == outlet_x
 *                                 and yi_n == outlet_y):
 *                             fill_height = n_height             # <<<<<<<<<<<<<<
 *                             pour_point = 1
 *                             break
*/
              __pyx_v_fill_height = __pyx_v_n_height;

              /* "pygeoprocessing/routing/routing.pyx":607
 *                                 and yi_n == outlet_y):
 *                             fill_height = n_height
 *                             pour_point = 1             # <<<<<<<<<<<<<<
 *                             break
 * 
*/
              __pyx_v_pour_point = 1;

              /* "pygeoprocessing/routing/routing.pyx":608
 *                             fill_height = n_height
 *                             pour_point = 1
 *                             break             # <<<<<<<<<<<<<<
 * 
 *                         if is_close(n_height, dem_nodata):
*/
              goto __pyx_L77_break;

              /* "pygeoprocessing/routing/routing.pyx":604
 * 
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if (single_outlet and xi_n == outlet_x             # <<<<<<<<<<<<<<
 *                                 and yi_n == outlet_y):
 *                             fill_height = n_height
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":610
 *                             break
 * 
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             # we encounter a neighbor not processed that
 *                             # is nodata
*/
            __pyx_t_1 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":613
 *                             # we encounter a neighbor not processed that
 *                             # is nodata
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 # it's only a pour point if we aren't in
 *                                 # single outlet mode
*/
              __pyx_t_1 = (!(__pyx_v_single_outlet != 0));
              if (__pyx_t_1) {

                /* "pygeoprocessing/routing/routing.pyx":616
 *                                 # it's only a pour point if we aren't in
 *                                 # single outlet mode
 *                                 pour_point = 1             # <<<<<<<<<<<<<<
 *                             # skip so we don't go negative
 *                             continue
*/
                __pyx_v_pour_point = 1;

                /* "pygeoprocessing/routing/routing.pyx":613
 *                             # we encounter a neighbor not processed that
 *                             # is nodata
 *                             if not single_outlet:             # <<<<<<<<<<<<<<
 *                                 # it's only a pour point if we aren't in
 *                                 # single outlet mode
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":618
 *                                 pour_point = 1
 *                             # skip so we don't go negative
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_height < fill_height:
 *                             # we encounter a neighbor not processed that is
*/
              goto __pyx_L76_continue;

              /* "pygeoprocessing/routing/routing.pyx":610
 *                             break
 * 
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             # we encounter a neighbor not processed that
 *                             # is nodata
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":619
 *                             # skip so we don't go negative
 *                             continue
 *                         if n_height < fill_height:             # <<<<<<<<<<<<<<
 *                             # we encounter a neighbor not processed that is
 *                             # lower than the current pixel
*/
            __pyx_t_1 = (__pyx_v_n_height < __pyx_v_fill_height);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":622
 *                             # we encounter a neighbor not processed that is
 *                             # lower than the current pixel
 *                             pour_point = 1             # <<<<<<<<<<<<<<
 *                             break
 * 
*/
              __pyx_v_pour_point = 1;

              /* "pygeoprocessing/routing/routing.pyx":623
 *                             # lower than the current pixel
 *                             pour_point = 1
 *                             break             # <<<<<<<<<<<<<<
 * 
 *                         # push onto queue, set the priority to be the block
*/
              goto __pyx_L77_break;

              /* "pygeoprocessing/routing/routing.pyx":619
 *                             # skip so we don't go negative
 *                             continue
 *                         if n_height < fill_height:             # <<<<<<<<<<<<<<
 *                             # we encounter a neighbor not processed that is
 *                             # lower than the current pixel
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":628
 *                         # index
 *                         pixel = PixelType(
 *                             n_height, xi_n, yi_n, (             # <<<<<<<<<<<<<<
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +
 *                                 xi_n >> BLOCK_BITS))
*/
            __pyx_t_34.value = __pyx_v_n_height;
            __pyx_t_34.xi = __pyx_v_xi_n;
            __pyx_t_34.yi = __pyx_v_yi_n;

            /* "pygeoprocessing/routing/routing.pyx":629
 *                         pixel = PixelType(
 *                             n_height, xi_n, yi_n, (
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +             # <<<<<<<<<<<<<<
 *                                 xi_n >> BLOCK_BITS))
 *                         pit_queue.push(pixel)
*/
            __pyx_t_4 = __Pyx_PyLong_From_unsigned_int(__pyx_v_n_x_blocks); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            __pyx_t_17 = __Pyx_PyLong_From_unsigned_int(__pyx_v_yi_n); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_17);
            __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_BLOCK_BITS); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_16);
            __pyx_t_3 = PyNumber_Rshift(__pyx_t_17, __pyx_t_16); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
            __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
            __pyx_t_16 = PyNumber_Multiply(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_16);
            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

            /* "pygeoprocessing/routing/routing.pyx":630
 *                             n_height, xi_n, yi_n, (
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +
 *                                 xi_n >> BLOCK_BITS))             # <<<<<<<<<<<<<<
 *                         pit_queue.push(pixel)
 * 
*/
            __pyx_t_3 = __Pyx_PyLong_From_unsigned_int(__pyx_v_xi_n); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 630, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);

            /* "pygeoprocessing/routing/routing.pyx":629
 *                         pixel = PixelType(
 *                             n_height, xi_n, yi_n, (
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +             # <<<<<<<<<<<<<<
 *                                 xi_n >> BLOCK_BITS))
 *                         pit_queue.push(pixel)
*/
            __pyx_t_4 = PyNumber_Add(__pyx_t_16, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 629, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

            /* "pygeoprocessing/routing/routing.pyx":630
 *                             n_height, xi_n, yi_n, (
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +
 *                                 xi_n >> BLOCK_BITS))             # <<<<<<<<<<<<<<
 *                         pit_queue.push(pixel)
 * 
*/
            __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_BLOCK_BITS); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 630, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_16 = PyNumber_Rshift(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 630, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_16);
            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            __pyx_t_7 = __Pyx_PyLong_As_int(__pyx_t_16); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 630, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
            __pyx_t_34.priority = __pyx_t_7;
            __pyx_v_pixel = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":631
 *                                 n_x_blocks * (yi_n >> BLOCK_BITS) +
 *                                 xi_n >> BLOCK_BITS))
 *                         pit_queue.push(pixel)             # <<<<<<<<<<<<<<
 * 
 *                     if pour_point:
*/
            __pyx_v_pit_queue.push(__pyx_v_pixel);
            __pyx_L76_continue:;
          }
          __pyx_L77_break:;

          /* "pygeoprocessing/routing/routing.pyx":633
 *                         pit_queue.push(pixel)
 * 
 *                     if pour_point:             # <<<<<<<<<<<<<<
 *                         # found a pour point, clear the queue
 *                         pit_queue = PitPriorityQueueType()
*/
          __pyx_t_1 = (__pyx_v_pour_point != 0);
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":635
 *                     if pour_point:
 *                         # found a pour point, clear the queue
 *                         pit_queue = PitPriorityQueueType()             # <<<<<<<<<<<<<<
 * 
 *                         # start from original pit seed rather than pour point
*/
            try {
              __pyx_t_35 = __pyx_t_15pygeoprocessing_7routing_7routing_PitPriorityQueueType();
            } catch(...) {
              __Pyx_CppExn2PyErr();
              __PYX_ERR(0, 635, __pyx_L1_error)
            }
            __pyx_v_pit_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_35);

            /* "pygeoprocessing/routing/routing.pyx":643
 *                         # differentiate the pixels on the inside of the pit
 *                         # and the outside.
 *                         fill_queue.push(CoordinateType(xi_root, yi_root))             # <<<<<<<<<<<<<<
 *                         filled_dem_managed_raster.set(
 *                             xi_root, yi_root, fill_height)
*/
            __pyx_t_33.xi = __pyx_v_xi_root;
            __pyx_t_33.yi = __pyx_v_yi_root;
            __pyx_v_fill_queue.push(__pyx_t_33);

            /* "pygeoprocessing/routing/routing.pyx":644
 *                         # and the outside.
 *                         fill_queue.push(CoordinateType(xi_root, yi_root))
 *                         filled_dem_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             xi_root, yi_root, fill_height)
 * 
*/
            __pyx_v_filled_dem_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, __pyx_v_fill_height);

            /* "pygeoprocessing/routing/routing.pyx":633
 *                         pit_queue.push(pixel)
 * 
 *                     if pour_point:             # <<<<<<<<<<<<<<
 *                         # found a pour point, clear the queue
 *                         pit_queue = PitPriorityQueueType()
*/
          }
        }
        __pyx_L72_break:;

        /* "pygeoprocessing/routing/routing.pyx":648
 * 
 *                 # this loop does a BFS to set all DEM pixels to `fill_height`
 *                 while not fill_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = fill_queue.front().xi
 *                     yi_q = fill_queue.front().yi
*/
        while (1) {
          __pyx_t_1 = (!__pyx_v_fill_queue.empty());
          if (!__pyx_t_1) break;

          /* "pygeoprocessing/routing/routing.pyx":649
 *                 # this loop does a BFS to set all DEM pixels to `fill_height`
 *                 while not fill_queue.empty():
 *                     xi_q = fill_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = fill_queue.front().yi
 *                     fill_queue.pop()
*/
          __pyx_t_32 = __pyx_v_fill_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":650
 *                 while not fill_queue.empty():
 *                     xi_q = fill_queue.front().xi
 *                     yi_q = fill_queue.front().yi             # <<<<<<<<<<<<<<
 *                     fill_queue.pop()
 * 
*/
          __pyx_t_32 = __pyx_v_fill_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":651
 *                     xi_q = fill_queue.front().xi
 *                     yi_q = fill_queue.front().yi
 *                     fill_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     for i_n in range(8):
*/
          __pyx_v_fill_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":653
 *                     fill_queue.pop()
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_32 = 0; __pyx_t_32 < 8; __pyx_t_32+=1) {
            __pyx_v_i_n = __pyx_t_32;

            /* "pygeoprocessing/routing/routing.pyx":654
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":655
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":656
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_31 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L98_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L98_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":657
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
*/
            __pyx_t_31 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_31) {
            } else {
              __pyx_t_1 = __pyx_t_31;
              goto __pyx_L98_bool_binop_done;
            }
            __pyx_t_31 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_1 = __pyx_t_31;
            __pyx_L98_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":656
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":658
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
*/
              goto __pyx_L95_continue;

              /* "pygeoprocessing/routing/routing.pyx":656
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":659
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                         if is_close(n_height, dem_nodata):
 *                             continue
*/
            __pyx_v_n_height = __pyx_v_filled_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":660
 *                             continue
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_height < fill_height:
*/
            __pyx_t_1 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":661
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_height < fill_height:
 *                             filled_dem_managed_raster.set(
*/
              goto __pyx_L95_continue;

              /* "pygeoprocessing/routing/routing.pyx":660
 *                             continue
 *                         n_height = filled_dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_height < fill_height:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":662
 *                         if is_close(n_height, dem_nodata):
 *                             continue
 *                         if n_height < fill_height:             # <<<<<<<<<<<<<<
 *                             filled_dem_managed_raster.set(
 *                                 xi_n, yi_n, fill_height)
*/
            __pyx_t_1 = (__pyx_v_n_height < __pyx_v_fill_height);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":663
 *                             continue
 *                         if n_height < fill_height:
 *                             filled_dem_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, fill_height)
 *                             fill_queue.push(CoordinateType(xi_n, yi_n))
*/
              __pyx_v_filled_dem_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, __pyx_v_fill_height);

              /* "pygeoprocessing/routing/routing.pyx":665
 *                             filled_dem_managed_raster.set(
 *                                 xi_n, yi_n, fill_height)
 *                             fill_queue.push(CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 * 
 *     pit_mask_managed_raster.close()
*/
              __pyx_t_33.xi = __pyx_v_xi_n;
              __pyx_t_33.yi = __pyx_v_yi_n;
              __pyx_v_fill_queue.push(__pyx_t_33);

              /* "pygeoprocessing/routing/routing.pyx":662
 *                         if is_close(n_height, dem_nodata):
 *                             continue
 *                         if n_height < fill_height:             # <<<<<<<<<<<<<<
 *                             filled_dem_managed_raster.set(
 *                                 xi_n, yi_n, fill_height)
*/
            }
            __pyx_L95_continue:;
          }
        }
        __pyx_L28_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":413
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":667
 *                             fill_queue.push(CoordinateType(xi_n, yi_n))
 * 
 *     pit_mask_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster.close()
 *     filled_dem_managed_raster.close()
*/
  __pyx_v_pit_mask_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":668
 * 
 *     pit_mask_managed_raster.close()
 *     flat_region_mask_managed_raster.close()             # <<<<<<<<<<<<<<
 *     filled_dem_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
*/
  __pyx_v_flat_region_mask_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":669
 *     pit_mask_managed_raster.close()
 *     flat_region_mask_managed_raster.close()
 *     filled_dem_managed_raster.close()             # <<<<<<<<<<<<<<
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('(fill pits): complete')
*/
  __pyx_v_filled_dem_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":670
 *     flat_region_mask_managed_raster.close()
 *     filled_dem_managed_raster.close()
 *     shutil.rmtree(working_dir_path)             # <<<<<<<<<<<<<<
 *     LOGGER.info('(fill pits): complete')
 * 
*/
  __pyx_t_16 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 670, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 670, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_16);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_16);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_16, __pyx_v_working_dir_path};
    __pyx_t_18 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 670, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":671
 *     filled_dem_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('(fill pits): complete')             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 671, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 671, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
  __pyx_t_9 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_9 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_fill_pits_complete};
    __pyx_t_18 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_9, (2-__pyx_t_9) | (__pyx_t_9*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 671, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_18);
  }
  __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;

  /* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/

  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_16);
  __Pyx_XDECREF(__pyx_t_17);
  __Pyx_XDECREF(__pyx_t_18);
  __Pyx_XDECREF(__pyx_t_19);
  __Pyx_XDECREF(__pyx_t_20);
  __Pyx_XDECREF(__pyx_t_21);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.fill_pits", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_dem_raster_info);
  __Pyx_XDECREF(__pyx_v_base_nodata);
  __Pyx_XDECREF(__pyx_v_working_dir_path);
  __Pyx_XDECREF(__pyx_v_flat_region_mask_path);
  __Pyx_XDECREF(__pyx_v_pit_mask_path);
  __Pyx_XDECREF(__pyx_v_base_datatype);
  __Pyx_XDECREF(__pyx_v_filled_dem_raster);
  __Pyx_XDECREF(__pyx_v_filled_dem_band);
  __Pyx_XDECREF(__pyx_v_offset_info);
  __Pyx_XDECREF(__pyx_v_block_array);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":674
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_34__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":677
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
 *         working_dir=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """D8 flow direction.
*/
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 674, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, Py_None) != (0)) __PYX_ERR(0, 674, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 674, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":674
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 674, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 674, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 674, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_5flow_dir_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_4flow_dir_d8, "D8 flow direction.\n\n    Parameters:\n        dem_raster_path_band (tuple): a path, band number tuple indicating the\n            DEM calculate flow direction. This DEM must not have hydrological\n            pits or else the target flow direction is undefined. Paths may use\n            any GDAL-supported scheme, including virtual file system /vsi schemes.\n        target_flow_dir_path (str): path to a byte raster created by this\n            call of same dimensions as ``dem_raster_path_band`` that has a value\n            indicating the direction of downhill flow. Values are defined as\n            pointing to one of the eight neighbors with the following\n            convention::\n\n                3 2 1\n                4 x 0\n                5 6 7\n\n        working_dir (str): If not None, indicates where temporary files\n            should be created during this run. If this directory doesn't exist\n            it is created by this call.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_5flow_dir_d8 = {"flow_dir_d8", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_5flow_dir_d8, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_4flow_dir_d8};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_5flow_dir_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_dem_raster_path_band = 0;
  PyObject *__pyx_v_target_flow_dir_path = 0;
  PyObject *__pyx_v_working_dir = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[4] = {0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("flow_dir_d8 (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_dem_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_flow_dir_path,&__pyx_mstate_global->__pyx_n_u_working_dir,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 674, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "flow_dir_d8", 0) < (0)) __PYX_ERR(0, 674, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":677
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
 *         working_dir=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """D8 flow direction.
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("flow_dir_d8", 0, 2, 4, i); __PYX_ERR(0, 674, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 674, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 674, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 674, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_dem_raster_path_band = values[0];
    __pyx_v_target_flow_dir_path = values[1];
    __pyx_v_working_dir = values[2];
    __pyx_v_raster_driver_creation_tuple = values[3];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("flow_dir_d8", 0, 2, 4, __pyx_nargs); __PYX_ERR(0, 674, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_dir_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_4flow_dir_d8(__pyx_self, __pyx_v_dem_raster_path_band, __pyx_v_target_flow_dir_path, __pyx_v_working_dir, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":674
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_4flow_dir_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_flow_dir_path, PyObject *__pyx_v_working_dir, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_dem_buffer_array = 0;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  int __pyx_v_i_n;
  int __pyx_v_xi;
  int __pyx_v_yi;
  int __pyx_v_xi_q;
  int __pyx_v_yi_q;
  int __pyx_v_xi_n;
  int __pyx_v_yi_n;
  double __pyx_v_root_height;
  double __pyx_v_n_height;
  double __pyx_v_dem_nodata;
  double __pyx_v_drain_distance;
  double __pyx_v_n_drain_distance;
  int __pyx_v_diagonal_nodata;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_v_search_queue;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_drain_queue;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_nodata_drain_queue;
  std::queue<int>  __pyx_v_nodata_flow_dir_queue;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  unsigned long __pyx_v_current_pixel;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_dem_raster_info = NULL;
  PyObject *__pyx_v_base_nodata = NULL;
  long __pyx_v_mask_nodata;
  PyObject *__pyx_v_working_dir_path = NULL;
  PyObject *__pyx_v_flat_region_mask_path = NULL;
  ManagedRaster __pyx_v_flat_region_mask_managed_raster;
  long __pyx_v_flow_dir_nodata;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  PyObject *__pyx_v_plateau_distance_path = NULL;
  ManagedRaster __pyx_v_plateau_distance_managed_raster;
  PyObject *__pyx_v_compatable_dem_raster_path_band = NULL;
  PyObject *__pyx_v_dem_block_xsize = NULL;
  PyObject *__pyx_v_dem_block_ysize = NULL;
  PyObject *__pyx_v_raster_driver = NULL;
  PyObject *__pyx_v_dem_raster = NULL;
  ManagedRaster __pyx_v_dem_managed_raster;
  PyObject *__pyx_v_dem_band = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  long __pyx_v_largest_slope_dir;
  double __pyx_v_largest_slope;
  double __pyx_v_n_slope;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_dem_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_dem_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  size_t __pyx_t_5;
  int __pyx_t_6;
  double __pyx_t_7;
  PyObject *(*__pyx_t_8)(PyObject *);
  unsigned int __pyx_t_9;
  unsigned int __pyx_t_10;
  PyObject *__pyx_t_11 = NULL;
  PyObject *__pyx_t_12 = NULL;
  PyObject *__pyx_t_13 = NULL;
  int __pyx_t_14;
  PyObject *__pyx_t_15 = NULL;
  PyObject *__pyx_t_16 = NULL;
  PyObject *__pyx_t_17 = NULL;
  PyObject *__pyx_t_18 = NULL;
  PyObject *__pyx_t_19 = NULL;
  PyObject *__pyx_t_20 = NULL;
  char *__pyx_t_21;
  ManagedRaster __pyx_t_22;
  int __pyx_t_23;
  Py_ssize_t __pyx_t_24;
  PyObject *(*__pyx_t_25)(PyObject *);
  PyObject *__pyx_t_26[5];
  long __pyx_t_27;
  long __pyx_t_28;
  long __pyx_t_29;
  long __pyx_t_30;
  int __pyx_t_31;
  Py_ssize_t __pyx_t_32;
  Py_ssize_t __pyx_t_33;
  int __pyx_t_34;
  int __pyx_t_35;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_t_36;
  __pyx_t_15pygeoprocessing_7routing_7routing_IntQueueType __pyx_t_37;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_t_38;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("flow_dir_d8", 0);
  __pyx_pybuffer_dem_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_dem_buffer_array.refcount = 0;
  __pyx_pybuffernd_dem_buffer_array.data = NULL;
  __pyx_pybuffernd_dem_buffer_array.rcbuffer = &__pyx_pybuffer_dem_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":754
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     # determine dem nodata in the working type, or set an improbable value
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":758
 *     # determine dem nodata in the working type, or set an improbable value
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 758, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 758, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 758, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 758, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_dem_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":759
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 759, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 759, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = __Pyx_PyLong_SubtractObjC(__pyx_t_4, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 759, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 759, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_base_nodata = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":760
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
  __pyx_t_6 = (__pyx_v_base_nodata != Py_None);
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":762
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)             # <<<<<<<<<<<<<<
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 762, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 762, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_base_nodata};
      __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 762, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __pyx_t_7 = __Pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 762, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_v_dem_nodata = __pyx_t_7;

    /* "pygeoprocessing/routing/routing.pyx":760
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
    goto __pyx_L3;
  }

  /* "pygeoprocessing/routing/routing.pyx":765
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     # these are used to determine if a sample is within the raster
*/
  /*else*/ {
    __pyx_v_dem_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
  }
  __pyx_L3:;

  /* "pygeoprocessing/routing/routing.pyx":768
 * 
 *     # these are used to determine if a sample is within the raster
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     # this is the nodata value for all the flat region and pit masks
*/
  __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 768, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
    PyObject* sequence = __pyx_t_4;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 768, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 768, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 768, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 768, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 768, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_1 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 768, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1);
    index = 0; __pyx_t_2 = __pyx_t_8(__pyx_t_1); if (unlikely(!__pyx_t_2)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_3 = __pyx_t_8(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_1), 2) < (0)) __PYX_ERR(0, 768, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    goto __pyx_L5_unpacking_done;
    __pyx_L4_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 768, __pyx_L1_error)
    __pyx_L5_unpacking_done:;
  }
  __pyx_t_9 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_9 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 768, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 768, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_raster_x_size = __pyx_t_9;
  __pyx_v_raster_y_size = __pyx_t_10;

  /* "pygeoprocessing/routing/routing.pyx":771
 * 
 *     # this is the nodata value for all the flat region and pit masks
 *     mask_nodata = 0             # <<<<<<<<<<<<<<
 * 
 *     # set up the working dir for the mask rasters
*/
  __pyx_v_mask_nodata = 0;

  /* "pygeoprocessing/routing/routing.pyx":774
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13);
    __Pyx_XGOTREF(__pyx_t_11);
    __Pyx_XGOTREF(__pyx_t_12);
    __Pyx_XGOTREF(__pyx_t_13);
    /*try:*/ {

      /* "pygeoprocessing/routing/routing.pyx":775
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      __pyx_t_6 = (__pyx_v_working_dir != Py_None);
      if (__pyx_t_6) {

        /* "pygeoprocessing/routing/routing.pyx":776
 *     try:
 *         if working_dir is not None:
 *             os.makedirs(working_dir)             # <<<<<<<<<<<<<<
 *     except OSError:
 *         pass
*/
        __pyx_t_3 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 776, __pyx_L6_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_makedirs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 776, __pyx_L6_error)
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_5 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_1))) {
          __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
          assert(__pyx_t_3);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_3);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
          __pyx_t_5 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_working_dir};
          __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 776, __pyx_L6_error)
          __Pyx_GOTREF(__pyx_t_4);
        }
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

        /* "pygeoprocessing/routing/routing.pyx":775
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":774
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    }
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    goto __pyx_L11_try_end;
    __pyx_L6_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_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":777
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
 *     except OSError:             # <<<<<<<<<<<<<<
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
*/
    __pyx_t_14 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_OSError))));
    if (__pyx_t_14) {
      __Pyx_ErrRestore(0,0,0);
      goto __pyx_L7_exception_handled;
    }
    goto __pyx_L8_except_error;

    /* "pygeoprocessing/routing/routing.pyx":774
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    __pyx_L8_except_error:;
    __Pyx_XGIVEREF(__pyx_t_11);
    __Pyx_XGIVEREF(__pyx_t_12);
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
    goto __pyx_L1_error;
    __pyx_L7_exception_handled:;
    __Pyx_XGIVEREF(__pyx_t_11);
    __Pyx_XGIVEREF(__pyx_t_12);
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
    __pyx_L11_try_end:;
  }

  /* "pygeoprocessing/routing/routing.pyx":779
 *     except OSError:
 *         pass
 *     working_dir_path = tempfile.mkdtemp(             # <<<<<<<<<<<<<<
 *         dir=working_dir, prefix='flow_dir_d8_%s_' % time.strftime(
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 779, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 779, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":780
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='flow_dir_d8_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_15 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 780, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_strftime); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 780, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":781
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='flow_dir_d8_%s_' % time.strftime(
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))             # <<<<<<<<<<<<<<
 * 
 *     # this raster is used to keep track of what pixels have been searched for
*/
  __pyx_t_18 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_19, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 781, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_19);
  __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_19, __pyx_mstate_global->__pyx_n_u_gmtime); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 781, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_20))) {
    __pyx_t_18 = PyMethod_GET_SELF(__pyx_t_20);
    assert(__pyx_t_18);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_20);
    __Pyx_INCREF(__pyx_t_18);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_20, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_18, NULL};
    __pyx_t_16 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_20, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 781, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
  }
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_17))) {
    __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_17);
    assert(__pyx_t_15);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_17);
    __Pyx_INCREF(__pyx_t_15);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_17, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_mstate_global->__pyx_kp_u_Y_m_d__H__M__S, __pyx_t_16};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_17, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 780, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }

  /* "pygeoprocessing/routing/routing.pyx":780
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir, prefix='flow_dir_d8_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_17 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_flow_dir_d8__s, __pyx_t_3); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 780, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_1, NULL};
    __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 779, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_v_working_dir, __pyx_t_3, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 779, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_t_17, __pyx_t_3, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 779, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 779, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_working_dir_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":786
 *     # a plateau. if a pixel is set, it means it is part of a locally
 *     # undrained area
 *     flat_region_mask_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 786, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 786, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_2 = __pyx_t_17;
  __Pyx_INCREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":787
 *     # undrained area
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
*/
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_flat_region_mask_tif};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 786, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_flat_region_mask_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":788
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
*/
  __pyx_t_17 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 788, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 788, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":789
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,             # <<<<<<<<<<<<<<
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 789, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 789, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 789, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":790
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __Pyx_PyLong_From_long(__pyx_v_mask_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 790, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = PyList_New(1); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 790, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_15, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 790, __pyx_L1_error);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":791
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_17);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_17);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_17, __pyx_t_2, __pyx_v_flat_region_mask_path, __pyx_t_16, __pyx_t_15};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 788, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_1, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 788, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 788, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":793
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_nodata = 128
*/
  __pyx_t_3 = __pyx_v_flat_region_mask_path;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 793, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 793, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":792
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flat_region_mask_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 792, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_flat_region_mask_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":795
 *         flat_region_mask_path.encode('utf-8'), 1, True)
 * 
 *     flow_dir_nodata = 128             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Byte,
*/
  __pyx_v_flow_dir_nodata = 0x80;

  /* "pygeoprocessing/routing/routing.pyx":796
 * 
 *     flow_dir_nodata = 128
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Byte,
 *         [flow_dir_nodata],
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 796, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 796, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":797
 *     flow_dir_nodata = 128
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Byte,             # <<<<<<<<<<<<<<
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 797, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 797, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 797, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":798
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Byte,
 *         [flow_dir_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_16 = __Pyx_PyLong_From_long(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 798, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = PyList_New(1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 798, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_GIVEREF(__pyx_t_16);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_17, 0, __pyx_t_16) != (0)) __PYX_ERR(0, 798, __pyx_L1_error);
  __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":799
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Byte,
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster = ManagedRaster(
 *         target_flow_dir_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_15))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_15);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_3, __pyx_t_1, __pyx_v_target_flow_dir_path, __pyx_t_2, __pyx_t_17};
    __pyx_t_16 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 796, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_16, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 796, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_16);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 796, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":801
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(
 *         target_flow_dir_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # this creates a raster that's used for a dynamic programming solution to
*/
  __pyx_t_15 = __pyx_v_target_flow_dir_path;
  __Pyx_INCREF(__pyx_t_15);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_15, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 801, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 801, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":800
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_flow_dir_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 800, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":807
 *     # raster_x_size * raster_y_size as a distance that's greater than the
 *     # longest plateau drain distance possible for this raster.
 *     plateau_distance_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'plateau_distance.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 807, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 807, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
  __pyx_t_15 = __pyx_t_17;
  __Pyx_INCREF(__pyx_t_15);

  /* "pygeoprocessing/routing/routing.pyx":808
 *     # longest plateau drain distance possible for this raster.
 *     plateau_distance_path = os.path.join(
 *         working_dir_path, 'plateau_distance.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
*/
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_plateau_distance_tif};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 807, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_plateau_distance_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":809
 *     plateau_distance_path = os.path.join(
 *         working_dir_path, 'plateau_distance.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [-1], fill_value_list=[raster_x_size * raster_y_size],
*/
  __pyx_t_17 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 809, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 809, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":810
 *         working_dir_path, 'plateau_distance.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,             # <<<<<<<<<<<<<<
 *         [-1], fill_value_list=[raster_x_size * raster_y_size],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_15 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 810, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 810, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 810, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":811
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [-1], fill_value_list=[raster_x_size * raster_y_size],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(
*/
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 811, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_neg_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_mstate_global->__pyx_int_neg_1) != (0)) __PYX_ERR(0, 811, __pyx_L1_error);
  __pyx_t_3 = __Pyx_PyLong_From_unsigned_int((__pyx_v_raster_x_size * __pyx_v_raster_y_size)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 811, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_20 = PyList_New(1); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 811, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __Pyx_GIVEREF(__pyx_t_3);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_20, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 811, __pyx_L1_error);
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":812
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [-1], fill_value_list=[raster_x_size * raster_y_size],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     plateau_distance_managed_raster = ManagedRaster(
 *         plateau_distance_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_16))) {
    __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_16);
    assert(__pyx_t_17);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_16);
    __Pyx_INCREF(__pyx_t_17);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_16, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_17, __pyx_t_15, __pyx_v_plateau_distance_path, __pyx_t_1, __pyx_t_2};
    __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 809, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_fill_value_list, __pyx_t_20, __pyx_t_3, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 809, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_3, __pyx_callargs+5, 1) < (0)) __PYX_ERR(0, 809, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_16, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
    __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 809, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":814
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(
 *         plateau_distance_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # this raster is for random access of the DEM
*/
  __pyx_t_16 = __pyx_v_plateau_distance_path;
  __Pyx_INCREF(__pyx_t_16);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_16, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 814, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 814, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":813
 *         [-1], fill_value_list=[raster_x_size * raster_y_size],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         plateau_distance_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 813, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_plateau_distance_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":818
 *     # this raster is for random access of the DEM
 * 
 *     compatable_dem_raster_path_band = None             # <<<<<<<<<<<<<<
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
*/
  __Pyx_INCREF(Py_None);
  __pyx_v_compatable_dem_raster_path_band = Py_None;

  /* "pygeoprocessing/routing/routing.pyx":819
 * 
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']             # <<<<<<<<<<<<<<
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
*/
  __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_block_size); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 819, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
    PyObject* sequence = __pyx_t_4;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 819, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_16 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_16);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_16 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 819, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_16);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_16 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 819, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 819, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_20 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 819, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_20);
    index = 0; __pyx_t_16 = __pyx_t_8(__pyx_t_20); if (unlikely(!__pyx_t_16)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_16);
    index = 1; __pyx_t_3 = __pyx_t_8(__pyx_t_20); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_20), 2) < (0)) __PYX_ERR(0, 819, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    goto __pyx_L16_unpacking_done;
    __pyx_L15_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 819, __pyx_L1_error)
    __pyx_L16_unpacking_done:;
  }
  __pyx_v_dem_block_xsize = __pyx_t_16;
  __pyx_t_16 = 0;
  __pyx_v_dem_block_ysize = __pyx_t_3;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":820
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
  __pyx_t_4 = __Pyx_PyLong_SubtractObjC(__pyx_v_dem_block_xsize, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 820, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = PyNumber_And(__pyx_v_dem_block_xsize, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 820, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_23 = (__Pyx_PyLong_BoolNeObjC(__pyx_t_3, __pyx_mstate_global->__pyx_int_0, 0, 0)); if (unlikely((__pyx_t_23 < 0))) __PYX_ERR(0, 820, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (!__pyx_t_23) {
  } else {
    __pyx_t_6 = __pyx_t_23;
    goto __pyx_L18_bool_binop_done;
  }

  /* "pygeoprocessing/routing/routing.pyx":821
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):             # <<<<<<<<<<<<<<
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
*/
  __pyx_t_3 = __Pyx_PyLong_SubtractObjC(__pyx_v_dem_block_ysize, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 821, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = PyNumber_And(__pyx_v_dem_block_ysize, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 821, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_23 = (__Pyx_PyLong_BoolNeObjC(__pyx_t_4, __pyx_mstate_global->__pyx_int_0, 0, 0)); if (unlikely((__pyx_t_23 < 0))) __PYX_ERR(0, 821, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_6 = __pyx_t_23;
  __pyx_L18_bool_binop_done:;

  /* "pygeoprocessing/routing/routing.pyx":820
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":822
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 822, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_warning); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 822, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_20))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_20);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_20);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_20, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_dem_is_not_a_power_of_2_creating};
      __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_20, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 822, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":824
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),             # <<<<<<<<<<<<<<
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
*/
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 824, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 824, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_20 = __pyx_t_16;
    __Pyx_INCREF(__pyx_t_20);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_20, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_compatable_dem_tif};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_20); __pyx_t_20 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 824, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }

    /* "pygeoprocessing/routing/routing.pyx":825
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
 *             dem_raster_path_band[1])             # <<<<<<<<<<<<<<
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
*/
    __pyx_t_16 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 825, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);

    /* "pygeoprocessing/routing/routing.pyx":824
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),             # <<<<<<<<<<<<<<
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
*/
    __pyx_t_20 = PyTuple_New(2); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 824, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_GIVEREF(__pyx_t_4);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_20, 0, __pyx_t_4) != (0)) __PYX_ERR(0, 824, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_16);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_20, 1, __pyx_t_16) != (0)) __PYX_ERR(0, 824, __pyx_L1_error);
    __pyx_t_4 = 0;
    __pyx_t_16 = 0;
    __Pyx_DECREF_SET(__pyx_v_compatable_dem_raster_path_band, __pyx_t_20);
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":826
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])             # <<<<<<<<<<<<<<
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(
*/
    __pyx_t_16 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 826, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_GetDriverByName); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 826, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_driver_creation_tuple, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 826, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_3);
      assert(__pyx_t_16);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_16);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_16, __pyx_t_4};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 826, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __pyx_v_raster_driver = __pyx_t_20;
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":827
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 827, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 827, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 827, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 827, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 827, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_16))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_16);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_16);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_16, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_t_4, __pyx_t_1};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_16, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 827, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __pyx_v_dem_raster = __pyx_t_20;
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":828
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])
*/
    __pyx_t_16 = __pyx_v_raster_driver;
    __Pyx_INCREF(__pyx_t_16);

    /* "pygeoprocessing/routing/routing.pyx":829
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,             # <<<<<<<<<<<<<<
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None
*/
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 829, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);

    /* "pygeoprocessing/routing/routing.pyx":830
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])             # <<<<<<<<<<<<<<
 *         dem_raster = None
 *         LOGGER.info("compatible dem complete")
*/
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_driver_creation_tuple, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 830, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_16, __pyx_t_1, __pyx_v_dem_raster};
      __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 828, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_options, __pyx_t_4, __pyx_t_3, __pyx_callargs+3, 0) < (0)) __PYX_ERR(0, 828, __pyx_L1_error)
      __pyx_t_20 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateCopy, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 828, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":831
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None             # <<<<<<<<<<<<<<
 *         LOGGER.info("compatible dem complete")
 *     else:
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_dem_raster, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":832
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None
 *         LOGGER.info("compatible dem complete")             # <<<<<<<<<<<<<<
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 832, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 832, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_compatible_dem_complete};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 832, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":820
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
    goto __pyx_L17;
  }

  /* "pygeoprocessing/routing/routing.pyx":834
 *         LOGGER.info("compatible dem complete")
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band             # <<<<<<<<<<<<<<
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
*/
  /*else*/ {
    __Pyx_INCREF(__pyx_v_dem_raster_path_band);
    __Pyx_DECREF_SET(__pyx_v_compatable_dem_raster_path_band, __pyx_v_dem_raster_path_band);
  }
  __pyx_L17:;

  /* "pygeoprocessing/routing/routing.pyx":836
 *         compatable_dem_raster_path_band = dem_raster_path_band
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[1], False)
 * 
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 836, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __pyx_t_3;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 836, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_20); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 836, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":837
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
 *         compatable_dem_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     # and this raster is for efficient block-by-block reading of the dem
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 837, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 837, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":835
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band
 *     dem_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
 *         compatable_dem_raster_path_band[1], False)
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, __pyx_t_14, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 835, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  __pyx_v_dem_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":840
 * 
 *     # and this raster is for efficient block-by-block reading of the dem
 *     dem_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)
 *     dem_band = dem_raster.GetRasterBand(compatable_dem_raster_path_band[1])
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 840, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 840, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":841
 *     # and this raster is for efficient block-by-block reading of the dem
 *     dem_raster = gdal.OpenEx(
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     dem_band = dem_raster.GetRasterBand(compatable_dem_raster_path_band[1])
 * 
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 841, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_t_1, __pyx_t_2};
    __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 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;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 840, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __Pyx_XDECREF_SET(__pyx_v_dem_raster, __pyx_t_20);
  __pyx_t_20 = 0;

  /* "pygeoprocessing/routing/routing.pyx":842
 *     dem_raster = gdal.OpenEx(
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)
 *     dem_band = dem_raster.GetRasterBand(compatable_dem_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for a pixel that is locally undrained
*/
  __pyx_t_4 = __pyx_v_dem_raster;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 842, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 842, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __pyx_v_dem_band = __pyx_t_20;
  __pyx_t_20 = 0;

  /* "pygeoprocessing/routing/routing.pyx":845
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 845, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 845, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":846
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             compatable_dem_raster_path_band, offset_only=True,             # <<<<<<<<<<<<<<
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_2, __pyx_v_compatable_dem_raster_path_band};
    __pyx_t_4 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 845, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_4, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 845, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_4, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 845, __pyx_L1_error)
    __pyx_t_20 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_4);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 845, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }

  /* "pygeoprocessing/routing/routing.pyx":845
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  if (likely(PyList_CheckExact(__pyx_t_20)) || PyTuple_CheckExact(__pyx_t_20)) {
    __pyx_t_1 = __pyx_t_20; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_24 = 0;
    __pyx_t_25 = NULL;
  } else {
    __pyx_t_24 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_20); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 845, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_25 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 845, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  for (;;) {
    if (likely(!__pyx_t_25)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 845, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        __pyx_t_20 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_24, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_24;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 845, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_20 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_24));
        #else
        __pyx_t_20 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_24);
        #endif
        ++__pyx_t_24;
      }
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 845, __pyx_L1_error)
    } else {
      __pyx_t_20 = __pyx_t_25(__pyx_t_1);
      if (unlikely(!__pyx_t_20)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 845, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_20);
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":848
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 848, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_20); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 848, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_win_xsize = __pyx_t_10;

    /* "pygeoprocessing/routing/routing.pyx":849
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 849, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_20); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 849, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_win_ysize = __pyx_t_10;

    /* "pygeoprocessing/routing/routing.pyx":850
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 850, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_20); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 850, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_xoff = __pyx_t_10;

    /* "pygeoprocessing/routing/routing.pyx":851
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 851, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_20); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 851, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_yoff = __pyx_t_10;

    /* "pygeoprocessing/routing/routing.pyx":853
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":854
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":855
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(flow dir d8): '
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":856
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(flow dir d8): '
 *                 f'{current_pixel} of {raster_x_size*raster_y_size} '
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 856, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 856, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":858
 *             LOGGER.info(
 *                 '(flow dir d8): '
 *                 f'{current_pixel} of {raster_x_size*raster_y_size} '             # <<<<<<<<<<<<<<
 *                 f'pixels complete')
 * 
*/
      __pyx_t_2 = __Pyx_PyUnicode_From_unsigned_long(__pyx_v_current_pixel, 0, ' ', 'd'); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 858, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_16 = __Pyx_PyUnicode_From_unsigned_int((__pyx_v_raster_x_size * __pyx_v_raster_y_size), 0, ' ', 'd'); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 858, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      __pyx_t_26[0] = __pyx_mstate_global->__pyx_kp_u_flow_dir_d8;
      __pyx_t_26[1] = __pyx_t_2;
      __pyx_t_26[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_26[3] = __pyx_t_16;
      __pyx_t_26[4] = __pyx_mstate_global->__pyx_kp_u_pixels_complete;

      /* "pygeoprocessing/routing/routing.pyx":857
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
 *                 '(flow dir d8): '             # <<<<<<<<<<<<<<
 *                 f'{current_pixel} of {raster_x_size*raster_y_size} '
 *                 f'pixels complete')
*/
      __pyx_t_15 = __Pyx_PyUnicode_Join(__pyx_t_26, 5, 15 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_16) + 16, 127);
      if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 857, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_3))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_15};
        __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 856, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_20);
      }
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

      /* "pygeoprocessing/routing/routing.pyx":853
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":862
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 862, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 862, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

    /* "pygeoprocessing/routing/routing.pyx":863
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.float64)
 *         dem_buffer_array[:] = dem_nodata
*/
    __pyx_t_15 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 863, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_16 = __Pyx_PyLong_AddObjC(__pyx_t_15, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 863, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __pyx_t_15 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 863, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_t_15, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 863, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __pyx_t_15 = PyTuple_New(2); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 863, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __Pyx_GIVEREF(__pyx_t_16);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_t_16) != (0)) __PYX_ERR(0, 863, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 863, __pyx_L1_error);
    __pyx_t_16 = 0;
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":864
 *         dem_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)             # <<<<<<<<<<<<<<
 *         dem_buffer_array[:] = dem_nodata
 * 
*/
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 864, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 864, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_4))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_3, __pyx_t_15};
      __pyx_t_2 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 862, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_16, __pyx_t_2, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 862, __pyx_L1_error)
      __pyx_t_20 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_2);
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 862, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }

    /* "pygeoprocessing/routing/routing.pyx":862
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
*/
    if (!(likely(((__pyx_t_20) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_20, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 862, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
      __pyx_t_14 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_20), &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_14 < 0)) {
        PyErr_Fetch(&__pyx_t_13, &__pyx_t_12, &__pyx_t_11);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_dem_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_13, __pyx_t_12, __pyx_t_11);
        }
        __pyx_t_13 = __pyx_t_12 = __pyx_t_11 = 0;
      }
      __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_14 < 0))) __PYX_ERR(0, 862, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_dem_buffer_array, ((PyArrayObject *)__pyx_t_20));
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":865
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
 *         dem_buffer_array[:] = dem_nodata             # <<<<<<<<<<<<<<
 * 
 *         # attempt to expand read block by a pixel boundary
*/
    __pyx_t_20 = PyFloat_FromDouble(__pyx_v_dem_nodata); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 865, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_dem_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_t_20) < 0))) __PYX_ERR(0, 865, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":868
 * 
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
*/
    __pyx_t_4 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 868, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":869
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)
*/
    __pyx_t_16 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 869, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __pyx_t_15 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 869, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_4);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_4, __pyx_v_offset_dict, __pyx_t_16, __pyx_t_15};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (4-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 868, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_20))) || (PyList_CheckExact(__pyx_t_20))) {
      PyObject* sequence = __pyx_t_20;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 868, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_15 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_15);
      } else {
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_15 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_15);
      }
      #else
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 868, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_15 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 868, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      #endif
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_16 = PyObject_GetIter(__pyx_t_20); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 868, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
      __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_16);
      index = 0; __pyx_t_2 = __pyx_t_8(__pyx_t_16); if (unlikely(!__pyx_t_2)) goto __pyx_L23_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      index = 1; __pyx_t_15 = __pyx_t_8(__pyx_t_16); if (unlikely(!__pyx_t_15)) goto __pyx_L23_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_15);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_16), 2) < (0)) __PYX_ERR(0, 868, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      goto __pyx_L24_unpacking_done;
      __pyx_L23_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 868, __pyx_L1_error)
      __pyx_L24_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":868
 * 
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 868, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_16);
        __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_4);
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_3);
        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_17);
      } else {
        __pyx_t_16 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_16);
        __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_4);
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
        __pyx_t_17 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 868, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_17);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_16,&__pyx_t_4,&__pyx_t_3,&__pyx_t_17};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 868, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_16,&__pyx_t_4,&__pyx_t_3,&__pyx_t_17};
      __pyx_t_18 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 868, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_18);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_18);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_8(__pyx_t_18); if (unlikely(!item)) goto __pyx_L25_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_18), 4) < (0)) __PYX_ERR(0, 868, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      goto __pyx_L26_unpacking_done;
      __pyx_L25_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 868, __pyx_L1_error)
      __pyx_L26_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_16);
    __pyx_t_16 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_4);
    __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_3);
    __pyx_t_3 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_17);
    __pyx_t_17 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_15);
    __pyx_t_15 = 0;

    /* "pygeoprocessing/routing/routing.pyx":870
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_dem_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":871
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 871, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_17 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 871, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
    } else {
      __pyx_t_17 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 870, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
    }

    /* "pygeoprocessing/routing/routing.pyx":870
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_17); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __pyx_t_15 = __pyx_t_3;
    __Pyx_INCREF(__pyx_t_15);

    /* "pygeoprocessing/routing/routing.pyx":871
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 871, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 871, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_15, __pyx_t_2};
      __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 871, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }

    /* "pygeoprocessing/routing/routing.pyx":870
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_3 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_2 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_15 = PyTuple_New(2); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __Pyx_GIVEREF(__pyx_t_3);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 870, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 870, __pyx_L1_error);
    __pyx_t_3 = 0;
    __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_dem_buffer_array), __pyx_t_15, __pyx_t_20) < 0))) __PYX_ERR(0, 870, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":874
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":875
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # search block for to set flow direction
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":878
 * 
 *         # search block for to set flow direction
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
*/
    __pyx_t_27 = (__pyx_v_win_ysize + 1);
    __pyx_t_28 = __pyx_t_27;
    for (__pyx_t_14 = 1; __pyx_t_14 < __pyx_t_28; __pyx_t_14+=1) {
      __pyx_v_yi = __pyx_t_14;

      /* "pygeoprocessing/routing/routing.pyx":879
 *         # search block for to set flow direction
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):
*/
      __pyx_t_29 = (__pyx_v_win_xsize + 1);
      __pyx_t_30 = __pyx_t_29;
      for (__pyx_t_31 = 1; __pyx_t_31 < __pyx_t_30; __pyx_t_31+=1) {
        __pyx_v_xi = __pyx_t_31;

        /* "pygeoprocessing/routing/routing.pyx":880
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]             # <<<<<<<<<<<<<<
 *                 if is_close(root_height, dem_nodata):
 *                     continue
*/
        __pyx_t_32 = __pyx_v_yi;
        __pyx_t_33 = __pyx_v_xi;
        __pyx_t_34 = -1;
        if (__pyx_t_32 < 0) {
          __pyx_t_32 += __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape;
          if (unlikely(__pyx_t_32 < 0)) __pyx_t_34 = 0;
        } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape)) __pyx_t_34 = 0;
        if (__pyx_t_33 < 0) {
          __pyx_t_33 += __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape;
          if (unlikely(__pyx_t_33 < 0)) __pyx_t_34 = 1;
        } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape)) __pyx_t_34 = 1;
        if (unlikely(__pyx_t_34 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_34);
          __PYX_ERR(0, 880, __pyx_L1_error)
        }
        __pyx_v_root_height = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float64_t *, __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_32, __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides));

        /* "pygeoprocessing/routing/routing.pyx":881
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_6 = is_close(__pyx_v_root_height, __pyx_v_dem_nodata);
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":882
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # this value is set in case it turns out to be the root of a
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":881
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":887
 *                 # pit, we'll start the fill from this pixel in the last phase
 *                 # of the algorithm
 *                 xi_root = xi-1+xoff             # <<<<<<<<<<<<<<
 *                 yi_root = yi-1+yoff
 * 
*/
        __pyx_v_xi_root = ((__pyx_v_xi - 1) + __pyx_v_xoff);

        /* "pygeoprocessing/routing/routing.pyx":888
 *                 # of the algorithm
 *                 xi_root = xi-1+xoff
 *                 yi_root = yi-1+yoff             # <<<<<<<<<<<<<<
 * 
 *                 if flow_dir_managed_raster.get(
*/
        __pyx_v_yi_root = ((__pyx_v_yi - 1) + __pyx_v_yoff);

        /* "pygeoprocessing/routing/routing.pyx":891
 * 
 *                 if flow_dir_managed_raster.get(
 *                         xi_root, yi_root) != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     # already been defined
 *                     continue
*/
        __pyx_t_6 = (__pyx_v_flow_dir_managed_raster.get(__pyx_v_xi_root, __pyx_v_yi_root) != __pyx_v_flow_dir_nodata);

        /* "pygeoprocessing/routing/routing.pyx":890
 *                 yi_root = yi-1+yoff
 * 
 *                 if flow_dir_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
*/
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":893
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # initialize variables to indicate the largest slope_dir is
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":890
 *                 yi_root = yi-1+yoff
 * 
 *                 if flow_dir_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":898
 *                 # undefined, the largest slope seen so far is flat, and the
 *                 # largest nodata is at least a diagonal away
 *                 largest_slope_dir = -1             # <<<<<<<<<<<<<<
 *                 largest_slope = 0.0
 * 
*/
        __pyx_v_largest_slope_dir = -1L;

        /* "pygeoprocessing/routing/routing.pyx":899
 *                 # largest nodata is at least a diagonal away
 *                 largest_slope_dir = -1
 *                 largest_slope = 0.0             # <<<<<<<<<<<<<<
 * 
 *                 for i_n in range(8):
*/
        __pyx_v_largest_slope = 0.0;

        /* "pygeoprocessing/routing/routing.pyx":901
 *                 largest_slope = 0.0
 * 
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]
*/
        for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
          __pyx_v_i_n = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":902
 * 
 *                 for i_n in range(8):
 *                     xi_n = xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
*/
          __pyx_v_xi_n = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":903
 *                 for i_n in range(8):
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):
*/
          __pyx_v_yi_n = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":904
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]             # <<<<<<<<<<<<<<
 *                     if is_close(n_height, dem_nodata):
 *                         continue
*/
          __pyx_t_33 = __pyx_v_yi_n;
          __pyx_t_32 = __pyx_v_xi_n;
          __pyx_t_35 = -1;
          if (__pyx_t_33 < 0) {
            __pyx_t_33 += __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape;
            if (unlikely(__pyx_t_33 < 0)) __pyx_t_35 = 0;
          } else if (unlikely(__pyx_t_33 >= __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape)) __pyx_t_35 = 0;
          if (__pyx_t_32 < 0) {
            __pyx_t_32 += __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape;
            if (unlikely(__pyx_t_32 < 0)) __pyx_t_35 = 1;
          } else if (unlikely(__pyx_t_32 >= __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape)) __pyx_t_35 = 1;
          if (unlikely(__pyx_t_35 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_35);
            __PYX_ERR(0, 904, __pyx_L1_error)
          }
          __pyx_v_n_height = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float64_t *, __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides, __pyx_t_32, __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides));

          /* "pygeoprocessing/routing/routing.pyx":905
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         continue
 *                     n_slope = root_height - n_height
*/
          __pyx_t_6 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":906
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):
 *                         continue             # <<<<<<<<<<<<<<
 *                     n_slope = root_height - n_height
 *                     if i_n & 1:
*/
            goto __pyx_L33_continue;

            /* "pygeoprocessing/routing/routing.pyx":905
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         continue
 *                     n_slope = root_height - n_height
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":907
 *                     if is_close(n_height, dem_nodata):
 *                         continue
 *                     n_slope = root_height - n_height             # <<<<<<<<<<<<<<
 *                     if i_n & 1:
 *                         # if diagonal, adjust the slope
*/
          __pyx_v_n_slope = (__pyx_v_root_height - __pyx_v_n_height);

          /* "pygeoprocessing/routing/routing.pyx":908
 *                         continue
 *                     n_slope = root_height - n_height
 *                     if i_n & 1:             # <<<<<<<<<<<<<<
 *                         # if diagonal, adjust the slope
 *                         n_slope *= SQRT2_INV
*/
          __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":910
 *                     if i_n & 1:
 *                         # if diagonal, adjust the slope
 *                         n_slope *= SQRT2_INV             # <<<<<<<<<<<<<<
 *                     if n_slope > largest_slope:
 *                         largest_slope_dir = i_n
*/
            __pyx_v_n_slope = (__pyx_v_n_slope * __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV);

            /* "pygeoprocessing/routing/routing.pyx":908
 *                         continue
 *                     n_slope = root_height - n_height
 *                     if i_n & 1:             # <<<<<<<<<<<<<<
 *                         # if diagonal, adjust the slope
 *                         n_slope *= SQRT2_INV
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":911
 *                         # if diagonal, adjust the slope
 *                         n_slope *= SQRT2_INV
 *                     if n_slope > largest_slope:             # <<<<<<<<<<<<<<
 *                         largest_slope_dir = i_n
 *                         largest_slope = n_slope
*/
          __pyx_t_6 = (__pyx_v_n_slope > __pyx_v_largest_slope);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":912
 *                         n_slope *= SQRT2_INV
 *                     if n_slope > largest_slope:
 *                         largest_slope_dir = i_n             # <<<<<<<<<<<<<<
 *                         largest_slope = n_slope
 * 
*/
            __pyx_v_largest_slope_dir = __pyx_v_i_n;

            /* "pygeoprocessing/routing/routing.pyx":913
 *                     if n_slope > largest_slope:
 *                         largest_slope_dir = i_n
 *                         largest_slope = n_slope             # <<<<<<<<<<<<<<
 * 
 *                 if largest_slope_dir >= 0:
*/
            __pyx_v_largest_slope = __pyx_v_n_slope;

            /* "pygeoprocessing/routing/routing.pyx":911
 *                         # if diagonal, adjust the slope
 *                         n_slope *= SQRT2_INV
 *                     if n_slope > largest_slope:             # <<<<<<<<<<<<<<
 *                         largest_slope_dir = i_n
 *                         largest_slope = n_slope
*/
          }
          __pyx_L33_continue:;
        }

        /* "pygeoprocessing/routing/routing.pyx":915
 *                         largest_slope = n_slope
 * 
 *                 if largest_slope_dir >= 0:             # <<<<<<<<<<<<<<
 *                     # define flow dir and move on
 *                     flow_dir_managed_raster.set(
*/
        __pyx_t_6 = (__pyx_v_largest_slope_dir >= 0);
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":917
 *                 if largest_slope_dir >= 0:
 *                     # define flow dir and move on
 *                     flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root, largest_slope_dir)
 *                     continue
*/
          __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, __pyx_v_largest_slope_dir);

          /* "pygeoprocessing/routing/routing.pyx":919
 *                     flow_dir_managed_raster.set(
 *                         xi_root, yi_root, largest_slope_dir)
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # otherwise, this pixel doesn't drain locally, so it must
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":915
 *                         largest_slope = n_slope
 * 
 *                 if largest_slope_dir >= 0:             # <<<<<<<<<<<<<<
 *                     # define flow dir and move on
 *                     flow_dir_managed_raster.set(
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":923
 *                 # otherwise, this pixel doesn't drain locally, so it must
 *                 # be a plateau, search for the drains of the plateau
 *                 search_queue.push(CoordinateType(xi_root, yi_root))             # <<<<<<<<<<<<<<
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)
 * 
*/
        __pyx_t_36.xi = __pyx_v_xi_root;
        __pyx_t_36.yi = __pyx_v_yi_root;
        __pyx_v_search_queue.push(__pyx_t_36);

        /* "pygeoprocessing/routing/routing.pyx":924
 *                 # be a plateau, search for the drains of the plateau
 *                 search_queue.push(CoordinateType(xi_root, yi_root))
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 * 
 *                 # this loop does a BFS starting at this pixel to all pixels
*/
        __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

        /* "pygeoprocessing/routing/routing.pyx":930
 *                 # on a queue for later processing.
 * 
 *                 while not search_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_search_queue.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":931
 * 
 *                 while not search_queue.empty():
 *                     xi_q = search_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()
*/
          __pyx_t_10 = __pyx_v_search_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_10;

          /* "pygeoprocessing/routing/routing.pyx":932
 *                 while not search_queue.empty():
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi             # <<<<<<<<<<<<<<
 *                     search_queue.pop()
 * 
*/
          __pyx_t_10 = __pyx_v_search_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_10;

          /* "pygeoprocessing/routing/routing.pyx":933
 *                     xi_q = search_queue.front().xi
 *                     yi_q = search_queue.front().yi
 *                     search_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     largest_slope_dir = -1
*/
          __pyx_v_search_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":935
 *                     search_queue.pop()
 * 
 *                     largest_slope_dir = -1             # <<<<<<<<<<<<<<
 *                     largest_slope = 0.0
 *                     diagonal_nodata = 1
*/
          __pyx_v_largest_slope_dir = -1L;

          /* "pygeoprocessing/routing/routing.pyx":936
 * 
 *                     largest_slope_dir = -1
 *                     largest_slope = 0.0             # <<<<<<<<<<<<<<
 *                     diagonal_nodata = 1
 *                     for i_n in range(8):
*/
          __pyx_v_largest_slope = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":937
 *                     largest_slope_dir = -1
 *                     largest_slope = 0.0
 *                     diagonal_nodata = 1             # <<<<<<<<<<<<<<
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
*/
          __pyx_v_diagonal_nodata = 1;

          /* "pygeoprocessing/routing/routing.pyx":938
 *                     largest_slope = 0.0
 *                     diagonal_nodata = 1
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":939
 *                     diagonal_nodata = 1
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":940
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":942
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
            __pyx_t_23 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L44_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L44_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":943
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             n_height = dem_nodata
 *                         else:
*/
            __pyx_t_23 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L44_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L44_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":942
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":944
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata             # <<<<<<<<<<<<<<
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
*/
              __pyx_v_n_height = __pyx_v_dem_nodata;

              /* "pygeoprocessing/routing/routing.pyx":942
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
              goto __pyx_L43;
            }

            /* "pygeoprocessing/routing/routing.pyx":946
 *                             n_height = dem_nodata
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                         if is_close(n_height, dem_nodata):
 *                             if diagonal_nodata and largest_slope == 0.0:
*/
            /*else*/ {
              __pyx_v_n_height = __pyx_v_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);
            }
            __pyx_L43:;

            /* "pygeoprocessing/routing/routing.pyx":947
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             if diagonal_nodata and largest_slope == 0.0:
 *                                 largest_slope_dir = i_n
*/
            __pyx_t_6 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":948
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             if diagonal_nodata and largest_slope == 0.0:             # <<<<<<<<<<<<<<
 *                                 largest_slope_dir = i_n
 *                                 diagonal_nodata = i_n & 1
*/
              __pyx_t_23 = (__pyx_v_diagonal_nodata != 0);
              if (__pyx_t_23) {
              } else {
                __pyx_t_6 = __pyx_t_23;
                goto __pyx_L50_bool_binop_done;
              }
              __pyx_t_23 = (__pyx_v_largest_slope == 0.0);
              __pyx_t_6 = __pyx_t_23;
              __pyx_L50_bool_binop_done:;
              if (__pyx_t_6) {

                /* "pygeoprocessing/routing/routing.pyx":949
 *                         if is_close(n_height, dem_nodata):
 *                             if diagonal_nodata and largest_slope == 0.0:
 *                                 largest_slope_dir = i_n             # <<<<<<<<<<<<<<
 *                                 diagonal_nodata = i_n & 1
 *                             continue
*/
                __pyx_v_largest_slope_dir = __pyx_v_i_n;

                /* "pygeoprocessing/routing/routing.pyx":950
 *                             if diagonal_nodata and largest_slope == 0.0:
 *                                 largest_slope_dir = i_n
 *                                 diagonal_nodata = i_n & 1             # <<<<<<<<<<<<<<
 *                             continue
 *                         n_slope = root_height - n_height
*/
                __pyx_v_diagonal_nodata = (__pyx_v_i_n & 1);

                /* "pygeoprocessing/routing/routing.pyx":948
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             if diagonal_nodata and largest_slope == 0.0:             # <<<<<<<<<<<<<<
 *                                 largest_slope_dir = i_n
 *                                 diagonal_nodata = i_n & 1
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":951
 *                                 largest_slope_dir = i_n
 *                                 diagonal_nodata = i_n & 1
 *                             continue             # <<<<<<<<<<<<<<
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:
*/
              goto __pyx_L41_continue;

              /* "pygeoprocessing/routing/routing.pyx":947
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             if diagonal_nodata and largest_slope == 0.0:
 *                                 largest_slope_dir = i_n
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":952
 *                                 diagonal_nodata = i_n & 1
 *                             continue
 *                         n_slope = root_height - n_height             # <<<<<<<<<<<<<<
 *                         if n_slope < 0:
 *                             continue
*/
            __pyx_v_n_slope = (__pyx_v_root_height - __pyx_v_n_height);

            /* "pygeoprocessing/routing/routing.pyx":953
 *                             continue
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_slope == 0.0:
*/
            __pyx_t_6 = (__pyx_v_n_slope < 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":954
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(
*/
              goto __pyx_L41_continue;

              /* "pygeoprocessing/routing/routing.pyx":953
 *                             continue
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_slope == 0.0:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":955
 *                         if n_slope < 0:
 *                             continue
 *                         if n_slope == 0.0:             # <<<<<<<<<<<<<<
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:
*/
            __pyx_t_6 = (__pyx_v_n_slope == 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":957
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:             # <<<<<<<<<<<<<<
 *                                 # only grow if it's at the same level and not
 *                                 # previously visited
*/
              __pyx_t_6 = (__pyx_v_flat_region_mask_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == __pyx_v_mask_nodata);

              /* "pygeoprocessing/routing/routing.pyx":956
 *                             continue
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n) == mask_nodata:
 *                                 # only grow if it's at the same level and not
*/
              if (__pyx_t_6) {

                /* "pygeoprocessing/routing/routing.pyx":960
 *                                 # only grow if it's at the same level and not
 *                                 # previously visited
 *                                 search_queue.push(CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                                 flat_region_mask_managed_raster.set(
 *                                     xi_n, yi_n, 1)
*/
                __pyx_t_36.xi = __pyx_v_xi_n;
                __pyx_t_36.yi = __pyx_v_yi_n;
                __pyx_v_search_queue.push(__pyx_t_36);

                /* "pygeoprocessing/routing/routing.pyx":961
 *                                 # previously visited
 *                                 search_queue.push(CoordinateType(xi_n, yi_n))
 *                                 flat_region_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n, 1)
 *                             continue
*/
                __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

                /* "pygeoprocessing/routing/routing.pyx":956
 *                             continue
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n) == mask_nodata:
 *                                 # only grow if it's at the same level and not
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":963
 *                                 flat_region_mask_managed_raster.set(
 *                                     xi_n, yi_n, 1)
 *                             continue             # <<<<<<<<<<<<<<
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV
*/
              goto __pyx_L41_continue;

              /* "pygeoprocessing/routing/routing.pyx":955
 *                         if n_slope < 0:
 *                             continue
 *                         if n_slope == 0.0:             # <<<<<<<<<<<<<<
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":964
 *                                     xi_n, yi_n, 1)
 *                             continue
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             n_slope *= SQRT2_INV
 *                         if n_slope > largest_slope:
*/
            __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":965
 *                             continue
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV             # <<<<<<<<<<<<<<
 *                         if n_slope > largest_slope:
 *                             largest_slope = n_slope
*/
              __pyx_v_n_slope = (__pyx_v_n_slope * __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV);

              /* "pygeoprocessing/routing/routing.pyx":964
 *                                     xi_n, yi_n, 1)
 *                             continue
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             n_slope *= SQRT2_INV
 *                         if n_slope > largest_slope:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":966
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV
 *                         if n_slope > largest_slope:             # <<<<<<<<<<<<<<
 *                             largest_slope = n_slope
 *                             largest_slope_dir = i_n
*/
            __pyx_t_6 = (__pyx_v_n_slope > __pyx_v_largest_slope);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":967
 *                             n_slope *= SQRT2_INV
 *                         if n_slope > largest_slope:
 *                             largest_slope = n_slope             # <<<<<<<<<<<<<<
 *                             largest_slope_dir = i_n
 * 
*/
              __pyx_v_largest_slope = __pyx_v_n_slope;

              /* "pygeoprocessing/routing/routing.pyx":968
 *                         if n_slope > largest_slope:
 *                             largest_slope = n_slope
 *                             largest_slope_dir = i_n             # <<<<<<<<<<<<<<
 * 
 *                     if largest_slope_dir >= 0:
*/
              __pyx_v_largest_slope_dir = __pyx_v_i_n;

              /* "pygeoprocessing/routing/routing.pyx":966
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV
 *                         if n_slope > largest_slope:             # <<<<<<<<<<<<<<
 *                             largest_slope = n_slope
 *                             largest_slope_dir = i_n
*/
            }
            __pyx_L41_continue:;
          }

          /* "pygeoprocessing/routing/routing.pyx":970
 *                             largest_slope_dir = i_n
 * 
 *                     if largest_slope_dir >= 0:             # <<<<<<<<<<<<<<
 *                         if largest_slope > 0.0:
 *                             # regular downhill pixel
*/
          __pyx_t_6 = (__pyx_v_largest_slope_dir >= 0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":971
 * 
 *                     if largest_slope_dir >= 0:
 *                         if largest_slope > 0.0:             # <<<<<<<<<<<<<<
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(
*/
            __pyx_t_6 = (__pyx_v_largest_slope > 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":973
 *                         if largest_slope > 0.0:
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_q, yi_q, largest_slope_dir)
 *                             plateau_distance_managed_raster.set(
*/
              __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_largest_slope_dir);

              /* "pygeoprocessing/routing/routing.pyx":975
 *                             flow_dir_managed_raster.set(
 *                                 xi_q, yi_q, largest_slope_dir)
 *                             plateau_distance_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_q, yi_q, 0.0)
 *                             drain_queue.push(CoordinateType(xi_q, yi_q))
*/
              __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 0.0);

              /* "pygeoprocessing/routing/routing.pyx":977
 *                             plateau_distance_managed_raster.set(
 *                                 xi_q, yi_q, 0.0)
 *                             drain_queue.push(CoordinateType(xi_q, yi_q))             # <<<<<<<<<<<<<<
 *                         else:
 *                             # must be a nodata drain, save on queue for later
*/
              __pyx_t_36.xi = __pyx_v_xi_q;
              __pyx_t_36.yi = __pyx_v_yi_q;
              __pyx_v_drain_queue.push(__pyx_t_36);

              /* "pygeoprocessing/routing/routing.pyx":971
 * 
 *                     if largest_slope_dir >= 0:
 *                         if largest_slope > 0.0:             # <<<<<<<<<<<<<<
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(
*/
              goto __pyx_L58;
            }

            /* "pygeoprocessing/routing/routing.pyx":980
 *                         else:
 *                             # must be a nodata drain, save on queue for later
 *                             nodata_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(largest_slope_dir)
*/
            /*else*/ {

              /* "pygeoprocessing/routing/routing.pyx":981
 *                             # must be a nodata drain, save on queue for later
 *                             nodata_drain_queue.push(
 *                                 CoordinateType(xi_q, yi_q))             # <<<<<<<<<<<<<<
 *                             nodata_flow_dir_queue.push(largest_slope_dir)
 * 
*/
              __pyx_t_36.xi = __pyx_v_xi_q;
              __pyx_t_36.yi = __pyx_v_yi_q;

              /* "pygeoprocessing/routing/routing.pyx":980
 *                         else:
 *                             # must be a nodata drain, save on queue for later
 *                             nodata_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(largest_slope_dir)
*/
              __pyx_v_nodata_drain_queue.push(__pyx_t_36);

              /* "pygeoprocessing/routing/routing.pyx":982
 *                             nodata_drain_queue.push(
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(largest_slope_dir)             # <<<<<<<<<<<<<<
 * 
 *                 # if there's no downhill drains, try the nodata drains
*/
              __pyx_v_nodata_flow_dir_queue.push(__pyx_v_largest_slope_dir);
            }
            __pyx_L58:;

            /* "pygeoprocessing/routing/routing.pyx":970
 *                             largest_slope_dir = i_n
 * 
 *                     if largest_slope_dir >= 0:             # <<<<<<<<<<<<<<
 *                         if largest_slope > 0.0:
 *                             # regular downhill pixel
*/
          }
        }

        /* "pygeoprocessing/routing/routing.pyx":985
 * 
 *                 # if there's no downhill drains, try the nodata drains
 *                 if drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     # push the nodata drain queue over to the drain queue
 *                     # and set all the flow directions on the nodata drain
*/
        __pyx_t_6 = __pyx_v_drain_queue.empty();
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":989
 *                     # and set all the flow directions on the nodata drain
 *                     # pixels
 *                     while not nodata_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                         xi_q = nodata_drain_queue.front().xi
 *                         yi_q = nodata_drain_queue.front().yi
*/
          while (1) {
            __pyx_t_6 = (!__pyx_v_nodata_drain_queue.empty());
            if (!__pyx_t_6) break;

            /* "pygeoprocessing/routing/routing.pyx":990
 *                     # pixels
 *                     while not nodata_drain_queue.empty():
 *                         xi_q = nodata_drain_queue.front().xi             # <<<<<<<<<<<<<<
 *                         yi_q = nodata_drain_queue.front().yi
 *                         flow_dir_managed_raster.set(
*/
            __pyx_t_10 = __pyx_v_nodata_drain_queue.front().xi;
            __pyx_v_xi_q = __pyx_t_10;

            /* "pygeoprocessing/routing/routing.pyx":991
 *                     while not nodata_drain_queue.empty():
 *                         xi_q = nodata_drain_queue.front().xi
 *                         yi_q = nodata_drain_queue.front().yi             # <<<<<<<<<<<<<<
 *                         flow_dir_managed_raster.set(
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
*/
            __pyx_t_10 = __pyx_v_nodata_drain_queue.front().yi;
            __pyx_v_yi_q = __pyx_t_10;

            /* "pygeoprocessing/routing/routing.pyx":992
 *                         xi_q = nodata_drain_queue.front().xi
 *                         yi_q = nodata_drain_queue.front().yi
 *                         flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
*/
            __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_nodata_flow_dir_queue.front());

            /* "pygeoprocessing/routing/routing.pyx":994
 *                         flow_dir_managed_raster.set(
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)             # <<<<<<<<<<<<<<
 *                         drain_queue.push(nodata_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()
*/
            __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 0.0);

            /* "pygeoprocessing/routing/routing.pyx":995
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
 *                         drain_queue.push(nodata_drain_queue.front())             # <<<<<<<<<<<<<<
 *                         nodata_flow_dir_queue.pop()
 *                         nodata_drain_queue.pop()
*/
            __pyx_v_drain_queue.push(__pyx_v_nodata_drain_queue.front());

            /* "pygeoprocessing/routing/routing.pyx":996
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
 *                         drain_queue.push(nodata_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()             # <<<<<<<<<<<<<<
 *                         nodata_drain_queue.pop()
 *                 else:
*/
            __pyx_v_nodata_flow_dir_queue.pop();

            /* "pygeoprocessing/routing/routing.pyx":997
 *                         drain_queue.push(nodata_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()
 *                         nodata_drain_queue.pop()             # <<<<<<<<<<<<<<
 *                 else:
 *                     # clear the nodata drain queues
*/
            __pyx_v_nodata_drain_queue.pop();
          }

          /* "pygeoprocessing/routing/routing.pyx":985
 * 
 *                 # if there's no downhill drains, try the nodata drains
 *                 if drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     # push the nodata drain queue over to the drain queue
 *                     # and set all the flow directions on the nodata drain
*/
          goto __pyx_L59;
        }

        /* "pygeoprocessing/routing/routing.pyx":1000
 *                 else:
 *                     # clear the nodata drain queues
 *                     nodata_flow_dir_queue = IntQueueType()             # <<<<<<<<<<<<<<
 *                     nodata_drain_queue = CoordinateQueueType()
 * 
*/
        /*else*/ {
          try {
            __pyx_t_37 = __pyx_t_15pygeoprocessing_7routing_7routing_IntQueueType();
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1000, __pyx_L1_error)
          }
          __pyx_v_nodata_flow_dir_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_37);

          /* "pygeoprocessing/routing/routing.pyx":1001
 *                     # clear the nodata drain queues
 *                     nodata_flow_dir_queue = IntQueueType()
 *                     nodata_drain_queue = CoordinateQueueType()             # <<<<<<<<<<<<<<
 * 
 *                 # this loop does a BFS from the plateau drain to any other
*/
          try {
            __pyx_t_38 = __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType();
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1001, __pyx_L1_error)
          }
          __pyx_v_nodata_drain_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_38);
        }
        __pyx_L59:;

        /* "pygeoprocessing/routing/routing.pyx":1005
 *                 # this loop does a BFS from the plateau drain to any other
 *                 # neighboring undefined pixels
 *                 while not drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = drain_queue.front().xi
 *                     yi_q = drain_queue.front().yi
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_drain_queue.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":1006
 *                 # neighboring undefined pixels
 *                 while not drain_queue.empty():
 *                     xi_q = drain_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = drain_queue.front().yi
 *                     drain_queue.pop()
*/
          __pyx_t_10 = __pyx_v_drain_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_10;

          /* "pygeoprocessing/routing/routing.pyx":1007
 *                 while not drain_queue.empty():
 *                     xi_q = drain_queue.front().xi
 *                     yi_q = drain_queue.front().yi             # <<<<<<<<<<<<<<
 *                     drain_queue.pop()
 * 
*/
          __pyx_t_10 = __pyx_v_drain_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_10;

          /* "pygeoprocessing/routing/routing.pyx":1008
 *                     xi_q = drain_queue.front().xi
 *                     yi_q = drain_queue.front().yi
 *                     drain_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(
*/
          __pyx_v_drain_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":1010
 *                     drain_queue.pop()
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_q, yi_q)
 * 
*/
          __pyx_v_drain_distance = __pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_q, __pyx_v_yi_q);

          /* "pygeoprocessing/routing/routing.pyx":1013
 *                         xi_q, yi_q)
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1014
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1015
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1016
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_23 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L67_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L67_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1017
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_23 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L67_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L67_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1016
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1018
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         n_drain_distance = drain_distance + (
*/
              goto __pyx_L64_continue;

              /* "pygeoprocessing/routing/routing.pyx":1016
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1021
 * 
 *                         n_drain_distance = drain_distance + (
 *                             SQRT2 if i_n & 1 else 1.0)             # <<<<<<<<<<<<<<
 * 
 *                         if dem_managed_raster.get(
*/
            __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
            if (__pyx_t_6) {
              __pyx_t_7 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2;
            } else {
              __pyx_t_7 = 1.0;
            }

            /* "pygeoprocessing/routing/routing.pyx":1020
 *                             continue
 * 
 *                         n_drain_distance = drain_distance + (             # <<<<<<<<<<<<<<
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
*/
            __pyx_v_n_drain_distance = (__pyx_v_drain_distance + __pyx_t_7);

            /* "pygeoprocessing/routing/routing.pyx":1024
 * 
 *                         if dem_managed_raster.get(
 *                                 xi_n, yi_n) == root_height and (             # <<<<<<<<<<<<<<
 *                                 plateau_distance_managed_raster.get(
 *                                     xi_n, yi_n) > n_drain_distance):
*/
            __pyx_t_23 = (__pyx_v_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == __pyx_v_root_height);
            if (__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L72_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1026
 *                                 xi_n, yi_n) == root_height and (
 *                                 plateau_distance_managed_raster.get(
 *                                     xi_n, yi_n) > n_drain_distance):             # <<<<<<<<<<<<<<
 *                             # neighbor is at same level and has longer drain
 *                             # flow path than current
*/
            __pyx_t_23 = (__pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) > __pyx_v_n_drain_distance);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L72_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1023
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
 *                         if dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == root_height and (
 *                                 plateau_distance_managed_raster.get(
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1029
 *                             # neighbor is at same level and has longer drain
 *                             # flow path than current
 *                             flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, INFLOW_OFFSETS[i_n])
 *                             plateau_distance_managed_raster.set(
*/
              __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, (INFLOW_OFFSETS[__pyx_v_i_n]));

              /* "pygeoprocessing/routing/routing.pyx":1031
 *                             flow_dir_managed_raster.set(
 *                                 xi_n, yi_n, INFLOW_OFFSETS[i_n])
 *                             plateau_distance_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, n_drain_distance)
 *                             drain_queue.push(CoordinateType(xi_n, yi_n))
*/
              __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, __pyx_v_n_drain_distance);

              /* "pygeoprocessing/routing/routing.pyx":1033
 *                             plateau_distance_managed_raster.set(
 *                                 xi_n, yi_n, n_drain_distance)
 *                             drain_queue.push(CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *     dem_band = None
 *     dem_raster = None
*/
              __pyx_t_36.xi = __pyx_v_xi_n;
              __pyx_t_36.yi = __pyx_v_yi_n;
              __pyx_v_drain_queue.push(__pyx_t_36);

              /* "pygeoprocessing/routing/routing.pyx":1023
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
 *                         if dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n) == root_height and (
 *                                 plateau_distance_managed_raster.get(
*/
            }
            __pyx_L64_continue:;
          }
        }
        __pyx_L29_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":845
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1034
 *                                 xi_n, yi_n, n_drain_distance)
 *                             drain_queue.push(CoordinateType(xi_n, yi_n))
 *     dem_band = None             # <<<<<<<<<<<<<<
 *     dem_raster = None
 *     flow_dir_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_dem_band, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":1035
 *                             drain_queue.push(CoordinateType(xi_n, yi_n))
 *     dem_band = None
 *     dem_raster = None             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_dem_raster, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":1036
 *     dem_band = None
 *     dem_raster = None
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1037
 *     dem_raster = None
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()             # <<<<<<<<<<<<<<
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()
*/
  __pyx_v_flat_region_mask_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1038
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()             # <<<<<<<<<<<<<<
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
*/
  __pyx_v_dem_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1039
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()             # <<<<<<<<<<<<<<
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('(flow dir d8): complete')
*/
  __pyx_v_plateau_distance_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1040
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)             # <<<<<<<<<<<<<<
 *     LOGGER.info('(flow dir d8): complete')
 * 
*/
  __pyx_t_20 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1040, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1040, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_20 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_20);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_20);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_20, __pyx_v_working_dir_path};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_20); __pyx_t_20 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1040, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1041
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('(flow dir d8): complete')             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_20, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1041, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_20, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1041, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_15))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_15);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_flow_dir_d8_complete};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1041, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":674
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_15);
  __Pyx_XDECREF(__pyx_t_16);
  __Pyx_XDECREF(__pyx_t_17);
  __Pyx_XDECREF(__pyx_t_18);
  __Pyx_XDECREF(__pyx_t_19);
  __Pyx_XDECREF(__pyx_t_20);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_dir_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_dem_buffer_array);
  __Pyx_XDECREF(__pyx_v_dem_raster_info);
  __Pyx_XDECREF(__pyx_v_base_nodata);
  __Pyx_XDECREF(__pyx_v_working_dir_path);
  __Pyx_XDECREF(__pyx_v_flat_region_mask_path);
  __Pyx_XDECREF(__pyx_v_plateau_distance_path);
  __Pyx_XDECREF(__pyx_v_compatable_dem_raster_path_band);
  __Pyx_XDECREF(__pyx_v_dem_block_xsize);
  __Pyx_XDECREF(__pyx_v_dem_block_ysize);
  __Pyx_XDECREF(__pyx_v_raster_driver);
  __Pyx_XDECREF(__pyx_v_dem_raster);
  __Pyx_XDECREF(__pyx_v_dem_band);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":1044
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_36__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":1048
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
 *         weight_raster_path_band=None, custom_decay_factor=None,
 *         double min_decay_proportion=0.001,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """D8 flow accumulation.
*/
  __pyx_t_1 = PyFloat_FromDouble(((double)0.001)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1048, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":1044
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
*/
  __pyx_t_2 = PyTuple_New(4); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1044, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, Py_None) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_t_1) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 3, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1044, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, Py_None) != (0)) __PYX_ERR(0, 1044, __pyx_L1_error);
  __pyx_t_2 = 0;
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_7flow_accumulation_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_6flow_accumulation_d8, "D8 flow accumulation.\n\n    Parameters:\n        flow_dir_raster_path_band (tuple): a path, band number tuple\n            for a flow accumulation raster whose pixels indicate the flow\n            out of a pixel in one of 8 directions in the following\n            configuration::\n\n                3 2 1\n                4 x 0\n                5 6 7\n\n            Paths may use any GDAL-supported scheme, including virtual\n            file system /vsi schemes.\n        target_flow_accum_raster_path (str): path to flow\n            accumulation raster created by this call. After this call, the\n            value of each pixel will be 1 plus the number of upstream pixels\n            that drain to that pixel. Note the target type of this raster\n            is a 64 bit float so there is minimal risk of overflow and the\n            possibility of handling a float dtype in\n            ``weight_raster_path_band``.\n        weight_raster_path_band (tuple): optional path and band number to a\n            raster that will be used as the per-pixel flow accumulation\n            weight. If ``None``, 1 is the default flow accumulation weight.\n            This raster must be the same dimensions as\n            ``flow_dir_mfd_raster_path_band``.\n        custom_decay_factor=None (float or tuple): a custom decay factor, either\n            represented as a float (where the same decay factor is applied to\n            all valid pixels) or a path/band tuple for a raster where pixel\n            values represent spatially-explicit decay values. As the on-pixel\n            load passes through a pixel, the decay factor is applied, so you\n            could think of this layer as representing the proportion of a\n            pollutant that is absorbed by the landscape as it passes through\n            along the flowpath.\n        min_decay_proportion=0.001 (float): A value representing the minimum\n            decayed value that should continue to be tracked along the flow\n     ""       path when using a custom decay factor.  If the upstream decayed\n            contribution falls below this value, it is not included.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_7flow_accumulation_d8 = {"flow_accumulation_d8", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_7flow_accumulation_d8, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_6flow_accumulation_d8};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_7flow_accumulation_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_raster_path_band = 0;
  PyObject *__pyx_v_target_flow_accum_raster_path = 0;
  PyObject *__pyx_v_weight_raster_path_band = 0;
  PyObject *__pyx_v_custom_decay_factor = 0;
  double __pyx_v_min_decay_proportion;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[6] = {0,0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("flow_accumulation_d8 (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_flow_accum_raster_path,&__pyx_mstate_global->__pyx_n_u_weight_raster_path_band,&__pyx_mstate_global->__pyx_n_u_custom_decay_factor,&__pyx_mstate_global->__pyx_n_u_min_decay_proportion,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 1044, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "flow_accumulation_d8", 0) < (0)) __PYX_ERR(0, 1044, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":1047
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
 *         weight_raster_path_band=None, custom_decay_factor=None,             # <<<<<<<<<<<<<<
 *         double min_decay_proportion=0.001,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("flow_accumulation_d8", 0, 2, 6, i); __PYX_ERR(0, 1044, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1044, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1044, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1044, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_dir_raster_path_band = values[0];
    __pyx_v_target_flow_accum_raster_path = values[1];
    __pyx_v_weight_raster_path_band = values[2];
    __pyx_v_custom_decay_factor = values[3];
    if (values[4]) {
      __pyx_v_min_decay_proportion = __Pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_min_decay_proportion == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1048, __pyx_L3_error)
    } else {
      __pyx_v_min_decay_proportion = ((double)((double)0.001));
    }
    __pyx_v_raster_driver_creation_tuple = values[5];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("flow_accumulation_d8", 0, 2, 6, __pyx_nargs); __PYX_ERR(0, 1044, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_accumulation_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_6flow_accumulation_d8(__pyx_self, __pyx_v_flow_dir_raster_path_band, __pyx_v_target_flow_accum_raster_path, __pyx_v_weight_raster_path_band, __pyx_v_custom_decay_factor, __pyx_v_min_decay_proportion, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":1044
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_6flow_accumulation_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_raster_path_band, PyObject *__pyx_v_target_flow_accum_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_custom_decay_factor, double __pyx_v_min_decay_proportion, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_flow_dir_buffer_array = 0;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  int __pyx_v_flow_dir;
  int __pyx_v_upstream_flow_dir;
  int __pyx_v_flow_dir_nodata;
  double __pyx_v_upstream_flow_accum;
  double __pyx_v_weight_val;
  double __pyx_v_weight_nodata;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_WeightedFlowPixelType>  __pyx_v_search_stack;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_WeightedFlowPixelType __pyx_v_flow_pixel;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  unsigned long __pyx_v_current_pixel;
  time_t __pyx_v_last_log_time;
  double __pyx_v_flow_accum_nodata;
  ManagedRaster __pyx_v_flow_accum_managed_raster;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  PyObject *__pyx_v_flow_dir_raster = NULL;
  PyObject *__pyx_v_flow_dir_band = NULL;
  ManagedRaster __pyx_v_weight_raster;
  PyObject *__pyx_v_raw_weight_nodata = NULL;
  short __pyx_v_do_decayed_accumulation;
  short __pyx_v_use_const_decay_factor;
  float __pyx_v_decay_factor;
  double __pyx_v_decay_factor_nodata;
  ManagedRaster __pyx_v_decay_factor_managed_raster;
  PyObject *__pyx_v__tmp_decay_factor_nodata = NULL;
  PyObject *__pyx_v_flow_dir_raster_info = NULL;
  PyObject *__pyx_v_tmp_flow_dir_nodata = NULL;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue>  __pyx_v_decay_from_upstream;
  double __pyx_v_upstream_transport_factor;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue __pyx_v_upstream_decaying_value;
  long __pyx_v_upstream_pixels_remain;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue __pyx_v_decayed_value;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_flow_dir_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_flow_dir_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  size_t __pyx_t_4;
  int __pyx_t_5;
  int __pyx_t_6;
  int __pyx_t_7;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  PyObject *__pyx_t_10 = NULL;
  PyObject *__pyx_t_11 = NULL;
  char *__pyx_t_12;
  ManagedRaster __pyx_t_13;
  int __pyx_t_14;
  double __pyx_t_15;
  float __pyx_t_16;
  PyObject *(*__pyx_t_17)(PyObject *);
  unsigned int __pyx_t_18;
  unsigned int __pyx_t_19;
  Py_ssize_t __pyx_t_20;
  PyObject *(*__pyx_t_21)(PyObject *);
  PyObject *__pyx_t_22 = NULL;
  PyObject *__pyx_t_23 = NULL;
  PyObject *__pyx_t_24 = NULL;
  PyObject *__pyx_t_25 = NULL;
  PyObject *__pyx_t_26 = NULL;
  long __pyx_t_27;
  long __pyx_t_28;
  long __pyx_t_29;
  long __pyx_t_30;
  size_t __pyx_t_31;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_WeightedFlowPixelType __pyx_t_32;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue>  __pyx_t_33;
  unsigned int __pyx_t_34;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue __pyx_t_35;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("flow_accumulation_d8", 0);
  __pyx_pybuffer_flow_dir_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_flow_dir_buffer_array.refcount = 0;
  __pyx_pybuffernd_flow_dir_buffer_array.data = NULL;
  __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer = &__pyx_pybuffer_flow_dir_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":1121
 *     # come from a predefined flow accumulation weight raster
 *     cdef double weight_val
 *     cdef double weight_nodata = IMPROBABLE_FLOAT_NODATA  # set to something             # <<<<<<<<<<<<<<
 * 
 *     # `search_stack` is used to walk upstream to calculate flow accumulation
*/
  __pyx_v_weight_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":1135
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_raster_path_band):
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":1137
 *     last_log_time = ctime(NULL)
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1137, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_flow_dir_raster_path_band};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1137, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1137, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_6 = (!__pyx_t_5);
  if (unlikely(__pyx_t_6)) {

    /* "pygeoprocessing/routing/routing.pyx":1138
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_raster_path_band):
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_raster_path_band))
*/
    __pyx_t_3 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":1139
 *     if not _is_raster_path_band_formatted(flow_dir_raster_path_band):
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                 flow_dir_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
*/
    __pyx_t_2 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_flow_dir_raster_path_band); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1139, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1138, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __PYX_ERR(0, 1138, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1137
 *     last_log_time = ctime(NULL)
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1141
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1141, __pyx_L1_error)
  if (__pyx_t_5) {
  } else {
    __pyx_t_6 = __pyx_t_5;
    goto __pyx_L5_bool_binop_done;
  }
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1141, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":1142
 *                 flow_dir_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
 *             weight_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_weight_raster_path_band};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1141, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }

  /* "pygeoprocessing/routing/routing.pyx":1141
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1141, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_7 = (!__pyx_t_5);
  __pyx_t_6 = __pyx_t_7;
  __pyx_L5_bool_binop_done:;
  if (unlikely(__pyx_t_6)) {

    /* "pygeoprocessing/routing/routing.pyx":1143
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
 *             weight_raster_path_band):
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 weight_raster_path_band))
*/
    __pyx_t_3 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":1144
 *             weight_raster_path_band):
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band))
 * 
*/
    __pyx_t_2 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_weight_raster_path_band); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1144, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1143, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __PYX_ERR(0, 1143, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1141
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1147
 *                 weight_raster_path_band))
 * 
 *     flow_accum_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_raster_path_band[0], target_flow_accum_raster_path,
*/
  __pyx_v_flow_accum_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":1148
 * 
 *     flow_accum_nodata = IMPROBABLE_FLOAT_NODATA
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1148, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1148, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1149
 *     flow_accum_nodata = IMPROBABLE_FLOAT_NODATA
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_raster_path_band[0], target_flow_accum_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Float64, [flow_accum_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1149, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":1150
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_accum_managed_raster = ManagedRaster(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1150, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1150, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = PyFloat_FromDouble(__pyx_v_flow_accum_nodata); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1150, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_11 = PyList_New(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1150, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_GIVEREF(__pyx_t_9);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_11, 0, __pyx_t_9) != (0)) __PYX_ERR(0, 1150, __pyx_L1_error);
  __pyx_t_9 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1151
 *         flow_dir_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flow_accum_managed_raster = ManagedRaster(
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_8);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_2, __pyx_t_3, __pyx_v_target_flow_accum_raster_path, __pyx_t_10, __pyx_t_11};
    __pyx_t_9 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1148, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_9, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1148, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (5-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_9);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1148, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1153
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_accum_managed_raster = ManagedRaster(
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_8 = __pyx_v_target_flow_accum_raster_path;
  __Pyx_INCREF(__pyx_t_8);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1153, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1153, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1152
 *         gdal.GDT_Float64, [flow_accum_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_accum_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1152, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_accum_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":1156
 * 
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(
*/
  __pyx_t_9 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_8 = __pyx_t_9;
  __Pyx_INCREF(__pyx_t_8);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1156, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1156, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1157
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_raster_path_band[0].encode('utf-8'),
 *         flow_dir_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
*/
  __pyx_t_9 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1157, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_9); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1157, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1155
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)
 * 
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0].encode('utf-8'),
 *         flow_dir_raster_path_band[1], False)
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_14, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1155, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":1158
 *         flow_dir_raster_path_band[0].encode('utf-8'),
 *         flow_dir_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1159
 *         flow_dir_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_raster_path_band[1])
*/
  __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1159, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1159, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1159, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_11);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_t_8, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1158, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_raster = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1160
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1])
 * 
*/
  __pyx_t_11 = __pyx_v_flow_dir_raster;
  __Pyx_INCREF(__pyx_t_11);

  /* "pygeoprocessing/routing/routing.pyx":1161
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster weight_raster
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1161, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1160, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_band = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1164
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 1164, __pyx_L1_error)
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":1166
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
*/
    __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1166, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_3 = __pyx_t_11;
    __Pyx_INCREF(__pyx_t_3);
    __pyx_t_4 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1166, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1166, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1167
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
*/
    __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1167, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_11); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1167, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1165
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
*/
    try {
      __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_14, Py_False);
    } catch(...) {
      __Pyx_CppExn2PyErr();
      __PYX_ERR(0, 1165, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_weight_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

    /* "pygeoprocessing/routing/routing.pyx":1168
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
*/
    __pyx_t_11 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1168, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1168, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1169
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1169, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_8))) {
      __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_8);
      assert(__pyx_t_11);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_11);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1168, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_8 = __Pyx_PyObject_Dict_GetItem(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1169, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1170
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata
*/
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1170, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_3 = __Pyx_PyLong_SubtractObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1170, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1169
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_8, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1169, __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_v_raw_weight_nodata = __pyx_t_1;
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1171
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    __pyx_t_6 = (__pyx_v_raw_weight_nodata != Py_None);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":1172
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata             # <<<<<<<<<<<<<<
 * 
 *     cdef short do_decayed_accumulation = False
*/
      __pyx_t_15 = __Pyx_PyFloat_AsDouble(__pyx_v_raw_weight_nodata); if (unlikely((__pyx_t_15 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1172, __pyx_L1_error)
      __pyx_v_weight_nodata = __pyx_t_15;

      /* "pygeoprocessing/routing/routing.pyx":1171
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":1164
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1174
 *             weight_nodata = raw_weight_nodata
 * 
 *     cdef short do_decayed_accumulation = False             # <<<<<<<<<<<<<<
 *     cdef short use_const_decay_factor = False
 *     cdef float decay_factor = 1.0
*/
  __pyx_v_do_decayed_accumulation = 0;

  /* "pygeoprocessing/routing/routing.pyx":1175
 * 
 *     cdef short do_decayed_accumulation = False
 *     cdef short use_const_decay_factor = False             # <<<<<<<<<<<<<<
 *     cdef float decay_factor = 1.0
 *     cdef double decay_factor_nodata
*/
  __pyx_v_use_const_decay_factor = 0;

  /* "pygeoprocessing/routing/routing.pyx":1176
 *     cdef short do_decayed_accumulation = False
 *     cdef short use_const_decay_factor = False
 *     cdef float decay_factor = 1.0             # <<<<<<<<<<<<<<
 *     cdef double decay_factor_nodata
 *     if custom_decay_factor is not None:
*/
  __pyx_v_decay_factor = 1.0;

  /* "pygeoprocessing/routing/routing.pyx":1178
 *     cdef float decay_factor = 1.0
 *     cdef double decay_factor_nodata
 *     if custom_decay_factor is not None:             # <<<<<<<<<<<<<<
 *         do_decayed_accumulation = True
 *         if isinstance(custom_decay_factor, (int, float)):
*/
  __pyx_t_6 = (__pyx_v_custom_decay_factor != Py_None);
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":1179
 *     cdef double decay_factor_nodata
 *     if custom_decay_factor is not None:
 *         do_decayed_accumulation = True             # <<<<<<<<<<<<<<
 *         if isinstance(custom_decay_factor, (int, float)):
 *             decay_factor = custom_decay_factor
*/
    __pyx_v_do_decayed_accumulation = 1;

    /* "pygeoprocessing/routing/routing.pyx":1180
 *     if custom_decay_factor is not None:
 *         do_decayed_accumulation = True
 *         if isinstance(custom_decay_factor, (int, float)):             # <<<<<<<<<<<<<<
 *             decay_factor = custom_decay_factor
 *             use_const_decay_factor = True
*/
    __pyx_t_7 = PyLong_Check(__pyx_v_custom_decay_factor); 
    if (!__pyx_t_7) {
    } else {
      __pyx_t_6 = __pyx_t_7;
      goto __pyx_L11_bool_binop_done;
    }
    __pyx_t_7 = PyFloat_Check(__pyx_v_custom_decay_factor); 
    __pyx_t_6 = __pyx_t_7;
    __pyx_L11_bool_binop_done:;
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":1181
 *         do_decayed_accumulation = True
 *         if isinstance(custom_decay_factor, (int, float)):
 *             decay_factor = custom_decay_factor             # <<<<<<<<<<<<<<
 *             use_const_decay_factor = True
 *         else:  # assume a path/band tuple
*/
      __pyx_t_16 = __Pyx_PyFloat_AsFloat(__pyx_v_custom_decay_factor); if (unlikely((__pyx_t_16 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 1181, __pyx_L1_error)
      __pyx_v_decay_factor = __pyx_t_16;

      /* "pygeoprocessing/routing/routing.pyx":1182
 *         if isinstance(custom_decay_factor, (int, float)):
 *             decay_factor = custom_decay_factor
 *             use_const_decay_factor = True             # <<<<<<<<<<<<<<
 *         else:  # assume a path/band tuple
 *             if not _is_raster_path_band_formatted(custom_decay_factor):
*/
      __pyx_v_use_const_decay_factor = 1;

      /* "pygeoprocessing/routing/routing.pyx":1180
 *     if custom_decay_factor is not None:
 *         do_decayed_accumulation = True
 *         if isinstance(custom_decay_factor, (int, float)):             # <<<<<<<<<<<<<<
 *             decay_factor = custom_decay_factor
 *             use_const_decay_factor = True
*/
      goto __pyx_L10;
    }

    /* "pygeoprocessing/routing/routing.pyx":1184
 *             use_const_decay_factor = True
 *         else:  # assume a path/band tuple
 *             if not _is_raster_path_band_formatted(custom_decay_factor):             # <<<<<<<<<<<<<<
 *                 raise ValueError(
 *                     "%s is supposed to be a raster band tuple but it's not." % (
*/
    /*else*/ {
      __pyx_t_3 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1184, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_8))) {
        __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_8);
        assert(__pyx_t_3);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_custom_decay_factor};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1184, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 1184, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_7 = (!__pyx_t_6);
      if (unlikely(__pyx_t_7)) {

        /* "pygeoprocessing/routing/routing.pyx":1185
 *         else:  # assume a path/band tuple
 *             if not _is_raster_path_band_formatted(custom_decay_factor):
 *                 raise ValueError(             # <<<<<<<<<<<<<<
 *                     "%s is supposed to be a raster band tuple but it's not." % (
 *                         custom_decay_factor))
*/
        __pyx_t_8 = NULL;

        /* "pygeoprocessing/routing/routing.pyx":1186
 *             if not _is_raster_path_band_formatted(custom_decay_factor):
 *                 raise ValueError(
 *                     "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                         custom_decay_factor))
 *             decay_factor_managed_raster = ManagedRaster(
*/
        __pyx_t_3 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_custom_decay_factor); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1186, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_4 = 1;
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_3};
          __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1185, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
        }
        __Pyx_Raise(__pyx_t_1, 0, 0, 0);
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __PYX_ERR(0, 1185, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":1184
 *             use_const_decay_factor = True
 *         else:  # assume a path/band tuple
 *             if not _is_raster_path_band_formatted(custom_decay_factor):             # <<<<<<<<<<<<<<
 *                 raise ValueError(
 *                     "%s is supposed to be a raster band tuple but it's not." % (
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":1189
 *                         custom_decay_factor))
 *             decay_factor_managed_raster = ManagedRaster(
 *                 custom_decay_factor[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *                 custom_decay_factor[1], False)
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(
*/
      __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_custom_decay_factor, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1189, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_3 = __pyx_t_8;
      __Pyx_INCREF(__pyx_t_3);
      __pyx_t_4 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
        __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1189, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1189, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":1190
 *             decay_factor_managed_raster = ManagedRaster(
 *                 custom_decay_factor[0].encode('utf-8'),
 *                 custom_decay_factor[1], False)             # <<<<<<<<<<<<<<
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(
 *                 custom_decay_factor[0])['nodata'][0]
*/
      __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_custom_decay_factor, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1190, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_8); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1190, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

      /* "pygeoprocessing/routing/routing.pyx":1188
 *                     "%s is supposed to be a raster band tuple but it's not." % (
 *                         custom_decay_factor))
 *             decay_factor_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *                 custom_decay_factor[0].encode('utf-8'),
 *                 custom_decay_factor[1], False)
*/
      try {
        __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_14, Py_False);
      } catch(...) {
        __Pyx_CppExn2PyErr();
        __PYX_ERR(0, 1188, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_v_decay_factor_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

      /* "pygeoprocessing/routing/routing.pyx":1191
 *                 custom_decay_factor[0].encode('utf-8'),
 *                 custom_decay_factor[1], False)
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *                 custom_decay_factor[0])['nodata'][0]
 *             if _tmp_decay_factor_nodata is None:
*/
      __pyx_t_8 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1191, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1191, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":1192
 *                 custom_decay_factor[1], False)
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(
 *                 custom_decay_factor[0])['nodata'][0]             # <<<<<<<<<<<<<<
 *             if _tmp_decay_factor_nodata is None:
 *                 decay_factor_nodata = float('nan')
*/
      __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_custom_decay_factor, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1192, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_11))) {
        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_11);
        assert(__pyx_t_8);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_3};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1191, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __pyx_t_11 = __Pyx_PyObject_Dict_GetItem(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1192, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_11, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1192, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __pyx_v__tmp_decay_factor_nodata = __pyx_t_1;
      __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":1193
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(
 *                 custom_decay_factor[0])['nodata'][0]
 *             if _tmp_decay_factor_nodata is None:             # <<<<<<<<<<<<<<
 *                 decay_factor_nodata = float('nan')
 *             else:
*/
      __pyx_t_7 = (__pyx_v__tmp_decay_factor_nodata == Py_None);
      if (__pyx_t_7) {

        /* "pygeoprocessing/routing/routing.pyx":1194
 *                 custom_decay_factor[0])['nodata'][0]
 *             if _tmp_decay_factor_nodata is None:
 *                 decay_factor_nodata = float('nan')             # <<<<<<<<<<<<<<
 *             else:
 *                 decay_factor_nodata = _tmp_decay_factor_nodata
*/
        __pyx_t_15 = __Pyx_PyUnicode_AsDouble(__pyx_mstate_global->__pyx_n_u_nan); if (unlikely(__PYX_CHECK_FLOAT_EXCEPTION(__pyx_t_15, ((double)((double)-1))) && PyErr_Occurred())) __PYX_ERR(0, 1194, __pyx_L1_error)
        __pyx_v_decay_factor_nodata = __pyx_t_15;

        /* "pygeoprocessing/routing/routing.pyx":1193
 *             _tmp_decay_factor_nodata = pygeoprocessing.get_raster_info(
 *                 custom_decay_factor[0])['nodata'][0]
 *             if _tmp_decay_factor_nodata is None:             # <<<<<<<<<<<<<<
 *                 decay_factor_nodata = float('nan')
 *             else:
*/
        goto __pyx_L14;
      }

      /* "pygeoprocessing/routing/routing.pyx":1196
 *                 decay_factor_nodata = float('nan')
 *             else:
 *                 decay_factor_nodata = _tmp_decay_factor_nodata             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
*/
      /*else*/ {
        __pyx_t_15 = __Pyx_PyFloat_AsDouble(__pyx_v__tmp_decay_factor_nodata); if (unlikely((__pyx_t_15 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1196, __pyx_L1_error)
        __pyx_v_decay_factor_nodata = __pyx_t_15;
      }
      __pyx_L14:;
    }
    __pyx_L10:;

    /* "pygeoprocessing/routing/routing.pyx":1178
 *     cdef float decay_factor = 1.0
 *     cdef double decay_factor_nodata
 *     if custom_decay_factor is not None:             # <<<<<<<<<<<<<<
 *         do_decayed_accumulation = True
 *         if isinstance(custom_decay_factor, (int, float)):
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1198
 *                 decay_factor_nodata = _tmp_decay_factor_nodata
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
*/
  __pyx_t_11 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1198, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1198, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1199
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 * 
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1199, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_8);
    assert(__pyx_t_11);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_11);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1198, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1200
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1200, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 1200, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_8);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1200, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_8);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1200, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_8 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1200, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1200, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_11 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1200, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11);
    index = 0; __pyx_t_8 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_8)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_8);
    index = 1; __pyx_t_3 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_11), 2) < (0)) __PYX_ERR(0, 1200, __pyx_L1_error)
    __pyx_t_17 = NULL;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    goto __pyx_L16_unpacking_done;
    __pyx_L15_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __pyx_t_17 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 1200, __pyx_L1_error)
    __pyx_L16_unpacking_done:;
  }
  __pyx_t_18 = __Pyx_PyLong_As_unsigned_int(__pyx_t_8); if (unlikely((__pyx_t_18 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1200, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1200, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_raster_x_size = __pyx_t_18;
  __pyx_v_raster_y_size = __pyx_t_19;

  /* "pygeoprocessing/routing/routing.pyx":1202
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 * 
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1]-1]
 *     if tmp_flow_dir_nodata is None:
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1202, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":1203
 * 
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][
 *         flow_dir_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     if tmp_flow_dir_nodata is None:
 *         flow_dir_nodata = 128
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1203, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyLong_SubtractObjC(__pyx_t_3, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1203, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1202
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 * 
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1]-1]
 *     if tmp_flow_dir_nodata is None:
*/
  __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_8); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1202, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_v_tmp_flow_dir_nodata = __pyx_t_3;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1204
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][
 *         flow_dir_raster_path_band[1]-1]
 *     if tmp_flow_dir_nodata is None:             # <<<<<<<<<<<<<<
 *         flow_dir_nodata = 128
 *     else:
*/
  __pyx_t_7 = (__pyx_v_tmp_flow_dir_nodata == Py_None);
  if (__pyx_t_7) {

    /* "pygeoprocessing/routing/routing.pyx":1205
 *         flow_dir_raster_path_band[1]-1]
 *     if tmp_flow_dir_nodata is None:
 *         flow_dir_nodata = 128             # <<<<<<<<<<<<<<
 *     else:
 *         flow_dir_nodata = tmp_flow_dir_nodata
*/
    __pyx_v_flow_dir_nodata = 0x80;

    /* "pygeoprocessing/routing/routing.pyx":1204
 *     tmp_flow_dir_nodata = flow_dir_raster_info['nodata'][
 *         flow_dir_raster_path_band[1]-1]
 *     if tmp_flow_dir_nodata is None:             # <<<<<<<<<<<<<<
 *         flow_dir_nodata = 128
 *     else:
*/
    goto __pyx_L17;
  }

  /* "pygeoprocessing/routing/routing.pyx":1207
 *         flow_dir_nodata = 128
 *     else:
 *         flow_dir_nodata = tmp_flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for a pixel that is locally undrained
*/
  /*else*/ {
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_v_tmp_flow_dir_nodata); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1207, __pyx_L1_error)
    __pyx_v_flow_dir_nodata = __pyx_t_14;
  }
  __pyx_L17:;

  /* "pygeoprocessing/routing/routing.pyx":1211
 *     # this outer loop searches for a pixel that is locally undrained
 *     cdef queue[DecayingValue] decay_from_upstream
 *     cdef double upstream_transport_factor = 1.0  # proportion of load transported to downstream pixel             # <<<<<<<<<<<<<<
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
*/
  __pyx_v_upstream_transport_factor = 1.0;

  /* "pygeoprocessing/routing/routing.pyx":1212
 *     cdef queue[DecayingValue] decay_from_upstream
 *     cdef double upstream_transport_factor = 1.0  # proportion of load transported to downstream pixel
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_8 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1212, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1212, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1213
 *     cdef double upstream_transport_factor = 1.0  # proportion of load transported to downstream pixel
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_11);
    assert(__pyx_t_8);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
    __Pyx_INCREF(__pyx_t_8);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_8, __pyx_v_flow_dir_raster_path_band};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_1, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 1212, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_1, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 1212, __pyx_L1_error)
    __pyx_t_3 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }

  /* "pygeoprocessing/routing/routing.pyx":1212
 *     cdef queue[DecayingValue] decay_from_upstream
 *     cdef double upstream_transport_factor = 1.0  # proportion of load transported to downstream pixel
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
    __pyx_t_11 = __pyx_t_3; __Pyx_INCREF(__pyx_t_11);
    __pyx_t_20 = 0;
    __pyx_t_21 = NULL;
  } else {
    __pyx_t_20 = -1; __pyx_t_11 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_21 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 1212, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  for (;;) {
    if (likely(!__pyx_t_21)) {
      if (likely(PyList_CheckExact(__pyx_t_11))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_11);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 1212, __pyx_L1_error)
          #endif
          if (__pyx_t_20 >= __pyx_temp) break;
        }
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(__pyx_t_11, __pyx_t_20, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_20;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_11);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 1212, __pyx_L1_error)
          #endif
          if (__pyx_t_20 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_3 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_11, __pyx_t_20));
        #else
        __pyx_t_3 = __Pyx_PySequence_ITEM(__pyx_t_11, __pyx_t_20);
        #endif
        ++__pyx_t_20;
      }
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1212, __pyx_L1_error)
    } else {
      __pyx_t_3 = __pyx_t_21(__pyx_t_11);
      if (unlikely(!__pyx_t_3)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 1212, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_3);
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1214
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1214, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1214, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_xsize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":1215
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1215, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1215, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_ysize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":1216
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1216, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1216, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_xoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":1217
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1217, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1217, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_yoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":1219
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_7 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_7) {

      /* "pygeoprocessing/routing/routing.pyx":1220
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0 * current_pixel / <float>(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":1221
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":1222
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      __pyx_t_1 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1222, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1222, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_15 = (100.0 * __pyx_v_current_pixel);

      /* "pygeoprocessing/routing/routing.pyx":1223
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 * 
 *         # make a buffer big enough to capture block and boundaries around it
*/
      __pyx_t_16 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

      /* "pygeoprocessing/routing/routing.pyx":1222
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      if (unlikely(__pyx_t_16 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 1222, __pyx_L1_error)
      }
      __pyx_t_8 = PyFloat_FromDouble((__pyx_t_15 / ((double)__pyx_t_16))); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1222, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_9);
        assert(__pyx_t_1);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_Flow_accumulation_D8_1f_complete, __pyx_t_8};
        __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1222, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":1219
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":1226
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    __pyx_t_9 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1226, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1226, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1227
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array[:] = flow_dir_nodata
*/
    __pyx_t_8 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_10 = __Pyx_PyLong_AddObjC(__pyx_t_8, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_8 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_t_8, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_GIVEREF(__pyx_t_10);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_10) != (0)) __PYX_ERR(0, 1227, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 1227, __pyx_L1_error);
    __pyx_t_10 = 0;
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1228
 *         flow_dir_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)             # <<<<<<<<<<<<<<
 *         flow_dir_buffer_array[:] = flow_dir_nodata
 * 
*/
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1228, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_uint8); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1228, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_9);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_9, __pyx_t_8};
      __pyx_t_2 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1226, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_10, __pyx_t_2, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 1226, __pyx_L1_error)
      __pyx_t_3 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_2);
      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 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;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1226, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }

    /* "pygeoprocessing/routing/routing.pyx":1226
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 1226, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
      __pyx_t_14 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_3), &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_14 < 0)) {
        PyErr_Fetch(&__pyx_t_22, &__pyx_t_23, &__pyx_t_24);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_flow_dir_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_22); Py_XDECREF(__pyx_t_23); Py_XDECREF(__pyx_t_24);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_22, __pyx_t_23, __pyx_t_24);
        }
        __pyx_t_22 = __pyx_t_23 = __pyx_t_24 = 0;
      }
      __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].strides = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].shape = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].strides = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].shape = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_14 < 0))) __PYX_ERR(0, 1226, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_flow_dir_buffer_array, ((PyArrayObject *)__pyx_t_3));
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1229
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array[:] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # attempt to expand read block by a pixel boundary
*/
    __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1229, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_t_3) < 0))) __PYX_ERR(0, 1229, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1232
 * 
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1232, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":1233
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.uint8)
*/
    __pyx_t_10 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1233, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_8 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1233, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_1, __pyx_v_offset_dict, __pyx_t_10, __pyx_t_8};
      __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_4, (4-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
      PyObject* sequence = __pyx_t_3;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 1232, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_8);
      } else {
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_8);
      }
      #else
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_8 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      #endif
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_10);
      index = 0; __pyx_t_2 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L21_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      index = 1; __pyx_t_8 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L21_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_8);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_10), 2) < (0)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      goto __pyx_L22_unpacking_done;
      __pyx_L21_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 1232, __pyx_L1_error)
      __pyx_L22_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":1232
 * 
 *         # attempt to expand read block by a pixel boundary
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 1232, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_10);
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_9 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_9);
        __pyx_t_25 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_25);
      } else {
        __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_10);
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_9 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_9);
        __pyx_t_25 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 1232, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_25);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_1,&__pyx_t_9,&__pyx_t_25};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 1232, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_1,&__pyx_t_9,&__pyx_t_25};
      __pyx_t_26 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_26);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_26);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_17(__pyx_t_26); if (unlikely(!item)) goto __pyx_L23_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_26), 4) < (0)) __PYX_ERR(0, 1232, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      goto __pyx_L24_unpacking_done;
      __pyx_L23_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 1232, __pyx_L1_error)
      __pyx_L24_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_10);
    __pyx_t_10 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_9);
    __pyx_t_9 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_25);
    __pyx_t_25 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_8);
    __pyx_t_8 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1234
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.uint8)
 * 
*/
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_flow_dir_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":1235
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.uint8)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 1235, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_25 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 1235, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    } else {
      __pyx_t_25 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 1234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    }

    /* "pygeoprocessing/routing/routing.pyx":1234
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.uint8)
 * 
*/
    __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_25); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_8 = __pyx_t_9;
    __Pyx_INCREF(__pyx_t_8);

    /* "pygeoprocessing/routing/routing.pyx":1235
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.uint8)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 1235, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_25);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_uint8); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1235, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_4 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_2};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1235, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }

    /* "pygeoprocessing/routing/routing.pyx":1234
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.uint8)
 * 
*/
    __pyx_t_9 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_2 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_GIVEREF(__pyx_t_9);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_9) != (0)) __PYX_ERR(0, 1234, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 1234, __pyx_L1_error);
    __pyx_t_9 = 0;
    __pyx_t_2 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_buffer_array), __pyx_t_8, __pyx_t_3) < 0))) __PYX_ERR(0, 1234, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1238
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":1239
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # Search the block for root pixels.
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":1244
 *         # A root pixel is a flow direction pixel that is nodata, which means it
 *         # may be a drain just off the edge.
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_buffer_array[yi, xi]
*/
    __pyx_t_27 = (__pyx_v_win_ysize + 1);
    __pyx_t_28 = __pyx_t_27;
    for (__pyx_t_19 = 1; __pyx_t_19 < __pyx_t_28; __pyx_t_19+=1) {
      __pyx_v_yi = __pyx_t_19;

      /* "pygeoprocessing/routing/routing.pyx":1245
 *         # may be a drain just off the edge.
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 flow_dir = flow_dir_buffer_array[yi, xi]
 *                 if flow_dir == flow_dir_nodata:
*/
      __pyx_t_29 = (__pyx_v_win_xsize + 1);
      __pyx_t_30 = __pyx_t_29;
      for (__pyx_t_18 = 1; __pyx_t_18 < __pyx_t_30; __pyx_t_18+=1) {
        __pyx_v_xi = __pyx_t_18;

        /* "pygeoprocessing/routing/routing.pyx":1246
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_buffer_array[yi, xi]             # <<<<<<<<<<<<<<
 *                 if flow_dir == flow_dir_nodata:
 *                     continue
*/
        __pyx_t_4 = __pyx_v_yi;
        __pyx_t_31 = __pyx_v_xi;
        __pyx_t_14 = -1;
        if (unlikely(__pyx_t_4 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].shape)) __pyx_t_14 = 0;
        if (unlikely(__pyx_t_31 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].shape)) __pyx_t_14 = 1;
        if (unlikely(__pyx_t_14 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_14);
          __PYX_ERR(0, 1246, __pyx_L1_error)
        }
        __pyx_v_flow_dir = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_uint8_t *, __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_4, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].strides));

        /* "pygeoprocessing/routing/routing.pyx":1247
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_buffer_array[yi, xi]
 *                 if flow_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_7 = (__pyx_v_flow_dir == __pyx_v_flow_dir_nodata);
        if (__pyx_t_7) {

          /* "pygeoprocessing/routing/routing.pyx":1248
 *                 flow_dir = flow_dir_buffer_array[yi, xi]
 *                 if flow_dir == flow_dir_nodata:
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 xi_n = xi+COL_OFFSETS[flow_dir]
*/
          goto __pyx_L27_continue;

          /* "pygeoprocessing/routing/routing.pyx":1247
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_buffer_array[yi, xi]
 *                 if flow_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":1250
 *                     continue
 * 
 *                 xi_n = xi+COL_OFFSETS[flow_dir]             # <<<<<<<<<<<<<<
 *                 yi_n = yi+ROW_OFFSETS[flow_dir]
 * 
*/
        __pyx_v_xi_n = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_flow_dir]));

        /* "pygeoprocessing/routing/routing.pyx":1251
 * 
 *                 xi_n = xi+COL_OFFSETS[flow_dir]
 *                 yi_n = yi+ROW_OFFSETS[flow_dir]             # <<<<<<<<<<<<<<
 * 
 *                 if flow_dir_buffer_array[yi_n, xi_n] == flow_dir_nodata:
*/
        __pyx_v_yi_n = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_flow_dir]));

        /* "pygeoprocessing/routing/routing.pyx":1253
 *                 yi_n = yi+ROW_OFFSETS[flow_dir]
 * 
 *                 if flow_dir_buffer_array[yi_n, xi_n] == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     xi_root = xi-1+xoff
 *                     yi_root = yi-1+yoff
*/
        __pyx_t_31 = __pyx_v_yi_n;
        __pyx_t_4 = __pyx_v_xi_n;
        __pyx_t_14 = -1;
        if (unlikely(__pyx_t_31 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].shape)) __pyx_t_14 = 0;
        if (unlikely(__pyx_t_4 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].shape)) __pyx_t_14 = 1;
        if (unlikely(__pyx_t_14 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_14);
          __PYX_ERR(0, 1253, __pyx_L1_error)
        }
        __pyx_t_7 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_uint8_t *, __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].strides, __pyx_t_4, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].strides)) == __pyx_v_flow_dir_nodata);
        if (__pyx_t_7) {

          /* "pygeoprocessing/routing/routing.pyx":1254
 * 
 *                 if flow_dir_buffer_array[yi_n, xi_n] == flow_dir_nodata:
 *                     xi_root = xi-1+xoff             # <<<<<<<<<<<<<<
 *                     yi_root = yi-1+yoff
 * 
*/
          __pyx_v_xi_root = ((__pyx_v_xi - 1) + __pyx_v_xoff);

          /* "pygeoprocessing/routing/routing.pyx":1255
 *                 if flow_dir_buffer_array[yi_n, xi_n] == flow_dir_nodata:
 *                     xi_root = xi-1+xoff
 *                     yi_root = yi-1+yoff             # <<<<<<<<<<<<<<
 * 
 *                     if weight_raster_path_band:
*/
          __pyx_v_yi_root = ((__pyx_v_yi - 1) + __pyx_v_yoff);

          /* "pygeoprocessing/routing/routing.pyx":1257
 *                     yi_root = yi-1+yoff
 * 
 *                     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                         weight_val = <double>weight_raster.get(
 *                             xi_root, yi_root)
*/
          __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_7 < 0))) __PYX_ERR(0, 1257, __pyx_L1_error)
          if (__pyx_t_7) {

            /* "pygeoprocessing/routing/routing.pyx":1258
 * 
 *                     if weight_raster_path_band:
 *                         weight_val = <double>weight_raster.get(             # <<<<<<<<<<<<<<
 *                             xi_root, yi_root)
 *                         if is_close(weight_val, weight_nodata):
*/
            __pyx_v_weight_val = ((double)__pyx_v_weight_raster.get(__pyx_v_xi_root, __pyx_v_yi_root));

            /* "pygeoprocessing/routing/routing.pyx":1260
 *                         weight_val = <double>weight_raster.get(
 *                             xi_root, yi_root)
 *                         if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                             weight_val = 0.0
 *                     else:
*/
            __pyx_t_7 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1261
 *                             xi_root, yi_root)
 *                         if is_close(weight_val, weight_nodata):
 *                             weight_val = 0.0             # <<<<<<<<<<<<<<
 *                     else:
 *                         weight_val = 1.0
*/
              __pyx_v_weight_val = 0.0;

              /* "pygeoprocessing/routing/routing.pyx":1260
 *                         weight_val = <double>weight_raster.get(
 *                             xi_root, yi_root)
 *                         if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                             weight_val = 0.0
 *                     else:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1257
 *                     yi_root = yi-1+yoff
 * 
 *                     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                         weight_val = <double>weight_raster.get(
 *                             xi_root, yi_root)
*/
            goto __pyx_L31;
          }

          /* "pygeoprocessing/routing/routing.pyx":1263
 *                             weight_val = 0.0
 *                     else:
 *                         weight_val = 1.0             # <<<<<<<<<<<<<<
 *                     search_stack.push(
 *                         WeightedFlowPixelType(xi_root, yi_root, 0, weight_val,
*/
          /*else*/ {
            __pyx_v_weight_val = 1.0;
          }
          __pyx_L31:;

          /* "pygeoprocessing/routing/routing.pyx":1265
 *                         weight_val = 1.0
 *                     search_stack.push(
 *                         WeightedFlowPixelType(xi_root, yi_root, 0, weight_val,             # <<<<<<<<<<<<<<
 *                                               queue[DecayingValue]()))
 * 
*/
          __pyx_t_32.xi = __pyx_v_xi_root;
          __pyx_t_32.yi = __pyx_v_yi_root;
          __pyx_t_32.last_flow_dir = 0;
          __pyx_t_32.value = __pyx_v_weight_val;

          /* "pygeoprocessing/routing/routing.pyx":1266
 *                     search_stack.push(
 *                         WeightedFlowPixelType(xi_root, yi_root, 0, weight_val,
 *                                               queue[DecayingValue]()))             # <<<<<<<<<<<<<<
 * 
 *                 # Drain the queue of upstream neighbors since we're starting
*/
          try {
            __pyx_t_33 = std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue> ();
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1266, __pyx_L1_error)
          }
          __pyx_t_32.decaying_values = __pyx_t_33;

          /* "pygeoprocessing/routing/routing.pyx":1264
 *                     else:
 *                         weight_val = 1.0
 *                     search_stack.push(             # <<<<<<<<<<<<<<
 *                         WeightedFlowPixelType(xi_root, yi_root, 0, weight_val,
 *                                               queue[DecayingValue]()))
*/
          try {
            __pyx_v_search_stack.push(__pyx_t_32);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1264, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":1253
 *                 yi_n = yi+ROW_OFFSETS[flow_dir]
 * 
 *                 if flow_dir_buffer_array[yi_n, xi_n] == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     xi_root = xi-1+xoff
 *                     yi_root = yi-1+yoff
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":1270
 *                 # Drain the queue of upstream neighbors since we're starting
 *                 # from a new root pixel.
 *                 while not decay_from_upstream.empty():             # <<<<<<<<<<<<<<
 *                     decay_from_upstream.pop()
 * 
*/
        while (1) {
          __pyx_t_7 = (!__pyx_v_decay_from_upstream.empty());
          if (!__pyx_t_7) break;

          /* "pygeoprocessing/routing/routing.pyx":1271
 *                 # from a new root pixel.
 *                 while not decay_from_upstream.empty():
 *                     decay_from_upstream.pop()             # <<<<<<<<<<<<<<
 * 
 *                 while not search_stack.empty():
*/
          __pyx_v_decay_from_upstream.pop();
        }

        /* "pygeoprocessing/routing/routing.pyx":1273
 *                     decay_from_upstream.pop()
 * 
 *                 while not search_stack.empty():             # <<<<<<<<<<<<<<
 *                     flow_pixel = search_stack.top()
 *                     search_stack.pop()
*/
        while (1) {
          __pyx_t_7 = (!__pyx_v_search_stack.empty());
          if (!__pyx_t_7) break;

          /* "pygeoprocessing/routing/routing.pyx":1274
 * 
 *                 while not search_stack.empty():
 *                     flow_pixel = search_stack.top()             # <<<<<<<<<<<<<<
 *                     search_stack.pop()
 * 
*/
          __pyx_v_flow_pixel = __pyx_v_search_stack.top();

          /* "pygeoprocessing/routing/routing.pyx":1275
 *                 while not search_stack.empty():
 *                     flow_pixel = search_stack.top()
 *                     search_stack.pop()             # <<<<<<<<<<<<<<
 * 
 *                     # Load any decaying values from upstream into the current flow pixel.
*/
          __pyx_v_search_stack.pop();

          /* "pygeoprocessing/routing/routing.pyx":1278
 * 
 *                     # Load any decaying values from upstream into the current flow pixel.
 *                     while not decay_from_upstream.empty():             # <<<<<<<<<<<<<<
 *                         upstream_decaying_value = decay_from_upstream.front()
 *                         decay_from_upstream.pop()
*/
          while (1) {
            __pyx_t_7 = (!__pyx_v_decay_from_upstream.empty());
            if (!__pyx_t_7) break;

            /* "pygeoprocessing/routing/routing.pyx":1279
 *                     # Load any decaying values from upstream into the current flow pixel.
 *                     while not decay_from_upstream.empty():
 *                         upstream_decaying_value = decay_from_upstream.front()             # <<<<<<<<<<<<<<
 *                         decay_from_upstream.pop()
 *                         if upstream_decaying_value.decayed_value > upstream_decaying_value.min_value:
*/
            __pyx_v_upstream_decaying_value = __pyx_v_decay_from_upstream.front();

            /* "pygeoprocessing/routing/routing.pyx":1280
 *                     while not decay_from_upstream.empty():
 *                         upstream_decaying_value = decay_from_upstream.front()
 *                         decay_from_upstream.pop()             # <<<<<<<<<<<<<<
 *                         if upstream_decaying_value.decayed_value > upstream_decaying_value.min_value:
 *                             flow_pixel.decaying_values.push(upstream_decaying_value)
*/
            __pyx_v_decay_from_upstream.pop();

            /* "pygeoprocessing/routing/routing.pyx":1281
 *                         upstream_decaying_value = decay_from_upstream.front()
 *                         decay_from_upstream.pop()
 *                         if upstream_decaying_value.decayed_value > upstream_decaying_value.min_value:             # <<<<<<<<<<<<<<
 *                             flow_pixel.decaying_values.push(upstream_decaying_value)
 * 
*/
            __pyx_t_7 = (__pyx_v_upstream_decaying_value.decayed_value > __pyx_v_upstream_decaying_value.min_value);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1282
 *                         decay_from_upstream.pop()
 *                         if upstream_decaying_value.decayed_value > upstream_decaying_value.min_value:
 *                             flow_pixel.decaying_values.push(upstream_decaying_value)             # <<<<<<<<<<<<<<
 * 
 *                     upstream_pixels_remain = 0
*/
              __pyx_v_flow_pixel.decaying_values.push(__pyx_v_upstream_decaying_value);

              /* "pygeoprocessing/routing/routing.pyx":1281
 *                         upstream_decaying_value = decay_from_upstream.front()
 *                         decay_from_upstream.pop()
 *                         if upstream_decaying_value.decayed_value > upstream_decaying_value.min_value:             # <<<<<<<<<<<<<<
 *                             flow_pixel.decaying_values.push(upstream_decaying_value)
 * 
*/
            }
          }

          /* "pygeoprocessing/routing/routing.pyx":1284
 *                             flow_pixel.decaying_values.push(upstream_decaying_value)
 * 
 *                     upstream_pixels_remain = 0             # <<<<<<<<<<<<<<
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
*/
          __pyx_v_upstream_pixels_remain = 0;

          /* "pygeoprocessing/routing/routing.pyx":1285
 * 
 *                     upstream_pixels_remain = 0
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):             # <<<<<<<<<<<<<<
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_34 = __pyx_v_flow_pixel.last_flow_dir; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1286
 *                     upstream_pixels_remain = 0
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_flow_pixel.xi + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1287
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_flow_pixel.yi + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1288
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # neighbor not upstream: off edges of the raster
*/
            __pyx_t_6 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_6) {
            } else {
              __pyx_t_7 = __pyx_t_6;
              goto __pyx_L43_bool_binop_done;
            }
            __pyx_t_6 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_6) {
            } else {
              __pyx_t_7 = __pyx_t_6;
              goto __pyx_L43_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1289
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             # neighbor not upstream: off edges of the raster
 *                             continue
*/
            __pyx_t_6 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_6) {
            } else {
              __pyx_t_7 = __pyx_t_6;
              goto __pyx_L43_bool_binop_done;
            }
            __pyx_t_6 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_7 = __pyx_t_6;
            __pyx_L43_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1288
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # neighbor not upstream: off edges of the raster
*/
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1291
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # neighbor not upstream: off edges of the raster
 *                             continue             # <<<<<<<<<<<<<<
 *                         upstream_flow_dir = <int>flow_dir_managed_raster.get(
 *                             xi_n, yi_n)
*/
              goto __pyx_L40_continue;

              /* "pygeoprocessing/routing/routing.pyx":1288
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # neighbor not upstream: off edges of the raster
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1292
 *                             # neighbor not upstream: off edges of the raster
 *                             continue
 *                         upstream_flow_dir = <int>flow_dir_managed_raster.get(             # <<<<<<<<<<<<<<
 *                             xi_n, yi_n)
 *                         if upstream_flow_dir == flow_dir_nodata or (
*/
            __pyx_v_upstream_flow_dir = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n));

            /* "pygeoprocessing/routing/routing.pyx":1294
 *                         upstream_flow_dir = <int>flow_dir_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if upstream_flow_dir == flow_dir_nodata or (             # <<<<<<<<<<<<<<
 *                                 upstream_flow_dir != INFLOW_OFFSETS[i_n]):
 *                             # neighbor not upstream: is nodata or doesn't flow in
*/
            __pyx_t_6 = (__pyx_v_upstream_flow_dir == __pyx_v_flow_dir_nodata);
            if (!__pyx_t_6) {
            } else {
              __pyx_t_7 = __pyx_t_6;
              goto __pyx_L48_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1295
 *                             xi_n, yi_n)
 *                         if upstream_flow_dir == flow_dir_nodata or (
 *                                 upstream_flow_dir != INFLOW_OFFSETS[i_n]):             # <<<<<<<<<<<<<<
 *                             # neighbor not upstream: is nodata or doesn't flow in
 *                             continue
*/
            __pyx_t_6 = (__pyx_v_upstream_flow_dir != (INFLOW_OFFSETS[__pyx_v_i_n]));
            __pyx_t_7 = __pyx_t_6;
            __pyx_L48_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1294
 *                         upstream_flow_dir = <int>flow_dir_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if upstream_flow_dir == flow_dir_nodata or (             # <<<<<<<<<<<<<<
 *                                 upstream_flow_dir != INFLOW_OFFSETS[i_n]):
 *                             # neighbor not upstream: is nodata or doesn't flow in
*/
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1297
 *                                 upstream_flow_dir != INFLOW_OFFSETS[i_n]):
 *                             # neighbor not upstream: is nodata or doesn't flow in
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         upstream_flow_accum = <double>(
*/
              goto __pyx_L40_continue;

              /* "pygeoprocessing/routing/routing.pyx":1294
 *                         upstream_flow_dir = <int>flow_dir_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if upstream_flow_dir == flow_dir_nodata or (             # <<<<<<<<<<<<<<
 *                                 upstream_flow_dir != INFLOW_OFFSETS[i_n]):
 *                             # neighbor not upstream: is nodata or doesn't flow in
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1299
 *                             continue
 * 
 *                         upstream_flow_accum = <double>(             # <<<<<<<<<<<<<<
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if is_close(upstream_flow_accum, flow_accum_nodata):
*/
            __pyx_v_upstream_flow_accum = ((double)__pyx_v_flow_accum_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n));

            /* "pygeoprocessing/routing/routing.pyx":1301
 *                         upstream_flow_accum = <double>(
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if is_close(upstream_flow_accum, flow_accum_nodata):             # <<<<<<<<<<<<<<
 *                             # Flow accumulation pixel is nodata until it and everything
 *                             # upstream of it has been computed.
*/
            __pyx_t_7 = is_close(__pyx_v_upstream_flow_accum, __pyx_v_flow_accum_nodata);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1304
 *                             # Flow accumulation pixel is nodata until it and everything
 *                             # upstream of it has been computed.
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
*/
              __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_7 < 0))) __PYX_ERR(0, 1304, __pyx_L1_error)
              if (__pyx_t_7) {

                /* "pygeoprocessing/routing/routing.pyx":1305
 *                             # upstream of it has been computed.
 *                             if weight_raster_path_band:
 *                                 weight_val = <double>weight_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
*/
                __pyx_v_weight_val = ((double)__pyx_v_weight_raster.get(__pyx_v_xi_n, __pyx_v_yi_n));

                /* "pygeoprocessing/routing/routing.pyx":1307
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                __pyx_t_7 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
                if (__pyx_t_7) {

                  /* "pygeoprocessing/routing/routing.pyx":1308
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
 *                                     weight_val = 0.0             # <<<<<<<<<<<<<<
 *                             else:
 *                                 weight_val = 1.0
*/
                  __pyx_v_weight_val = 0.0;

                  /* "pygeoprocessing/routing/routing.pyx":1307
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                }

                /* "pygeoprocessing/routing/routing.pyx":1304
 *                             # Flow accumulation pixel is nodata until it and everything
 *                             # upstream of it has been computed.
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
*/
                goto __pyx_L51;
              }

              /* "pygeoprocessing/routing/routing.pyx":1310
 *                                     weight_val = 0.0
 *                             else:
 *                                 weight_val = 1.0             # <<<<<<<<<<<<<<
 *                             if do_decayed_accumulation:
 *                                 flow_pixel.decaying_values.push(
*/
              /*else*/ {
                __pyx_v_weight_val = 1.0;
              }
              __pyx_L51:;

              /* "pygeoprocessing/routing/routing.pyx":1311
 *                             else:
 *                                 weight_val = 1.0
 *                             if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                                 flow_pixel.decaying_values.push(
 *                                     DecayingValue(weight_val,
*/
              __pyx_t_7 = (__pyx_v_do_decayed_accumulation != 0);
              if (__pyx_t_7) {

                /* "pygeoprocessing/routing/routing.pyx":1313
 *                             if do_decayed_accumulation:
 *                                 flow_pixel.decaying_values.push(
 *                                     DecayingValue(weight_val,             # <<<<<<<<<<<<<<
 *                                                   weight_val * min_decay_proportion))
 * 
*/
                __pyx_t_35.decayed_value = __pyx_v_weight_val;

                /* "pygeoprocessing/routing/routing.pyx":1314
 *                                 flow_pixel.decaying_values.push(
 *                                     DecayingValue(weight_val,
 *                                                   weight_val * min_decay_proportion))             # <<<<<<<<<<<<<<
 * 
 *                             # process upstream pixel before this neighbor
*/
                __pyx_t_35.min_value = (__pyx_v_weight_val * __pyx_v_min_decay_proportion);

                /* "pygeoprocessing/routing/routing.pyx":1312
 *                                 weight_val = 1.0
 *                             if do_decayed_accumulation:
 *                                 flow_pixel.decaying_values.push(             # <<<<<<<<<<<<<<
 *                                     DecayingValue(weight_val,
 *                                                   weight_val * min_decay_proportion))
*/
                __pyx_v_flow_pixel.decaying_values.push(__pyx_t_35);

                /* "pygeoprocessing/routing/routing.pyx":1311
 *                             else:
 *                                 weight_val = 1.0
 *                             if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                                 flow_pixel.decaying_values.push(
 *                                     DecayingValue(weight_val,
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":1317
 * 
 *                             # process upstream pixel before this neighbor
 *                             flow_pixel.last_flow_dir = i_n             # <<<<<<<<<<<<<<
 *                             search_stack.push(flow_pixel)
 *                             search_stack.push(
*/
              __pyx_v_flow_pixel.last_flow_dir = __pyx_v_i_n;

              /* "pygeoprocessing/routing/routing.pyx":1318
 *                             # process upstream pixel before this neighbor
 *                             flow_pixel.last_flow_dir = i_n
 *                             search_stack.push(flow_pixel)             # <<<<<<<<<<<<<<
 *                             search_stack.push(
 *                                 WeightedFlowPixelType(xi_n, yi_n, 0, weight_val,
*/
              try {
                __pyx_v_search_stack.push(__pyx_v_flow_pixel);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 1318, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":1320
 *                             search_stack.push(flow_pixel)
 *                             search_stack.push(
 *                                 WeightedFlowPixelType(xi_n, yi_n, 0, weight_val,             # <<<<<<<<<<<<<<
 *                                                       queue[DecayingValue]()))
 *                             upstream_pixels_remain = 1
*/
              __pyx_t_32.xi = __pyx_v_xi_n;
              __pyx_t_32.yi = __pyx_v_yi_n;
              __pyx_t_32.last_flow_dir = 0;
              __pyx_t_32.value = __pyx_v_weight_val;

              /* "pygeoprocessing/routing/routing.pyx":1321
 *                             search_stack.push(
 *                                 WeightedFlowPixelType(xi_n, yi_n, 0, weight_val,
 *                                                       queue[DecayingValue]()))             # <<<<<<<<<<<<<<
 *                             upstream_pixels_remain = 1
 *                             break
*/
              try {
                __pyx_t_33 = std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_DecayingValue> ();
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 1321, __pyx_L1_error)
              }
              __pyx_t_32.decaying_values = __pyx_t_33;

              /* "pygeoprocessing/routing/routing.pyx":1319
 *                             flow_pixel.last_flow_dir = i_n
 *                             search_stack.push(flow_pixel)
 *                             search_stack.push(             # <<<<<<<<<<<<<<
 *                                 WeightedFlowPixelType(xi_n, yi_n, 0, weight_val,
 *                                                       queue[DecayingValue]()))
*/
              try {
                __pyx_v_search_stack.push(__pyx_t_32);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 1319, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":1322
 *                                 WeightedFlowPixelType(xi_n, yi_n, 0, weight_val,
 *                                                       queue[DecayingValue]()))
 *                             upstream_pixels_remain = 1             # <<<<<<<<<<<<<<
 *                             break
 * 
*/
              __pyx_v_upstream_pixels_remain = 1;

              /* "pygeoprocessing/routing/routing.pyx":1323
 *                                                       queue[DecayingValue]()))
 *                             upstream_pixels_remain = 1
 *                             break             # <<<<<<<<<<<<<<
 * 
 *                         if not do_decayed_accumulation:
*/
              goto __pyx_L41_break;

              /* "pygeoprocessing/routing/routing.pyx":1301
 *                         upstream_flow_accum = <double>(
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if is_close(upstream_flow_accum, flow_accum_nodata):             # <<<<<<<<<<<<<<
 *                             # Flow accumulation pixel is nodata until it and everything
 *                             # upstream of it has been computed.
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1325
 *                             break
 * 
 *                         if not do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                             flow_pixel.value += upstream_flow_accum
 * 
*/
            __pyx_t_7 = (!(__pyx_v_do_decayed_accumulation != 0));
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1326
 * 
 *                         if not do_decayed_accumulation:
 *                             flow_pixel.value += upstream_flow_accum             # <<<<<<<<<<<<<<
 * 
 *                     if not upstream_pixels_remain:
*/
              __pyx_v_flow_pixel.value = (__pyx_v_flow_pixel.value + __pyx_v_upstream_flow_accum);

              /* "pygeoprocessing/routing/routing.pyx":1325
 *                             break
 * 
 *                         if not do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                             flow_pixel.value += upstream_flow_accum
 * 
*/
            }
            __pyx_L40_continue:;
          }
          __pyx_L41_break:;

          /* "pygeoprocessing/routing/routing.pyx":1328
 *                             flow_pixel.value += upstream_flow_accum
 * 
 *                     if not upstream_pixels_remain:             # <<<<<<<<<<<<<<
 *                         # flow_pixel.value already has the on-pixel load
 *                         # from upstream, so we just need to add it from the
*/
          __pyx_t_7 = (!(__pyx_v_upstream_pixels_remain != 0));
          if (__pyx_t_7) {

            /* "pygeoprocessing/routing/routing.pyx":1332
 *                         # from upstream, so we just need to add it from the
 *                         # decaying values queue
 *                         if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                             if use_const_decay_factor:
 *                                 upstream_transport_factor = decay_factor
*/
            __pyx_t_7 = (__pyx_v_do_decayed_accumulation != 0);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":1333
 *                         # decaying values queue
 *                         if do_decayed_accumulation:
 *                             if use_const_decay_factor:             # <<<<<<<<<<<<<<
 *                                 upstream_transport_factor = decay_factor
 *                             else:
*/
              __pyx_t_7 = (__pyx_v_use_const_decay_factor != 0);
              if (__pyx_t_7) {

                /* "pygeoprocessing/routing/routing.pyx":1334
 *                         if do_decayed_accumulation:
 *                             if use_const_decay_factor:
 *                                 upstream_transport_factor = decay_factor             # <<<<<<<<<<<<<<
 *                             else:
 *                                 upstream_transport_factor = (
*/
                __pyx_v_upstream_transport_factor = __pyx_v_decay_factor;

                /* "pygeoprocessing/routing/routing.pyx":1333
 *                         # decaying values queue
 *                         if do_decayed_accumulation:
 *                             if use_const_decay_factor:             # <<<<<<<<<<<<<<
 *                                 upstream_transport_factor = decay_factor
 *                             else:
*/
                goto __pyx_L57;
              }

              /* "pygeoprocessing/routing/routing.pyx":1336
 *                                 upstream_transport_factor = decay_factor
 *                             else:
 *                                 upstream_transport_factor = (             # <<<<<<<<<<<<<<
 *                                     decay_factor_managed_raster.get(flow_pixel.xi, flow_pixel.yi))
 *                                 # If nodata, assume nothing will be transported from this pixel.
*/
              /*else*/ {

                /* "pygeoprocessing/routing/routing.pyx":1337
 *                             else:
 *                                 upstream_transport_factor = (
 *                                     decay_factor_managed_raster.get(flow_pixel.xi, flow_pixel.yi))             # <<<<<<<<<<<<<<
 *                                 # If nodata, assume nothing will be transported from this pixel.
 *                                 if is_close(upstream_transport_factor, decay_factor_nodata):
*/
                __pyx_v_upstream_transport_factor = __pyx_v_decay_factor_managed_raster.get(__pyx_v_flow_pixel.xi, __pyx_v_flow_pixel.yi);

                /* "pygeoprocessing/routing/routing.pyx":1339
 *                                     decay_factor_managed_raster.get(flow_pixel.xi, flow_pixel.yi))
 *                                 # If nodata, assume nothing will be transported from this pixel.
 *                                 if is_close(upstream_transport_factor, decay_factor_nodata):             # <<<<<<<<<<<<<<
 *                                     upstream_transport_factor = 0.0
 * 
*/
                __pyx_t_7 = is_close(__pyx_v_upstream_transport_factor, __pyx_v_decay_factor_nodata);
                if (__pyx_t_7) {

                  /* "pygeoprocessing/routing/routing.pyx":1340
 *                                 # If nodata, assume nothing will be transported from this pixel.
 *                                 if is_close(upstream_transport_factor, decay_factor_nodata):
 *                                     upstream_transport_factor = 0.0             # <<<<<<<<<<<<<<
 * 
 *                             while not flow_pixel.decaying_values.empty():
*/
                  __pyx_v_upstream_transport_factor = 0.0;

                  /* "pygeoprocessing/routing/routing.pyx":1339
 *                                     decay_factor_managed_raster.get(flow_pixel.xi, flow_pixel.yi))
 *                                 # If nodata, assume nothing will be transported from this pixel.
 *                                 if is_close(upstream_transport_factor, decay_factor_nodata):             # <<<<<<<<<<<<<<
 *                                     upstream_transport_factor = 0.0
 * 
*/
                }
              }
              __pyx_L57:;

              /* "pygeoprocessing/routing/routing.pyx":1342
 *                                     upstream_transport_factor = 0.0
 * 
 *                             while not flow_pixel.decaying_values.empty():             # <<<<<<<<<<<<<<
 *                                 decayed_value = flow_pixel.decaying_values.front()
 *                                 flow_pixel.decaying_values.pop()
*/
              while (1) {
                __pyx_t_7 = (!__pyx_v_flow_pixel.decaying_values.empty());
                if (!__pyx_t_7) break;

                /* "pygeoprocessing/routing/routing.pyx":1343
 * 
 *                             while not flow_pixel.decaying_values.empty():
 *                                 decayed_value = flow_pixel.decaying_values.front()             # <<<<<<<<<<<<<<
 *                                 flow_pixel.decaying_values.pop()
 *                                 decayed_value.decayed_value *= upstream_transport_factor
*/
                __pyx_v_decayed_value = __pyx_v_flow_pixel.decaying_values.front();

                /* "pygeoprocessing/routing/routing.pyx":1344
 *                             while not flow_pixel.decaying_values.empty():
 *                                 decayed_value = flow_pixel.decaying_values.front()
 *                                 flow_pixel.decaying_values.pop()             # <<<<<<<<<<<<<<
 *                                 decayed_value.decayed_value *= upstream_transport_factor
 *                                 flow_pixel.value += decayed_value.decayed_value
*/
                __pyx_v_flow_pixel.decaying_values.pop();

                /* "pygeoprocessing/routing/routing.pyx":1345
 *                                 decayed_value = flow_pixel.decaying_values.front()
 *                                 flow_pixel.decaying_values.pop()
 *                                 decayed_value.decayed_value *= upstream_transport_factor             # <<<<<<<<<<<<<<
 *                                 flow_pixel.value += decayed_value.decayed_value
 *                                 decay_from_upstream.push(decayed_value)
*/
                __pyx_v_decayed_value.decayed_value = (__pyx_v_decayed_value.decayed_value * __pyx_v_upstream_transport_factor);

                /* "pygeoprocessing/routing/routing.pyx":1346
 *                                 flow_pixel.decaying_values.pop()
 *                                 decayed_value.decayed_value *= upstream_transport_factor
 *                                 flow_pixel.value += decayed_value.decayed_value             # <<<<<<<<<<<<<<
 *                                 decay_from_upstream.push(decayed_value)
 * 
*/
                __pyx_v_flow_pixel.value = (__pyx_v_flow_pixel.value + __pyx_v_decayed_value.decayed_value);

                /* "pygeoprocessing/routing/routing.pyx":1347
 *                                 decayed_value.decayed_value *= upstream_transport_factor
 *                                 flow_pixel.value += decayed_value.decayed_value
 *                                 decay_from_upstream.push(decayed_value)             # <<<<<<<<<<<<<<
 * 
 *                         flow_accum_managed_raster.set(
*/
                __pyx_v_decay_from_upstream.push(__pyx_v_decayed_value);
              }

              /* "pygeoprocessing/routing/routing.pyx":1332
 *                         # from upstream, so we just need to add it from the
 *                         # decaying values queue
 *                         if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *                             if use_const_decay_factor:
 *                                 upstream_transport_factor = decay_factor
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1349
 *                                 decay_from_upstream.push(decayed_value)
 * 
 *                         flow_accum_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             flow_pixel.xi, flow_pixel.yi,
 *                             flow_pixel.value)
*/
            __pyx_v_flow_accum_managed_raster.set(__pyx_v_flow_pixel.xi, __pyx_v_flow_pixel.yi, __pyx_v_flow_pixel.value);

            /* "pygeoprocessing/routing/routing.pyx":1328
 *                             flow_pixel.value += upstream_flow_accum
 * 
 *                     if not upstream_pixels_remain:             # <<<<<<<<<<<<<<
 *                         # flow_pixel.value already has the on-pixel load
 *                         # from upstream, so we just need to add it from the
*/
          }
        }
        __pyx_L27_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":1212
 *     cdef queue[DecayingValue] decay_from_upstream
 *     cdef double upstream_transport_factor = 1.0  # proportion of load transported to downstream pixel
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  }
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1352
 *                             flow_pixel.xi, flow_pixel.yi,
 *                             flow_pixel.value)
 *     flow_accum_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster.close()
 *     if do_decayed_accumulation:
*/
  __pyx_v_flow_accum_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1353
 *                             flow_pixel.value)
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     if do_decayed_accumulation:
 *         if not use_const_decay_factor:
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1354
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()
 *     if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *         if not use_const_decay_factor:
 *             decay_factor_managed_raster.close()
*/
  __pyx_t_7 = (__pyx_v_do_decayed_accumulation != 0);
  if (__pyx_t_7) {

    /* "pygeoprocessing/routing/routing.pyx":1355
 *     flow_dir_managed_raster.close()
 *     if do_decayed_accumulation:
 *         if not use_const_decay_factor:             # <<<<<<<<<<<<<<
 *             decay_factor_managed_raster.close()
 *     if weight_raster_path_band:
*/
    __pyx_t_7 = (!(__pyx_v_use_const_decay_factor != 0));
    if (__pyx_t_7) {

      /* "pygeoprocessing/routing/routing.pyx":1356
 *     if do_decayed_accumulation:
 *         if not use_const_decay_factor:
 *             decay_factor_managed_raster.close()             # <<<<<<<<<<<<<<
 *     if weight_raster_path_band:
 *         weight_raster.close()
*/
      __pyx_v_decay_factor_managed_raster.close();

      /* "pygeoprocessing/routing/routing.pyx":1355
 *     flow_dir_managed_raster.close()
 *     if do_decayed_accumulation:
 *         if not use_const_decay_factor:             # <<<<<<<<<<<<<<
 *             decay_factor_managed_raster.close()
 *     if weight_raster_path_band:
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":1354
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()
 *     if do_decayed_accumulation:             # <<<<<<<<<<<<<<
 *         if not use_const_decay_factor:
 *             decay_factor_managed_raster.close()
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1357
 *         if not use_const_decay_factor:
 *             decay_factor_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0)
*/
  __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_7 < 0))) __PYX_ERR(0, 1357, __pyx_L1_error)
  if (__pyx_t_7) {

    /* "pygeoprocessing/routing/routing.pyx":1358
 *             decay_factor_managed_raster.close()
 *     if weight_raster_path_band:
 *         weight_raster.close()             # <<<<<<<<<<<<<<
 *     LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0)
 * 
*/
    __pyx_v_weight_raster.close();

    /* "pygeoprocessing/routing/routing.pyx":1357
 *         if not use_const_decay_factor:
 *             decay_factor_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0)
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1359
 *     if weight_raster_path_band:
 *         weight_raster.close()
 *     LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_mstate_global->__pyx_tuple[0], NULL); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1044
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_25);
  __Pyx_XDECREF(__pyx_t_26);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_accumulation_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_flow_dir_buffer_array);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster);
  __Pyx_XDECREF(__pyx_v_flow_dir_band);
  __Pyx_XDECREF(__pyx_v_raw_weight_nodata);
  __Pyx_XDECREF(__pyx_v__tmp_decay_factor_nodata);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster_info);
  __Pyx_XDECREF(__pyx_v_tmp_flow_dir_nodata);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":1362
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_38__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":1364
 * @gdal_use_exceptions
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Multiple flow direction.
*/
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1362, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, Py_None) != (0)) __PYX_ERR(0, 1362, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 1362, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":1362
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1362, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1362, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 1362, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_9flow_dir_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_8flow_dir_mfd, "Multiple flow direction.\n\n    Parameters:\n        dem_raster_path_band (tuple): a path, band number tuple indicating the\n            DEM calculate flow direction. This DEM must not have hydrological\n            pits or else the target flow direction will be undefined. Paths may\n            use any GDAL-supported scheme, including virtual file system /vsi schemes.\n        target_flow_dir_path (str): path to a raster created by this call\n            of a 32 bit int raster of the same dimensions and projections as\n            ``dem_raster_path_band[0]``. The value of the pixel indicates the\n            proportion of flow from that pixel to its neighbors given these\n            indexes::\n\n                3 2 1\n                4 x 0\n                5 6 7\n\n            The pixel value is formatted as 8 separate 4 bit integers\n            compressed into a 32 bit int. To extract the proportion of flow\n            from a particular direction given the pixel value 'x' one can\n            shift and mask as follows ``0xF & (x >> (4*dir))``, where ``dir``\n            is one of the 8 directions indicated above.\n        working_dir (str): If not None, indicates where temporary files\n            should be created during this run. If this directory doesn't exist\n            it is created by this call.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_9flow_dir_mfd = {"flow_dir_mfd", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_9flow_dir_mfd, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_8flow_dir_mfd};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_9flow_dir_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_dem_raster_path_band = 0;
  PyObject *__pyx_v_target_flow_dir_path = 0;
  PyObject *__pyx_v_working_dir = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[4] = {0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("flow_dir_mfd (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_dem_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_flow_dir_path,&__pyx_mstate_global->__pyx_n_u_working_dir,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 1362, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "flow_dir_mfd", 0) < (0)) __PYX_ERR(0, 1362, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":1364
 * @gdal_use_exceptions
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Multiple flow direction.
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("flow_dir_mfd", 0, 2, 4, i); __PYX_ERR(0, 1362, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1362, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1362, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1362, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_dem_raster_path_band = values[0];
    __pyx_v_target_flow_dir_path = values[1];
    __pyx_v_working_dir = values[2];
    __pyx_v_raster_driver_creation_tuple = values[3];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("flow_dir_mfd", 0, 2, 4, __pyx_nargs); __PYX_ERR(0, 1362, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_dir_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_8flow_dir_mfd(__pyx_self, __pyx_v_dem_raster_path_band, __pyx_v_target_flow_dir_path, __pyx_v_working_dir, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":1362
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_8flow_dir_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_flow_dir_path, PyObject *__pyx_v_working_dir, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_dem_buffer_array = 0;
  int __pyx_v_win_ysize;
  int __pyx_v_win_xsize;
  int __pyx_v_xoff;
  int __pyx_v_yoff;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_q;
  unsigned int __pyx_v_yi_q;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  double __pyx_v_root_height;
  double __pyx_v_n_height;
  double __pyx_v_dem_nodata;
  double __pyx_v_n_slope;
  double __pyx_v_drain_distance;
  double __pyx_v_n_drain_distance;
  std::queue<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_v_drain_search_queue;
  double __pyx_v_downhill_slope_array[8];
  double __pyx_v_nodata_downhill_slope_array[8];
  double *__pyx_v_working_downhill_slope_array;
  double __pyx_v_sum_of_slope_weights;
  double __pyx_v_sum_of_nodata_slope_weights;
  int __pyx_v_compressed_integer_slopes;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_distance_drain_queue;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_nodata_distance_drain_queue;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_direction_drain_queue;
  std::queue<int>  __pyx_v_nodata_flow_dir_queue;
  unsigned long __pyx_v_raster_x_size;
  unsigned long __pyx_v_raster_y_size;
  time_t __pyx_v_last_log_time;
  unsigned long __pyx_v_current_pixel;
  PyObject *__pyx_v_dem_raster_info = NULL;
  PyObject *__pyx_v_base_nodata = NULL;
  long __pyx_v_mask_nodata;
  PyObject *__pyx_v_working_dir_path = NULL;
  PyObject *__pyx_v_flat_region_mask_path = NULL;
  ManagedRaster __pyx_v_flat_region_mask_managed_raster;
  long __pyx_v_flow_dir_nodata;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  PyObject *__pyx_v_plateu_drain_mask_path = NULL;
  ManagedRaster __pyx_v_plateau_drain_mask_managed_raster;
  PyObject *__pyx_v_plateau_distance_path = NULL;
  unsigned long __pyx_v_plateau_distance_nodata;
  ManagedRaster __pyx_v_plateau_distance_managed_raster;
  PyObject *__pyx_v_compatable_dem_raster_path_band = NULL;
  PyObject *__pyx_v_dem_block_xsize = NULL;
  PyObject *__pyx_v_dem_block_ysize = NULL;
  PyObject *__pyx_v_raster_driver = NULL;
  PyObject *__pyx_v_dem_raster = NULL;
  ManagedRaster __pyx_v_dem_managed_raster;
  PyObject *__pyx_v_dem_band = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  double __pyx_v_sum_of_downhill_slopes;
  double __pyx_v_working_downhill_slope_sum;
  CYTHON_UNUSED size_t __pyx_v__;
  double __pyx_v_n_distance;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_dem_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_dem_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  size_t __pyx_t_5;
  int __pyx_t_6;
  double __pyx_t_7;
  PyObject *(*__pyx_t_8)(PyObject *);
  unsigned long __pyx_t_9;
  unsigned long __pyx_t_10;
  PyObject *__pyx_t_11 = NULL;
  PyObject *__pyx_t_12 = NULL;
  PyObject *__pyx_t_13 = NULL;
  int __pyx_t_14;
  PyObject *__pyx_t_15 = NULL;
  PyObject *__pyx_t_16 = NULL;
  PyObject *__pyx_t_17 = NULL;
  PyObject *__pyx_t_18 = NULL;
  PyObject *__pyx_t_19 = NULL;
  PyObject *__pyx_t_20 = NULL;
  char *__pyx_t_21;
  ManagedRaster __pyx_t_22;
  int __pyx_t_23;
  Py_ssize_t __pyx_t_24;
  PyObject *(*__pyx_t_25)(PyObject *);
  float __pyx_t_26;
  long __pyx_t_27;
  long __pyx_t_28;
  unsigned int __pyx_t_29;
  long __pyx_t_30;
  long __pyx_t_31;
  unsigned int __pyx_t_32;
  size_t __pyx_t_33;
  unsigned int __pyx_t_34;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_t_35;
  __pyx_t_15pygeoprocessing_7routing_7routing_IntQueueType __pyx_t_36;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_t_37;
  size_t __pyx_t_38;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("flow_dir_mfd", 0);
  __pyx_pybuffer_dem_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_dem_buffer_array.refcount = 0;
  __pyx_pybuffernd_dem_buffer_array.data = NULL;
  __pyx_pybuffernd_dem_buffer_array.rcbuffer = &__pyx_pybuffer_dem_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":1462
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     # This is used in progress logging to represent how many pixels have been
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":1470
 *     # determine dem nodata in the working type, or set an improbable value
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1470, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1470, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1470, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1470, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_dem_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1471
 *     # if one can't be determined
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1471, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1471, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = __Pyx_PyLong_SubtractObjC(__pyx_t_4, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1471, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1471, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_base_nodata = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1472
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
  __pyx_t_6 = (__pyx_v_base_nodata != Py_None);
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":1474
 *     if base_nodata is not None:
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)             # <<<<<<<<<<<<<<
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1474, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1474, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_base_nodata};
      __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1474, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __pyx_t_7 = __Pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1474, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_v_dem_nodata = __pyx_t_7;

    /* "pygeoprocessing/routing/routing.pyx":1472
 *     dem_raster_info = pygeoprocessing.get_raster_info(dem_raster_path_band[0])
 *     base_nodata = dem_raster_info['nodata'][dem_raster_path_band[1]-1]
 *     if base_nodata is not None:             # <<<<<<<<<<<<<<
 *         # cast to a float64 since that's our operating array type
 *         dem_nodata = numpy.float64(base_nodata)
*/
    goto __pyx_L3;
  }

  /* "pygeoprocessing/routing/routing.pyx":1477
 *     else:
 *         # pick some very improbable value since it's hard to deal with NaNs
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     # these are used to determine if a sample is within the raster
*/
  /*else*/ {
    __pyx_v_dem_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
  }
  __pyx_L3:;

  /* "pygeoprocessing/routing/routing.pyx":1480
 * 
 *     # these are used to determine if a sample is within the raster
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     # this is the nodata value for all the flat region and pit masks
*/
  __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1480, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
    PyObject* sequence = __pyx_t_4;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 1480, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1480, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1480, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1480, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1480, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_1 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1480, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1);
    index = 0; __pyx_t_2 = __pyx_t_8(__pyx_t_1); if (unlikely(!__pyx_t_2)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_3 = __pyx_t_8(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_1), 2) < (0)) __PYX_ERR(0, 1480, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    goto __pyx_L5_unpacking_done;
    __pyx_L4_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 1480, __pyx_L1_error)
    __pyx_L5_unpacking_done:;
  }
  __pyx_t_9 = __Pyx_PyLong_As_unsigned_long(__pyx_t_2); if (unlikely((__pyx_t_9 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 1480, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_10 = __Pyx_PyLong_As_unsigned_long(__pyx_t_3); if (unlikely((__pyx_t_10 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 1480, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_raster_x_size = __pyx_t_9;
  __pyx_v_raster_y_size = __pyx_t_10;

  /* "pygeoprocessing/routing/routing.pyx":1483
 * 
 *     # this is the nodata value for all the flat region and pit masks
 *     mask_nodata = 0             # <<<<<<<<<<<<<<
 * 
 *     # set up the working dir for the mask rasters
*/
  __pyx_v_mask_nodata = 0;

  /* "pygeoprocessing/routing/routing.pyx":1486
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_11, &__pyx_t_12, &__pyx_t_13);
    __Pyx_XGOTREF(__pyx_t_11);
    __Pyx_XGOTREF(__pyx_t_12);
    __Pyx_XGOTREF(__pyx_t_13);
    /*try:*/ {

      /* "pygeoprocessing/routing/routing.pyx":1487
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      __pyx_t_6 = (__pyx_v_working_dir != Py_None);
      if (__pyx_t_6) {

        /* "pygeoprocessing/routing/routing.pyx":1488
 *     try:
 *         if working_dir is not None:
 *             os.makedirs(working_dir)             # <<<<<<<<<<<<<<
 *     except OSError:
 *         pass
*/
        __pyx_t_3 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1488, __pyx_L6_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_makedirs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1488, __pyx_L6_error)
        __Pyx_GOTREF(__pyx_t_1);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_5 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_1))) {
          __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
          assert(__pyx_t_3);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_3);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
          __pyx_t_5 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_working_dir};
          __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1488, __pyx_L6_error)
          __Pyx_GOTREF(__pyx_t_4);
        }
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

        /* "pygeoprocessing/routing/routing.pyx":1487
 *     # set up the working dir for the mask rasters
 *     try:
 *         if working_dir is not None:             # <<<<<<<<<<<<<<
 *             os.makedirs(working_dir)
 *     except OSError:
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":1486
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    }
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    goto __pyx_L11_try_end;
    __pyx_L6_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_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1489
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
 *     except OSError:             # <<<<<<<<<<<<<<
 *         pass
 *     working_dir_path = tempfile.mkdtemp(
*/
    __pyx_t_14 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_OSError))));
    if (__pyx_t_14) {
      __Pyx_ErrRestore(0,0,0);
      goto __pyx_L7_exception_handled;
    }
    goto __pyx_L8_except_error;

    /* "pygeoprocessing/routing/routing.pyx":1486
 * 
 *     # set up the working dir for the mask rasters
 *     try:             # <<<<<<<<<<<<<<
 *         if working_dir is not None:
 *             os.makedirs(working_dir)
*/
    __pyx_L8_except_error:;
    __Pyx_XGIVEREF(__pyx_t_11);
    __Pyx_XGIVEREF(__pyx_t_12);
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
    goto __pyx_L1_error;
    __pyx_L7_exception_handled:;
    __Pyx_XGIVEREF(__pyx_t_11);
    __Pyx_XGIVEREF(__pyx_t_12);
    __Pyx_XGIVEREF(__pyx_t_13);
    __Pyx_ExceptionReset(__pyx_t_11, __pyx_t_12, __pyx_t_13);
    __pyx_L11_try_end:;
  }

  /* "pygeoprocessing/routing/routing.pyx":1491
 *     except OSError:
 *         pass
 *     working_dir_path = tempfile.mkdtemp(             # <<<<<<<<<<<<<<
 *         dir=working_dir,
 *         prefix='flow_dir_multiple_flow_dir_%s_' % time.strftime(
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1491, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1491, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1493
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir,
 *         prefix='flow_dir_multiple_flow_dir_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_15 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_strftime); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1494
 *         dir=working_dir,
 *         prefix='flow_dir_multiple_flow_dir_%s_' % time.strftime(
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))             # <<<<<<<<<<<<<<
 * 
 *     # this raster is used to keep track of what pixels have been searched for
*/
  __pyx_t_18 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_19, __pyx_mstate_global->__pyx_n_u_time); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 1494, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_19);
  __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_19, __pyx_mstate_global->__pyx_n_u_gmtime); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1494, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __Pyx_DECREF(__pyx_t_19); __pyx_t_19 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_20))) {
    __pyx_t_18 = PyMethod_GET_SELF(__pyx_t_20);
    assert(__pyx_t_18);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_20);
    __Pyx_INCREF(__pyx_t_18);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_20, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_18, NULL};
    __pyx_t_16 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_20, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_18); __pyx_t_18 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1494, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
  }
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_17))) {
    __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_17);
    assert(__pyx_t_15);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_17);
    __Pyx_INCREF(__pyx_t_15);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_17, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_mstate_global->__pyx_kp_u_Y_m_d__H__M__S, __pyx_t_16};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_17, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1493, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }

  /* "pygeoprocessing/routing/routing.pyx":1493
 *     working_dir_path = tempfile.mkdtemp(
 *         dir=working_dir,
 *         prefix='flow_dir_multiple_flow_dir_%s_' % time.strftime(             # <<<<<<<<<<<<<<
 *             '%Y-%m-%d_%H_%M_%S', time.gmtime()))
 * 
*/
  __pyx_t_17 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_flow_dir_multiple_flow_dir__s, __pyx_t_3); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1493, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_1, NULL};
    __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1491, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_v_working_dir, __pyx_t_3, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 1491, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_t_17, __pyx_t_3, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 1491, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1491, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_working_dir_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1499
 *     # a plateau. if a pixel is set, it means it is part of a locally
 *     # undrained area
 *     flat_region_mask_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1499, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1499, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_2 = __pyx_t_17;
  __Pyx_INCREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":1500
 *     # undrained area
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
*/
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_flat_region_mask_tif};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1499, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_flat_region_mask_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1501
 *     flat_region_mask_path = os.path.join(
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
*/
  __pyx_t_17 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1502
 *         working_dir_path, 'flat_region_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,             # <<<<<<<<<<<<<<
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1502, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1502, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1502, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1503
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __Pyx_PyLong_From_long(__pyx_v_mask_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1503, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = PyList_New(1); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1503, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_15, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1503, __pyx_L1_error);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1504
 *         dem_raster_path_band[0], flat_region_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_17);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_17);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_17, __pyx_t_2, __pyx_v_flat_region_mask_path, __pyx_t_16, __pyx_t_15};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1501, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_1, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1501, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1501, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1506
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(
 *         flat_region_mask_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_nodata = 0
*/
  __pyx_t_3 = __pyx_v_flat_region_mask_path;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1506, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 1506, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1505
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flat_region_mask_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flat_region_mask_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1505, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_flat_region_mask_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":1508
 *         flat_region_mask_path.encode('utf-8'), 1, True)
 * 
 *     flow_dir_nodata = 0             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Int32,
*/
  __pyx_v_flow_dir_nodata = 0;

  /* "pygeoprocessing/routing/routing.pyx":1509
 * 
 *     flow_dir_nodata = 0
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Int32,
 *         [flow_dir_nodata],
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1509, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1509, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1510
 *     flow_dir_nodata = 0
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Int32,             # <<<<<<<<<<<<<<
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1510, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1510, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_GDT_Int32); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1510, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1511
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Int32,
 *         [flow_dir_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_16 = __Pyx_PyLong_From_long(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1511, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = PyList_New(1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1511, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_GIVEREF(__pyx_t_16);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_17, 0, __pyx_t_16) != (0)) __PYX_ERR(0, 1511, __pyx_L1_error);
  __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1512
 *         dem_raster_path_band[0], target_flow_dir_path, gdal.GDT_Int32,
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster = ManagedRaster(
 *         target_flow_dir_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_15))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_15);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_3, __pyx_t_1, __pyx_v_target_flow_dir_path, __pyx_t_2, __pyx_t_17};
    __pyx_t_16 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1509, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_16, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1509, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_16);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1509, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1514
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(
 *         target_flow_dir_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     plateu_drain_mask_path = os.path.join(
*/
  __pyx_t_15 = __pyx_v_target_flow_dir_path;
  __Pyx_INCREF(__pyx_t_15);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_15, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1514, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 1514, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1513
 *         [flow_dir_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_flow_dir_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1513, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":1516
 *         target_flow_dir_path.encode('utf-8'), 1, True)
 * 
 *     plateu_drain_mask_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'plateu_drain_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1516, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1516, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
  __pyx_t_15 = __pyx_t_17;
  __Pyx_INCREF(__pyx_t_15);

  /* "pygeoprocessing/routing/routing.pyx":1517
 * 
 *     plateu_drain_mask_path = os.path.join(
 *         working_dir_path, 'plateu_drain_mask.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateu_drain_mask_path, gdal.GDT_Byte,
*/
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_plateu_drain_mask_tif};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1516, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_plateu_drain_mask_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1518
 *     plateu_drain_mask_path = os.path.join(
 *         working_dir_path, 'plateu_drain_mask.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], plateu_drain_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
*/
  __pyx_t_17 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1518, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1518, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1519
 *         working_dir_path, 'plateu_drain_mask.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateu_drain_mask_path, gdal.GDT_Byte,             # <<<<<<<<<<<<<<
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_15 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1519, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1519, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1519, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1520
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateu_drain_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_drain_mask_managed_raster = ManagedRaster(
*/
  __pyx_t_2 = __Pyx_PyLong_From_long(__pyx_v_mask_nodata); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1520, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1520, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 1520, __pyx_L1_error);
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1521
 *         dem_raster_path_band[0], plateu_drain_mask_path, gdal.GDT_Byte,
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     plateau_drain_mask_managed_raster = ManagedRaster(
 *         plateu_drain_mask_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_16))) {
    __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_16);
    assert(__pyx_t_17);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_16);
    __Pyx_INCREF(__pyx_t_17);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_16, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_17, __pyx_t_15, __pyx_v_plateu_drain_mask_path, __pyx_t_1, __pyx_t_3};
    __pyx_t_2 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1518, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_2, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1518, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_16, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_2);
    __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1518, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1523
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_drain_mask_managed_raster = ManagedRaster(
 *         plateu_drain_mask_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # this creates a raster that's used for a dynamic programming solution to
*/
  __pyx_t_16 = __pyx_v_plateu_drain_mask_path;
  __Pyx_INCREF(__pyx_t_16);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_16, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1523, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 1523, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1522
 *         [mask_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_drain_mask_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         plateu_drain_mask_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1522, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_plateau_drain_mask_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":1529
 *     # raster_x_size * raster_y_size as a distance that's greater than the
 *     # longest plateau drain distance possible for this raster.
 *     plateau_distance_path = os.path.join(             # <<<<<<<<<<<<<<
 *         working_dir_path, 'plateau_distance.tif')
 *     cdef unsigned long plateau_distance_nodata = raster_x_size * raster_y_size
*/
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1529, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1529, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_16 = __pyx_t_3;
  __Pyx_INCREF(__pyx_t_16);

  /* "pygeoprocessing/routing/routing.pyx":1530
 *     # longest plateau drain distance possible for this raster.
 *     plateau_distance_path = os.path.join(
 *         working_dir_path, 'plateau_distance.tif')             # <<<<<<<<<<<<<<
 *     cdef unsigned long plateau_distance_nodata = raster_x_size * raster_y_size
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_16, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_plateau_distance_tif};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_v_plateau_distance_path = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1531
 *     plateau_distance_path = os.path.join(
 *         working_dir_path, 'plateau_distance.tif')
 *     cdef unsigned long plateau_distance_nodata = raster_x_size * raster_y_size             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
*/
  __pyx_v_plateau_distance_nodata = (__pyx_v_raster_x_size * __pyx_v_raster_y_size);

  /* "pygeoprocessing/routing/routing.pyx":1532
 *         working_dir_path, 'plateau_distance.tif')
 *     cdef unsigned long plateau_distance_nodata = raster_x_size * raster_y_size
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [plateau_distance_nodata],
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1532, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1532, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1533
 *     cdef unsigned long plateau_distance_nodata = raster_x_size * raster_y_size
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,             # <<<<<<<<<<<<<<
 *         [plateau_distance_nodata],
 *         fill_value_list=[plateau_distance_nodata],
*/
  __pyx_t_16 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1533, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1533, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1533, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1534
 *     pygeoprocessing.new_raster_from_base(
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [plateau_distance_nodata],             # <<<<<<<<<<<<<<
 *         fill_value_list=[plateau_distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_1 = __Pyx_PyLong_From_unsigned_long(__pyx_v_plateau_distance_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1534, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_17 = PyList_New(1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1534, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_17, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1534, __pyx_L1_error);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1535
 *         dem_raster_path_band[0], plateau_distance_path, gdal.GDT_Float64,
 *         [plateau_distance_nodata],
 *         fill_value_list=[plateau_distance_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __Pyx_PyLong_From_unsigned_long(__pyx_v_plateau_distance_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1535, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_20 = PyList_New(1); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1535, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_20);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_20, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1535, __pyx_L1_error);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1536
 *         [plateau_distance_nodata],
 *         fill_value_list=[plateau_distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     plateau_distance_managed_raster = ManagedRaster(
 *         plateau_distance_path.encode('utf-8'), 1, True)
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_3, __pyx_t_16, __pyx_v_plateau_distance_path, __pyx_t_15, __pyx_t_17};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_fill_value_list, __pyx_t_20, __pyx_t_1, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1532, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_1, __pyx_callargs+5, 1) < (0)) __PYX_ERR(0, 1532, __pyx_L1_error)
    __pyx_t_4 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1532, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1538
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(
 *         plateau_distance_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # this raster is for random access of the DEM
*/
  __pyx_t_2 = __pyx_v_plateau_distance_path;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_4); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 1538, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1537
 *         fill_value_list=[plateau_distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     plateau_distance_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         plateau_distance_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1537, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_plateau_distance_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":1541
 * 
 *     # this raster is for random access of the DEM
 *     compatable_dem_raster_path_band = None             # <<<<<<<<<<<<<<
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
*/
  __Pyx_INCREF(Py_None);
  __pyx_v_compatable_dem_raster_path_band = Py_None;

  /* "pygeoprocessing/routing/routing.pyx":1542
 *     # this raster is for random access of the DEM
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']             # <<<<<<<<<<<<<<
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
*/
  __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_block_size); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1542, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
    PyObject* sequence = __pyx_t_4;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 1542, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_1);
    } else {
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1542, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1542, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_1);
    }
    #else
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1542, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1542, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    #endif
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_20 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1542, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_20);
    index = 0; __pyx_t_2 = __pyx_t_8(__pyx_t_20); if (unlikely(!__pyx_t_2)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_1 = __pyx_t_8(__pyx_t_20); if (unlikely(!__pyx_t_1)) goto __pyx_L15_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_20), 2) < (0)) __PYX_ERR(0, 1542, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    goto __pyx_L16_unpacking_done;
    __pyx_L15_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 1542, __pyx_L1_error)
    __pyx_L16_unpacking_done:;
  }
  __pyx_v_dem_block_xsize = __pyx_t_2;
  __pyx_t_2 = 0;
  __pyx_v_dem_block_ysize = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1543
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
  __pyx_t_4 = __Pyx_PyLong_SubtractObjC(__pyx_v_dem_block_xsize, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1543, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = PyNumber_And(__pyx_v_dem_block_xsize, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1543, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_23 = (__Pyx_PyLong_BoolNeObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_0, 0, 0)); if (unlikely((__pyx_t_23 < 0))) __PYX_ERR(0, 1543, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!__pyx_t_23) {
  } else {
    __pyx_t_6 = __pyx_t_23;
    goto __pyx_L18_bool_binop_done;
  }

  /* "pygeoprocessing/routing/routing.pyx":1544
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):             # <<<<<<<<<<<<<<
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
*/
  __pyx_t_1 = __Pyx_PyLong_SubtractObjC(__pyx_v_dem_block_ysize, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1544, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = PyNumber_And(__pyx_v_dem_block_ysize, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1544, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_23 = (__Pyx_PyLong_BoolNeObjC(__pyx_t_4, __pyx_mstate_global->__pyx_int_0, 0, 0)); if (unlikely((__pyx_t_23 < 0))) __PYX_ERR(0, 1544, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_6 = __pyx_t_23;
  __pyx_L18_bool_binop_done:;

  /* "pygeoprocessing/routing/routing.pyx":1543
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":1545
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1545, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_20 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_warning); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1545, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_20))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_20);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_20);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_20, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_dem_is_not_a_power_of_2_creating};
      __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_20, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1545, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1547
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),             # <<<<<<<<<<<<<<
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
*/
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1547, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1547, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_20 = __pyx_t_2;
    __Pyx_INCREF(__pyx_t_20);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_20, __pyx_v_working_dir_path, __pyx_mstate_global->__pyx_kp_u_compatable_dem_tif};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_20); __pyx_t_20 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1547, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }

    /* "pygeoprocessing/routing/routing.pyx":1548
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
 *             dem_raster_path_band[1])             # <<<<<<<<<<<<<<
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
*/
    __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1548, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":1547
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
 *         compatable_dem_raster_path_band = (
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),             # <<<<<<<<<<<<<<
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
*/
    __pyx_t_20 = PyTuple_New(2); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1547, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_GIVEREF(__pyx_t_4);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_20, 0, __pyx_t_4) != (0)) __PYX_ERR(0, 1547, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_20, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 1547, __pyx_L1_error);
    __pyx_t_4 = 0;
    __pyx_t_2 = 0;
    __Pyx_DECREF_SET(__pyx_v_compatable_dem_raster_path_band, __pyx_t_20);
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1549
 *             os.path.join(working_dir_path, 'compatable_dem.tif'),
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])             # <<<<<<<<<<<<<<
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(
*/
    __pyx_t_2 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1549, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_GetDriverByName); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1549, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_driver_creation_tuple, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1549, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_2);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1549, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __pyx_v_raster_driver = __pyx_t_20;
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1550
 *             dem_raster_path_band[1])
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1550, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1550, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1550, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1550, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1550, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_t_4, __pyx_t_15};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1550, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __pyx_v_dem_raster = __pyx_t_20;
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1551
 *         raster_driver = gdal.GetDriverByName(raster_driver_creation_tuple[0])
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])
*/
    __pyx_t_2 = __pyx_v_raster_driver;
    __Pyx_INCREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":1552
 *         dem_raster = gdal.OpenEx(dem_raster_path_band[0], gdal.OF_RASTER)
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,             # <<<<<<<<<<<<<<
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None
*/
    __pyx_t_15 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1552, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);

    /* "pygeoprocessing/routing/routing.pyx":1553
 *         raster_driver.CreateCopy(
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])             # <<<<<<<<<<<<<<
 *         dem_raster = None
 *         LOGGER.info("compatible dem complete")
*/
    __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_driver_creation_tuple, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1553, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_2, __pyx_t_15, __pyx_v_dem_raster};
      __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1551, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_options, __pyx_t_4, __pyx_t_1, __pyx_callargs+3, 0) < (0)) __PYX_ERR(0, 1551, __pyx_L1_error)
      __pyx_t_20 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateCopy, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1551, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1554
 *             compatable_dem_raster_path_band[0], dem_raster,
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None             # <<<<<<<<<<<<<<
 *         LOGGER.info("compatible dem complete")
 *     else:
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_dem_raster, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":1555
 *             options=raster_driver_creation_tuple[1])
 *         dem_raster = None
 *         LOGGER.info("compatible dem complete")             # <<<<<<<<<<<<<<
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1555, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1555, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_15))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_15);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_compatible_dem_complete};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1555, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1543
 *     compatable_dem_raster_path_band = None
 *     dem_block_xsize, dem_block_ysize = dem_raster_info['block_size']
 *     if (dem_block_xsize & (dem_block_xsize - 1) != 0) or (             # <<<<<<<<<<<<<<
 *             dem_block_ysize & (dem_block_ysize - 1) != 0):
 *         LOGGER.warning("dem is not a power of 2, creating a copy that is.")
*/
    goto __pyx_L17;
  }

  /* "pygeoprocessing/routing/routing.pyx":1557
 *         LOGGER.info("compatible dem complete")
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band             # <<<<<<<<<<<<<<
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
*/
  /*else*/ {
    __Pyx_INCREF(__pyx_v_dem_raster_path_band);
    __Pyx_DECREF_SET(__pyx_v_compatable_dem_raster_path_band, __pyx_v_dem_raster_path_band);
  }
  __pyx_L17:;

  /* "pygeoprocessing/routing/routing.pyx":1559
 *         compatable_dem_raster_path_band = dem_raster_path_band
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[1], False)
 * 
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1559, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_15 = __pyx_t_1;
  __Pyx_INCREF(__pyx_t_15);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_15, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1559, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __pyx_t_21 = __Pyx_PyObject_AsWritableString(__pyx_t_20); if (unlikely((!__pyx_t_21) && PyErr_Occurred())) __PYX_ERR(0, 1559, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1560
 *     dem_managed_raster = ManagedRaster(
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
 *         compatable_dem_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     # and this raster is for efficient block-by-block reading of the dem
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1560, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_1); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1560, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1558
 *     else:
 *         compatable_dem_raster_path_band = dem_raster_path_band
 *     dem_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[0].encode('utf-8'),
 *         compatable_dem_raster_path_band[1], False)
*/
  try {
    __pyx_t_22 = ManagedRaster(__pyx_t_21, __pyx_t_14, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1558, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  __pyx_v_dem_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_22);

  /* "pygeoprocessing/routing/routing.pyx":1563
 * 
 *     # and this raster is for efficient block-by-block reading of the dem
 *     dem_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)
 *     dem_band = dem_raster.GetRasterBand(
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1563, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1563, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1564
 *     # and this raster is for efficient block-by-block reading of the dem
 *     dem_raster = gdal.OpenEx(
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     dem_band = dem_raster.GetRasterBand(
 *         compatable_dem_raster_path_band[1])
*/
  __pyx_t_15 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1564, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1564, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1564, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_t_15, __pyx_t_17};
    __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1563, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __Pyx_XDECREF_SET(__pyx_v_dem_raster, __pyx_t_20);
  __pyx_t_20 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1565
 *     dem_raster = gdal.OpenEx(
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)
 *     dem_band = dem_raster.GetRasterBand(             # <<<<<<<<<<<<<<
 *         compatable_dem_raster_path_band[1])
 * 
*/
  __pyx_t_4 = __pyx_v_dem_raster;
  __Pyx_INCREF(__pyx_t_4);

  /* "pygeoprocessing/routing/routing.pyx":1566
 *         compatable_dem_raster_path_band[0], gdal.OF_RASTER)
 *     dem_band = dem_raster.GetRasterBand(
 *         compatable_dem_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for a pixel that is locally undrained
*/
  __pyx_t_17 = __Pyx_GetItemInt(__pyx_v_compatable_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1566, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_17};
    __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1565, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }
  __pyx_v_dem_band = __pyx_t_20;
  __pyx_t_20 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1569
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  __pyx_t_17 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1569, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1569, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1570
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             compatable_dem_raster_path_band, offset_only=True,             # <<<<<<<<<<<<<<
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_15))) {
    __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_15);
    assert(__pyx_t_17);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
    __Pyx_INCREF(__pyx_t_17);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_17, __pyx_v_compatable_dem_raster_path_band};
    __pyx_t_4 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1569, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_4, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 1569, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_4, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 1569, __pyx_L1_error)
    __pyx_t_20 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_4);
    __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1569, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
  }

  /* "pygeoprocessing/routing/routing.pyx":1569
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  if (likely(PyList_CheckExact(__pyx_t_20)) || PyTuple_CheckExact(__pyx_t_20)) {
    __pyx_t_15 = __pyx_t_20; __Pyx_INCREF(__pyx_t_15);
    __pyx_t_24 = 0;
    __pyx_t_25 = NULL;
  } else {
    __pyx_t_24 = -1; __pyx_t_15 = PyObject_GetIter(__pyx_t_20); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1569, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_25 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_15); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 1569, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
  for (;;) {
    if (likely(!__pyx_t_25)) {
      if (likely(PyList_CheckExact(__pyx_t_15))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_15);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 1569, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        __pyx_t_20 = __Pyx_PyList_GetItemRefFast(__pyx_t_15, __pyx_t_24, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_24;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_15);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 1569, __pyx_L1_error)
          #endif
          if (__pyx_t_24 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_20 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_15, __pyx_t_24));
        #else
        __pyx_t_20 = __Pyx_PySequence_ITEM(__pyx_t_15, __pyx_t_24);
        #endif
        ++__pyx_t_24;
      }
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1569, __pyx_L1_error)
    } else {
      __pyx_t_20 = __pyx_t_25(__pyx_t_15);
      if (unlikely(!__pyx_t_20)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 1569, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_20);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_20);
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1572
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1572, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_20); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1572, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_win_xsize = __pyx_t_14;

    /* "pygeoprocessing/routing/routing.pyx":1573
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1573, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_20); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1573, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_win_ysize = __pyx_t_14;

    /* "pygeoprocessing/routing/routing.pyx":1574
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1574, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_20); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1574, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_xoff = __pyx_t_14;

    /* "pygeoprocessing/routing/routing.pyx":1575
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_20 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1575, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_20); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1575, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    __pyx_v_yoff = __pyx_t_14;

    /* "pygeoprocessing/routing/routing.pyx":1577
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":1578
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('%.1f%% complete', 100.0 * current_pixel / <float>(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":1579
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info('%.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":1580
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('%.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1580, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1580, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
      __pyx_t_7 = (100.0 * __pyx_v_current_pixel);

      /* "pygeoprocessing/routing/routing.pyx":1581
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('%.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 * 
 *         # make a buffer big enough to capture block and boundaries around it
*/
      __pyx_t_26 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

      /* "pygeoprocessing/routing/routing.pyx":1580
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('%.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      if (unlikely(__pyx_t_26 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 1580, __pyx_L1_error)
      }
      __pyx_t_17 = PyFloat_FromDouble((__pyx_t_7 / ((double)__pyx_t_26))); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1580, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_1f_complete, __pyx_t_17};
        __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1580, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_20);
      }
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

      /* "pygeoprocessing/routing/routing.pyx":1577
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":1584
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1584, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1584, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1585
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.float64)
 *         dem_buffer_array[:] = dem_nodata
*/
    __pyx_t_17 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1585, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_t_17, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1585, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __pyx_t_17 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1585, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_16 = __Pyx_PyLong_AddObjC(__pyx_t_17, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1585, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __pyx_t_17 = PyTuple_New(2); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1585, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 1585, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_16);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 1, __pyx_t_16) != (0)) __PYX_ERR(0, 1585, __pyx_L1_error);
    __pyx_t_2 = 0;
    __pyx_t_16 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1586
 *         dem_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)             # <<<<<<<<<<<<<<
 *         dem_buffer_array[:] = dem_nodata
 * 
*/
    __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1586, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1586, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_4))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_1, __pyx_t_17};
      __pyx_t_16 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1584, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_2, __pyx_t_16, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 1584, __pyx_L1_error)
      __pyx_t_20 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_16);
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1584, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }

    /* "pygeoprocessing/routing/routing.pyx":1584
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         dem_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
*/
    if (!(likely(((__pyx_t_20) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_20, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 1584, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
      __pyx_t_14 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_20), &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_14 < 0)) {
        PyErr_Fetch(&__pyx_t_13, &__pyx_t_12, &__pyx_t_11);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_dem_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_float64_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_13); Py_XDECREF(__pyx_t_12); Py_XDECREF(__pyx_t_11);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_13, __pyx_t_12, __pyx_t_11);
        }
        __pyx_t_13 = __pyx_t_12 = __pyx_t_11 = 0;
      }
      __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dem_buffer_array.diminfo[0].shape = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_dem_buffer_array.diminfo[1].shape = __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_14 < 0))) __PYX_ERR(0, 1584, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_dem_buffer_array, ((PyArrayObject *)__pyx_t_20));
    __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1587
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
 *         dem_buffer_array[:] = dem_nodata             # <<<<<<<<<<<<<<
 * 
 *         # check if we can widen the border to include real data from the
*/
    __pyx_t_20 = PyFloat_FromDouble(__pyx_v_dem_nodata); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1587, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_20);
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_dem_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_t_20) < 0))) __PYX_ERR(0, 1587, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1591
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
*/
    __pyx_t_4 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_16, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1591, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);

    /* "pygeoprocessing/routing/routing.pyx":1592
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)
*/
    __pyx_t_2 = __Pyx_PyLong_From_unsigned_long(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1592, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_17 = __Pyx_PyLong_From_unsigned_long(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1592, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_16))) {
      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_16);
      assert(__pyx_t_4);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_16);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_16, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_4, __pyx_v_offset_dict, __pyx_t_2, __pyx_t_17};
      __pyx_t_20 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_16, __pyx_callargs+__pyx_t_5, (4-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_20))) || (PyList_CheckExact(__pyx_t_20))) {
      PyObject* sequence = __pyx_t_20;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 1591, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_16);
        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_17);
      } else {
        __pyx_t_16 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_16);
        __pyx_t_17 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_17);
      }
      #else
      __pyx_t_16 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      __pyx_t_17 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_17);
      #endif
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_2 = PyObject_GetIter(__pyx_t_20); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;
      __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2);
      index = 0; __pyx_t_16 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_16)) goto __pyx_L23_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_16);
      index = 1; __pyx_t_17 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_17)) goto __pyx_L23_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_17);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_2), 2) < (0)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      goto __pyx_L24_unpacking_done;
      __pyx_L23_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 1591, __pyx_L1_error)
      __pyx_L24_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":1591
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_16))) || (PyList_CheckExact(__pyx_t_16))) {
      PyObject* sequence = __pyx_t_16;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 1591, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_4);
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_3);
      } else {
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_4);
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1591, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_2,&__pyx_t_4,&__pyx_t_1,&__pyx_t_3};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 1591, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_2,&__pyx_t_4,&__pyx_t_1,&__pyx_t_3};
      __pyx_t_18 = PyObject_GetIter(__pyx_t_16); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_18);
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_18);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_8(__pyx_t_18); if (unlikely(!item)) goto __pyx_L25_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_18), 4) < (0)) __PYX_ERR(0, 1591, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      goto __pyx_L26_unpacking_done;
      __pyx_L25_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 1591, __pyx_L1_error)
      __pyx_L26_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_2);
    __pyx_t_2 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_4);
    __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_3);
    __pyx_t_3 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_17);
    __pyx_t_17 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1593
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_v_dem_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);

    /* "pygeoprocessing/routing/routing.pyx":1594
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 1594, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_3 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1594, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    } else {
      __pyx_t_3 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1593, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }

    /* "pygeoprocessing/routing/routing.pyx":1593
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_16, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_17 = __pyx_t_1;
    __Pyx_INCREF(__pyx_t_17);

    /* "pygeoprocessing/routing/routing.pyx":1594
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.float64)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1594, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_float64); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1594, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_17, __pyx_t_16};
      __pyx_t_20 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 1594, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_20);
    }

    /* "pygeoprocessing/routing/routing.pyx":1593
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         dem_buffer_array[ya:yb, xa:xb] = dem_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.float64)
 * 
*/
    __pyx_t_1 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_16 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_16);
    __pyx_t_17 = PyTuple_New(2); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_17);
    __Pyx_GIVEREF(__pyx_t_1);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1593, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_16);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 1, __pyx_t_16) != (0)) __PYX_ERR(0, 1593, __pyx_L1_error);
    __pyx_t_1 = 0;
    __pyx_t_16 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_dem_buffer_array), __pyx_t_17, __pyx_t_20) < 0))) __PYX_ERR(0, 1593, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
    __Pyx_DECREF(__pyx_t_20); __pyx_t_20 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1597
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":1598
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # search block for to set flow direction
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":1601
 * 
 *         # search block for to set flow direction
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
*/
    __pyx_t_27 = (__pyx_v_win_ysize + 1);
    __pyx_t_28 = __pyx_t_27;
    for (__pyx_t_29 = 1; __pyx_t_29 < __pyx_t_28; __pyx_t_29+=1) {
      __pyx_v_yi = __pyx_t_29;

      /* "pygeoprocessing/routing/routing.pyx":1602
 *         # search block for to set flow direction
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):
*/
      __pyx_t_30 = (__pyx_v_win_xsize + 1);
      __pyx_t_31 = __pyx_t_30;
      for (__pyx_t_32 = 1; __pyx_t_32 < __pyx_t_31; __pyx_t_32+=1) {
        __pyx_v_xi = __pyx_t_32;

        /* "pygeoprocessing/routing/routing.pyx":1603
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]             # <<<<<<<<<<<<<<
 *                 if is_close(root_height, dem_nodata):
 *                     continue
*/
        __pyx_t_5 = __pyx_v_yi;
        __pyx_t_33 = __pyx_v_xi;
        __pyx_t_14 = -1;
        if (unlikely(__pyx_t_5 >= (size_t)__pyx_pybuffernd_dem_buffer_array.diminfo[0].shape)) __pyx_t_14 = 0;
        if (unlikely(__pyx_t_33 >= (size_t)__pyx_pybuffernd_dem_buffer_array.diminfo[1].shape)) __pyx_t_14 = 1;
        if (unlikely(__pyx_t_14 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_14);
          __PYX_ERR(0, 1603, __pyx_L1_error)
        }
        __pyx_v_root_height = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float64_t *, __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides, __pyx_t_33, __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides));

        /* "pygeoprocessing/routing/routing.pyx":1604
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_6 = is_close(__pyx_v_root_height, __pyx_v_dem_nodata);
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":1605
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # this value is set in case it turns out to be the root of a
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":1604
 *             for xi in range(1, win_xsize+1):
 *                 root_height = dem_buffer_array[yi, xi]
 *                 if is_close(root_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":1610
 *                 # pit, we'll start the fill from this pixel in the last phase
 *                 # of the algorithm
 *                 xi_root = xi-1+xoff             # <<<<<<<<<<<<<<
 *                 yi_root = yi-1+yoff
 * 
*/
        __pyx_v_xi_root = ((__pyx_v_xi - 1) + __pyx_v_xoff);

        /* "pygeoprocessing/routing/routing.pyx":1611
 *                 # of the algorithm
 *                 xi_root = xi-1+xoff
 *                 yi_root = yi-1+yoff             # <<<<<<<<<<<<<<
 * 
 *                 if flow_dir_managed_raster.get(
*/
        __pyx_v_yi_root = ((__pyx_v_yi - 1) + __pyx_v_yoff);

        /* "pygeoprocessing/routing/routing.pyx":1614
 * 
 *                 if flow_dir_managed_raster.get(
 *                         xi_root, yi_root) != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     # already been defined
 *                     continue
*/
        __pyx_t_6 = (__pyx_v_flow_dir_managed_raster.get(__pyx_v_xi_root, __pyx_v_yi_root) != __pyx_v_flow_dir_nodata);

        /* "pygeoprocessing/routing/routing.pyx":1613
 *                 yi_root = yi-1+yoff
 * 
 *                 if flow_dir_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
*/
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":1616
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # PHASE 1 - try to set the direction based on local values
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":1613
 *                 yi_root = yi-1+yoff
 * 
 *                 if flow_dir_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root) != flow_dir_nodata:
 *                     # already been defined
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":1622
 *                 # undefined, the largest slope seen so far is flat, and the
 *                 # largest nodata is at least a diagonal away
 *                 sum_of_downhill_slopes = 0.0             # <<<<<<<<<<<<<<
 *                 for i_n in range(8):
 *                     # initialize downhill slopes to 0.0
*/
        __pyx_v_sum_of_downhill_slopes = 0.0;

        /* "pygeoprocessing/routing/routing.pyx":1623
 *                 # largest nodata is at least a diagonal away
 *                 sum_of_downhill_slopes = 0.0
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     # initialize downhill slopes to 0.0
 *                     downhill_slope_array[i_n] = 0.0
*/
        for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
          __pyx_v_i_n = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1625
 *                 for i_n in range(8):
 *                     # initialize downhill slopes to 0.0
 *                     downhill_slope_array[i_n] = 0.0             # <<<<<<<<<<<<<<
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]
*/
          (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":1626
 *                     # initialize downhill slopes to 0.0
 *                     downhill_slope_array[i_n] = 0.0
 *                     xi_n = xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
*/
          __pyx_v_xi_n = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":1627
 *                     downhill_slope_array[i_n] = 0.0
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):
*/
          __pyx_v_yi_n = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":1628
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]             # <<<<<<<<<<<<<<
 *                     if is_close(n_height, dem_nodata):
 *                         continue
*/
          __pyx_t_33 = __pyx_v_yi_n;
          __pyx_t_5 = __pyx_v_xi_n;
          __pyx_t_14 = -1;
          if (unlikely(__pyx_t_33 >= (size_t)__pyx_pybuffernd_dem_buffer_array.diminfo[0].shape)) __pyx_t_14 = 0;
          if (unlikely(__pyx_t_5 >= (size_t)__pyx_pybuffernd_dem_buffer_array.diminfo[1].shape)) __pyx_t_14 = 1;
          if (unlikely(__pyx_t_14 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_14);
            __PYX_ERR(0, 1628, __pyx_L1_error)
          }
          __pyx_v_n_height = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_float64_t *, __pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_33, __pyx_pybuffernd_dem_buffer_array.diminfo[0].strides, __pyx_t_5, __pyx_pybuffernd_dem_buffer_array.diminfo[1].strides));

          /* "pygeoprocessing/routing/routing.pyx":1629
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         continue
 *                     n_slope = root_height - n_height
*/
          __pyx_t_6 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1630
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):
 *                         continue             # <<<<<<<<<<<<<<
 *                     n_slope = root_height - n_height
 *                     if n_slope > 0.0:
*/
            goto __pyx_L33_continue;

            /* "pygeoprocessing/routing/routing.pyx":1629
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 *                     n_height = dem_buffer_array[yi_n, xi_n]
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         continue
 *                     n_slope = root_height - n_height
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":1631
 *                     if is_close(n_height, dem_nodata):
 *                         continue
 *                     n_slope = root_height - n_height             # <<<<<<<<<<<<<<
 *                     if n_slope > 0.0:
 *                         if i_n & 1:
*/
          __pyx_v_n_slope = (__pyx_v_root_height - __pyx_v_n_height);

          /* "pygeoprocessing/routing/routing.pyx":1632
 *                         continue
 *                     n_slope = root_height - n_height
 *                     if n_slope > 0.0:             # <<<<<<<<<<<<<<
 *                         if i_n & 1:
 *                             # if diagonal, adjust the slope
*/
          __pyx_t_6 = (__pyx_v_n_slope > 0.0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1633
 *                     n_slope = root_height - n_height
 *                     if n_slope > 0.0:
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             # if diagonal, adjust the slope
 *                             n_slope *= SQRT2_INV
*/
            __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1635
 *                         if i_n & 1:
 *                             # if diagonal, adjust the slope
 *                             n_slope *= SQRT2_INV             # <<<<<<<<<<<<<<
 *                         downhill_slope_array[i_n] = n_slope
 *                         sum_of_downhill_slopes += n_slope
*/
              __pyx_v_n_slope = (__pyx_v_n_slope * __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV);

              /* "pygeoprocessing/routing/routing.pyx":1633
 *                     n_slope = root_height - n_height
 *                     if n_slope > 0.0:
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             # if diagonal, adjust the slope
 *                             n_slope *= SQRT2_INV
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1636
 *                             # if diagonal, adjust the slope
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope             # <<<<<<<<<<<<<<
 *                         sum_of_downhill_slopes += n_slope
 * 
*/
            (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = __pyx_v_n_slope;

            /* "pygeoprocessing/routing/routing.pyx":1637
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope
 *                         sum_of_downhill_slopes += n_slope             # <<<<<<<<<<<<<<
 * 
 *                 if sum_of_downhill_slopes > 0.0:
*/
            __pyx_v_sum_of_downhill_slopes = (__pyx_v_sum_of_downhill_slopes + __pyx_v_n_slope);

            /* "pygeoprocessing/routing/routing.pyx":1632
 *                         continue
 *                     n_slope = root_height - n_height
 *                     if n_slope > 0.0:             # <<<<<<<<<<<<<<
 *                         if i_n & 1:
 *                             # if diagonal, adjust the slope
*/
          }
          __pyx_L33_continue:;
        }

        /* "pygeoprocessing/routing/routing.pyx":1639
 *                         sum_of_downhill_slopes += n_slope
 * 
 *                 if sum_of_downhill_slopes > 0.0:             # <<<<<<<<<<<<<<
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):
*/
        __pyx_t_6 = (__pyx_v_sum_of_downhill_slopes > 0.0);
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":1640
 * 
 *                 if sum_of_downhill_slopes > 0.0:
 *                     compressed_integer_slopes = 0             # <<<<<<<<<<<<<<
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(
*/
          __pyx_v_compressed_integer_slopes = 0;

          /* "pygeoprocessing/routing/routing.pyx":1641
 *                 if sum_of_downhill_slopes > 0.0:
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         compressed_integer_slopes |= (<int>(
 *                             0.5 + downhill_slope_array[i_n] /
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1643
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(
 *                             0.5 + downhill_slope_array[i_n] /             # <<<<<<<<<<<<<<
 *                             sum_of_downhill_slopes * 0xF)) << (i_n * 4)
 * 
*/
            if (unlikely(__pyx_v_sum_of_downhill_slopes == 0)) {
              PyErr_SetString(PyExc_ZeroDivisionError, "float division");
              __PYX_ERR(0, 1643, __pyx_L1_error)
            }

            /* "pygeoprocessing/routing/routing.pyx":1642
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(             # <<<<<<<<<<<<<<
 *                             0.5 + downhill_slope_array[i_n] /
 *                             sum_of_downhill_slopes * 0xF)) << (i_n * 4)
*/
            __pyx_v_compressed_integer_slopes = (__pyx_v_compressed_integer_slopes | (((int)(0.5 + (((__pyx_v_downhill_slope_array[__pyx_v_i_n]) / __pyx_v_sum_of_downhill_slopes) * 15.0))) << (__pyx_v_i_n * 4)));
          }

          /* "pygeoprocessing/routing/routing.pyx":1646
 *                             sum_of_downhill_slopes * 0xF)) << (i_n * 4)
 * 
 *                     flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root, compressed_integer_slopes)
 *                     continue
*/
          __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, __pyx_v_compressed_integer_slopes);

          /* "pygeoprocessing/routing/routing.pyx":1648
 *                     flow_dir_managed_raster.set(
 *                         xi_root, yi_root, compressed_integer_slopes)
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # PHASE 2 - search for what drains the plateau, prefer
*/
          goto __pyx_L29_continue;

          /* "pygeoprocessing/routing/routing.pyx":1639
 *                         sum_of_downhill_slopes += n_slope
 * 
 *                 if sum_of_downhill_slopes > 0.0:             # <<<<<<<<<<<<<<
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":1656
 *                 # otherwise, this pixel doesn't drain locally, so it must
 *                 # be a plateau, search for the drains of the plateau
 *                 drain_search_queue.push(CoordinateType(xi_root, yi_root))             # <<<<<<<<<<<<<<
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)
 * 
*/
        __pyx_t_35.xi = __pyx_v_xi_root;
        __pyx_t_35.yi = __pyx_v_yi_root;
        __pyx_v_drain_search_queue.push(__pyx_t_35);

        /* "pygeoprocessing/routing/routing.pyx":1657
 *                 # be a plateau, search for the drains of the plateau
 *                 drain_search_queue.push(CoordinateType(xi_root, yi_root))
 *                 flat_region_mask_managed_raster.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 * 
 *                 # this loop does a BFS starting at this pixel to all pixels
*/
        __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

        /* "pygeoprocessing/routing/routing.pyx":1662
 *                 # of the same height. if a drain is encountered, it is pushed
 *                 # on a queue for later processing.
 *                 while not drain_search_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = drain_search_queue.front().xi
 *                     yi_q = drain_search_queue.front().yi
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_drain_search_queue.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":1663
 *                 # on a queue for later processing.
 *                 while not drain_search_queue.empty():
 *                     xi_q = drain_search_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = drain_search_queue.front().yi
 *                     drain_search_queue.pop()
*/
          __pyx_t_34 = __pyx_v_drain_search_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1664
 *                 while not drain_search_queue.empty():
 *                     xi_q = drain_search_queue.front().xi
 *                     yi_q = drain_search_queue.front().yi             # <<<<<<<<<<<<<<
 *                     drain_search_queue.pop()
 * 
*/
          __pyx_t_34 = __pyx_v_drain_search_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1665
 *                     xi_q = drain_search_queue.front().xi
 *                     yi_q = drain_search_queue.front().yi
 *                     drain_search_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     sum_of_slope_weights = 0.0
*/
          __pyx_v_drain_search_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":1667
 *                     drain_search_queue.pop()
 * 
 *                     sum_of_slope_weights = 0.0             # <<<<<<<<<<<<<<
 *                     sum_of_nodata_slope_weights = 0.0
 *                     for i_n in range(8):
*/
          __pyx_v_sum_of_slope_weights = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":1668
 * 
 *                     sum_of_slope_weights = 0.0
 *                     sum_of_nodata_slope_weights = 0.0             # <<<<<<<<<<<<<<
 *                     for i_n in range(8):
 *                         # initialize downhill slopes to 0.0
*/
          __pyx_v_sum_of_nodata_slope_weights = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":1669
 *                     sum_of_slope_weights = 0.0
 *                     sum_of_nodata_slope_weights = 0.0
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         # initialize downhill slopes to 0.0
 *                         downhill_slope_array[i_n] = 0.0
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1671
 *                     for i_n in range(8):
 *                         # initialize downhill slopes to 0.0
 *                         downhill_slope_array[i_n] = 0.0             # <<<<<<<<<<<<<<
 *                         nodata_downhill_slope_array[i_n] = 0.0
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
*/
            (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = 0.0;

            /* "pygeoprocessing/routing/routing.pyx":1672
 *                         # initialize downhill slopes to 0.0
 *                         downhill_slope_array[i_n] = 0.0
 *                         nodata_downhill_slope_array[i_n] = 0.0             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
            (__pyx_v_nodata_downhill_slope_array[__pyx_v_i_n]) = 0.0;

            /* "pygeoprocessing/routing/routing.pyx":1673
 *                         downhill_slope_array[i_n] = 0.0
 *                         nodata_downhill_slope_array[i_n] = 0.0
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1674
 *                         nodata_downhill_slope_array[i_n] = 0.0
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1676
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
            __pyx_t_23 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L46_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L46_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1677
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             n_height = dem_nodata
 *                         else:
*/
            __pyx_t_23 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L46_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L46_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1676
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1678
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata             # <<<<<<<<<<<<<<
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
*/
              __pyx_v_n_height = __pyx_v_dem_nodata;

              /* "pygeoprocessing/routing/routing.pyx":1676
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             n_height = dem_nodata
*/
              goto __pyx_L45;
            }

            /* "pygeoprocessing/routing/routing.pyx":1680
 *                             n_height = dem_nodata
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                         if is_close(n_height, dem_nodata):
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
*/
            /*else*/ {
              __pyx_v_n_height = __pyx_v_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);
            }
            __pyx_L45:;

            /* "pygeoprocessing/routing/routing.pyx":1681
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             sum_of_nodata_slope_weights += n_slope
*/
            __pyx_t_6 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1682
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0             # <<<<<<<<<<<<<<
 *                             sum_of_nodata_slope_weights += n_slope
 *                             nodata_downhill_slope_array[i_n] = n_slope
*/
              __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
              if (__pyx_t_6) {
                __pyx_t_7 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV;
              } else {
                __pyx_t_7 = 1.0;
              }
              __pyx_v_n_slope = __pyx_t_7;

              /* "pygeoprocessing/routing/routing.pyx":1683
 *                         if is_close(n_height, dem_nodata):
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             sum_of_nodata_slope_weights += n_slope             # <<<<<<<<<<<<<<
 *                             nodata_downhill_slope_array[i_n] = n_slope
 *                             continue
*/
              __pyx_v_sum_of_nodata_slope_weights = (__pyx_v_sum_of_nodata_slope_weights + __pyx_v_n_slope);

              /* "pygeoprocessing/routing/routing.pyx":1684
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             sum_of_nodata_slope_weights += n_slope
 *                             nodata_downhill_slope_array[i_n] = n_slope             # <<<<<<<<<<<<<<
 *                             continue
 *                         n_slope = root_height - n_height
*/
              (__pyx_v_nodata_downhill_slope_array[__pyx_v_i_n]) = __pyx_v_n_slope;

              /* "pygeoprocessing/routing/routing.pyx":1685
 *                             sum_of_nodata_slope_weights += n_slope
 *                             nodata_downhill_slope_array[i_n] = n_slope
 *                             continue             # <<<<<<<<<<<<<<
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:
*/
              goto __pyx_L43_continue;

              /* "pygeoprocessing/routing/routing.pyx":1681
 *                         else:
 *                             n_height = dem_managed_raster.get(xi_n, yi_n)
 *                         if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             sum_of_nodata_slope_weights += n_slope
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1686
 *                             nodata_downhill_slope_array[i_n] = n_slope
 *                             continue
 *                         n_slope = root_height - n_height             # <<<<<<<<<<<<<<
 *                         if n_slope < 0:
 *                             continue
*/
            __pyx_v_n_slope = (__pyx_v_root_height - __pyx_v_n_height);

            /* "pygeoprocessing/routing/routing.pyx":1687
 *                             continue
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_slope == 0.0:
*/
            __pyx_t_6 = (__pyx_v_n_slope < 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1688
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(
*/
              goto __pyx_L43_continue;

              /* "pygeoprocessing/routing/routing.pyx":1687
 *                             continue
 *                         n_slope = root_height - n_height
 *                         if n_slope < 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_slope == 0.0:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1689
 *                         if n_slope < 0:
 *                             continue
 *                         if n_slope == 0.0:             # <<<<<<<<<<<<<<
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:
*/
            __pyx_t_6 = (__pyx_v_n_slope == 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1691
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:             # <<<<<<<<<<<<<<
 *                                 # only grow if it's at the same level and not
 *                                 # previously visited
*/
              __pyx_t_6 = (__pyx_v_flat_region_mask_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == __pyx_v_mask_nodata);

              /* "pygeoprocessing/routing/routing.pyx":1690
 *                             continue
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n) == mask_nodata:
 *                                 # only grow if it's at the same level and not
*/
              if (__pyx_t_6) {

                /* "pygeoprocessing/routing/routing.pyx":1695
 *                                 # previously visited
 *                                 drain_search_queue.push(
 *                                     CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                                 flat_region_mask_managed_raster.set(
 *                                     xi_n, yi_n, 1)
*/
                __pyx_t_35.xi = __pyx_v_xi_n;
                __pyx_t_35.yi = __pyx_v_yi_n;

                /* "pygeoprocessing/routing/routing.pyx":1694
 *                                 # only grow if it's at the same level and not
 *                                 # previously visited
 *                                 drain_search_queue.push(             # <<<<<<<<<<<<<<
 *                                     CoordinateType(xi_n, yi_n))
 *                                 flat_region_mask_managed_raster.set(
*/
                __pyx_v_drain_search_queue.push(__pyx_t_35);

                /* "pygeoprocessing/routing/routing.pyx":1696
 *                                 drain_search_queue.push(
 *                                     CoordinateType(xi_n, yi_n))
 *                                 flat_region_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n, 1)
 *                             continue
*/
                __pyx_v_flat_region_mask_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

                /* "pygeoprocessing/routing/routing.pyx":1690
 *                             continue
 *                         if n_slope == 0.0:
 *                             if flat_region_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n) == mask_nodata:
 *                                 # only grow if it's at the same level and not
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":1698
 *                                 flat_region_mask_managed_raster.set(
 *                                     xi_n, yi_n, 1)
 *                             continue             # <<<<<<<<<<<<<<
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV
*/
              goto __pyx_L43_continue;

              /* "pygeoprocessing/routing/routing.pyx":1689
 *                         if n_slope < 0:
 *                             continue
 *                         if n_slope == 0.0:             # <<<<<<<<<<<<<<
 *                             if flat_region_mask_managed_raster.get(
 *                                     xi_n, yi_n) == mask_nodata:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1699
 *                                     xi_n, yi_n, 1)
 *                             continue
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope
*/
            __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1700
 *                             continue
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV             # <<<<<<<<<<<<<<
 *                         downhill_slope_array[i_n] = n_slope
 *                         sum_of_slope_weights += downhill_slope_array[i_n]
*/
              __pyx_v_n_slope = (__pyx_v_n_slope * __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV);

              /* "pygeoprocessing/routing/routing.pyx":1699
 *                                     xi_n, yi_n, 1)
 *                             continue
 *                         if i_n & 1:             # <<<<<<<<<<<<<<
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1701
 *                         if i_n & 1:
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope             # <<<<<<<<<<<<<<
 *                         sum_of_slope_weights += downhill_slope_array[i_n]
 * 
*/
            (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = __pyx_v_n_slope;

            /* "pygeoprocessing/routing/routing.pyx":1702
 *                             n_slope *= SQRT2_INV
 *                         downhill_slope_array[i_n] = n_slope
 *                         sum_of_slope_weights += downhill_slope_array[i_n]             # <<<<<<<<<<<<<<
 * 
 *                     working_downhill_slope_sum = 0.0
*/
            __pyx_v_sum_of_slope_weights = (__pyx_v_sum_of_slope_weights + (__pyx_v_downhill_slope_array[__pyx_v_i_n]));
            __pyx_L43_continue:;
          }

          /* "pygeoprocessing/routing/routing.pyx":1704
 *                         sum_of_slope_weights += downhill_slope_array[i_n]
 * 
 *                     working_downhill_slope_sum = 0.0             # <<<<<<<<<<<<<<
 *                     working_downhill_slope_array = NULL
 *                     if sum_of_slope_weights > 0.0:
*/
          __pyx_v_working_downhill_slope_sum = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":1705
 * 
 *                     working_downhill_slope_sum = 0.0
 *                     working_downhill_slope_array = NULL             # <<<<<<<<<<<<<<
 *                     if sum_of_slope_weights > 0.0:
 *                         working_downhill_slope_array = downhill_slope_array
*/
          __pyx_v_working_downhill_slope_array = NULL;

          /* "pygeoprocessing/routing/routing.pyx":1706
 *                     working_downhill_slope_sum = 0.0
 *                     working_downhill_slope_array = NULL
 *                     if sum_of_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_array = downhill_slope_array
 *                         working_downhill_slope_sum = sum_of_slope_weights
*/
          __pyx_t_6 = (__pyx_v_sum_of_slope_weights > 0.0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1707
 *                     working_downhill_slope_array = NULL
 *                     if sum_of_slope_weights > 0.0:
 *                         working_downhill_slope_array = downhill_slope_array             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_sum = sum_of_slope_weights
 *                     elif sum_of_nodata_slope_weights > 0.0:
*/
            __pyx_v_working_downhill_slope_array = __pyx_v_downhill_slope_array;

            /* "pygeoprocessing/routing/routing.pyx":1708
 *                     if sum_of_slope_weights > 0.0:
 *                         working_downhill_slope_array = downhill_slope_array
 *                         working_downhill_slope_sum = sum_of_slope_weights             # <<<<<<<<<<<<<<
 *                     elif sum_of_nodata_slope_weights > 0.0:
 *                         working_downhill_slope_array = (
*/
            __pyx_v_working_downhill_slope_sum = __pyx_v_sum_of_slope_weights;

            /* "pygeoprocessing/routing/routing.pyx":1706
 *                     working_downhill_slope_sum = 0.0
 *                     working_downhill_slope_array = NULL
 *                     if sum_of_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_array = downhill_slope_array
 *                         working_downhill_slope_sum = sum_of_slope_weights
*/
            goto __pyx_L55;
          }

          /* "pygeoprocessing/routing/routing.pyx":1709
 *                         working_downhill_slope_array = downhill_slope_array
 *                         working_downhill_slope_sum = sum_of_slope_weights
 *                     elif sum_of_nodata_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_array = (
 *                             nodata_downhill_slope_array)
*/
          __pyx_t_6 = (__pyx_v_sum_of_nodata_slope_weights > 0.0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1711
 *                     elif sum_of_nodata_slope_weights > 0.0:
 *                         working_downhill_slope_array = (
 *                             nodata_downhill_slope_array)             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_sum = (
 *                             sum_of_nodata_slope_weights)
*/
            __pyx_v_working_downhill_slope_array = __pyx_v_nodata_downhill_slope_array;

            /* "pygeoprocessing/routing/routing.pyx":1713
 *                             nodata_downhill_slope_array)
 *                         working_downhill_slope_sum = (
 *                             sum_of_nodata_slope_weights)             # <<<<<<<<<<<<<<
 * 
 *                     if working_downhill_slope_sum > 0.0:
*/
            __pyx_v_working_downhill_slope_sum = __pyx_v_sum_of_nodata_slope_weights;

            /* "pygeoprocessing/routing/routing.pyx":1709
 *                         working_downhill_slope_array = downhill_slope_array
 *                         working_downhill_slope_sum = sum_of_slope_weights
 *                     elif sum_of_nodata_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                         working_downhill_slope_array = (
 *                             nodata_downhill_slope_array)
*/
          }
          __pyx_L55:;

          /* "pygeoprocessing/routing/routing.pyx":1715
 *                             sum_of_nodata_slope_weights)
 * 
 *                     if working_downhill_slope_sum > 0.0:             # <<<<<<<<<<<<<<
 *                         compressed_integer_slopes = 0
 *                         for i_n in range(8):
*/
          __pyx_t_6 = (__pyx_v_working_downhill_slope_sum > 0.0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1716
 * 
 *                     if working_downhill_slope_sum > 0.0:
 *                         compressed_integer_slopes = 0             # <<<<<<<<<<<<<<
 *                         for i_n in range(8):
 *                             compressed_integer_slopes |= (<int>(
*/
            __pyx_v_compressed_integer_slopes = 0;

            /* "pygeoprocessing/routing/routing.pyx":1717
 *                     if working_downhill_slope_sum > 0.0:
 *                         compressed_integer_slopes = 0
 *                         for i_n in range(8):             # <<<<<<<<<<<<<<
 *                             compressed_integer_slopes |= (<int>(
 *                                 0.5 + working_downhill_slope_array[i_n] /
*/
            for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
              __pyx_v_i_n = __pyx_t_34;

              /* "pygeoprocessing/routing/routing.pyx":1719
 *                         for i_n in range(8):
 *                             compressed_integer_slopes |= (<int>(
 *                                 0.5 + working_downhill_slope_array[i_n] /             # <<<<<<<<<<<<<<
 *                                 working_downhill_slope_sum * 0xF)) << (
 *                                 i_n * 4)
*/
              if (unlikely(__pyx_v_working_downhill_slope_sum == 0)) {
                PyErr_SetString(PyExc_ZeroDivisionError, "float division");
                __PYX_ERR(0, 1719, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":1718
 *                         compressed_integer_slopes = 0
 *                         for i_n in range(8):
 *                             compressed_integer_slopes |= (<int>(             # <<<<<<<<<<<<<<
 *                                 0.5 + working_downhill_slope_array[i_n] /
 *                                 working_downhill_slope_sum * 0xF)) << (
*/
              __pyx_v_compressed_integer_slopes = (__pyx_v_compressed_integer_slopes | (((int)(0.5 + (((__pyx_v_working_downhill_slope_array[__pyx_v_i_n]) / __pyx_v_working_downhill_slope_sum) * 15.0))) << (__pyx_v_i_n * 4)));
            }

            /* "pygeoprocessing/routing/routing.pyx":1722
 *                                 working_downhill_slope_sum * 0xF)) << (
 *                                 i_n * 4)
 *                         if sum_of_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(
*/
            __pyx_t_6 = (__pyx_v_sum_of_slope_weights > 0.0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1724
 *                         if sum_of_slope_weights > 0.0:
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_q, yi_q, compressed_integer_slopes)
 *                             plateau_distance_managed_raster.set(
*/
              __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_compressed_integer_slopes);

              /* "pygeoprocessing/routing/routing.pyx":1726
 *                             flow_dir_managed_raster.set(
 *                                 xi_q, yi_q, compressed_integer_slopes)
 *                             plateau_distance_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_q, yi_q, 0.0)
 *                             plateau_drain_mask_managed_raster.set(
*/
              __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 0.0);

              /* "pygeoprocessing/routing/routing.pyx":1728
 *                             plateau_distance_managed_raster.set(
 *                                 xi_q, yi_q, 0.0)
 *                             plateau_drain_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_q, yi_q, 1)
 *                             distance_drain_queue.push(
*/
              __pyx_v_plateau_drain_mask_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 1.0);

              /* "pygeoprocessing/routing/routing.pyx":1731
 *                                 xi_q, yi_q, 1)
 *                             distance_drain_queue.push(
 *                                 CoordinateType(xi_q, yi_q))             # <<<<<<<<<<<<<<
 *                         else:
 *                             nodata_distance_drain_queue.push(
*/
              __pyx_t_35.xi = __pyx_v_xi_q;
              __pyx_t_35.yi = __pyx_v_yi_q;

              /* "pygeoprocessing/routing/routing.pyx":1730
 *                             plateau_drain_mask_managed_raster.set(
 *                                 xi_q, yi_q, 1)
 *                             distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_q, yi_q))
 *                         else:
*/
              __pyx_v_distance_drain_queue.push(__pyx_t_35);

              /* "pygeoprocessing/routing/routing.pyx":1722
 *                                 working_downhill_slope_sum * 0xF)) << (
 *                                 i_n * 4)
 *                         if sum_of_slope_weights > 0.0:             # <<<<<<<<<<<<<<
 *                             # regular downhill pixel
 *                             flow_dir_managed_raster.set(
*/
              goto __pyx_L59;
            }

            /* "pygeoprocessing/routing/routing.pyx":1733
 *                                 CoordinateType(xi_q, yi_q))
 *                         else:
 *                             nodata_distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(
*/
            /*else*/ {

              /* "pygeoprocessing/routing/routing.pyx":1734
 *                         else:
 *                             nodata_distance_drain_queue.push(
 *                                 CoordinateType(xi_q, yi_q))             # <<<<<<<<<<<<<<
 *                             nodata_flow_dir_queue.push(
 *                                 compressed_integer_slopes)
*/
              __pyx_t_35.xi = __pyx_v_xi_q;
              __pyx_t_35.yi = __pyx_v_yi_q;

              /* "pygeoprocessing/routing/routing.pyx":1733
 *                                 CoordinateType(xi_q, yi_q))
 *                         else:
 *                             nodata_distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(
*/
              __pyx_v_nodata_distance_drain_queue.push(__pyx_t_35);

              /* "pygeoprocessing/routing/routing.pyx":1735
 *                             nodata_distance_drain_queue.push(
 *                                 CoordinateType(xi_q, yi_q))
 *                             nodata_flow_dir_queue.push(             # <<<<<<<<<<<<<<
 *                                 compressed_integer_slopes)
 * 
*/
              __pyx_v_nodata_flow_dir_queue.push(__pyx_v_compressed_integer_slopes);
            }
            __pyx_L59:;

            /* "pygeoprocessing/routing/routing.pyx":1715
 *                             sum_of_nodata_slope_weights)
 * 
 *                     if working_downhill_slope_sum > 0.0:             # <<<<<<<<<<<<<<
 *                         compressed_integer_slopes = 0
 *                         for i_n in range(8):
*/
          }
        }

        /* "pygeoprocessing/routing/routing.pyx":1739
 * 
 *                 # if there's no downhill drains, try the nodata drains
 *                 if distance_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     # push the nodata drain queue over to the drain queue
 *                     # and set all the flow directions on the nodata drain
*/
        __pyx_t_6 = __pyx_v_distance_drain_queue.empty();
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":1743
 *                     # and set all the flow directions on the nodata drain
 *                     # pixels
 *                     while not nodata_distance_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                         xi_q = nodata_distance_drain_queue.front().xi
 *                         yi_q = nodata_distance_drain_queue.front().yi
*/
          while (1) {
            __pyx_t_6 = (!__pyx_v_nodata_distance_drain_queue.empty());
            if (!__pyx_t_6) break;

            /* "pygeoprocessing/routing/routing.pyx":1744
 *                     # pixels
 *                     while not nodata_distance_drain_queue.empty():
 *                         xi_q = nodata_distance_drain_queue.front().xi             # <<<<<<<<<<<<<<
 *                         yi_q = nodata_distance_drain_queue.front().yi
 *                         flow_dir_managed_raster.set(
*/
            __pyx_t_34 = __pyx_v_nodata_distance_drain_queue.front().xi;
            __pyx_v_xi_q = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1745
 *                     while not nodata_distance_drain_queue.empty():
 *                         xi_q = nodata_distance_drain_queue.front().xi
 *                         yi_q = nodata_distance_drain_queue.front().yi             # <<<<<<<<<<<<<<
 *                         flow_dir_managed_raster.set(
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
*/
            __pyx_t_34 = __pyx_v_nodata_distance_drain_queue.front().yi;
            __pyx_v_yi_q = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1746
 *                         xi_q = nodata_distance_drain_queue.front().xi
 *                         yi_q = nodata_distance_drain_queue.front().yi
 *                         flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
*/
            __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_nodata_flow_dir_queue.front());

            /* "pygeoprocessing/routing/routing.pyx":1748
 *                         flow_dir_managed_raster.set(
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)             # <<<<<<<<<<<<<<
 *                         plateau_drain_mask_managed_raster.set(xi_q, yi_q, 1)
 *                         distance_drain_queue.push(
*/
            __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 0.0);

            /* "pygeoprocessing/routing/routing.pyx":1749
 *                             xi_q, yi_q, nodata_flow_dir_queue.front())
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
 *                         plateau_drain_mask_managed_raster.set(xi_q, yi_q, 1)             # <<<<<<<<<<<<<<
 *                         distance_drain_queue.push(
 *                             nodata_distance_drain_queue.front())
*/
            __pyx_v_plateau_drain_mask_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, 1.0);

            /* "pygeoprocessing/routing/routing.pyx":1750
 *                         plateau_distance_managed_raster.set(xi_q, yi_q, 0.0)
 *                         plateau_drain_mask_managed_raster.set(xi_q, yi_q, 1)
 *                         distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                             nodata_distance_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()
*/
            __pyx_v_distance_drain_queue.push(__pyx_v_nodata_distance_drain_queue.front());

            /* "pygeoprocessing/routing/routing.pyx":1752
 *                         distance_drain_queue.push(
 *                             nodata_distance_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()             # <<<<<<<<<<<<<<
 *                         nodata_distance_drain_queue.pop()
 *                 else:
*/
            __pyx_v_nodata_flow_dir_queue.pop();

            /* "pygeoprocessing/routing/routing.pyx":1753
 *                             nodata_distance_drain_queue.front())
 *                         nodata_flow_dir_queue.pop()
 *                         nodata_distance_drain_queue.pop()             # <<<<<<<<<<<<<<
 *                 else:
 *                     # clear the nodata drain queues
*/
            __pyx_v_nodata_distance_drain_queue.pop();
          }

          /* "pygeoprocessing/routing/routing.pyx":1739
 * 
 *                 # if there's no downhill drains, try the nodata drains
 *                 if distance_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     # push the nodata drain queue over to the drain queue
 *                     # and set all the flow directions on the nodata drain
*/
          goto __pyx_L60;
        }

        /* "pygeoprocessing/routing/routing.pyx":1756
 *                 else:
 *                     # clear the nodata drain queues
 *                     nodata_flow_dir_queue = IntQueueType()             # <<<<<<<<<<<<<<
 *                     nodata_distance_drain_queue = CoordinateQueueType()
 * 
*/
        /*else*/ {
          try {
            __pyx_t_36 = __pyx_t_15pygeoprocessing_7routing_7routing_IntQueueType();
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1756, __pyx_L1_error)
          }
          __pyx_v_nodata_flow_dir_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_36);

          /* "pygeoprocessing/routing/routing.pyx":1757
 *                     # clear the nodata drain queues
 *                     nodata_flow_dir_queue = IntQueueType()
 *                     nodata_distance_drain_queue = CoordinateQueueType()             # <<<<<<<<<<<<<<
 * 
 *                 # copy the drain queue to another queue
*/
          try {
            __pyx_t_37 = __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType();
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 1757, __pyx_L1_error)
          }
          __pyx_v_nodata_distance_drain_queue = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_37);
        }
        __pyx_L60:;

        /* "pygeoprocessing/routing/routing.pyx":1760
 * 
 *                 # copy the drain queue to another queue
 *                 for _ in range(distance_drain_queue.size()):             # <<<<<<<<<<<<<<
 *                     distance_drain_queue.push(
 *                         distance_drain_queue.front())
*/
        __pyx_t_5 = __pyx_v_distance_drain_queue.size();
        __pyx_t_33 = __pyx_t_5;
        for (__pyx_t_38 = 0; __pyx_t_38 < __pyx_t_33; __pyx_t_38+=1) {
          __pyx_v__ = __pyx_t_38;

          /* "pygeoprocessing/routing/routing.pyx":1761
 *                 # copy the drain queue to another queue
 *                 for _ in range(distance_drain_queue.size()):
 *                     distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                         distance_drain_queue.front())
 *                     direction_drain_queue.push(distance_drain_queue.front())
*/
          __pyx_v_distance_drain_queue.push(__pyx_v_distance_drain_queue.front());

          /* "pygeoprocessing/routing/routing.pyx":1763
 *                     distance_drain_queue.push(
 *                         distance_drain_queue.front())
 *                     direction_drain_queue.push(distance_drain_queue.front())             # <<<<<<<<<<<<<<
 *                     distance_drain_queue.pop()
 * 
*/
          __pyx_v_direction_drain_queue.push(__pyx_v_distance_drain_queue.front());

          /* "pygeoprocessing/routing/routing.pyx":1764
 *                         distance_drain_queue.front())
 *                     direction_drain_queue.push(distance_drain_queue.front())
 *                     distance_drain_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                 # PHASE 3 - build up a distance raster for the plateau such
*/
          __pyx_v_distance_drain_queue.pop();
        }

        /* "pygeoprocessing/routing/routing.pyx":1772
 *                 # this loop does a BFS from the plateau drain to any other
 *                 # neighboring undefined pixels
 *                 while not distance_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = distance_drain_queue.front().xi
 *                     yi_q = distance_drain_queue.front().yi
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_distance_drain_queue.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":1773
 *                 # neighboring undefined pixels
 *                 while not distance_drain_queue.empty():
 *                     xi_q = distance_drain_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = distance_drain_queue.front().yi
 *                     distance_drain_queue.pop()
*/
          __pyx_t_34 = __pyx_v_distance_drain_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1774
 *                 while not distance_drain_queue.empty():
 *                     xi_q = distance_drain_queue.front().xi
 *                     yi_q = distance_drain_queue.front().yi             # <<<<<<<<<<<<<<
 *                     distance_drain_queue.pop()
 * 
*/
          __pyx_t_34 = __pyx_v_distance_drain_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1775
 *                     xi_q = distance_drain_queue.front().xi
 *                     yi_q = distance_drain_queue.front().yi
 *                     distance_drain_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(
*/
          __pyx_v_distance_drain_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":1777
 *                     distance_drain_queue.pop()
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_q, yi_q)
 * 
*/
          __pyx_v_drain_distance = __pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_q, __pyx_v_yi_q);

          /* "pygeoprocessing/routing/routing.pyx":1780
 *                         xi_q, yi_q)
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1781
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1782
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1783
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_23 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L70_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L70_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1784
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_23 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L70_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L70_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1783
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1785
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         n_drain_distance = drain_distance + (
*/
              goto __pyx_L67_continue;

              /* "pygeoprocessing/routing/routing.pyx":1783
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1788
 * 
 *                         n_drain_distance = drain_distance + (
 *                             SQRT2 if i_n & 1 else 1.0)             # <<<<<<<<<<<<<<
 * 
 *                         if (<double>(dem_managed_raster.get(
*/
            __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
            if (__pyx_t_6) {
              __pyx_t_7 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2;
            } else {
              __pyx_t_7 = 1.0;
            }

            /* "pygeoprocessing/routing/routing.pyx":1787
 *                             continue
 * 
 *                         n_drain_distance = drain_distance + (             # <<<<<<<<<<<<<<
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
*/
            __pyx_v_n_drain_distance = (__pyx_v_drain_distance + __pyx_t_7);

            /* "pygeoprocessing/routing/routing.pyx":1791
 * 
 *                         if (<double>(dem_managed_raster.get(
 *                                 xi_n, yi_n)) == root_height) and (             # <<<<<<<<<<<<<<
 *                                 plateau_distance_managed_raster.get(
 *                                     xi_n, yi_n) > n_drain_distance):
*/
            __pyx_t_23 = (((double)__pyx_v_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n)) == __pyx_v_root_height);
            if (__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L75_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1793
 *                                 xi_n, yi_n)) == root_height) and (
 *                                 plateau_distance_managed_raster.get(
 *                                     xi_n, yi_n) > n_drain_distance):             # <<<<<<<<<<<<<<
 *                             # neighbor is at same level and has longer drain
 *                             # flow path than current
*/
            __pyx_t_23 = (__pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) > __pyx_v_n_drain_distance);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L75_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1790
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
 *                         if (<double>(dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n)) == root_height) and (
 *                                 plateau_distance_managed_raster.get(
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1796
 *                             # neighbor is at same level and has longer drain
 *                             # flow path than current
 *                             plateau_distance_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, n_drain_distance)
 *                             distance_drain_queue.push(
*/
              __pyx_v_plateau_distance_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, __pyx_v_n_drain_distance);

              /* "pygeoprocessing/routing/routing.pyx":1799
 *                                 xi_n, yi_n, n_drain_distance)
 *                             distance_drain_queue.push(
 *                                 CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 * 
 *                 # PHASE 4 - set the plateau pixel flow direction based on the
*/
              __pyx_t_35.xi = __pyx_v_xi_n;
              __pyx_t_35.yi = __pyx_v_yi_n;

              /* "pygeoprocessing/routing/routing.pyx":1798
 *                             plateau_distance_managed_raster.set(
 *                                 xi_n, yi_n, n_drain_distance)
 *                             distance_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_n, yi_n))
 * 
*/
              __pyx_v_distance_drain_queue.push(__pyx_t_35);

              /* "pygeoprocessing/routing/routing.pyx":1790
 *                             SQRT2 if i_n & 1 else 1.0)
 * 
 *                         if (<double>(dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n)) == root_height) and (
 *                                 plateau_distance_managed_raster.get(
*/
            }
            __pyx_L67_continue:;
          }
        }

        /* "pygeoprocessing/routing/routing.pyx":1803
 *                 # PHASE 4 - set the plateau pixel flow direction based on the
 *                 # distance to the nearest drain
 *                 while not direction_drain_queue.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = direction_drain_queue.front().xi
 *                     yi_q = direction_drain_queue.front().yi
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_direction_drain_queue.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":1804
 *                 # distance to the nearest drain
 *                 while not direction_drain_queue.empty():
 *                     xi_q = direction_drain_queue.front().xi             # <<<<<<<<<<<<<<
 *                     yi_q = direction_drain_queue.front().yi
 *                     direction_drain_queue.pop()
*/
          __pyx_t_34 = __pyx_v_direction_drain_queue.front().xi;
          __pyx_v_xi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1805
 *                 while not direction_drain_queue.empty():
 *                     xi_q = direction_drain_queue.front().xi
 *                     yi_q = direction_drain_queue.front().yi             # <<<<<<<<<<<<<<
 *                     direction_drain_queue.pop()
 * 
*/
          __pyx_t_34 = __pyx_v_direction_drain_queue.front().yi;
          __pyx_v_yi_q = __pyx_t_34;

          /* "pygeoprocessing/routing/routing.pyx":1806
 *                     xi_q = direction_drain_queue.front().xi
 *                     yi_q = direction_drain_queue.front().yi
 *                     direction_drain_queue.pop()             # <<<<<<<<<<<<<<
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(
*/
          __pyx_v_direction_drain_queue.pop();

          /* "pygeoprocessing/routing/routing.pyx":1808
 *                     direction_drain_queue.pop()
 * 
 *                     drain_distance = plateau_distance_managed_raster.get(             # <<<<<<<<<<<<<<
 *                         xi_q, yi_q)
 * 
*/
          __pyx_v_drain_distance = __pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_q, __pyx_v_yi_q);

          /* "pygeoprocessing/routing/routing.pyx":1811
 *                         xi_q, yi_q)
 * 
 *                     sum_of_slope_weights = 0.0             # <<<<<<<<<<<<<<
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
*/
          __pyx_v_sum_of_slope_weights = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":1812
 * 
 *                     sum_of_slope_weights = 0.0
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1813
 *                     sum_of_slope_weights = 0.0
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         downhill_slope_array[i_n] = 0.0
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1814
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         downhill_slope_array[i_n] = 0.0
 * 
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":1815
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 *                         downhill_slope_array[i_n] = 0.0             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = 0.0;

            /* "pygeoprocessing/routing/routing.pyx":1817
 *                         downhill_slope_array[i_n] = 0.0
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_23 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L82_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L82_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":1818
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_23 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_23) {
            } else {
              __pyx_t_6 = __pyx_t_23;
              goto __pyx_L82_bool_binop_done;
            }
            __pyx_t_23 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_23;
            __pyx_L82_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":1817
 *                         downhill_slope_array[i_n] = 0.0
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1819
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         if dem_managed_raster.get(xi_n, yi_n) != root_height:
*/
              goto __pyx_L79_continue;

              /* "pygeoprocessing/routing/routing.pyx":1817
 *                         downhill_slope_array[i_n] = 0.0
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1821
 *                             continue
 * 
 *                         if dem_managed_raster.get(xi_n, yi_n) != root_height:             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_6 = (__pyx_v_dem_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) != __pyx_v_root_height);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1822
 * 
 *                         if dem_managed_raster.get(xi_n, yi_n) != root_height:
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         n_distance = plateau_distance_managed_raster.get(
*/
              goto __pyx_L79_continue;

              /* "pygeoprocessing/routing/routing.pyx":1821
 *                             continue
 * 
 *                         if dem_managed_raster.get(xi_n, yi_n) != root_height:             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1824
 *                             continue
 * 
 *                         n_distance = plateau_distance_managed_raster.get(             # <<<<<<<<<<<<<<
 *                             xi_n, yi_n)
 *                         if n_distance == plateau_distance_nodata:
*/
            __pyx_v_n_distance = __pyx_v_plateau_distance_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":1826
 *                         n_distance = plateau_distance_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if n_distance == plateau_distance_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_distance < drain_distance:
*/
            __pyx_t_6 = (__pyx_v_n_distance == __pyx_v_plateau_distance_nodata);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1827
 *                             xi_n, yi_n)
 *                         if n_distance == plateau_distance_nodata:
 *                             continue             # <<<<<<<<<<<<<<
 *                         if n_distance < drain_distance:
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
*/
              goto __pyx_L79_continue;

              /* "pygeoprocessing/routing/routing.pyx":1826
 *                         n_distance = plateau_distance_managed_raster.get(
 *                             xi_n, yi_n)
 *                         if n_distance == plateau_distance_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if n_distance < drain_distance:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":1828
 *                         if n_distance == plateau_distance_nodata:
 *                             continue
 *                         if n_distance < drain_distance:             # <<<<<<<<<<<<<<
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             downhill_slope_array[i_n] = n_slope
*/
            __pyx_t_6 = (__pyx_v_n_distance < __pyx_v_drain_distance);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1829
 *                             continue
 *                         if n_distance < drain_distance:
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0             # <<<<<<<<<<<<<<
 *                             downhill_slope_array[i_n] = n_slope
 *                             sum_of_slope_weights += n_slope
*/
              __pyx_t_6 = ((__pyx_v_i_n & 1) != 0);
              if (__pyx_t_6) {
                __pyx_t_7 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV;
              } else {
                __pyx_t_7 = 1.0;
              }
              __pyx_v_n_slope = __pyx_t_7;

              /* "pygeoprocessing/routing/routing.pyx":1830
 *                         if n_distance < drain_distance:
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             downhill_slope_array[i_n] = n_slope             # <<<<<<<<<<<<<<
 *                             sum_of_slope_weights += n_slope
 *                         elif not plateau_drain_mask_managed_raster.get(
*/
              (__pyx_v_downhill_slope_array[__pyx_v_i_n]) = __pyx_v_n_slope;

              /* "pygeoprocessing/routing/routing.pyx":1831
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             downhill_slope_array[i_n] = n_slope
 *                             sum_of_slope_weights += n_slope             # <<<<<<<<<<<<<<
 *                         elif not plateau_drain_mask_managed_raster.get(
 *                                 xi_n, yi_n):
*/
              __pyx_v_sum_of_slope_weights = (__pyx_v_sum_of_slope_weights + __pyx_v_n_slope);

              /* "pygeoprocessing/routing/routing.pyx":1828
 *                         if n_distance == plateau_distance_nodata:
 *                             continue
 *                         if n_distance < drain_distance:             # <<<<<<<<<<<<<<
 *                             n_slope = SQRT2_INV if i_n & 1 else 1.0
 *                             downhill_slope_array[i_n] = n_slope
*/
              goto __pyx_L88;
            }

            /* "pygeoprocessing/routing/routing.pyx":1832
 *                             downhill_slope_array[i_n] = n_slope
 *                             sum_of_slope_weights += n_slope
 *                         elif not plateau_drain_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n):
 *                             direction_drain_queue.push(
*/
            __pyx_t_6 = (!(__pyx_v_plateau_drain_mask_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) != 0));
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":1835
 *                                 xi_n, yi_n):
 *                             direction_drain_queue.push(
 *                                 CoordinateType(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                             plateau_drain_mask_managed_raster.set(
 *                                 xi_n, yi_n, 1)
*/
              __pyx_t_35.xi = __pyx_v_xi_n;
              __pyx_t_35.yi = __pyx_v_yi_n;

              /* "pygeoprocessing/routing/routing.pyx":1834
 *                         elif not plateau_drain_mask_managed_raster.get(
 *                                 xi_n, yi_n):
 *                             direction_drain_queue.push(             # <<<<<<<<<<<<<<
 *                                 CoordinateType(xi_n, yi_n))
 *                             plateau_drain_mask_managed_raster.set(
*/
              __pyx_v_direction_drain_queue.push(__pyx_t_35);

              /* "pygeoprocessing/routing/routing.pyx":1836
 *                             direction_drain_queue.push(
 *                                 CoordinateType(xi_n, yi_n))
 *                             plateau_drain_mask_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n, 1)
 * 
*/
              __pyx_v_plateau_drain_mask_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

              /* "pygeoprocessing/routing/routing.pyx":1832
 *                             downhill_slope_array[i_n] = n_slope
 *                             sum_of_slope_weights += n_slope
 *                         elif not plateau_drain_mask_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_n, yi_n):
 *                             direction_drain_queue.push(
*/
            }
            __pyx_L88:;
            __pyx_L79_continue:;
          }

          /* "pygeoprocessing/routing/routing.pyx":1839
 *                                 xi_n, yi_n, 1)
 * 
 *                     if sum_of_slope_weights == 0:             # <<<<<<<<<<<<<<
 *                         continue
 *                     compressed_integer_slopes = 0
*/
          __pyx_t_6 = (__pyx_v_sum_of_slope_weights == 0.0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":1840
 * 
 *                     if sum_of_slope_weights == 0:
 *                         continue             # <<<<<<<<<<<<<<
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):
*/
            goto __pyx_L77_continue;

            /* "pygeoprocessing/routing/routing.pyx":1839
 *                                 xi_n, yi_n, 1)
 * 
 *                     if sum_of_slope_weights == 0:             # <<<<<<<<<<<<<<
 *                         continue
 *                     compressed_integer_slopes = 0
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":1841
 *                     if sum_of_slope_weights == 0:
 *                         continue
 *                     compressed_integer_slopes = 0             # <<<<<<<<<<<<<<
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(
*/
          __pyx_v_compressed_integer_slopes = 0;

          /* "pygeoprocessing/routing/routing.pyx":1842
 *                         continue
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         compressed_integer_slopes |= (<int>(
 *                             0.5 + downhill_slope_array[i_n] /
*/
          for (__pyx_t_34 = 0; __pyx_t_34 < 8; __pyx_t_34+=1) {
            __pyx_v_i_n = __pyx_t_34;

            /* "pygeoprocessing/routing/routing.pyx":1844
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(
 *                             0.5 + downhill_slope_array[i_n] /             # <<<<<<<<<<<<<<
 *                             sum_of_slope_weights * 0xF)) << (i_n * 4)
 *                     flow_dir_managed_raster.set(
*/
            if (unlikely(__pyx_v_sum_of_slope_weights == 0)) {
              PyErr_SetString(PyExc_ZeroDivisionError, "float division");
              __PYX_ERR(0, 1844, __pyx_L1_error)
            }

            /* "pygeoprocessing/routing/routing.pyx":1843
 *                     compressed_integer_slopes = 0
 *                     for i_n in range(8):
 *                         compressed_integer_slopes |= (<int>(             # <<<<<<<<<<<<<<
 *                             0.5 + downhill_slope_array[i_n] /
 *                             sum_of_slope_weights * 0xF)) << (i_n * 4)
*/
            __pyx_v_compressed_integer_slopes = (__pyx_v_compressed_integer_slopes | (((int)(0.5 + (((__pyx_v_downhill_slope_array[__pyx_v_i_n]) / __pyx_v_sum_of_slope_weights) * 15.0))) << (__pyx_v_i_n * 4)));
          }

          /* "pygeoprocessing/routing/routing.pyx":1846
 *                             0.5 + downhill_slope_array[i_n] /
 *                             sum_of_slope_weights * 0xF)) << (i_n * 4)
 *                     flow_dir_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_q, yi_q, compressed_integer_slopes)
 * 
*/
          __pyx_v_flow_dir_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_compressed_integer_slopes);
          __pyx_L77_continue:;
        }
        __pyx_L29_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":1569
 * 
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             compatable_dem_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  }
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1849
 *                         xi_q, yi_q, compressed_integer_slopes)
 * 
 *     dem_band = None             # <<<<<<<<<<<<<<
 *     dem_raster = None
 *     plateau_drain_mask_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_dem_band, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":1850
 * 
 *     dem_band = None
 *     dem_raster = None             # <<<<<<<<<<<<<<
 *     plateau_drain_mask_managed_raster.close()
 *     flow_dir_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_dem_raster, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":1851
 *     dem_band = None
 *     dem_raster = None
 *     plateau_drain_mask_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()
*/
  __pyx_v_plateau_drain_mask_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1852
 *     dem_raster = None
 *     plateau_drain_mask_managed_raster.close()
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1853
 *     plateau_drain_mask_managed_raster.close()
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()             # <<<<<<<<<<<<<<
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()
*/
  __pyx_v_flat_region_mask_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1854
 *     flow_dir_managed_raster.close()
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()             # <<<<<<<<<<<<<<
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
*/
  __pyx_v_dem_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1855
 *     flat_region_mask_managed_raster.close()
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()             # <<<<<<<<<<<<<<
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('Flow dir MFD %.1f%% complete', 100.0)
*/
  __pyx_v_plateau_distance_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":1856
 *     dem_managed_raster.close()
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)             # <<<<<<<<<<<<<<
 *     LOGGER.info('Flow dir MFD %.1f%% complete', 100.0)
 * 
*/
  __pyx_t_20 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 1856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_17);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_17, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_16))) {
    __pyx_t_20 = PyMethod_GET_SELF(__pyx_t_16);
    assert(__pyx_t_20);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_16);
    __Pyx_INCREF(__pyx_t_20);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_16, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_20, __pyx_v_working_dir_path};
    __pyx_t_15 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_16, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_20); __pyx_t_20 = 0;
    __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
    if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1856, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
  }
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1857
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('Flow dir MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 1857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_16);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
  __pyx_t_15 = __Pyx_PyObject_Call(__pyx_t_16, __pyx_mstate_global->__pyx_tuple[1], NULL); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 1857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1362
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_15);
  __Pyx_XDECREF(__pyx_t_16);
  __Pyx_XDECREF(__pyx_t_17);
  __Pyx_XDECREF(__pyx_t_18);
  __Pyx_XDECREF(__pyx_t_19);
  __Pyx_XDECREF(__pyx_t_20);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_dir_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dem_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_dem_buffer_array);
  __Pyx_XDECREF(__pyx_v_dem_raster_info);
  __Pyx_XDECREF(__pyx_v_base_nodata);
  __Pyx_XDECREF(__pyx_v_working_dir_path);
  __Pyx_XDECREF(__pyx_v_flat_region_mask_path);
  __Pyx_XDECREF(__pyx_v_plateu_drain_mask_path);
  __Pyx_XDECREF(__pyx_v_plateau_distance_path);
  __Pyx_XDECREF(__pyx_v_compatable_dem_raster_path_band);
  __Pyx_XDECREF(__pyx_v_dem_block_xsize);
  __Pyx_XDECREF(__pyx_v_dem_block_ysize);
  __Pyx_XDECREF(__pyx_v_raster_driver);
  __Pyx_XDECREF(__pyx_v_dem_raster);
  __Pyx_XDECREF(__pyx_v_dem_band);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":1860
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_40__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":1863
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
 *         weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Multiple flow direction accumulation.
*/
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1860, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, Py_None) != (0)) __PYX_ERR(0, 1860, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 1860, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":1860
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1860, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 1860, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 1860, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_11flow_accumulation_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_10flow_accumulation_mfd, "Multiple flow direction accumulation.\n\n    Parameters:\n        flow_dir_mfd_raster_path_band (tuple): a path, band number tuple\n            for a multiple flow direction raster generated from a call to\n            ``flow_dir_mfd``. The format of this raster is described in the\n            docstring of that function. Paths may use any GDAL-supported\n            scheme, including virtual file system /vsi schemes.\n        target_flow_accum_raster_path (str): a path to a raster created by\n            a call to this function that is the same dimensions and projection\n            as ``flow_dir_mfd_raster_path_band[0]``. The value in each pixel is\n            1 plus the proportional contribution of all upstream pixels that\n            flow into it. The proportion is determined as the value of the\n            upstream flow dir pixel in the downslope direction pointing to\n            the current pixel divided by the sum of all the flow weights\n            exiting that pixel. Note the target type of this raster\n            is a 64 bit float so there is minimal risk of overflow and the\n            possibility of handling a float dtype in\n            ``weight_raster_path_band``.\n        weight_raster_path_band (tuple): optional path and band number to a\n            raster that will be used as the per-pixel flow accumulation\n            weight. If ``None``, 1 is the default flow accumulation weight.\n            This raster must be the same dimensions as\n            ``flow_dir_mfd_raster_path_band``. If a weight nodata pixel is\n            encountered it will be treated as a weight value of 0. Paths may\n            use any GDAL-supported scheme, including virtual file system /vsi schemes.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT""_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_11flow_accumulation_mfd = {"flow_accumulation_mfd", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_11flow_accumulation_mfd, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_10flow_accumulation_mfd};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_11flow_accumulation_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_mfd_raster_path_band = 0;
  PyObject *__pyx_v_target_flow_accum_raster_path = 0;
  PyObject *__pyx_v_weight_raster_path_band = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[4] = {0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("flow_accumulation_mfd (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_mfd_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_flow_accum_raster_path,&__pyx_mstate_global->__pyx_n_u_weight_raster_path_band,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 1860, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "flow_accumulation_mfd", 0) < (0)) __PYX_ERR(0, 1860, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":1863
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
 *         weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Multiple flow direction accumulation.
*/
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 2; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("flow_accumulation_mfd", 0, 2, 4, i); __PYX_ERR(0, 1860, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 1860, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 1860, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 1860, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[2]) values[2] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[3]) values[3] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_dir_mfd_raster_path_band = values[0];
    __pyx_v_target_flow_accum_raster_path = values[1];
    __pyx_v_weight_raster_path_band = values[2];
    __pyx_v_raster_driver_creation_tuple = values[3];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("flow_accumulation_mfd", 0, 2, 4, __pyx_nargs); __PYX_ERR(0, 1860, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_accumulation_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_10flow_accumulation_mfd(__pyx_self, __pyx_v_flow_dir_mfd_raster_path_band, __pyx_v_target_flow_accum_raster_path, __pyx_v_weight_raster_path_band, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":1860
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_10flow_accumulation_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_mfd_raster_path_band, PyObject *__pyx_v_target_flow_accum_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_flow_dir_mfd_buffer_array = 0;
  unsigned long __pyx_v_win_ysize;
  unsigned long __pyx_v_win_xsize;
  unsigned long __pyx_v_xoff;
  unsigned long __pyx_v_yoff;
  unsigned PY_LONG_LONG __pyx_v_visit_count;
  unsigned PY_LONG_LONG __pyx_v_pixel_count;
  unsigned long __pyx_v_xi_root;
  unsigned long __pyx_v_yi_root;
  int __pyx_v_i_n;
  int __pyx_v_xi;
  int __pyx_v_yi;
  int __pyx_v_xi_n;
  int __pyx_v_yi_n;
  int __pyx_v_i_upstream_flow;
  int __pyx_v_flow_dir_mfd;
  int __pyx_v_upstream_flow_weight;
  int __pyx_v_compressed_upstream_flow_dir;
  int __pyx_v_upstream_flow_dir_sum;
  double __pyx_v_upstream_flow_accum;
  double __pyx_v_flow_accum_nodata;
  double __pyx_v_weight_nodata;
  double __pyx_v_weight_val;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_FlowPixelType>  __pyx_v_search_stack;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_FlowPixelType __pyx_v_flow_pixel;
  unsigned long __pyx_v_raster_x_size;
  unsigned long __pyx_v_raster_y_size;
  time_t __pyx_v_last_log_time;
  unsigned long __pyx_v_current_pixel;
  ManagedRaster __pyx_v_flow_accum_managed_raster;
  PyObject *__pyx_v_tmp_dir_root = NULL;
  PyObject *__pyx_v_tmp_dir = NULL;
  PyObject *__pyx_v_visited_raster_path = NULL;
  ManagedRaster __pyx_v_visited_managed_raster;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  PyObject *__pyx_v_flow_dir_raster = NULL;
  PyObject *__pyx_v_flow_dir_band = NULL;
  ManagedRaster __pyx_v_weight_raster;
  PyObject *__pyx_v_raw_weight_nodata = NULL;
  PyObject *__pyx_v_flow_dir_raster_info = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  long __pyx_v_preempted;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_flow_dir_mfd_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_flow_dir_mfd_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  size_t __pyx_t_4;
  int __pyx_t_5;
  int __pyx_t_6;
  int __pyx_t_7;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  PyObject *__pyx_t_10 = NULL;
  PyObject *__pyx_t_11 = NULL;
  char *__pyx_t_12;
  ManagedRaster __pyx_t_13;
  PyObject *__pyx_t_14 = NULL;
  int __pyx_t_15;
  double __pyx_t_16;
  PyObject *(*__pyx_t_17)(PyObject *);
  unsigned long __pyx_t_18;
  unsigned long __pyx_t_19;
  Py_ssize_t __pyx_t_20;
  PyObject *(*__pyx_t_21)(PyObject *);
  float __pyx_t_22;
  PyObject *__pyx_t_23 = NULL;
  PyObject *__pyx_t_24 = NULL;
  PyObject *__pyx_t_25 = NULL;
  PyObject *__pyx_t_26 = NULL;
  unsigned long __pyx_t_27;
  unsigned long __pyx_t_28;
  int __pyx_t_29;
  Py_ssize_t __pyx_t_30;
  Py_ssize_t __pyx_t_31;
  int __pyx_t_32;
  int __pyx_t_33;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_FlowPixelType __pyx_t_34;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("flow_accumulation_mfd", 0);
  __pyx_pybuffer_flow_dir_mfd_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_flow_dir_mfd_buffer_array.refcount = 0;
  __pyx_pybuffernd_flow_dir_mfd_buffer_array.data = NULL;
  __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer = &__pyx_pybuffer_flow_dir_mfd_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":1929
 *     cdef double upstream_flow_accum
 * 
 *     cdef double flow_accum_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 *     cdef double weight_nodata = IMPROBABLE_FLOAT_NODATA
 * 
*/
  __pyx_v_flow_accum_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":1930
 * 
 *     cdef double flow_accum_nodata = IMPROBABLE_FLOAT_NODATA
 *     cdef double weight_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     # this value is used to store the current weight which might be 1 or
*/
  __pyx_v_weight_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":1947
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned long current_pixel
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":1951
 *     cdef unsigned long current_pixel
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_mfd_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1951, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_flow_dir_mfd_raster_path_band};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1951, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1951, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_6 = (!__pyx_t_5);
  if (unlikely(__pyx_t_6)) {

    /* "pygeoprocessing/routing/routing.pyx":1952
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_mfd_raster_path_band):
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_mfd_raster_path_band))
*/
    __pyx_t_3 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":1953
 *     if not _is_raster_path_band_formatted(flow_dir_mfd_raster_path_band):
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                 flow_dir_mfd_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
*/
    __pyx_t_2 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_flow_dir_mfd_raster_path_band); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1953, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1952, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __PYX_ERR(0, 1952, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1951
 *     cdef unsigned long current_pixel
 * 
 *     if not _is_raster_path_band_formatted(flow_dir_mfd_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1955
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_mfd_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1955, __pyx_L1_error)
  if (__pyx_t_5) {
  } else {
    __pyx_t_6 = __pyx_t_5;
    goto __pyx_L5_bool_binop_done;
  }
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1955, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":1956
 *                 flow_dir_mfd_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
 *             weight_raster_path_band):             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_weight_raster_path_band};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1955, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }

  /* "pygeoprocessing/routing/routing.pyx":1955
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_mfd_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 1955, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_7 = (!__pyx_t_5);
  __pyx_t_6 = __pyx_t_7;
  __pyx_L5_bool_binop_done:;
  if (unlikely(__pyx_t_6)) {

    /* "pygeoprocessing/routing/routing.pyx":1957
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(
 *             weight_raster_path_band):
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 weight_raster_path_band))
*/
    __pyx_t_3 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":1958
 *             weight_raster_path_band):
 *         raise ValueError(
 *             "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band))
 * 
*/
    __pyx_t_2 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_weight_raster_path_band); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1958, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1957, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __PYX_ERR(0, 1957, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1955
 *             "%s is supposed to be a raster band tuple but it's not." % (
 *                 flow_dir_mfd_raster_path_band))
 *     if weight_raster_path_band and not _is_raster_path_band_formatted(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         raise ValueError(
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":1961
 *                 weight_raster_path_band))
 * 
 *     LOGGER.debug('creating target flow accum raster layer')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], target_flow_accum_raster_path,
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1961, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1961, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_8);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_creating_target_flow_accum_raste};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1961, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1962
 * 
 *     LOGGER.debug('creating target flow accum raster layer')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],
*/
  __pyx_t_8 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1962, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1962, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1963
 *     LOGGER.debug('creating target flow accum raster layer')
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], target_flow_accum_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Float64, [flow_accum_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1963, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":1964
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1964, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1964, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = PyFloat_FromDouble(__pyx_v_flow_accum_nodata); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1964, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_11 = PyList_New(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1964, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_GIVEREF(__pyx_t_9);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_11, 0, __pyx_t_9) != (0)) __PYX_ERR(0, 1964, __pyx_L1_error);
  __pyx_t_9 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1965
 *         flow_dir_mfd_raster_path_band[0], target_flow_accum_raster_path,
 *         gdal.GDT_Float64, [flow_accum_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 * 
 *     flow_accum_managed_raster = ManagedRaster(
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_8);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_8);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_8, __pyx_t_2, __pyx_v_target_flow_accum_raster_path, __pyx_t_10, __pyx_t_11};
    __pyx_t_9 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1962, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_9, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1962, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (5-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_9);
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1962, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1968
 * 
 *     flow_accum_managed_raster = ManagedRaster(
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     # make a temporary raster to mark where we have visisted
*/
  __pyx_t_3 = __pyx_v_target_flow_accum_raster_path;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1968, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1968, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1967
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 * 
 *     flow_accum_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_flow_accum_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1967, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_accum_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":1971
 * 
 *     # make a temporary raster to mark where we have visisted
 *     LOGGER.debug('creating visited raster layer')             # <<<<<<<<<<<<<<
 *     tmp_dir_root = os.path.dirname(target_flow_accum_raster_path)
 *     tmp_dir = tempfile.mkdtemp(dir=tmp_dir_root, prefix='mfd_flow_dir_')
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1971, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1971, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_11);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_creating_visited_raster_layer};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1971, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1972
 *     # make a temporary raster to mark where we have visisted
 *     LOGGER.debug('creating visited raster layer')
 *     tmp_dir_root = os.path.dirname(target_flow_accum_raster_path)             # <<<<<<<<<<<<<<
 *     tmp_dir = tempfile.mkdtemp(dir=tmp_dir_root, prefix='mfd_flow_dir_')
 *     visited_raster_path = os.path.join(tmp_dir, 'visited.tif')
*/
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1972, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1972, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_11 = __pyx_t_9;
  __Pyx_INCREF(__pyx_t_11);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_v_target_flow_accum_raster_path};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_dirname, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1972, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_tmp_dir_root = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1973
 *     LOGGER.debug('creating visited raster layer')
 *     tmp_dir_root = os.path.dirname(target_flow_accum_raster_path)
 *     tmp_dir = tempfile.mkdtemp(dir=tmp_dir_root, prefix='mfd_flow_dir_')             # <<<<<<<<<<<<<<
 *     visited_raster_path = os.path.join(tmp_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1973, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1973, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_9, NULL};
    __pyx_t_11 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1973, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_v_tmp_dir_root, __pyx_t_11, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 1973, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_mstate_global->__pyx_n_u_mfd_flow_dir, __pyx_t_11, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 1973, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (1-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_11);
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1973, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_tmp_dir = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1974
 *     tmp_dir_root = os.path.dirname(target_flow_accum_raster_path)
 *     tmp_dir = tempfile.mkdtemp(dir=tmp_dir_root, prefix='mfd_flow_dir_')
 *     visited_raster_path = os.path.join(tmp_dir, 'visited.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], visited_raster_path,
*/
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1974, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1974, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_3 = __pyx_t_9;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_v_tmp_dir, __pyx_mstate_global->__pyx_kp_u_visited_tif};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1974, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_visited_raster_path = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1975
 *     tmp_dir = tempfile.mkdtemp(dir=tmp_dir_root, prefix='mfd_flow_dir_')
 *     visited_raster_path = os.path.join(tmp_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0], visited_raster_path,
 *         gdal.GDT_Byte, [0],
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1975, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1975, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1976
 *     visited_raster_path = os.path.join(tmp_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], visited_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Byte, [0],
 *         raster_driver_creation_tuple=('GTiff', SPARSE_CREATION_OPTIONS))
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 1976, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":1977
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0], visited_raster_path,
 *         gdal.GDT_Byte, [0],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=('GTiff', SPARSE_CREATION_OPTIONS))
 *     visited_managed_raster = ManagedRaster(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1977, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1977, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = PyList_New(1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1977, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_0);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_10, 0, __pyx_mstate_global->__pyx_int_0) != (0)) __PYX_ERR(0, 1977, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":1978
 *         flow_dir_mfd_raster_path_band[0], visited_raster_path,
 *         gdal.GDT_Byte, [0],
 *         raster_driver_creation_tuple=('GTiff', SPARSE_CREATION_OPTIONS))             # <<<<<<<<<<<<<<
 *     visited_managed_raster = ManagedRaster(
 *         visited_raster_path.encode('utf-8'), 1, True)
*/
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_SPARSE_CREATION_OPTIONS); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1978, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_14 = PyTuple_New(2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 1978, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_n_u_GTiff);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_n_u_GTiff);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_mstate_global->__pyx_n_u_GTiff) != (0)) __PYX_ERR(0, 1978, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_8);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_14, 1, __pyx_t_8) != (0)) __PYX_ERR(0, 1978, __pyx_L1_error);
  __pyx_t_8 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_11);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_9, __pyx_t_3, __pyx_v_visited_raster_path, __pyx_t_2, __pyx_t_10};
    __pyx_t_8 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1975, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_t_14, __pyx_t_8, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 1975, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (5-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_8);
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1975, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1980
 *         raster_driver_creation_tuple=('GTiff', SPARSE_CREATION_OPTIONS))
 *     visited_managed_raster = ManagedRaster(
 *         visited_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_11 = __pyx_v_visited_raster_path;
  __Pyx_INCREF(__pyx_t_11);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1980, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1980, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1979
 *         gdal.GDT_Byte, [0],
 *         raster_driver_creation_tuple=('GTiff', SPARSE_CREATION_OPTIONS))
 *     visited_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         visited_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1979, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_visited_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":1983
 * 
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(
*/
  __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1983, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_11 = __pyx_t_8;
  __Pyx_INCREF(__pyx_t_11);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1983, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1983, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1984
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
*/
  __pyx_t_8 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 1984, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_8); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1984, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1982
 *         visited_raster_path.encode('utf-8'), 1, True)
 * 
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_15, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 1982, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":1985
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
*/
  __pyx_t_8 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1985, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 1985, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1986
 *         flow_dir_mfd_raster_path_band[1], False)
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_mfd_raster_path_band[1])
*/
  __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1986, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 1986, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1986, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_14);
    assert(__pyx_t_8);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
    __Pyx_INCREF(__pyx_t_8);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_8, __pyx_t_11, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1985, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_raster = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1987
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[1])
 * 
*/
  __pyx_t_14 = __pyx_v_flow_dir_raster;
  __Pyx_INCREF(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":1988
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_mfd_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster weight_raster
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1988, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_14, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1987, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_band = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1991
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 1991, __pyx_L1_error)
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":1993
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
*/
    __pyx_t_14 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 1993, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_2 = __pyx_t_14;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_4 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1993, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 1993, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":1994
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
*/
    __pyx_t_14 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 1994, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_14); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1994, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1992
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
*/
    try {
      __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_15, Py_False);
    } catch(...) {
      __Pyx_CppExn2PyErr();
      __PYX_ERR(0, 1992, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_weight_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

    /* "pygeoprocessing/routing/routing.pyx":1995
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
*/
    __pyx_t_14 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1995, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1995, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1996
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1996, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_11))) {
      __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_11);
      assert(__pyx_t_14);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
      __Pyx_INCREF(__pyx_t_14);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_14, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1995, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_11 = __Pyx_PyObject_Dict_GetItem(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 1996, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1997
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata
*/
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1997, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyLong_SubtractObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1997, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1996
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_11, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1996, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_raw_weight_nodata = __pyx_t_1;
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":1998
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    __pyx_t_6 = (__pyx_v_raw_weight_nodata != Py_None);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":1999
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
*/
      __pyx_t_16 = __Pyx_PyFloat_AsDouble(__pyx_v_raw_weight_nodata); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 1999, __pyx_L1_error)
      __pyx_v_weight_nodata = __pyx_t_16;

      /* "pygeoprocessing/routing/routing.pyx":1998
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":1991
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2001
 *             weight_nodata = raw_weight_nodata
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2002
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_mfd_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 *     pixel_count = raster_x_size * raster_y_size
*/
  __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2002, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_14);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_11};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2001, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2003
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_mfd_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']             # <<<<<<<<<<<<<<
 *     pixel_count = raster_x_size * raster_y_size
 *     visit_count = 0
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2003, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 2003, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_14 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_14);
      __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_11);
    } else {
      __pyx_t_14 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2003, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_14);
      __pyx_t_11 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2003, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_11);
    }
    #else
    __pyx_t_14 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2003, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_11 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2003, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2003, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2);
    index = 0; __pyx_t_14 = __pyx_t_17(__pyx_t_2); if (unlikely(!__pyx_t_14)) goto __pyx_L9_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_14);
    index = 1; __pyx_t_11 = __pyx_t_17(__pyx_t_2); if (unlikely(!__pyx_t_11)) goto __pyx_L9_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_11);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_2), 2) < (0)) __PYX_ERR(0, 2003, __pyx_L1_error)
    __pyx_t_17 = NULL;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L10_unpacking_done;
    __pyx_L9_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_17 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 2003, __pyx_L1_error)
    __pyx_L10_unpacking_done:;
  }
  __pyx_t_18 = __Pyx_PyLong_As_unsigned_long(__pyx_t_14); if (unlikely((__pyx_t_18 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2003, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  __pyx_t_19 = __Pyx_PyLong_As_unsigned_long(__pyx_t_11); if (unlikely((__pyx_t_19 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2003, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_v_raster_x_size = __pyx_t_18;
  __pyx_v_raster_y_size = __pyx_t_19;

  /* "pygeoprocessing/routing/routing.pyx":2004
 *         flow_dir_mfd_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 *     pixel_count = raster_x_size * raster_y_size             # <<<<<<<<<<<<<<
 *     visit_count = 0
 * 
*/
  __pyx_v_pixel_count = (__pyx_v_raster_x_size * __pyx_v_raster_y_size);

  /* "pygeoprocessing/routing/routing.pyx":2005
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 *     pixel_count = raster_x_size * raster_y_size
 *     visit_count = 0             # <<<<<<<<<<<<<<
 * 
 *     LOGGER.debug('starting search')
*/
  __pyx_v_visit_count = 0;

  /* "pygeoprocessing/routing/routing.pyx":2007
 *     visit_count = 0
 * 
 *     LOGGER.debug('starting search')             # <<<<<<<<<<<<<<
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(
*/
  __pyx_t_11 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2007, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2007, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_11);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_11);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_mstate_global->__pyx_kp_u_starting_search};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2007, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2009
 *     LOGGER.debug('starting search')
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_mfd_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2009, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2009, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2010
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_mfd_raster_path_band, offset_only=True,             # <<<<<<<<<<<<<<
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_4 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_14);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
    __pyx_t_4 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_2, __pyx_v_flow_dir_mfd_raster_path_band};
    __pyx_t_11 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2009, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_11, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2009, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_11, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 2009, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_11);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2009, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }

  /* "pygeoprocessing/routing/routing.pyx":2009
 *     LOGGER.debug('starting search')
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_mfd_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_14 = __pyx_t_1; __Pyx_INCREF(__pyx_t_14);
    __pyx_t_20 = 0;
    __pyx_t_21 = NULL;
  } else {
    __pyx_t_20 = -1; __pyx_t_14 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2009, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_21 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_14); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 2009, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_21)) {
      if (likely(PyList_CheckExact(__pyx_t_14))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_14);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2009, __pyx_L1_error)
          #endif
          if (__pyx_t_20 >= __pyx_temp) break;
        }
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(__pyx_t_14, __pyx_t_20, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_20;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_14);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2009, __pyx_L1_error)
          #endif
          if (__pyx_t_20 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_14, __pyx_t_20));
        #else
        __pyx_t_1 = __Pyx_PySequence_ITEM(__pyx_t_14, __pyx_t_20);
        #endif
        ++__pyx_t_20;
      }
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2009, __pyx_L1_error)
    } else {
      __pyx_t_1 = __pyx_t_21(__pyx_t_14);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 2009, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2012
 *             flow_dir_mfd_raster_path_band, offset_only=True,
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2012, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_long(__pyx_t_1); if (unlikely((__pyx_t_19 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2012, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_win_xsize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2013
 *             largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2013, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_long(__pyx_t_1); if (unlikely((__pyx_t_19 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2013, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_win_ysize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2014
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2014, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_long(__pyx_t_1); if (unlikely((__pyx_t_19 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2014, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_xoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2015
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2015, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_long(__pyx_t_1); if (unlikely((__pyx_t_19 == (unsigned long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2015, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_yoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2017
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":2018
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accum MFD %.1f%% complete', 100.0 * current_pixel / <float>(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":2019
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info('Flow accum MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":2020
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accum MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      __pyx_t_11 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2020, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2020, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_16 = (100.0 * __pyx_v_current_pixel);

      /* "pygeoprocessing/routing/routing.pyx":2021
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accum MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 * 
 *         # make a buffer big enough to capture block and boundaries around it
*/
      __pyx_t_22 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

      /* "pygeoprocessing/routing/routing.pyx":2020
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Flow accum MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      if (unlikely(__pyx_t_22 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 2020, __pyx_L1_error)
      }
      __pyx_t_2 = PyFloat_FromDouble((__pyx_t_16 / ((double)__pyx_t_22))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2020, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_8))) {
        __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_8);
        assert(__pyx_t_11);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
        __Pyx_INCREF(__pyx_t_11);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_11, __pyx_mstate_global->__pyx_kp_u_Flow_accum_MFD_1f_complete, __pyx_t_2};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2020, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":2017
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2024
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_mfd_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
*/
    __pyx_t_8 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2024, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2024, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2025
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_mfd_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.int32)
 *         flow_dir_mfd_buffer_array[:] = 0  # 0 means no flow at all
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2025, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_10 = __Pyx_PyLong_AddObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2025, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2025, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PyLong_AddObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2025, __pyx_L1_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_ERR(0, 2025, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_GIVEREF(__pyx_t_10);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_10) != (0)) __PYX_ERR(0, 2025, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_3);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3) != (0)) __PYX_ERR(0, 2025, __pyx_L1_error);
    __pyx_t_10 = 0;
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2026
 *         flow_dir_mfd_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_buffer_array[:] = 0  # 0 means no flow at all
 * 
*/
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2026, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2026, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_11))) {
      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_11);
      assert(__pyx_t_8);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
      __Pyx_INCREF(__pyx_t_8);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_8, __pyx_t_2};
      __pyx_t_3 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2024, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_10, __pyx_t_3, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2024, __pyx_L1_error)
      __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2024, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }

    /* "pygeoprocessing/routing/routing.pyx":2024
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         flow_dir_mfd_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
*/
    if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2024, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer);
      __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_1), &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_15 < 0)) {
        PyErr_Fetch(&__pyx_t_23, &__pyx_t_24, &__pyx_t_25);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_flow_dir_mfd_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_23); Py_XDECREF(__pyx_t_24); Py_XDECREF(__pyx_t_25);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_23, __pyx_t_24, __pyx_t_25);
        }
        __pyx_t_23 = __pyx_t_24 = __pyx_t_25 = 0;
      }
      __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].strides = __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].shape = __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].strides = __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].shape = __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_15 < 0))) __PYX_ERR(0, 2024, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_flow_dir_mfd_buffer_array, ((PyArrayObject *)__pyx_t_1));
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2027
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
 *         flow_dir_mfd_buffer_array[:] = 0  # 0 means no flow at all             # <<<<<<<<<<<<<<
 * 
 *         # check if we can widen the border to include real data from the
*/
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_mfd_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_0) < 0))) __PYX_ERR(0, 2027, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2031
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
*/
    __pyx_t_11 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2031, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);

    /* "pygeoprocessing/routing/routing.pyx":2032
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.int32)
*/
    __pyx_t_10 = __Pyx_PyLong_From_unsigned_long(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2032, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_2 = __Pyx_PyLong_From_unsigned_long(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2032, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_3);
      assert(__pyx_t_11);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_11);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_11, __pyx_v_offset_dict, __pyx_t_10, __pyx_t_2};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (4-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
      PyObject* sequence = __pyx_t_1;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2031, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_3);
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_2);
      } else {
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
      }
      #else
      __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_10 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_10);
      index = 0; __pyx_t_3 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_3)) goto __pyx_L14_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_3);
      index = 1; __pyx_t_2 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L14_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_10), 2) < (0)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      goto __pyx_L15_unpacking_done;
      __pyx_L14_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2031, __pyx_L1_error)
      __pyx_L15_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":2031
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
      PyObject* sequence = __pyx_t_3;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2031, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_10);
        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_11);
        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_8);
        __pyx_t_9 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_9);
      } else {
        __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_10);
        __pyx_t_11 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_11);
        __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_8);
        __pyx_t_9 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2031, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_9);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_11,&__pyx_t_8,&__pyx_t_9};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 2031, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_11,&__pyx_t_8,&__pyx_t_9};
      __pyx_t_26 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_26);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_26);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_17(__pyx_t_26); if (unlikely(!item)) goto __pyx_L16_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_26), 4) < (0)) __PYX_ERR(0, 2031, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      goto __pyx_L17_unpacking_done;
      __pyx_L16_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2031, __pyx_L1_error)
      __pyx_L17_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_10);
    __pyx_t_10 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_11);
    __pyx_t_11 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_8);
    __pyx_t_8 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_9);
    __pyx_t_9 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2033
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_flow_dir_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);

    /* "pygeoprocessing/routing/routing.pyx":2034
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 2034, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_9 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2034, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
    } else {
      __pyx_t_9 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2033, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
    }

    /* "pygeoprocessing/routing/routing.pyx":2033
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_9); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_2 = __pyx_t_8;
    __Pyx_INCREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":2034
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(
 *                 **modified_offset_dict).astype(numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2034, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2034, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __pyx_t_4 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2034, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }

    /* "pygeoprocessing/routing/routing.pyx":2033
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         flow_dir_mfd_buffer_array[ya:yb, xa:xb] = flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_8 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_3 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_GIVEREF(__pyx_t_8);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_8) != (0)) __PYX_ERR(0, 2033, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_3);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3) != (0)) __PYX_ERR(0, 2033, __pyx_L1_error);
    __pyx_t_8 = 0;
    __pyx_t_3 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_mfd_buffer_array), __pyx_t_2, __pyx_t_1) < 0))) __PYX_ERR(0, 2033, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2037
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2038
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # search block for to set flow accumulation
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2041
 * 
 *         # search block for to set flow accumulation
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir_mfd = flow_dir_mfd_buffer_array[yi, xi]
*/
    __pyx_t_19 = (__pyx_v_win_ysize + 1);
    __pyx_t_18 = __pyx_t_19;
    for (__pyx_t_15 = 1; __pyx_t_15 < __pyx_t_18; __pyx_t_15+=1) {
      __pyx_v_yi = __pyx_t_15;

      /* "pygeoprocessing/routing/routing.pyx":2042
 *         # search block for to set flow accumulation
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 flow_dir_mfd = flow_dir_mfd_buffer_array[yi, xi]
 *                 if flow_dir_mfd == 0:
*/
      __pyx_t_27 = (__pyx_v_win_xsize + 1);
      __pyx_t_28 = __pyx_t_27;
      for (__pyx_t_29 = 1; __pyx_t_29 < __pyx_t_28; __pyx_t_29+=1) {
        __pyx_v_xi = __pyx_t_29;

        /* "pygeoprocessing/routing/routing.pyx":2043
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir_mfd = flow_dir_mfd_buffer_array[yi, xi]             # <<<<<<<<<<<<<<
 *                 if flow_dir_mfd == 0:
 *                     # no flow in this pixel, so skip
*/
        __pyx_t_30 = __pyx_v_yi;
        __pyx_t_31 = __pyx_v_xi;
        __pyx_t_32 = -1;
        if (__pyx_t_30 < 0) {
          __pyx_t_30 += __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].shape;
          if (unlikely(__pyx_t_30 < 0)) __pyx_t_32 = 0;
        } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].shape)) __pyx_t_32 = 0;
        if (__pyx_t_31 < 0) {
          __pyx_t_31 += __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].shape;
          if (unlikely(__pyx_t_31 < 0)) __pyx_t_32 = 1;
        } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].shape)) __pyx_t_32 = 1;
        if (unlikely(__pyx_t_32 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_32);
          __PYX_ERR(0, 2043, __pyx_L1_error)
        }
        __pyx_v_flow_dir_mfd = (*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int32_t *, __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_30, __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].strides));

        /* "pygeoprocessing/routing/routing.pyx":2044
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir_mfd = flow_dir_mfd_buffer_array[yi, xi]
 *                 if flow_dir_mfd == 0:             # <<<<<<<<<<<<<<
 *                     # no flow in this pixel, so skip
 *                     continue
*/
        __pyx_t_6 = (__pyx_v_flow_dir_mfd == 0);
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":2046
 *                 if flow_dir_mfd == 0:
 *                     # no flow in this pixel, so skip
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 for i_n in range(8):
*/
          goto __pyx_L20_continue;

          /* "pygeoprocessing/routing/routing.pyx":2044
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir_mfd = flow_dir_mfd_buffer_array[yi, xi]
 *                 if flow_dir_mfd == 0:             # <<<<<<<<<<<<<<
 *                     # no flow in this pixel, so skip
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2048
 *                     continue
 * 
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:
 *                         # no flow in that direction
*/
        for (__pyx_t_32 = 0; __pyx_t_32 < 8; __pyx_t_32+=1) {
          __pyx_v_i_n = __pyx_t_32;

          /* "pygeoprocessing/routing/routing.pyx":2049
 * 
 *                 for i_n in range(8):
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:             # <<<<<<<<<<<<<<
 *                         # no flow in that direction
 *                         continue
*/
          __pyx_t_6 = (((__pyx_v_flow_dir_mfd >> (__pyx_v_i_n * 4)) & 0xF) == 0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":2051
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:
 *                         # no flow in that direction
 *                         continue             # <<<<<<<<<<<<<<
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]
*/
            goto __pyx_L23_continue;

            /* "pygeoprocessing/routing/routing.pyx":2049
 * 
 *                 for i_n in range(8):
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:             # <<<<<<<<<<<<<<
 *                         # no flow in that direction
 *                         continue
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2052
 *                         # no flow in that direction
 *                         continue
 *                     xi_n = xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 * 
*/
          __pyx_v_xi_n = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":2053
 *                         continue
 *                     xi_n = xi+COL_OFFSETS[i_n]
 *                     yi_n = yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                     if flow_dir_mfd_buffer_array[yi_n, xi_n] == 0:
*/
          __pyx_v_yi_n = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":2055
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 * 
 *                     if flow_dir_mfd_buffer_array[yi_n, xi_n] == 0:             # <<<<<<<<<<<<<<
 *                         # if the entire value is zero, it flows nowhere
 *                         # and the root pixel is draining to it, thus the
*/
          __pyx_t_31 = __pyx_v_yi_n;
          __pyx_t_30 = __pyx_v_xi_n;
          __pyx_t_33 = -1;
          if (__pyx_t_31 < 0) {
            __pyx_t_31 += __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].shape;
            if (unlikely(__pyx_t_31 < 0)) __pyx_t_33 = 0;
          } else if (unlikely(__pyx_t_31 >= __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].shape)) __pyx_t_33 = 0;
          if (__pyx_t_30 < 0) {
            __pyx_t_30 += __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].shape;
            if (unlikely(__pyx_t_30 < 0)) __pyx_t_33 = 1;
          } else if (unlikely(__pyx_t_30 >= __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].shape)) __pyx_t_33 = 1;
          if (unlikely(__pyx_t_33 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_33);
            __PYX_ERR(0, 2055, __pyx_L1_error)
          }
          __pyx_t_6 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int32_t *, __pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[0].strides, __pyx_t_30, __pyx_pybuffernd_flow_dir_mfd_buffer_array.diminfo[1].strides)) == 0);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":2059
 *                         # and the root pixel is draining to it, thus the
 *                         # root must be a drain
 *                         xi_root = xi-1+xoff             # <<<<<<<<<<<<<<
 *                         yi_root = yi-1+yoff
 *                         if weight_raster_path_band:
*/
            __pyx_v_xi_root = ((__pyx_v_xi - 1) + __pyx_v_xoff);

            /* "pygeoprocessing/routing/routing.pyx":2060
 *                         # root must be a drain
 *                         xi_root = xi-1+xoff
 *                         yi_root = yi-1+yoff             # <<<<<<<<<<<<<<
 *                         if weight_raster_path_band:
 *                             weight_val = <double>weight_raster.get(
*/
            __pyx_v_yi_root = ((__pyx_v_yi - 1) + __pyx_v_yoff);

            /* "pygeoprocessing/routing/routing.pyx":2061
 *                         xi_root = xi-1+xoff
 *                         yi_root = yi-1+yoff
 *                         if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                             weight_val = <double>weight_raster.get(
 *                                 xi_root, yi_root)
*/
            __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 2061, __pyx_L1_error)
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":2062
 *                         yi_root = yi-1+yoff
 *                         if weight_raster_path_band:
 *                             weight_val = <double>weight_raster.get(             # <<<<<<<<<<<<<<
 *                                 xi_root, yi_root)
 *                             if is_close(weight_val, weight_nodata):
*/
              __pyx_v_weight_val = ((double)__pyx_v_weight_raster.get(__pyx_v_xi_root, __pyx_v_yi_root));

              /* "pygeoprocessing/routing/routing.pyx":2064
 *                             weight_val = <double>weight_raster.get(
 *                                 xi_root, yi_root)
 *                             if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                 weight_val = 0.0
 *                         else:
*/
              __pyx_t_6 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
              if (__pyx_t_6) {

                /* "pygeoprocessing/routing/routing.pyx":2065
 *                                 xi_root, yi_root)
 *                             if is_close(weight_val, weight_nodata):
 *                                 weight_val = 0.0             # <<<<<<<<<<<<<<
 *                         else:
 *                             weight_val = 1.0
*/
                __pyx_v_weight_val = 0.0;

                /* "pygeoprocessing/routing/routing.pyx":2064
 *                             weight_val = <double>weight_raster.get(
 *                                 xi_root, yi_root)
 *                             if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                 weight_val = 0.0
 *                         else:
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":2061
 *                         xi_root = xi-1+xoff
 *                         yi_root = yi-1+yoff
 *                         if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                             weight_val = <double>weight_raster.get(
 *                                 xi_root, yi_root)
*/
              goto __pyx_L27;
            }

            /* "pygeoprocessing/routing/routing.pyx":2067
 *                                 weight_val = 0.0
 *                         else:
 *                             weight_val = 1.0             # <<<<<<<<<<<<<<
 *                         search_stack.push(
 *                             FlowPixelType(xi_root, yi_root, 0, weight_val))
*/
            /*else*/ {
              __pyx_v_weight_val = 1.0;
            }
            __pyx_L27:;

            /* "pygeoprocessing/routing/routing.pyx":2069
 *                             weight_val = 1.0
 *                         search_stack.push(
 *                             FlowPixelType(xi_root, yi_root, 0, weight_val))             # <<<<<<<<<<<<<<
 *                         visited_managed_raster.set(xi_root, yi_root, 1)
 *                         visit_count += 1
*/
            __pyx_t_34.xi = __pyx_v_xi_root;
            __pyx_t_34.yi = __pyx_v_yi_root;
            __pyx_t_34.last_flow_dir = 0;
            __pyx_t_34.value = __pyx_v_weight_val;

            /* "pygeoprocessing/routing/routing.pyx":2068
 *                         else:
 *                             weight_val = 1.0
 *                         search_stack.push(             # <<<<<<<<<<<<<<
 *                             FlowPixelType(xi_root, yi_root, 0, weight_val))
 *                         visited_managed_raster.set(xi_root, yi_root, 1)
*/
            try {
              __pyx_v_search_stack.push(__pyx_t_34);
            } catch(...) {
              __Pyx_CppExn2PyErr();
              __PYX_ERR(0, 2068, __pyx_L1_error)
            }

            /* "pygeoprocessing/routing/routing.pyx":2070
 *                         search_stack.push(
 *                             FlowPixelType(xi_root, yi_root, 0, weight_val))
 *                         visited_managed_raster.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 *                         visit_count += 1
 *                         break
*/
            __pyx_v_visited_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

            /* "pygeoprocessing/routing/routing.pyx":2071
 *                             FlowPixelType(xi_root, yi_root, 0, weight_val))
 *                         visited_managed_raster.set(xi_root, yi_root, 1)
 *                         visit_count += 1             # <<<<<<<<<<<<<<
 *                         break
 * 
*/
            __pyx_v_visit_count = (__pyx_v_visit_count + 1);

            /* "pygeoprocessing/routing/routing.pyx":2072
 *                         visited_managed_raster.set(xi_root, yi_root, 1)
 *                         visit_count += 1
 *                         break             # <<<<<<<<<<<<<<
 * 
 *                 while not search_stack.empty():
*/
            goto __pyx_L24_break;

            /* "pygeoprocessing/routing/routing.pyx":2055
 *                     yi_n = yi+ROW_OFFSETS[i_n]
 * 
 *                     if flow_dir_mfd_buffer_array[yi_n, xi_n] == 0:             # <<<<<<<<<<<<<<
 *                         # if the entire value is zero, it flows nowhere
 *                         # and the root pixel is draining to it, thus the
*/
          }
          __pyx_L23_continue:;
        }
        __pyx_L24_break:;

        /* "pygeoprocessing/routing/routing.pyx":2074
 *                         break
 * 
 *                 while not search_stack.empty():             # <<<<<<<<<<<<<<
 *                     flow_pixel = search_stack.top()
 *                     search_stack.pop()
*/
        while (1) {
          __pyx_t_6 = (!__pyx_v_search_stack.empty());
          if (!__pyx_t_6) break;

          /* "pygeoprocessing/routing/routing.pyx":2075
 * 
 *                 while not search_stack.empty():
 *                     flow_pixel = search_stack.top()             # <<<<<<<<<<<<<<
 *                     search_stack.pop()
 * 
*/
          __pyx_v_flow_pixel = __pyx_v_search_stack.top();

          /* "pygeoprocessing/routing/routing.pyx":2076
 *                 while not search_stack.empty():
 *                     flow_pixel = search_stack.top()
 *                     search_stack.pop()             # <<<<<<<<<<<<<<
 * 
 *                     if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
          __pyx_v_search_stack.pop();

          /* "pygeoprocessing/routing/routing.pyx":2078
 *                     search_stack.pop()
 * 
 *                     if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *                         last_log_time = ctime(NULL)
 *                         LOGGER.info(
*/
          __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":2079
 * 
 *                     if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *                         last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *                         LOGGER.info(
 *                             'Flow accum MFD %.1f%% complete',
*/
            __pyx_v_last_log_time = time(NULL);

            /* "pygeoprocessing/routing/routing.pyx":2080
 *                     if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *                         last_log_time = ctime(NULL)
 *                         LOGGER.info(             # <<<<<<<<<<<<<<
 *                             'Flow accum MFD %.1f%% complete',
 *                             100.0 * visit_count / float(pixel_count))
*/
            __pyx_t_2 = NULL;
            __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2080, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2080, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_8);
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

            /* "pygeoprocessing/routing/routing.pyx":2082
 *                         LOGGER.info(
 *                             'Flow accum MFD %.1f%% complete',
 *                             100.0 * visit_count / float(pixel_count))             # <<<<<<<<<<<<<<
 * 
 *                     preempted = 0
*/
            __pyx_t_16 = (100.0 * __pyx_v_visit_count);
            if (unlikely(((double)__pyx_v_pixel_count) == 0)) {
              PyErr_SetString(PyExc_ZeroDivisionError, "float division");
              __PYX_ERR(0, 2082, __pyx_L1_error)
            }
            __pyx_t_3 = PyFloat_FromDouble((__pyx_t_16 / ((double)__pyx_v_pixel_count))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2082, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_4 = 1;
            #if CYTHON_UNPACK_METHODS
            if (unlikely(PyMethod_Check(__pyx_t_8))) {
              __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_8);
              assert(__pyx_t_2);
              PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
              __Pyx_INCREF(__pyx_t_2);
              __Pyx_INCREF(__pyx__function);
              __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
              __pyx_t_4 = 0;
            }
            #endif
            {
              PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_Flow_accum_MFD_1f_complete, __pyx_t_3};
              __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
              __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
              __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
              if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2080, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_1);
            }
            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

            /* "pygeoprocessing/routing/routing.pyx":2078
 *                     search_stack.pop()
 * 
 *                     if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *                         last_log_time = ctime(NULL)
 *                         LOGGER.info(
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2084
 *                             100.0 * visit_count / float(pixel_count))
 * 
 *                     preempted = 0             # <<<<<<<<<<<<<<
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
*/
          __pyx_v_preempted = 0;

          /* "pygeoprocessing/routing/routing.pyx":2085
 * 
 *                     preempted = 0
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):             # <<<<<<<<<<<<<<
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_32 = __pyx_v_flow_pixel.last_flow_dir; __pyx_t_32 < 8; __pyx_t_32+=1) {
            __pyx_v_i_n = __pyx_t_32;

            /* "pygeoprocessing/routing/routing.pyx":2086
 *                     preempted = 0
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_flow_pixel.xi + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2087
 *                     for i_n in range(flow_pixel.last_flow_dir, 8):
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_flow_pixel.yi + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2088
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # no upstream here
*/
            __pyx_t_7 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_7) {
            } else {
              __pyx_t_6 = __pyx_t_7;
              goto __pyx_L35_bool_binop_done;
            }
            __pyx_t_7 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_7) {
            } else {
              __pyx_t_6 = __pyx_t_7;
              goto __pyx_L35_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":2089
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             # no upstream here
 *                             continue
*/
            __pyx_t_7 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_7) {
            } else {
              __pyx_t_6 = __pyx_t_7;
              goto __pyx_L35_bool_binop_done;
            }
            __pyx_t_7 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_6 = __pyx_t_7;
            __pyx_L35_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":2088
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # no upstream here
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":2091
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # no upstream here
 *                             continue             # <<<<<<<<<<<<<<
 *                         compressed_upstream_flow_dir = (
 *                             <int>flow_dir_managed_raster.get(xi_n, yi_n))
*/
              goto __pyx_L32_continue;

              /* "pygeoprocessing/routing/routing.pyx":2088
 *                         xi_n = flow_pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = flow_pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             # no upstream here
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2093
 *                             continue
 *                         compressed_upstream_flow_dir = (
 *                             <int>flow_dir_managed_raster.get(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                         upstream_flow_weight = (
 *                             compressed_upstream_flow_dir >> (
*/
            __pyx_v_compressed_upstream_flow_dir = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n));

            /* "pygeoprocessing/routing/routing.pyx":2096
 *                         upstream_flow_weight = (
 *                             compressed_upstream_flow_dir >> (
 *                                 INFLOW_OFFSETS[i_n] * 4)) & 0xF             # <<<<<<<<<<<<<<
 *                         if upstream_flow_weight == 0:
 *                             # no upstream flow to this pixel
*/
            __pyx_v_upstream_flow_weight = ((__pyx_v_compressed_upstream_flow_dir >> ((INFLOW_OFFSETS[__pyx_v_i_n]) * 4)) & 0xF);

            /* "pygeoprocessing/routing/routing.pyx":2097
 *                             compressed_upstream_flow_dir >> (
 *                                 INFLOW_OFFSETS[i_n] * 4)) & 0xF
 *                         if upstream_flow_weight == 0:             # <<<<<<<<<<<<<<
 *                             # no upstream flow to this pixel
 *                             continue
*/
            __pyx_t_6 = (__pyx_v_upstream_flow_weight == 0);
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":2099
 *                         if upstream_flow_weight == 0:
 *                             # no upstream flow to this pixel
 *                             continue             # <<<<<<<<<<<<<<
 *                         upstream_flow_accum = (
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
*/
              goto __pyx_L32_continue;

              /* "pygeoprocessing/routing/routing.pyx":2097
 *                             compressed_upstream_flow_dir >> (
 *                                 INFLOW_OFFSETS[i_n] * 4)) & 0xF
 *                         if upstream_flow_weight == 0:             # <<<<<<<<<<<<<<
 *                             # no upstream flow to this pixel
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2101
 *                             continue
 *                         upstream_flow_accum = (
 *                             flow_accum_managed_raster.get(xi_n, yi_n))             # <<<<<<<<<<<<<<
 *                         if (is_close(upstream_flow_accum, flow_accum_nodata)
 *                                 and not visited_managed_raster.get(
*/
            __pyx_v_upstream_flow_accum = __pyx_v_flow_accum_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":2102
 *                         upstream_flow_accum = (
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if (is_close(upstream_flow_accum, flow_accum_nodata)             # <<<<<<<<<<<<<<
 *                                 and not visited_managed_raster.get(
 *                                     xi_n, yi_n)):
*/
            __pyx_t_7 = is_close(__pyx_v_upstream_flow_accum, __pyx_v_flow_accum_nodata);
            if (__pyx_t_7) {
            } else {
              __pyx_t_6 = __pyx_t_7;
              goto __pyx_L41_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":2103
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if (is_close(upstream_flow_accum, flow_accum_nodata)
 *                                 and not visited_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n)):
 *                             # process upstream before this one
*/
            __pyx_t_7 = (!(__pyx_v_visited_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) != 0));
            __pyx_t_6 = __pyx_t_7;
            __pyx_L41_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":2102
 *                         upstream_flow_accum = (
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if (is_close(upstream_flow_accum, flow_accum_nodata)             # <<<<<<<<<<<<<<
 *                                 and not visited_managed_raster.get(
 *                                     xi_n, yi_n)):
*/
            if (__pyx_t_6) {

              /* "pygeoprocessing/routing/routing.pyx":2106
 *                                     xi_n, yi_n)):
 *                             # process upstream before this one
 *                             flow_pixel.last_flow_dir = i_n             # <<<<<<<<<<<<<<
 *                             search_stack.push(flow_pixel)
 *                             if weight_raster_path_band:
*/
              __pyx_v_flow_pixel.last_flow_dir = __pyx_v_i_n;

              /* "pygeoprocessing/routing/routing.pyx":2107
 *                             # process upstream before this one
 *                             flow_pixel.last_flow_dir = i_n
 *                             search_stack.push(flow_pixel)             # <<<<<<<<<<<<<<
 *                             if weight_raster_path_band:
 *                                 weight_val = <double>weight_raster.get(
*/
              try {
                __pyx_v_search_stack.push(__pyx_v_flow_pixel);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 2107, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":2108
 *                             flow_pixel.last_flow_dir = i_n
 *                             search_stack.push(flow_pixel)
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
*/
              __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 2108, __pyx_L1_error)
              if (__pyx_t_6) {

                /* "pygeoprocessing/routing/routing.pyx":2109
 *                             search_stack.push(flow_pixel)
 *                             if weight_raster_path_band:
 *                                 weight_val = <double>weight_raster.get(             # <<<<<<<<<<<<<<
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
*/
                __pyx_v_weight_val = ((double)__pyx_v_weight_raster.get(__pyx_v_xi_n, __pyx_v_yi_n));

                /* "pygeoprocessing/routing/routing.pyx":2111
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                __pyx_t_6 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
                if (__pyx_t_6) {

                  /* "pygeoprocessing/routing/routing.pyx":2112
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
 *                                     weight_val = 0.0             # <<<<<<<<<<<<<<
 *                             else:
 *                                 weight_val = 1.0
*/
                  __pyx_v_weight_val = 0.0;

                  /* "pygeoprocessing/routing/routing.pyx":2111
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                }

                /* "pygeoprocessing/routing/routing.pyx":2108
 *                             flow_pixel.last_flow_dir = i_n
 *                             search_stack.push(flow_pixel)
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = <double>weight_raster.get(
 *                                     xi_n, yi_n)
*/
                goto __pyx_L43;
              }

              /* "pygeoprocessing/routing/routing.pyx":2114
 *                                     weight_val = 0.0
 *                             else:
 *                                 weight_val = 1.0             # <<<<<<<<<<<<<<
 *                             search_stack.push(
 *                                 FlowPixelType(xi_n, yi_n, 0, weight_val))
*/
              /*else*/ {
                __pyx_v_weight_val = 1.0;
              }
              __pyx_L43:;

              /* "pygeoprocessing/routing/routing.pyx":2116
 *                                 weight_val = 1.0
 *                             search_stack.push(
 *                                 FlowPixelType(xi_n, yi_n, 0, weight_val))             # <<<<<<<<<<<<<<
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             visit_count += 1
*/
              __pyx_t_34.xi = __pyx_v_xi_n;
              __pyx_t_34.yi = __pyx_v_yi_n;
              __pyx_t_34.last_flow_dir = 0;
              __pyx_t_34.value = __pyx_v_weight_val;

              /* "pygeoprocessing/routing/routing.pyx":2115
 *                             else:
 *                                 weight_val = 1.0
 *                             search_stack.push(             # <<<<<<<<<<<<<<
 *                                 FlowPixelType(xi_n, yi_n, 0, weight_val))
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
*/
              try {
                __pyx_v_search_stack.push(__pyx_t_34);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 2115, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":2117
 *                             search_stack.push(
 *                                 FlowPixelType(xi_n, yi_n, 0, weight_val))
 *                             visited_managed_raster.set(xi_n, yi_n, 1)             # <<<<<<<<<<<<<<
 *                             visit_count += 1
 *                             preempted = 1
*/
              __pyx_v_visited_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

              /* "pygeoprocessing/routing/routing.pyx":2118
 *                                 FlowPixelType(xi_n, yi_n, 0, weight_val))
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             visit_count += 1             # <<<<<<<<<<<<<<
 *                             preempted = 1
 *                             break
*/
              __pyx_v_visit_count = (__pyx_v_visit_count + 1);

              /* "pygeoprocessing/routing/routing.pyx":2119
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             visit_count += 1
 *                             preempted = 1             # <<<<<<<<<<<<<<
 *                             break
 *                         upstream_flow_dir_sum = 0
*/
              __pyx_v_preempted = 1;

              /* "pygeoprocessing/routing/routing.pyx":2120
 *                             visit_count += 1
 *                             preempted = 1
 *                             break             # <<<<<<<<<<<<<<
 *                         upstream_flow_dir_sum = 0
 *                         for i_upstream_flow in range(8):
*/
              goto __pyx_L33_break;

              /* "pygeoprocessing/routing/routing.pyx":2102
 *                         upstream_flow_accum = (
 *                             flow_accum_managed_raster.get(xi_n, yi_n))
 *                         if (is_close(upstream_flow_accum, flow_accum_nodata)             # <<<<<<<<<<<<<<
 *                                 and not visited_managed_raster.get(
 *                                     xi_n, yi_n)):
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2121
 *                             preempted = 1
 *                             break
 *                         upstream_flow_dir_sum = 0             # <<<<<<<<<<<<<<
 *                         for i_upstream_flow in range(8):
 *                             upstream_flow_dir_sum += (
*/
            __pyx_v_upstream_flow_dir_sum = 0;

            /* "pygeoprocessing/routing/routing.pyx":2122
 *                             break
 *                         upstream_flow_dir_sum = 0
 *                         for i_upstream_flow in range(8):             # <<<<<<<<<<<<<<
 *                             upstream_flow_dir_sum += (
 *                                 compressed_upstream_flow_dir >> (
*/
            for (__pyx_t_33 = 0; __pyx_t_33 < 8; __pyx_t_33+=1) {
              __pyx_v_i_upstream_flow = __pyx_t_33;

              /* "pygeoprocessing/routing/routing.pyx":2123
 *                         upstream_flow_dir_sum = 0
 *                         for i_upstream_flow in range(8):
 *                             upstream_flow_dir_sum += (             # <<<<<<<<<<<<<<
 *                                 compressed_upstream_flow_dir >> (
 *                                     i_upstream_flow * 4)) & 0xF
*/
              __pyx_v_upstream_flow_dir_sum = (__pyx_v_upstream_flow_dir_sum + ((__pyx_v_compressed_upstream_flow_dir >> (__pyx_v_i_upstream_flow * 4)) & 0xF));
            }

            /* "pygeoprocessing/routing/routing.pyx":2128
 * 
 *                         flow_pixel.value += (
 *                             upstream_flow_accum * upstream_flow_weight /             # <<<<<<<<<<<<<<
 *                             <float>upstream_flow_dir_sum)
 *                     if not preempted:
*/
            __pyx_t_16 = (__pyx_v_upstream_flow_accum * __pyx_v_upstream_flow_weight);

            /* "pygeoprocessing/routing/routing.pyx":2129
 *                         flow_pixel.value += (
 *                             upstream_flow_accum * upstream_flow_weight /
 *                             <float>upstream_flow_dir_sum)             # <<<<<<<<<<<<<<
 *                     if not preempted:
 *                         flow_accum_managed_raster.set(
*/
            if (unlikely(((float)__pyx_v_upstream_flow_dir_sum) == 0)) {
              PyErr_SetString(PyExc_ZeroDivisionError, "float division");
              __PYX_ERR(0, 2128, __pyx_L1_error)
            }

            /* "pygeoprocessing/routing/routing.pyx":2127
 *                                     i_upstream_flow * 4)) & 0xF
 * 
 *                         flow_pixel.value += (             # <<<<<<<<<<<<<<
 *                             upstream_flow_accum * upstream_flow_weight /
 *                             <float>upstream_flow_dir_sum)
*/
            __pyx_v_flow_pixel.value = (__pyx_v_flow_pixel.value + (__pyx_t_16 / ((double)((float)__pyx_v_upstream_flow_dir_sum))));
            __pyx_L32_continue:;
          }
          __pyx_L33_break:;

          /* "pygeoprocessing/routing/routing.pyx":2130
 *                             upstream_flow_accum * upstream_flow_weight /
 *                             <float>upstream_flow_dir_sum)
 *                     if not preempted:             # <<<<<<<<<<<<<<
 *                         flow_accum_managed_raster.set(
 *                             flow_pixel.xi, flow_pixel.yi,
*/
          __pyx_t_6 = (!(__pyx_v_preempted != 0));
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":2131
 *                             <float>upstream_flow_dir_sum)
 *                     if not preempted:
 *                         flow_accum_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             flow_pixel.xi, flow_pixel.yi,
 *                             flow_pixel.value)
*/
            __pyx_v_flow_accum_managed_raster.set(__pyx_v_flow_pixel.xi, __pyx_v_flow_pixel.yi, __pyx_v_flow_pixel.value);

            /* "pygeoprocessing/routing/routing.pyx":2130
 *                             upstream_flow_accum * upstream_flow_weight /
 *                             <float>upstream_flow_dir_sum)
 *                     if not preempted:             # <<<<<<<<<<<<<<
 *                         flow_accum_managed_raster.set(
 *                             flow_pixel.xi, flow_pixel.yi,
*/
          }
        }
        __pyx_L20_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":2009
 *     LOGGER.debug('starting search')
 *     # this outer loop searches for a pixel that is locally undrained
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_mfd_raster_path_band, offset_only=True,
 *             largest_block=0):
*/
  }
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2134
 *                             flow_pixel.xi, flow_pixel.yi,
 *                             flow_pixel.value)
 *     flow_accum_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster.close()
 *     if weight_raster_path_band:
*/
  __pyx_v_flow_accum_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2135
 *                             flow_pixel.value)
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     if weight_raster_path_band:
 *         weight_raster.close()
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2136
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     visited_managed_raster.close()
*/
  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 2136, __pyx_L1_error)
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":2137
 *     flow_dir_managed_raster.close()
 *     if weight_raster_path_band:
 *         weight_raster.close()             # <<<<<<<<<<<<<<
 *     visited_managed_raster.close()
 *     try:
*/
    __pyx_v_weight_raster.close();

    /* "pygeoprocessing/routing/routing.pyx":2136
 *     flow_accum_managed_raster.close()
 *     flow_dir_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     visited_managed_raster.close()
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2138
 *     if weight_raster_path_band:
 *         weight_raster.close()
 *     visited_managed_raster.close()             # <<<<<<<<<<<<<<
 *     try:
 *         shutil.rmtree(tmp_dir)
*/
  __pyx_v_visited_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2139
 *         weight_raster.close()
 *     visited_managed_raster.close()
 *     try:             # <<<<<<<<<<<<<<
 *         shutil.rmtree(tmp_dir)
 *     except OSError:
*/
  {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ExceptionSave(&__pyx_t_25, &__pyx_t_24, &__pyx_t_23);
    __Pyx_XGOTREF(__pyx_t_25);
    __Pyx_XGOTREF(__pyx_t_24);
    __Pyx_XGOTREF(__pyx_t_23);
    /*try:*/ {

      /* "pygeoprocessing/routing/routing.pyx":2140
 *     visited_managed_raster.close()
 *     try:
 *         shutil.rmtree(tmp_dir)             # <<<<<<<<<<<<<<
 *     except OSError:
 *         LOGGER.exception("couldn't remove temp dir")
*/
      __pyx_t_1 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2140, __pyx_L50_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2140, __pyx_L50_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_3))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
        assert(__pyx_t_1);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_v_tmp_dir};
        __pyx_t_14 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2140, __pyx_L50_error)
        __Pyx_GOTREF(__pyx_t_14);
      }
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;

      /* "pygeoprocessing/routing/routing.pyx":2139
 *         weight_raster.close()
 *     visited_managed_raster.close()
 *     try:             # <<<<<<<<<<<<<<
 *         shutil.rmtree(tmp_dir)
 *     except OSError:
*/
    }
    __Pyx_XDECREF(__pyx_t_25); __pyx_t_25 = 0;
    __Pyx_XDECREF(__pyx_t_24); __pyx_t_24 = 0;
    __Pyx_XDECREF(__pyx_t_23); __pyx_t_23 = 0;
    goto __pyx_L55_try_end;
    __pyx_L50_error:;
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF(__pyx_t_26); __pyx_t_26 = 0;
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2141
 *     try:
 *         shutil.rmtree(tmp_dir)
 *     except OSError:             # <<<<<<<<<<<<<<
 *         LOGGER.exception("couldn't remove temp dir")
 *     LOGGER.info('Flow accum MFD %.1f%% complete', 100.0)
*/
    __pyx_t_15 = __Pyx_PyErr_ExceptionMatches(((PyObject *)(((PyTypeObject*)PyExc_OSError))));
    if (__pyx_t_15) {
      __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_accumulation_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
      if (__Pyx_GetException(&__pyx_t_14, &__pyx_t_3, &__pyx_t_1) < 0) __PYX_ERR(0, 2141, __pyx_L52_except_error)
      __Pyx_XGOTREF(__pyx_t_14);
      __Pyx_XGOTREF(__pyx_t_3);
      __Pyx_XGOTREF(__pyx_t_1);

      /* "pygeoprocessing/routing/routing.pyx":2142
 *         shutil.rmtree(tmp_dir)
 *     except OSError:
 *         LOGGER.exception("couldn't remove temp dir")             # <<<<<<<<<<<<<<
 *     LOGGER.info('Flow accum MFD %.1f%% complete', 100.0)
 * 
*/
      __pyx_t_2 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2142, __pyx_L52_except_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_exception); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2142, __pyx_L52_except_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __pyx_t_4 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_11))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_11);
        assert(__pyx_t_2);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
        __pyx_t_4 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_couldn_t_remove_temp_dir};
        __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2142, __pyx_L52_except_error)
        __Pyx_GOTREF(__pyx_t_8);
      }
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      goto __pyx_L51_exception_handled;
    }
    goto __pyx_L52_except_error;

    /* "pygeoprocessing/routing/routing.pyx":2139
 *         weight_raster.close()
 *     visited_managed_raster.close()
 *     try:             # <<<<<<<<<<<<<<
 *         shutil.rmtree(tmp_dir)
 *     except OSError:
*/
    __pyx_L52_except_error:;
    __Pyx_XGIVEREF(__pyx_t_25);
    __Pyx_XGIVEREF(__pyx_t_24);
    __Pyx_XGIVEREF(__pyx_t_23);
    __Pyx_ExceptionReset(__pyx_t_25, __pyx_t_24, __pyx_t_23);
    goto __pyx_L1_error;
    __pyx_L51_exception_handled:;
    __Pyx_XGIVEREF(__pyx_t_25);
    __Pyx_XGIVEREF(__pyx_t_24);
    __Pyx_XGIVEREF(__pyx_t_23);
    __Pyx_ExceptionReset(__pyx_t_25, __pyx_t_24, __pyx_t_23);
    __pyx_L55_try_end:;
  }

  /* "pygeoprocessing/routing/routing.pyx":2143
 *     except OSError:
 *         LOGGER.exception("couldn't remove temp dir")
 *     LOGGER.info('Flow accum MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2143, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2143, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_mstate_global->__pyx_tuple[2], NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2143, __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;

  /* "pygeoprocessing/routing/routing.pyx":1860
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_14);
  __Pyx_XDECREF(__pyx_t_26);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.flow_accumulation_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_mfd_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_flow_dir_mfd_buffer_array);
  __Pyx_XDECREF(__pyx_v_tmp_dir_root);
  __Pyx_XDECREF(__pyx_v_tmp_dir);
  __Pyx_XDECREF(__pyx_v_visited_raster_path);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster);
  __Pyx_XDECREF(__pyx_v_flow_dir_band);
  __Pyx_XDECREF(__pyx_v_raw_weight_nodata);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster_info);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":2146
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_d8(
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_42__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":2150
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
 *         target_distance_to_channel_raster_path,
 *         weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Calculate distance to channel with D8 flow.
*/
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2146, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, Py_None) != (0)) __PYX_ERR(0, 2146, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 2146, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":2146
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_d8(
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2146, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 2146, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 2146, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_13distance_to_channel_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_12distance_to_channel_d8, "Calculate distance to channel with D8 flow.\n\n    Parameters:\n        flow_dir_d8_raster_path_band (tuple): a path/band index tuple\n            indicating the raster that defines the D8 flow direction\n            raster for this call. The pixel values are integers that\n            correspond to outflow in the following configuration::\n\n                3 2 1\n                4 x 0\n                5 6 7\n\n            Paths may use any GDAL-supported scheme, including virtual\n            file system /vsi schemes.\n        channel_raster_path_band (tuple): a path/band tuple of the same\n            dimensions and projection as ``flow_dir_d8_raster_path_band[0]``\n            that indicates where the channels in the problem space lie. A\n            channel is indicated if the value of the pixel is 1. Other values\n            are ignored. Paths may use any GDAL-supported scheme, including\n            virtual file system /vsi schemes.\n        target_distance_to_channel_raster_path (str): path to a raster\n            created by this call that has per-pixel distances from a given\n            pixel to the nearest downhill channel.\n        weight_raster_path_band (tuple): optional path and band number to a\n            raster that will be used as the per-pixel flow distance\n            weight. If ``None``, 1 is the default distance between neighboring\n            pixels. This raster must be the same dimensions as\n            ``flow_dir_mfd_raster_path_band``. Paths may use any GDAL-supported\n            scheme, including virtual file system /vsi schemes.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_13distance_to_channel_d8 = {"distance_to_channel_d8", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_13distance_to_channel_d8, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_12distance_to_channel_d8};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_13distance_to_channel_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_d8_raster_path_band = 0;
  PyObject *__pyx_v_channel_raster_path_band = 0;
  PyObject *__pyx_v_target_distance_to_channel_raster_path = 0;
  PyObject *__pyx_v_weight_raster_path_band = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[5] = {0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("distance_to_channel_d8 (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_d8_raster_path_band,&__pyx_mstate_global->__pyx_n_u_channel_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_distance_to_channel_raste,&__pyx_mstate_global->__pyx_n_u_weight_raster_path_band,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2146, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "distance_to_channel_d8", 0) < (0)) __PYX_ERR(0, 2146, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":2150
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
 *         target_distance_to_channel_raster_path,
 *         weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Calculate distance to channel with D8 flow.
*/
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[4]) values[4] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("distance_to_channel_d8", 0, 3, 5, i); __PYX_ERR(0, 2146, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2146, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2146, __pyx_L3_error)
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2146, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2146, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[4]) values[4] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_dir_d8_raster_path_band = values[0];
    __pyx_v_channel_raster_path_band = values[1];
    __pyx_v_target_distance_to_channel_raster_path = values[2];
    __pyx_v_weight_raster_path_band = values[3];
    __pyx_v_raster_driver_creation_tuple = values[4];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("distance_to_channel_d8", 0, 3, 5, __pyx_nargs); __PYX_ERR(0, 2146, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.distance_to_channel_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_12distance_to_channel_d8(__pyx_self, __pyx_v_flow_dir_d8_raster_path_band, __pyx_v_channel_raster_path_band, __pyx_v_target_distance_to_channel_raster_path, __pyx_v_weight_raster_path_band, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":2146
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_d8(
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_12distance_to_channel_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_channel_raster_path_band, PyObject *__pyx_v_target_distance_to_channel_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_channel_buffer_array = 0;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_q;
  unsigned int __pyx_v_yi_q;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType>  __pyx_v_distance_to_channel_stack;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  double __pyx_v_weight_val;
  double __pyx_v_pixel_val;
  double __pyx_v_weight_nodata;
  unsigned long __pyx_v_current_pixel;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_path = NULL;
  long __pyx_v_distance_nodata;
  ManagedRaster __pyx_v_distance_to_channel_managed_raster;
  ManagedRaster __pyx_v_weight_raster;
  PyObject *__pyx_v_raw_weight_nodata = NULL;
  ManagedRaster __pyx_v_channel_managed_raster;
  ManagedRaster __pyx_v_flow_dir_d8_managed_raster;
  PyObject *__pyx_v_channel_raster = NULL;
  PyObject *__pyx_v_channel_band = NULL;
  PyObject *__pyx_v_flow_dir_raster_info = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_channel_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_channel_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  Py_ssize_t __pyx_t_3;
  int __pyx_t_4;
  int __pyx_t_5;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  size_t __pyx_t_8;
  int __pyx_t_9;
  PyObject *__pyx_t_10 = NULL;
  PyObject *__pyx_t_11 = NULL;
  PyObject *__pyx_t_12 = NULL;
  char *__pyx_t_13;
  ManagedRaster __pyx_t_14;
  int __pyx_t_15;
  double __pyx_t_16;
  PyObject *(*__pyx_t_17)(PyObject *);
  unsigned int __pyx_t_18;
  unsigned int __pyx_t_19;
  PyObject *(*__pyx_t_20)(PyObject *);
  float __pyx_t_21;
  PyObject *__pyx_t_22 = NULL;
  PyObject *__pyx_t_23 = NULL;
  PyObject *__pyx_t_24 = NULL;
  PyObject *__pyx_t_25 = NULL;
  PyObject *__pyx_t_26 = NULL;
  long __pyx_t_27;
  long __pyx_t_28;
  long __pyx_t_29;
  long __pyx_t_30;
  size_t __pyx_t_31;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_PixelType __pyx_t_32;
  unsigned int __pyx_t_33;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("distance_to_channel_d8", 0);
  __pyx_pybuffer_channel_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_channel_buffer_array.refcount = 0;
  __pyx_pybuffernd_channel_buffer_array.data = NULL;
  __pyx_pybuffernd_channel_buffer_array.rcbuffer = &__pyx_pybuffer_channel_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":2208
 *     # for distance updates
 *     cdef double weight_val, pixel_val
 *     cdef double weight_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned long current_pixel
*/
  __pyx_v_weight_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":2214
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     for path in (
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":2217
 * 
 *     for path in (
 *             flow_dir_d8_raster_path_band, channel_raster_path_band,             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):
*/
  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2217, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_v_flow_dir_d8_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_flow_dir_d8_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_flow_dir_d8_raster_path_band) != (0)) __PYX_ERR(0, 2217, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_channel_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_channel_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_channel_raster_path_band) != (0)) __PYX_ERR(0, 2217, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_weight_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_weight_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_weight_raster_path_band) != (0)) __PYX_ERR(0, 2217, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":2216
 *     last_log_time = ctime(NULL)
 * 
 *     for path in (             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
*/
  __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2);
  __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (__pyx_t_3 >= 3) break;
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    __pyx_t_1 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3));
    #else
    __pyx_t_1 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_3);
    #endif
    ++__pyx_t_3;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2216, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_path, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2219
 *             flow_dir_d8_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):             # <<<<<<<<<<<<<<
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (
*/
    __pyx_t_5 = (__pyx_v_path != Py_None);
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L6_bool_binop_done;
    }
    __pyx_t_6 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2219, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7);
      assert(__pyx_t_6);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_v_path};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2219, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 2219, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_9 = (!__pyx_t_5);
    __pyx_t_4 = __pyx_t_9;
    __pyx_L6_bool_binop_done:;
    if (unlikely(__pyx_t_4)) {

      /* "pygeoprocessing/routing/routing.pyx":2220
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):
 *             raise ValueError(             # <<<<<<<<<<<<<<
 *                 "%s is supposed to be a raster band tuple but it's not." % (
 *                     path))
*/
      __pyx_t_7 = NULL;

      /* "pygeoprocessing/routing/routing.pyx":2221
 *         if path is not None and not _is_raster_path_band_formatted(path):
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                     path))
 * 
*/
      __pyx_t_6 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_path); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2221, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __pyx_t_8 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_6};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2220, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_Raise(__pyx_t_1, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __PYX_ERR(0, 2220, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":2219
 *             flow_dir_d8_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):             # <<<<<<<<<<<<<<
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2216
 *     last_log_time = ctime(NULL)
 * 
 *     for path in (             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
*/
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2224
 *                     path))
 * 
 *     distance_nodata = -1             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0],
*/
  __pyx_v_distance_nodata = -1L;

  /* "pygeoprocessing/routing/routing.pyx":2225
 * 
 *     distance_nodata = -1
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0],
 *         target_distance_to_channel_raster_path,
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2225, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2226
 *     distance_nodata = -1
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0],             # <<<<<<<<<<<<<<
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2226, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);

  /* "pygeoprocessing/routing/routing.pyx":2228
 *         flow_dir_d8_raster_path_band[0],
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = __Pyx_PyLong_From_long(__pyx_v_distance_nodata); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_12 = PyList_New(1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2228, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_GIVEREF(__pyx_t_10);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_12, 0, __pyx_t_10) != (0)) __PYX_ERR(0, 2228, __pyx_L1_error);
  __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2229
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     distance_to_channel_managed_raster = ManagedRaster(
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
*/
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_1, __pyx_t_6, __pyx_v_target_distance_to_channel_raster_path, __pyx_t_11, __pyx_t_12};
    __pyx_t_10 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2225, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_10, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 2225, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (5-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_10);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2225, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2231
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster weight_raster
*/
  __pyx_t_7 = __pyx_v_target_distance_to_channel_raster_path;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2231, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2231, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2230
 *         gdal.GDT_Float64, [distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2230, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_distance_to_channel_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2234
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2234, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":2236
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
*/
    __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2236, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_7 = __pyx_t_10;
    __Pyx_INCREF(__pyx_t_7);
    __pyx_t_8 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_utf_8};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2236, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2236, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2237
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
*/
    __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2237, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_10); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2237, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2235
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
*/
    try {
      __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
    } catch(...) {
      __Pyx_CppExn2PyErr();
      __PYX_ERR(0, 2235, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_weight_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

    /* "pygeoprocessing/routing/routing.pyx":2238
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
*/
    __pyx_t_10 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2238, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2238, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2239
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_7 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2239, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_12))) {
      __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_12);
      assert(__pyx_t_10);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
      __Pyx_INCREF(__pyx_t_10);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_7};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2238, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_12 = __Pyx_PyObject_Dict_GetItem(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2239, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2240
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata
*/
    __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2240, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_7 = __Pyx_PyLong_SubtractObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2240, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2239
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_t_12, __pyx_t_7); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2239, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_v_raw_weight_nodata = __pyx_t_2;
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2241
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    __pyx_t_4 = (__pyx_v_raw_weight_nodata != Py_None);
    if (__pyx_t_4) {

      /* "pygeoprocessing/routing/routing.pyx":2242
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata             # <<<<<<<<<<<<<<
 * 
 *     channel_managed_raster = ManagedRaster(
*/
      __pyx_t_16 = __Pyx_PyFloat_AsDouble(__pyx_v_raw_weight_nodata); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 2242, __pyx_L1_error)
      __pyx_v_weight_nodata = __pyx_t_16;

      /* "pygeoprocessing/routing/routing.pyx":2241
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 * 
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2234
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2245
 * 
 *     channel_managed_raster = ManagedRaster(
 *         channel_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         channel_raster_path_band[1], False)
 * 
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2245, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_7 = __pyx_t_12;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2245, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2245, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2246
 *     channel_managed_raster = ManagedRaster(
 *         channel_raster_path_band[0].encode('utf-8'),
 *         channel_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_d8_managed_raster = ManagedRaster(
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_12); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2246, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2244
 *             weight_nodata = raw_weight_nodata
 * 
 *     channel_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         channel_raster_path_band[0].encode('utf-8'),
 *         channel_raster_path_band[1], False)
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2244, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_channel_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2249
 * 
 *     flow_dir_d8_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
*/
  __pyx_t_7 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2249, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_12 = __pyx_t_7;
  __Pyx_INCREF(__pyx_t_12);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2249, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2249, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2250
 *     flow_dir_d8_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
*/
  __pyx_t_7 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2250, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_7); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2250, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2248
 *         channel_raster_path_band[1], False)
 * 
 *     flow_dir_d8_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2248, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_flow_dir_d8_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2251
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
 * 
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_10))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_10);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_10);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_10, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_t_12, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_10, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2251, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_channel_raster = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2252
 *         flow_dir_d8_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
*/
  __pyx_t_10 = __pyx_v_channel_raster;
  __Pyx_INCREF(__pyx_t_10);
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2252, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2252, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_channel_band = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2254
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2254, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2254, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2255
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 * 
*/
  __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2255, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_10};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2254, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_flow_dir_raster_info = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2256
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for undefined channels
*/
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2256, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
    PyObject* sequence = __pyx_t_2;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 2256, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_12);
      __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_10);
    } else {
      __pyx_t_12 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2256, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_12);
      __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2256, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_10);
    }
    #else
    __pyx_t_12 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2256, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __pyx_t_10 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2256, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    #endif
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_6 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2256, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6);
    index = 0; __pyx_t_12 = __pyx_t_17(__pyx_t_6); if (unlikely(!__pyx_t_12)) goto __pyx_L11_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_12);
    index = 1; __pyx_t_10 = __pyx_t_17(__pyx_t_6); if (unlikely(!__pyx_t_10)) goto __pyx_L11_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_10);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_6), 2) < (0)) __PYX_ERR(0, 2256, __pyx_L1_error)
    __pyx_t_17 = NULL;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    goto __pyx_L12_unpacking_done;
    __pyx_L11_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_17 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 2256, __pyx_L1_error)
    __pyx_L12_unpacking_done:;
  }
  __pyx_t_18 = __Pyx_PyLong_As_unsigned_int(__pyx_t_12); if (unlikely((__pyx_t_18 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2256, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_10); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2256, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_v_raster_x_size = __pyx_t_18;
  __pyx_v_raster_y_size = __pyx_t_19;

  /* "pygeoprocessing/routing/routing.pyx":2259
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_10 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2259, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2259, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2260
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             channel_raster_path_band, offset_only=True, largest_block=0):             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_6);
    assert(__pyx_t_10);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
    __Pyx_INCREF(__pyx_t_10);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_10, __pyx_v_channel_raster_path_band};
    __pyx_t_12 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2259, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_12, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2259, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_12, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 2259, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_12);
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2259, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }

  /* "pygeoprocessing/routing/routing.pyx":2259
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_6 = __pyx_t_2; __Pyx_INCREF(__pyx_t_6);
    __pyx_t_3 = 0;
    __pyx_t_20 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2259, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_20 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 2259, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_20)) {
      if (likely(PyList_CheckExact(__pyx_t_6))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2259, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_6, __pyx_t_3, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_3;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2259, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_3));
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_6, __pyx_t_3);
        #endif
        ++__pyx_t_3;
      }
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2259, __pyx_L1_error)
    } else {
      __pyx_t_2 = __pyx_t_20(__pyx_t_6);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 2259, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2261
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2261, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2261, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_win_xsize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2262
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2262, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2262, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_win_ysize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2263
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2263, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2263, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_xoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2264
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2264, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2264, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_yoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2266
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_4 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_4) {

      /* "pygeoprocessing/routing/routing.pyx":2267
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel D8 %.1f%% complete', 100.0 * current_pixel / <float>(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":2268
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info('Dist to channel D8 %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":2269
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel D8 %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      __pyx_t_12 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2269, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2269, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __pyx_t_16 = (100.0 * __pyx_v_current_pixel);

      /* "pygeoprocessing/routing/routing.pyx":2270
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel D8 %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 * 
 *         # make a buffer big enough to capture block and boundaries around it
*/
      __pyx_t_21 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

      /* "pygeoprocessing/routing/routing.pyx":2269
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel D8 %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      if (unlikely(__pyx_t_21 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 2269, __pyx_L1_error)
      }
      __pyx_t_10 = PyFloat_FromDouble((__pyx_t_16 / ((double)__pyx_t_21))); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2269, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_8 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_7))) {
        __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_7);
        assert(__pyx_t_12);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
        __Pyx_INCREF(__pyx_t_12);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
        __pyx_t_8 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_Dist_to_channel_D8_1f_complete, __pyx_t_10};
        __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2269, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":2266
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2273
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    __pyx_t_7 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2273, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2273, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2274
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.uint8)
 *         channel_buffer_array[:] = 0  # 0 means no channel
*/
    __pyx_t_10 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_11 = __Pyx_PyLong_AddObjC(__pyx_t_10, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __pyx_t_10 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_1 = __Pyx_PyLong_AddObjC(__pyx_t_10, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_GIVEREF(__pyx_t_11);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_11) != (0)) __PYX_ERR(0, 2274, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_1);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_1) != (0)) __PYX_ERR(0, 2274, __pyx_L1_error);
    __pyx_t_11 = 0;
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2275
 *         channel_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)             # <<<<<<<<<<<<<<
 *         channel_buffer_array[:] = 0  # 0 means no channel
 * 
*/
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2275, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_uint8); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2275, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_12))) {
      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_12);
      assert(__pyx_t_7);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_7, __pyx_t_10};
      __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2273, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_11, __pyx_t_1, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2273, __pyx_L1_error)
      __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2273, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2273
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2273, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
      __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_2), &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_15 < 0)) {
        PyErr_Fetch(&__pyx_t_22, &__pyx_t_23, &__pyx_t_24);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_channel_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_22); Py_XDECREF(__pyx_t_23); Py_XDECREF(__pyx_t_24);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_22, __pyx_t_23, __pyx_t_24);
        }
        __pyx_t_22 = __pyx_t_23 = __pyx_t_24 = 0;
      }
      __pyx_pybuffernd_channel_buffer_array.diminfo[0].strides = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_channel_buffer_array.diminfo[0].shape = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_channel_buffer_array.diminfo[1].strides = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_channel_buffer_array.diminfo[1].shape = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_15 < 0))) __PYX_ERR(0, 2273, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_channel_buffer_array, ((PyArrayObject *)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2276
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
 *         channel_buffer_array[:] = 0  # 0 means no channel             # <<<<<<<<<<<<<<
 * 
 *         # check if we can widen the border to include real data from the
*/
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_channel_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_0) < 0))) __PYX_ERR(0, 2276, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2280
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
*/
    __pyx_t_12 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2280, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);

    /* "pygeoprocessing/routing/routing.pyx":2281
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)
*/
    __pyx_t_11 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2281, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_10 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2281, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_12);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_12);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_12, __pyx_v_offset_dict, __pyx_t_11, __pyx_t_10};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_8, (4-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2280, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_10);
      } else {
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_10);
      }
      #else
      __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_10 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_11 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11);
      index = 0; __pyx_t_1 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_1)) goto __pyx_L16_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_1);
      index = 1; __pyx_t_10 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_10)) goto __pyx_L16_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_10);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_11), 2) < (0)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      goto __pyx_L17_unpacking_done;
      __pyx_L16_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2280, __pyx_L1_error)
      __pyx_L17_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":2280
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
      PyObject* sequence = __pyx_t_1;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2280, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_11);
        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_12);
        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_7);
        __pyx_t_25 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_25);
      } else {
        __pyx_t_11 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_11);
        __pyx_t_12 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_12);
        __pyx_t_7 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_7);
        __pyx_t_25 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2280, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_25);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_11,&__pyx_t_12,&__pyx_t_7,&__pyx_t_25};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 2280, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_11,&__pyx_t_12,&__pyx_t_7,&__pyx_t_25};
      __pyx_t_26 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_26);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_26);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_17(__pyx_t_26); if (unlikely(!item)) goto __pyx_L18_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_26), 4) < (0)) __PYX_ERR(0, 2280, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      goto __pyx_L19_unpacking_done;
      __pyx_L18_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2280, __pyx_L1_error)
      __pyx_L19_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_11);
    __pyx_t_11 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_12);
    __pyx_t_12 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_7);
    __pyx_t_7 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_25);
    __pyx_t_25 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_10);
    __pyx_t_10 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2282
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_channel_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);

    /* "pygeoprocessing/routing/routing.pyx":2283
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 2283, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_25 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2283, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    } else {
      __pyx_t_25 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2282, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    }

    /* "pygeoprocessing/routing/routing.pyx":2282
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_25); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_10 = __pyx_t_7;
    __Pyx_INCREF(__pyx_t_10);

    /* "pygeoprocessing/routing/routing.pyx":2283
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2283, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_25);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_int8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2283, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_8 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_1};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2283, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2282
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_7 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_1 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_GIVEREF(__pyx_t_7);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_7) != (0)) __PYX_ERR(0, 2282, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_1);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_1) != (0)) __PYX_ERR(0, 2282, __pyx_L1_error);
    __pyx_t_7 = 0;
    __pyx_t_1 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_channel_buffer_array), __pyx_t_10, __pyx_t_2) < 0))) __PYX_ERR(0, 2282, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2286
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2287
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # search block for to search for a channel seed
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2290
 * 
 *         # search block for to search for a channel seed
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 if channel_buffer_array[yi, xi] != 1:
*/
    __pyx_t_27 = (__pyx_v_win_ysize + 1);
    __pyx_t_28 = __pyx_t_27;
    for (__pyx_t_19 = 1; __pyx_t_19 < __pyx_t_28; __pyx_t_19+=1) {
      __pyx_v_yi = __pyx_t_19;

      /* "pygeoprocessing/routing/routing.pyx":2291
 *         # search block for to search for a channel seed
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 if channel_buffer_array[yi, xi] != 1:
 *                     # no channel seed
*/
      __pyx_t_29 = (__pyx_v_win_xsize + 1);
      __pyx_t_30 = __pyx_t_29;
      for (__pyx_t_18 = 1; __pyx_t_18 < __pyx_t_30; __pyx_t_18+=1) {
        __pyx_v_xi = __pyx_t_18;

        /* "pygeoprocessing/routing/routing.pyx":2292
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 if channel_buffer_array[yi, xi] != 1:             # <<<<<<<<<<<<<<
 *                     # no channel seed
 *                     continue
*/
        __pyx_t_8 = __pyx_v_yi;
        __pyx_t_31 = __pyx_v_xi;
        __pyx_t_15 = -1;
        if (unlikely(__pyx_t_8 >= (size_t)__pyx_pybuffernd_channel_buffer_array.diminfo[0].shape)) __pyx_t_15 = 0;
        if (unlikely(__pyx_t_31 >= (size_t)__pyx_pybuffernd_channel_buffer_array.diminfo[1].shape)) __pyx_t_15 = 1;
        if (unlikely(__pyx_t_15 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_15);
          __PYX_ERR(0, 2292, __pyx_L1_error)
        }
        __pyx_t_4 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_uint8_t *, __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_channel_buffer_array.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_channel_buffer_array.diminfo[1].strides)) != 1);
        if (__pyx_t_4) {

          /* "pygeoprocessing/routing/routing.pyx":2294
 *                 if channel_buffer_array[yi, xi] != 1:
 *                     # no channel seed
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 distance_to_channel_stack.push(
*/
          goto __pyx_L22_continue;

          /* "pygeoprocessing/routing/routing.pyx":2292
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 if channel_buffer_array[yi, xi] != 1:             # <<<<<<<<<<<<<<
 *                     # no channel seed
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2297
 * 
 *                 distance_to_channel_stack.push(
 *                     PixelType(0.0, xi+xoff-1, yi+yoff-1, 0))             # <<<<<<<<<<<<<<
 * 
 *                 while not distance_to_channel_stack.empty():
*/
        __pyx_t_32.value = 0.0;
        __pyx_t_32.xi = ((__pyx_v_xi + __pyx_v_xoff) - 1);
        __pyx_t_32.yi = ((__pyx_v_yi + __pyx_v_yoff) - 1);
        __pyx_t_32.priority = 0;

        /* "pygeoprocessing/routing/routing.pyx":2296
 *                     continue
 * 
 *                 distance_to_channel_stack.push(             # <<<<<<<<<<<<<<
 *                     PixelType(0.0, xi+xoff-1, yi+yoff-1, 0))
 * 
*/
        try {
          __pyx_v_distance_to_channel_stack.push(__pyx_t_32);
        } catch(...) {
          __Pyx_CppExn2PyErr();
          __PYX_ERR(0, 2296, __pyx_L1_error)
        }

        /* "pygeoprocessing/routing/routing.pyx":2299
 *                     PixelType(0.0, xi+xoff-1, yi+yoff-1, 0))
 * 
 *                 while not distance_to_channel_stack.empty():             # <<<<<<<<<<<<<<
 *                     xi_q = distance_to_channel_stack.top().xi
 *                     yi_q = distance_to_channel_stack.top().yi
*/
        while (1) {
          __pyx_t_4 = (!__pyx_v_distance_to_channel_stack.empty());
          if (!__pyx_t_4) break;

          /* "pygeoprocessing/routing/routing.pyx":2300
 * 
 *                 while not distance_to_channel_stack.empty():
 *                     xi_q = distance_to_channel_stack.top().xi             # <<<<<<<<<<<<<<
 *                     yi_q = distance_to_channel_stack.top().yi
 *                     pixel_val = distance_to_channel_stack.top().value
*/
          __pyx_t_33 = __pyx_v_distance_to_channel_stack.top().xi;
          __pyx_v_xi_q = __pyx_t_33;

          /* "pygeoprocessing/routing/routing.pyx":2301
 *                 while not distance_to_channel_stack.empty():
 *                     xi_q = distance_to_channel_stack.top().xi
 *                     yi_q = distance_to_channel_stack.top().yi             # <<<<<<<<<<<<<<
 *                     pixel_val = distance_to_channel_stack.top().value
 *                     distance_to_channel_stack.pop()
*/
          __pyx_t_33 = __pyx_v_distance_to_channel_stack.top().yi;
          __pyx_v_yi_q = __pyx_t_33;

          /* "pygeoprocessing/routing/routing.pyx":2302
 *                     xi_q = distance_to_channel_stack.top().xi
 *                     yi_q = distance_to_channel_stack.top().yi
 *                     pixel_val = distance_to_channel_stack.top().value             # <<<<<<<<<<<<<<
 *                     distance_to_channel_stack.pop()
 * 
*/
          __pyx_t_16 = __pyx_v_distance_to_channel_stack.top().value;
          __pyx_v_pixel_val = __pyx_t_16;

          /* "pygeoprocessing/routing/routing.pyx":2303
 *                     yi_q = distance_to_channel_stack.top().yi
 *                     pixel_val = distance_to_channel_stack.top().value
 *                     distance_to_channel_stack.pop()             # <<<<<<<<<<<<<<
 * 
 *                     distance_to_channel_managed_raster.set(
*/
          __pyx_v_distance_to_channel_stack.pop();

          /* "pygeoprocessing/routing/routing.pyx":2305
 *                     distance_to_channel_stack.pop()
 * 
 *                     distance_to_channel_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_q, yi_q, pixel_val)
 * 
*/
          __pyx_v_distance_to_channel_managed_raster.set(__pyx_v_xi_q, __pyx_v_yi_q, __pyx_v_pixel_val);

          /* "pygeoprocessing/routing/routing.pyx":2308
 *                         xi_q, yi_q, pixel_val)
 * 
 *                     for i_n in range(8):             # <<<<<<<<<<<<<<
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
*/
          for (__pyx_t_33 = 0; __pyx_t_33 < 8; __pyx_t_33+=1) {
            __pyx_v_i_n = __pyx_t_33;

            /* "pygeoprocessing/routing/routing.pyx":2309
 * 
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
*/
            __pyx_v_xi_n = (__pyx_v_xi_q + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2310
 *                     for i_n in range(8):
 *                         xi_n = xi_q+COL_OFFSETS[i_n]
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_yi_n = (__pyx_v_yi_q + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2312
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_9 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L30_bool_binop_done;
            }
            __pyx_t_9 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L30_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":2313
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_9 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L30_bool_binop_done;
            }
            __pyx_t_9 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_4 = __pyx_t_9;
            __pyx_L30_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":2312
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2314
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         if channel_managed_raster.get(xi_n, yi_n) == 1:
*/
              goto __pyx_L27_continue;

              /* "pygeoprocessing/routing/routing.pyx":2312
 *                         yi_n = yi_q+ROW_OFFSETS[i_n]
 * 
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2316
 *                             continue
 * 
 *                         if channel_managed_raster.get(xi_n, yi_n) == 1:             # <<<<<<<<<<<<<<
 *                             # it's a channel, it'll get picked up in the
 *                             # outer loop
*/
            __pyx_t_4 = (__pyx_v_channel_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == 1.0);
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2319
 *                             # it's a channel, it'll get picked up in the
 *                             # outer loop
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         if (flow_dir_d8_managed_raster.get(xi_n, yi_n) ==
*/
              goto __pyx_L27_continue;

              /* "pygeoprocessing/routing/routing.pyx":2316
 *                             continue
 * 
 *                         if channel_managed_raster.get(xi_n, yi_n) == 1:             # <<<<<<<<<<<<<<
 *                             # it's a channel, it'll get picked up in the
 *                             # outer loop
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2321
 *                             continue
 * 
 *                         if (flow_dir_d8_managed_raster.get(xi_n, yi_n) ==             # <<<<<<<<<<<<<<
 *                                 INFLOW_OFFSETS[i_n]):
 *                             # if a weight is passed we use it directly and do
*/
            __pyx_t_4 = (__pyx_v_flow_dir_d8_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == (INFLOW_OFFSETS[__pyx_v_i_n]));
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2328
 *                             # then "distance" is being calculated and we
 *                             # account for diagonal distance.
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = weight_raster.get(xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
*/
              __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2328, __pyx_L1_error)
              if (__pyx_t_4) {

                /* "pygeoprocessing/routing/routing.pyx":2329
 *                             # account for diagonal distance.
 *                             if weight_raster_path_band:
 *                                 weight_val = weight_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                                 if is_close(weight_val, weight_nodata):
 *                                     weight_val = 0.0
*/
                __pyx_v_weight_val = __pyx_v_weight_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

                /* "pygeoprocessing/routing/routing.pyx":2330
 *                             if weight_raster_path_band:
 *                                 weight_val = weight_raster.get(xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                __pyx_t_4 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
                if (__pyx_t_4) {

                  /* "pygeoprocessing/routing/routing.pyx":2331
 *                                 weight_val = weight_raster.get(xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
 *                                     weight_val = 0.0             # <<<<<<<<<<<<<<
 *                             else:
 *                                 weight_val = (SQRT2 if i_n % 2 else 1)
*/
                  __pyx_v_weight_val = 0.0;

                  /* "pygeoprocessing/routing/routing.pyx":2330
 *                             if weight_raster_path_band:
 *                                 weight_val = weight_raster.get(xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                     weight_val = 0.0
 *                             else:
*/
                }

                /* "pygeoprocessing/routing/routing.pyx":2328
 *                             # then "distance" is being calculated and we
 *                             # account for diagonal distance.
 *                             if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                                 weight_val = weight_raster.get(xi_n, yi_n)
 *                                 if is_close(weight_val, weight_nodata):
*/
                goto __pyx_L36;
              }

              /* "pygeoprocessing/routing/routing.pyx":2333
 *                                     weight_val = 0.0
 *                             else:
 *                                 weight_val = (SQRT2 if i_n % 2 else 1)             # <<<<<<<<<<<<<<
 * 
 *                             distance_to_channel_stack.push(
*/
              /*else*/ {
                __pyx_t_4 = (__Pyx_mod_long(__pyx_v_i_n, 2, 1) != 0);
                if (__pyx_t_4) {
                  __pyx_t_16 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2;
                } else {
                  __pyx_t_16 = 1.0;
                }
                __pyx_v_weight_val = __pyx_t_16;
              }
              __pyx_L36:;

              /* "pygeoprocessing/routing/routing.pyx":2337
 *                             distance_to_channel_stack.push(
 *                                 PixelType(
 *                                     weight_val + pixel_val, xi_n, yi_n, 0))             # <<<<<<<<<<<<<<
 * 
 *     distance_to_channel_managed_raster.close()
*/
              __pyx_t_32.value = (__pyx_v_weight_val + __pyx_v_pixel_val);
              __pyx_t_32.xi = __pyx_v_xi_n;
              __pyx_t_32.yi = __pyx_v_yi_n;
              __pyx_t_32.priority = 0;

              /* "pygeoprocessing/routing/routing.pyx":2335
 *                                 weight_val = (SQRT2 if i_n % 2 else 1)
 * 
 *                             distance_to_channel_stack.push(             # <<<<<<<<<<<<<<
 *                                 PixelType(
 *                                     weight_val + pixel_val, xi_n, yi_n, 0))
*/
              try {
                __pyx_v_distance_to_channel_stack.push(__pyx_t_32);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 2335, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":2321
 *                             continue
 * 
 *                         if (flow_dir_d8_managed_raster.get(xi_n, yi_n) ==             # <<<<<<<<<<<<<<
 *                                 INFLOW_OFFSETS[i_n]):
 *                             # if a weight is passed we use it directly and do
*/
            }
            __pyx_L27_continue:;
          }
        }
        __pyx_L22_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":2259
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2339
 *                                     weight_val + pixel_val, xi_n, yi_n, 0))
 * 
 *     distance_to_channel_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_dir_d8_managed_raster.close()
 *     channel_managed_raster.close()
*/
  __pyx_v_distance_to_channel_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2340
 * 
 *     distance_to_channel_managed_raster.close()
 *     flow_dir_d8_managed_raster.close()             # <<<<<<<<<<<<<<
 *     channel_managed_raster.close()
 *     if weight_raster_path_band:
*/
  __pyx_v_flow_dir_d8_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2341
 *     distance_to_channel_managed_raster.close()
 *     flow_dir_d8_managed_raster.close()
 *     channel_managed_raster.close()             # <<<<<<<<<<<<<<
 *     if weight_raster_path_band:
 *         weight_raster.close()
*/
  __pyx_v_channel_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2342
 *     flow_dir_d8_managed_raster.close()
 *     channel_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 * 
*/
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2342, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":2343
 *     channel_managed_raster.close()
 *     if weight_raster_path_band:
 *         weight_raster.close()             # <<<<<<<<<<<<<<
 * 
 * 
*/
    __pyx_v_weight_raster.close();

    /* "pygeoprocessing/routing/routing.pyx":2342
 *     flow_dir_d8_managed_raster.close()
 *     channel_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 * 
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2146
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_d8(
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
*/

  /* function exit code */
  __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_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_XDECREF(__pyx_t_25);
  __Pyx_XDECREF(__pyx_t_26);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.distance_to_channel_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_channel_buffer_array);
  __Pyx_XDECREF(__pyx_v_path);
  __Pyx_XDECREF(__pyx_v_raw_weight_nodata);
  __Pyx_XDECREF(__pyx_v_channel_raster);
  __Pyx_XDECREF(__pyx_v_channel_band);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster_info);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":2346
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_44__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":2349
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *         target_distance_to_channel_raster_path, weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Calculate distance to channel with multiple flow direction.
*/
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2346, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, Py_None) != (0)) __PYX_ERR(0, 2346, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 2346, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":2346
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2346, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 2346, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, Py_None) != (0)) __PYX_ERR(0, 2346, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_15distance_to_channel_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_14distance_to_channel_mfd, "Calculate distance to channel with multiple flow direction.\n\n    MFD distance to channel for a pixel ``i`` is the average distance that\n    water travels from ``i`` until it reaches a stream, defined as::\n\n              \342\216\247 0,                                       if i is a stream pixel\n              \342\216\252\n              \342\216\252 undefined,   if i is not a stream and there are 0 elements in N\n       d_i =  \342\216\250\n              \342\216\252\n              \342\216\252   \342\216\262 ((d_n + l(i, n)) * p(i, n),                       otherwise\n              \342\216\252   \342\216\263\n              \342\216\251  n \342\210\210 N\n\n        where\n        - N is the set of immediate downstream neighbors of i that drain to\n          a stream on the map\n        - p(i, n) is the proportion of water on pixel i that flows onto n\n        - l(i, n) is the distance between i and n. This is 1 for lateral\n          neighbors, and \342\210\2322 for diagonal neighbors.\n\n    Distance is measured in units of pixel lengths. Pixels must be square, and\n    both input rasters must have the same spatial reference, geotransform, and\n    extent, so that their pixels overlap exactly.\n\n    If a none of a pixel's flow drains to any stream on the map, ``d_i`` is\n    undefined, and that pixel has nodata in the output.\n\n    If only some of a pixel's flow reaches a stream on the map, ``d_i`` is\n    defined in terms of only that portion of flow that reaches a stream. It is\n    the average distance traveled by the water that does reach a stream.\n\n    The algorithm begins from an arbitrary pixel and pushes downstream\n    neighbors to the stack depth-first, until reaching a stream (the first case\n    in the function for ``d_i`` above) or a raster edge (the second case).\n    Non-stream pixels are only calculated once all their downstream neighbors\n    have been calculated (the third case).\n\n    Args:\n        flow_dir_mfd_raster_path_band (tupl""e): a path/band index tuple\n            indicating the raster that defines the mfd flow accumulation\n            raster for this call. This raster should be generated by a call\n            to ``pygeoprocessing.routing.flow_dir_mfd``. Paths may use any\n            GDAL-supported scheme, including virtual file system /vsi schemes.\n        channel_raster_path_band (tuple): a path/band tuple of the same\n            dimensions and projection as ``flow_dir_mfd_raster_path_band[0]``\n            that indicates where the channels in the problem space lie. A\n            channel is indicated if the value of the pixel is 1. Other values\n            are ignored. Paths may use any GDAL-supported scheme, including\n            virtual file system /vsi schemes.\n        target_distance_to_channel_raster_path (str): path to a raster\n            created by this call that has per-pixel distances from a given\n            pixel to the nearest downhill channel.\n        weight_raster_path_band (tuple): optional path and band number to a\n            raster that will be used as the per-pixel flow distance\n            weight. If ``None``, 1 is the default distance between neighboring\n            pixels. This raster must be the same dimensions as\n            ``flow_dir_mfd_raster_path_band``. Paths may use any GDAL-supported\n            scheme, including virtual file system /vsi schemes.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name string as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at ``geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS``.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_15distance_to_channel_mfd = {"distance_to_channel_mfd", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_15distance_to_channel_mfd, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_14distance_to_channel_mfd};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_15distance_to_channel_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_mfd_raster_path_band = 0;
  PyObject *__pyx_v_channel_raster_path_band = 0;
  PyObject *__pyx_v_target_distance_to_channel_raster_path = 0;
  PyObject *__pyx_v_weight_raster_path_band = 0;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[5] = {0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("distance_to_channel_mfd (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_mfd_raster_path_band,&__pyx_mstate_global->__pyx_n_u_channel_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_distance_to_channel_raste,&__pyx_mstate_global->__pyx_n_u_weight_raster_path_band,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2346, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "distance_to_channel_mfd", 0) < (0)) __PYX_ERR(0, 2346, __pyx_L3_error)

      /* "pygeoprocessing/routing/routing.pyx":2349
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *         target_distance_to_channel_raster_path, weight_raster_path_band=None,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Calculate distance to channel with multiple flow direction.
*/
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[4]) values[4] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("distance_to_channel_mfd", 0, 3, 5, i); __PYX_ERR(0, 2346, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2346, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2346, __pyx_L3_error)
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2346, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2346, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)Py_None));
      if (!values[4]) values[4] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_dir_mfd_raster_path_band = values[0];
    __pyx_v_channel_raster_path_band = values[1];
    __pyx_v_target_distance_to_channel_raster_path = values[2];
    __pyx_v_weight_raster_path_band = values[3];
    __pyx_v_raster_driver_creation_tuple = values[4];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("distance_to_channel_mfd", 0, 3, 5, __pyx_nargs); __PYX_ERR(0, 2346, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.distance_to_channel_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_14distance_to_channel_mfd(__pyx_self, __pyx_v_flow_dir_mfd_raster_path_band, __pyx_v_channel_raster_path_band, __pyx_v_target_distance_to_channel_raster_path, __pyx_v_weight_raster_path_band, __pyx_v_raster_driver_creation_tuple);

  /* "pygeoprocessing/routing/routing.pyx":2346
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_14distance_to_channel_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_mfd_raster_path_band, PyObject *__pyx_v_channel_raster_path_band, PyObject *__pyx_v_target_distance_to_channel_raster_path, PyObject *__pyx_v_weight_raster_path_band, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyArrayObject *__pyx_v_channel_buffer_array = 0;
  PyArrayObject *__pyx_v_flow_dir_buffer_array = 0;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  int __pyx_v_flow_dir_weight;
  int __pyx_v_mfd_value;
  int __pyx_v_is_a_channel;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_MFDFlowPixelType>  __pyx_v_distance_to_channel_stack;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  double __pyx_v_weight_val;
  double __pyx_v_weight_nodata;
  time_t __pyx_v_last_log_time;
  unsigned long __pyx_v_current_pixel;
  PyObject *__pyx_v_path = NULL;
  long __pyx_v_distance_nodata;
  ManagedRaster __pyx_v_distance_to_channel_managed_raster;
  ManagedRaster __pyx_v_channel_managed_raster;
  PyObject *__pyx_v_tmp_work_dir = NULL;
  PyObject *__pyx_v_visited_raster_path = NULL;
  ManagedRaster __pyx_v_visited_managed_raster;
  ManagedRaster __pyx_v_flow_dir_mfd_managed_raster;
  PyObject *__pyx_v_channel_raster = NULL;
  PyObject *__pyx_v_channel_band = NULL;
  PyObject *__pyx_v_flow_dir_mfd_raster = NULL;
  PyObject *__pyx_v_flow_dir_mfd_band = NULL;
  ManagedRaster __pyx_v_weight_raster;
  PyObject *__pyx_v_raw_weight_nodata = NULL;
  PyObject *__pyx_v_flow_dir_raster_info = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_xa = NULL;
  PyObject *__pyx_v_xb = NULL;
  PyObject *__pyx_v_ya = NULL;
  PyObject *__pyx_v_yb = NULL;
  PyObject *__pyx_v_modified_offset_dict = NULL;
  long __pyx_v_xi_root;
  long __pyx_v_yi_root;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_MFDFlowPixelType __pyx_v_pixel;
  long __pyx_v_preempted;
  double __pyx_v_n_distance;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_channel_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_channel_buffer_array;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_flow_dir_buffer_array;
  __Pyx_Buffer __pyx_pybuffer_flow_dir_buffer_array;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  Py_ssize_t __pyx_t_3;
  int __pyx_t_4;
  int __pyx_t_5;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  size_t __pyx_t_8;
  int __pyx_t_9;
  PyObject *__pyx_t_10 = NULL;
  PyObject *__pyx_t_11 = NULL;
  PyObject *__pyx_t_12 = NULL;
  char *__pyx_t_13;
  ManagedRaster __pyx_t_14;
  int __pyx_t_15;
  double __pyx_t_16;
  PyObject *(*__pyx_t_17)(PyObject *);
  unsigned int __pyx_t_18;
  unsigned int __pyx_t_19;
  PyObject *(*__pyx_t_20)(PyObject *);
  float __pyx_t_21;
  PyObject *__pyx_t_22 = NULL;
  PyObject *__pyx_t_23 = NULL;
  PyObject *__pyx_t_24 = NULL;
  PyObject *__pyx_t_25 = NULL;
  PyObject *__pyx_t_26 = NULL;
  long __pyx_t_27;
  long __pyx_t_28;
  long __pyx_t_29;
  long __pyx_t_30;
  size_t __pyx_t_31;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_MFDFlowPixelType __pyx_t_32;
  unsigned int __pyx_t_33;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("distance_to_channel_mfd", 0);
  __pyx_pybuffer_channel_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_channel_buffer_array.refcount = 0;
  __pyx_pybuffernd_channel_buffer_array.data = NULL;
  __pyx_pybuffernd_channel_buffer_array.rcbuffer = &__pyx_pybuffer_channel_buffer_array;
  __pyx_pybuffer_flow_dir_buffer_array.pybuffer.buf = NULL;
  __pyx_pybuffer_flow_dir_buffer_array.refcount = 0;
  __pyx_pybuffernd_flow_dir_buffer_array.data = NULL;
  __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer = &__pyx_pybuffer_flow_dir_buffer_array;

  /* "pygeoprocessing/routing/routing.pyx":2442
 *     # come from a predefined flow accumulation weight raster
 *     cdef double weight_val
 *     cdef double weight_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     # used for time-delayed logging
*/
  __pyx_v_weight_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;

  /* "pygeoprocessing/routing/routing.pyx":2446
 *     # used for time-delayed logging
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned long current_pixel
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":2451
 * 
 *     for path in (
 *             flow_dir_mfd_raster_path_band, channel_raster_path_band,             # <<<<<<<<<<<<<<
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):
*/
  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2451, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_v_flow_dir_mfd_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_flow_dir_mfd_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_flow_dir_mfd_raster_path_band) != (0)) __PYX_ERR(0, 2451, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_channel_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_channel_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_channel_raster_path_band) != (0)) __PYX_ERR(0, 2451, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_weight_raster_path_band);
  __Pyx_GIVEREF(__pyx_v_weight_raster_path_band);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_weight_raster_path_band) != (0)) __PYX_ERR(0, 2451, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":2450
 *     cdef unsigned long current_pixel
 * 
 *     for path in (             # <<<<<<<<<<<<<<
 *             flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
*/
  __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2);
  __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (__pyx_t_3 >= 3) break;
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    __pyx_t_1 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3));
    #else
    __pyx_t_1 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_3);
    #endif
    ++__pyx_t_3;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2450, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_path, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2453
 *             flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):             # <<<<<<<<<<<<<<
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (
*/
    __pyx_t_5 = (__pyx_v_path != Py_None);
    if (__pyx_t_5) {
    } else {
      __pyx_t_4 = __pyx_t_5;
      goto __pyx_L6_bool_binop_done;
    }
    __pyx_t_6 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2453, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7);
      assert(__pyx_t_6);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_v_path};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 2453, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_9 = (!__pyx_t_5);
    __pyx_t_4 = __pyx_t_9;
    __pyx_L6_bool_binop_done:;
    if (unlikely(__pyx_t_4)) {

      /* "pygeoprocessing/routing/routing.pyx":2454
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):
 *             raise ValueError(             # <<<<<<<<<<<<<<
 *                 "%s is supposed to be a raster band tuple but it's not." % (
 *                     path))
*/
      __pyx_t_7 = NULL;

      /* "pygeoprocessing/routing/routing.pyx":2455
 *         if path is not None and not _is_raster_path_band_formatted(path):
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (             # <<<<<<<<<<<<<<
 *                     path))
 * 
*/
      __pyx_t_6 = __Pyx_PyUnicode_FormatSafe(__pyx_mstate_global->__pyx_kp_u_s_is_supposed_to_be_a_raster_ba, __pyx_v_path); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2455, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __pyx_t_8 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_6};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2454, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_Raise(__pyx_t_1, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __PYX_ERR(0, 2454, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":2453
 *             flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
 *         if path is not None and not _is_raster_path_band_formatted(path):             # <<<<<<<<<<<<<<
 *             raise ValueError(
 *                 "%s is supposed to be a raster band tuple but it's not." % (
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2450
 *     cdef unsigned long current_pixel
 * 
 *     for path in (             # <<<<<<<<<<<<<<
 *             flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *             weight_raster_path_band):
*/
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2458
 *                     path))
 * 
 *     distance_nodata = -1             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0],
*/
  __pyx_v_distance_nodata = -1L;

  /* "pygeoprocessing/routing/routing.pyx":2459
 * 
 *     distance_nodata = -1
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0],
 *         target_distance_to_channel_raster_path,
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2459, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2459, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2460
 *     distance_nodata = -1
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0],             # <<<<<<<<<<<<<<
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2460, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);

  /* "pygeoprocessing/routing/routing.pyx":2462
 *         flow_dir_mfd_raster_path_band[0],
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = __Pyx_PyLong_From_long(__pyx_v_distance_nodata); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_12 = PyList_New(1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_GIVEREF(__pyx_t_10);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_12, 0, __pyx_t_10) != (0)) __PYX_ERR(0, 2462, __pyx_L1_error);
  __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2463
 *         target_distance_to_channel_raster_path,
 *         gdal.GDT_Float64, [distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     distance_to_channel_managed_raster = ManagedRaster(
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
*/
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_1, __pyx_t_6, __pyx_v_target_distance_to_channel_raster_path, __pyx_t_11, __pyx_t_12};
    __pyx_t_10 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2459, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_10, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 2459, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (5-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_10);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2459, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2465
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 *     channel_managed_raster = ManagedRaster(
 *         channel_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_7 = __pyx_v_target_distance_to_channel_raster_path;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2465, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2465, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2464
 *         gdal.GDT_Float64, [distance_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     distance_to_channel_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
 *     channel_managed_raster = ManagedRaster(
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2464, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_distance_to_channel_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2467
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
 *     channel_managed_raster = ManagedRaster(
 *         channel_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         channel_raster_path_band[1], False)
 * 
*/
  __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2467, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_7 = __pyx_t_10;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2467, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2467, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2468
 *     channel_managed_raster = ManagedRaster(
 *         channel_raster_path_band[0].encode('utf-8'),
 *         channel_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     tmp_work_dir = tempfile.mkdtemp(
*/
  __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2468, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_10); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2468, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2466
 *     distance_to_channel_managed_raster = ManagedRaster(
 *         target_distance_to_channel_raster_path.encode('utf-8'), 1, True)
 *     channel_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         channel_raster_path_band[0].encode('utf-8'),
 *         channel_raster_path_band[1], False)
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2466, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_channel_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2470
 *         channel_raster_path_band[1], False)
 * 
 *     tmp_work_dir = tempfile.mkdtemp(             # <<<<<<<<<<<<<<
 *         suffix=None, prefix='dist_to_channel_mfd_work_dir',
 *         dir=os.path.dirname(target_distance_to_channel_raster_path))
*/
  __pyx_t_10 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2470, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2470, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2472
 *     tmp_work_dir = tempfile.mkdtemp(
 *         suffix=None, prefix='dist_to_channel_mfd_work_dir',
 *         dir=os.path.dirname(target_distance_to_channel_raster_path))             # <<<<<<<<<<<<<<
 *     visited_raster_path = os.path.join(tmp_work_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2472, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2472, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_11 = __pyx_t_1;
  __Pyx_INCREF(__pyx_t_11);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_v_target_distance_to_channel_raster_path};
    __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_dirname, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2472, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
  }
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_10);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_10);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 3 : 0)] = {__pyx_t_10, NULL};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2470, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_suffix, Py_None, __pyx_t_1, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 2470, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_mstate_global->__pyx_n_u_dist_to_channel_mfd_work_dir, __pyx_t_1, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 2470, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_t_7, __pyx_t_1, __pyx_callargs+1, 2) < (0)) __PYX_ERR(0, 2470, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (1-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2470, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_tmp_work_dir = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2473
 *         suffix=None, prefix='dist_to_channel_mfd_work_dir',
 *         dir=os.path.dirname(target_distance_to_channel_raster_path))
 *     visited_raster_path = os.path.join(tmp_work_dir, 'visited.tif')             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0],
*/
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2473, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2473, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_12 = __pyx_t_7;
  __Pyx_INCREF(__pyx_t_12);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_12, __pyx_v_tmp_work_dir, __pyx_mstate_global->__pyx_kp_u_visited_tif};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2473, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_visited_raster_path = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2474
 *         dir=os.path.dirname(target_distance_to_channel_raster_path))
 *     visited_raster_path = os.path.join(tmp_work_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0],
 *         visited_raster_path,
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2474, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2474, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2475
 *     visited_raster_path = os.path.join(tmp_work_dir, 'visited.tif')
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_mfd_raster_path_band[0],             # <<<<<<<<<<<<<<
 *         visited_raster_path,
 *         gdal.GDT_Byte, [0],
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2475, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);

  /* "pygeoprocessing/routing/routing.pyx":2477
 *         flow_dir_mfd_raster_path_band[0],
 *         visited_raster_path,
 *         gdal.GDT_Byte, [0],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     visited_managed_raster = ManagedRaster(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2477, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2477, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = PyList_New(1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2477, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_0);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_10, 0, __pyx_mstate_global->__pyx_int_0) != (0)) __PYX_ERR(0, 2477, __pyx_L1_error);

  /* "pygeoprocessing/routing/routing.pyx":2478
 *         visited_raster_path,
 *         gdal.GDT_Byte, [0],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 *     visited_managed_raster = ManagedRaster(
 *         visited_raster_path.encode('utf-8'), 1, True)
*/
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_7, __pyx_t_12, __pyx_v_visited_raster_path, __pyx_t_11, __pyx_t_10};
    __pyx_t_6 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2474, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_6, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 2474, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_8, (5-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_6);
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2474, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2480
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     visited_managed_raster = ManagedRaster(
 *         visited_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_mfd_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __pyx_v_visited_raster_path;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2480, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2480, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2479
 *         gdal.GDT_Byte, [0],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 *     visited_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         visited_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2479, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_visited_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2483
 * 
 *     flow_dir_mfd_managed_raster = ManagedRaster(
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2483, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_1 = __pyx_t_6;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2483, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2483, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2484
 *     flow_dir_mfd_managed_raster = ManagedRaster(
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2484, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_6); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2484, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2482
 *         visited_raster_path.encode('utf-8'), 1, True)
 * 
 *     flow_dir_mfd_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)
*/
  try {
    __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2482, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_flow_dir_mfd_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":2485
 *         flow_dir_mfd_raster_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
 * 
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2485, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2485, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2485, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2485, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2485, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_10))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_10);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_10);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_10, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_6, __pyx_t_1, __pyx_t_12};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_10, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2485, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_channel_raster = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2486
 *         flow_dir_mfd_raster_path_band[1], False)
 *     channel_raster = gdal.OpenEx(channel_raster_path_band[0], gdal.OF_RASTER)
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_mfd_raster = gdal.OpenEx(
*/
  __pyx_t_10 = __pyx_v_channel_raster;
  __Pyx_INCREF(__pyx_t_10);
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_channel_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2486, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_12};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2486, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_channel_band = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2488
 *     channel_band = channel_raster.GetRasterBand(channel_raster_path_band[1])
 * 
 *     flow_dir_mfd_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_mfd_band = flow_dir_mfd_raster.GetRasterBand(
*/
  __pyx_t_12 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2488, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2488, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2489
 * 
 *     flow_dir_mfd_raster = gdal.OpenEx(
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     flow_dir_mfd_band = flow_dir_mfd_raster.GetRasterBand(
 *         flow_dir_mfd_raster_path_band[1])
*/
  __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2489, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2489, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2489, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_12);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_12);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_12, __pyx_t_10, __pyx_t_11};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2488, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_flow_dir_mfd_raster = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2490
 *     flow_dir_mfd_raster = gdal.OpenEx(
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_mfd_band = flow_dir_mfd_raster.GetRasterBand(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[1])
 * 
*/
  __pyx_t_1 = __pyx_v_flow_dir_mfd_raster;
  __Pyx_INCREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":2491
 *         flow_dir_mfd_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_mfd_band = flow_dir_mfd_raster.GetRasterBand(
 *         flow_dir_mfd_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster weight_raster
*/
  __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2491, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_8 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_11};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2490, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_flow_dir_mfd_band = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2494
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2494, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":2496
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
*/
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2496, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_11 = __pyx_t_1;
    __Pyx_INCREF(__pyx_t_11);
    __pyx_t_8 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_mstate_global->__pyx_kp_u_utf_8};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2496, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_13 = __Pyx_PyObject_AsWritableString(__pyx_t_2); if (unlikely((!__pyx_t_13) && PyErr_Occurred())) __PYX_ERR(0, 2496, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2497
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
*/
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2497, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_15 = __Pyx_PyLong_As_int(__pyx_t_1); if (unlikely((__pyx_t_15 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2497, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2495
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:
 *         weight_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
*/
    try {
      __pyx_t_14 = ManagedRaster(__pyx_t_13, __pyx_t_15, Py_False);
    } catch(...) {
      __Pyx_CppExn2PyErr();
      __PYX_ERR(0, 2495, __pyx_L1_error)
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_weight_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_14);

    /* "pygeoprocessing/routing/routing.pyx":2498
 *             weight_raster_path_band[0].encode('utf-8'),
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2498, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2498, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2499
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2499, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_10))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_10);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_10);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_10, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_11};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_10, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2498, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_10 = __Pyx_PyObject_Dict_GetItem(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2499, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2500
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata
*/
    __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_weight_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2500, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_11 = __Pyx_PyLong_SubtractObjC(__pyx_t_2, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2500, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2499
 *             weight_raster_path_band[1], False)
 *         raw_weight_nodata = pygeoprocessing.get_raster_info(
 *             weight_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
*/
    __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_t_10, __pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2499, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __pyx_v_raw_weight_nodata = __pyx_t_2;
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2501
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 *         else:
*/
    __pyx_t_4 = (__pyx_v_raw_weight_nodata != Py_None);
    if (__pyx_t_4) {

      /* "pygeoprocessing/routing/routing.pyx":2502
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:
 *             weight_nodata = raw_weight_nodata             # <<<<<<<<<<<<<<
 *         else:
 *             weight_nodata = IMPROBABLE_FLOAT_NODATA
*/
      __pyx_t_16 = __Pyx_PyFloat_AsDouble(__pyx_v_raw_weight_nodata); if (unlikely((__pyx_t_16 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 2502, __pyx_L1_error)
      __pyx_v_weight_nodata = __pyx_t_16;

      /* "pygeoprocessing/routing/routing.pyx":2501
 *             weight_raster_path_band[0])['nodata'][
 *                 weight_raster_path_band[1]-1]
 *         if raw_weight_nodata is not None:             # <<<<<<<<<<<<<<
 *             weight_nodata = raw_weight_nodata
 *         else:
*/
      goto __pyx_L10;
    }

    /* "pygeoprocessing/routing/routing.pyx":2504
 *             weight_nodata = raw_weight_nodata
 *         else:
 *             weight_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
*/
    /*else*/ {
      __pyx_v_weight_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
    }
    __pyx_L10:;

    /* "pygeoprocessing/routing/routing.pyx":2494
 * 
 *     cdef ManagedRaster weight_raster
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster = ManagedRaster(
 *             weight_raster_path_band[0].encode('utf-8'),
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2506
 *             weight_nodata = IMPROBABLE_FLOAT_NODATA
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
*/
  __pyx_t_11 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2506, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2506, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2507
 * 
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_mfd_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']
 * 
*/
  __pyx_t_10 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2507, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_11);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_11);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_11, __pyx_t_10};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2506, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_v_flow_dir_raster_info = __pyx_t_2;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2508
 *     flow_dir_raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_mfd_raster_path_band[0])
 *     raster_x_size, raster_y_size = flow_dir_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     # this outer loop searches for undefined channels
*/
  __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2508, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
    PyObject* sequence = __pyx_t_2;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 2508, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_1);
      __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_10);
    } else {
      __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2508, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_1);
      __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2508, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_10);
    }
    #else
    __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2508, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_10 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2508, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    #endif
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_11 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2508, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11);
    index = 0; __pyx_t_1 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_1)) goto __pyx_L11_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_1);
    index = 1; __pyx_t_10 = __pyx_t_17(__pyx_t_11); if (unlikely(!__pyx_t_10)) goto __pyx_L11_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_10);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_11), 2) < (0)) __PYX_ERR(0, 2508, __pyx_L1_error)
    __pyx_t_17 = NULL;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    goto __pyx_L12_unpacking_done;
    __pyx_L11_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __pyx_t_17 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 2508, __pyx_L1_error)
    __pyx_L12_unpacking_done:;
  }
  __pyx_t_18 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_18 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2508, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_10); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2508, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_v_raster_x_size = __pyx_t_18;
  __pyx_v_raster_y_size = __pyx_t_19;

  /* "pygeoprocessing/routing/routing.pyx":2511
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_10 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2511, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2511, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2512
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             channel_raster_path_band, offset_only=True, largest_block=0):             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_11);
    assert(__pyx_t_10);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
    __Pyx_INCREF(__pyx_t_10);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_10, __pyx_v_channel_raster_path_band};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2511, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_1, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2511, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_1, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 2511, __pyx_L1_error)
    __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2511, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }

  /* "pygeoprocessing/routing/routing.pyx":2511
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_11 = __pyx_t_2; __Pyx_INCREF(__pyx_t_11);
    __pyx_t_3 = 0;
    __pyx_t_20 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_11 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2511, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
    __pyx_t_20 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11); if (unlikely(!__pyx_t_20)) __PYX_ERR(0, 2511, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_20)) {
      if (likely(PyList_CheckExact(__pyx_t_11))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_11);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2511, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_11, __pyx_t_3, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_3;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_11);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2511, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_11, __pyx_t_3));
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_11, __pyx_t_3);
        #endif
        ++__pyx_t_3;
      }
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2511, __pyx_L1_error)
    } else {
      __pyx_t_2 = __pyx_t_20(__pyx_t_11);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 2511, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2513
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2513, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2513, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_win_xsize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2514
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2514, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2514, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_win_ysize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2515
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2515, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2515, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_xoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2516
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2516, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2516, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_v_yoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2518
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_4 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_4) {

      /* "pygeoprocessing/routing/routing.pyx":2519
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0 * current_pixel / <float>(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":2520
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))
*/
      __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

      /* "pygeoprocessing/routing/routing.pyx":2521
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      __pyx_t_1 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2521, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2521, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __pyx_t_16 = (100.0 * __pyx_v_current_pixel);

      /* "pygeoprocessing/routing/routing.pyx":2522
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                 raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 * 
 *         # make a buffer big enough to capture block and boundaries around it
*/
      __pyx_t_21 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

      /* "pygeoprocessing/routing/routing.pyx":2521
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                 raster_x_size * raster_y_size))
 * 
*/
      if (unlikely(__pyx_t_21 == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 2521, __pyx_L1_error)
      }
      __pyx_t_10 = PyFloat_FromDouble((__pyx_t_16 / ((double)__pyx_t_21))); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2521, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __pyx_t_8 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_12))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_12);
        assert(__pyx_t_1);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
        __pyx_t_8 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_Dist_to_channel_MFD_1f_complete, __pyx_t_10};
        __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (3-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2521, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":2518
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":2525
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    __pyx_t_12 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2525, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2525, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2526
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array = numpy.empty(
*/
    __pyx_t_10 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_6 = __Pyx_PyLong_AddObjC(__pyx_t_10, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __pyx_t_10 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_7 = __Pyx_PyLong_AddObjC(__pyx_t_10, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    __pyx_t_10 = PyTuple_New(2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2526, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_GIVEREF(__pyx_t_6);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 0, __pyx_t_6) != (0)) __PYX_ERR(0, 2526, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_7);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_10, 1, __pyx_t_7) != (0)) __PYX_ERR(0, 2526, __pyx_L1_error);
    __pyx_t_6 = 0;
    __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2527
 *         channel_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)             # <<<<<<<<<<<<<<
 *         flow_dir_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
*/
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2527, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_uint8); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2527, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_12);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_12);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_12, __pyx_t_10};
      __pyx_t_7 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2525, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_6, __pyx_t_7, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2525, __pyx_L1_error)
      __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_7);
      __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2525, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2525
 * 
 *         # make a buffer big enough to capture block and boundaries around it
 *         channel_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
*/
    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2525, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
      __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_2), &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_15 < 0)) {
        PyErr_Fetch(&__pyx_t_22, &__pyx_t_23, &__pyx_t_24);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_channel_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_uint8_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_22); Py_XDECREF(__pyx_t_23); Py_XDECREF(__pyx_t_24);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_22, __pyx_t_23, __pyx_t_24);
        }
        __pyx_t_22 = __pyx_t_23 = __pyx_t_24 = 0;
      }
      __pyx_pybuffernd_channel_buffer_array.diminfo[0].strides = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_channel_buffer_array.diminfo[0].shape = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_channel_buffer_array.diminfo[1].strides = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_channel_buffer_array.diminfo[1].shape = __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_15 < 0))) __PYX_ERR(0, 2525, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_channel_buffer_array, ((PyArrayObject *)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2528
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2528, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2528, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2529
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),             # <<<<<<<<<<<<<<
 *             dtype=numpy.int32)
 *         channel_buffer_array[:] = 0  # 0 means no channel
*/
    __pyx_t_7 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_10 = __Pyx_PyLong_AddObjC(__pyx_t_7, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_7 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_12 = __Pyx_PyLong_AddObjC(__pyx_t_7, __pyx_mstate_global->__pyx_int_2, 2, 0, 0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2529, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_GIVEREF(__pyx_t_10);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_10) != (0)) __PYX_ERR(0, 2529, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_12);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_12) != (0)) __PYX_ERR(0, 2529, __pyx_L1_error);
    __pyx_t_10 = 0;
    __pyx_t_12 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2530
 *         flow_dir_buffer_array = numpy.empty(
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)             # <<<<<<<<<<<<<<
 *         channel_buffer_array[:] = 0  # 0 means no channel
 *         flow_dir_buffer_array[:] = 0  # 0 means no flow
*/
    __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2530, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_6))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_6);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_1, __pyx_t_7};
      __pyx_t_12 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2528, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_10, __pyx_t_12, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2528, __pyx_L1_error)
      __pyx_t_2 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_12);
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2528, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2528
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.uint8)
 *         flow_dir_buffer_array = numpy.empty(             # <<<<<<<<<<<<<<
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
*/
    if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2528, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
      __pyx_t_15 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_2), &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_15 < 0)) {
        PyErr_Fetch(&__pyx_t_24, &__pyx_t_23, &__pyx_t_22);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer, (PyObject*)__pyx_v_flow_dir_buffer_array, &__Pyx_TypeInfo_nn___pyx_t_5numpy_int32_t, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_24); Py_XDECREF(__pyx_t_23); Py_XDECREF(__pyx_t_22);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_24, __pyx_t_23, __pyx_t_22);
        }
        __pyx_t_24 = __pyx_t_23 = __pyx_t_22 = 0;
      }
      __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].strides = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].shape = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].strides = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].shape = __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_15 < 0))) __PYX_ERR(0, 2528, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_flow_dir_buffer_array, ((PyArrayObject *)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2531
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.int32)
 *         channel_buffer_array[:] = 0  # 0 means no channel             # <<<<<<<<<<<<<<
 *         flow_dir_buffer_array[:] = 0  # 0 means no flow
 * 
*/
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_channel_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_0) < 0))) __PYX_ERR(0, 2531, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2532
 *             dtype=numpy.int32)
 *         channel_buffer_array[:] = 0  # 0 means no channel
 *         flow_dir_buffer_array[:] = 0  # 0 means no flow             # <<<<<<<<<<<<<<
 * 
 *         # check if we can widen the border to include real data from the
*/
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_buffer_array), __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_0) < 0))) __PYX_ERR(0, 2532, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2536
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
*/
    __pyx_t_6 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_generate_read_bounds); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2536, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);

    /* "pygeoprocessing/routing/routing.pyx":2537
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)             # <<<<<<<<<<<<<<
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)
*/
    __pyx_t_10 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_x_size); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2537, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __pyx_t_7 = __Pyx_PyLong_From_unsigned_int(__pyx_v_raster_y_size); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2537, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_8 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_12))) {
      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_12);
      assert(__pyx_t_6);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
      __Pyx_INCREF(__pyx_t_6);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
      __pyx_t_8 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_6, __pyx_v_offset_dict, __pyx_t_10, __pyx_t_7};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (4-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2536, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_12);
        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_7);
      } else {
        __pyx_t_12 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_12);
        __pyx_t_7 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_7);
      }
      #else
      __pyx_t_12 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      __pyx_t_7 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_10 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_10);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_10);
      index = 0; __pyx_t_12 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_12)) goto __pyx_L16_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_12);
      index = 1; __pyx_t_7 = __pyx_t_17(__pyx_t_10); if (unlikely(!__pyx_t_7)) goto __pyx_L16_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_7);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_10), 2) < (0)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      goto __pyx_L17_unpacking_done;
      __pyx_L16_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2536, __pyx_L1_error)
      __pyx_L17_unpacking_done:;
    }

    /* "pygeoprocessing/routing/routing.pyx":2536
 *         # check if we can widen the border to include real data from the
 *         # raster
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(             # <<<<<<<<<<<<<<
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
*/
    if ((likely(PyTuple_CheckExact(__pyx_t_12))) || (PyList_CheckExact(__pyx_t_12))) {
      PyObject* sequence = __pyx_t_12;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 4)) {
        if (size > 4) __Pyx_RaiseTooManyValuesError(4);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 2536, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_10);
        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_6);
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_25 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_25);
      } else {
        __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_10);
        __pyx_t_6 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_6);
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_25 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2536, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_25);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_6,&__pyx_t_1,&__pyx_t_25};
        for (i=0; i < 4; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 2536, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[4] = {&__pyx_t_10,&__pyx_t_6,&__pyx_t_1,&__pyx_t_25};
      __pyx_t_26 = PyObject_GetIter(__pyx_t_12); if (unlikely(!__pyx_t_26)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_26);
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_26);
      for (index=0; index < 4; index++) {
        PyObject* item = __pyx_t_17(__pyx_t_26); if (unlikely(!item)) goto __pyx_L18_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_17(__pyx_t_26), 4) < (0)) __PYX_ERR(0, 2536, __pyx_L1_error)
      __pyx_t_17 = NULL;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      goto __pyx_L19_unpacking_done;
      __pyx_L18_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_26); __pyx_t_26 = 0;
      __pyx_t_17 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 2536, __pyx_L1_error)
      __pyx_L19_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_xa, __pyx_t_10);
    __pyx_t_10 = 0;
    __Pyx_XDECREF_SET(__pyx_v_xb, __pyx_t_6);
    __pyx_t_6 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ya, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_XDECREF_SET(__pyx_v_yb, __pyx_t_25);
    __pyx_t_25 = 0;
    __Pyx_XDECREF_SET(__pyx_v_modified_offset_dict, __pyx_t_7);
    __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2538
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_channel_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);

    /* "pygeoprocessing/routing/routing.pyx":2539
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)             # <<<<<<<<<<<<<<
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 2539, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_25 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2539, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    } else {
      __pyx_t_25 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2538, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_25);
    }

    /* "pygeoprocessing/routing/routing.pyx":2538
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_25); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_7 = __pyx_t_1;
    __Pyx_INCREF(__pyx_t_7);

    /* "pygeoprocessing/routing/routing.pyx":2539
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int8)             # <<<<<<<<<<<<<<
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(
*/
    __Pyx_GetModuleGlobalName(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2539, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_25);
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_25, __pyx_mstate_global->__pyx_n_u_int8); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2539, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
    __pyx_t_8 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_12};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2539, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2538
 *         (xa, xb, ya, yb), modified_offset_dict = _generate_read_bounds(
 *             offset_dict, raster_x_size, raster_y_size)
 *         channel_buffer_array[ya:yb, xa:xb] = channel_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int8)
 * 
*/
    __pyx_t_1 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_12 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_GIVEREF(__pyx_t_1);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 2538, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_12);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_12) != (0)) __PYX_ERR(0, 2538, __pyx_L1_error);
    __pyx_t_1 = 0;
    __pyx_t_12 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_channel_buffer_array), __pyx_t_7, __pyx_t_2) < 0))) __PYX_ERR(0, 2538, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2541
 *             **modified_offset_dict).astype(numpy.int8)
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_v_flow_dir_mfd_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);

    /* "pygeoprocessing/routing/routing.pyx":2542
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    if (unlikely(__pyx_v_modified_offset_dict == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 2542, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_modified_offset_dict))) {
      __pyx_t_1 = PyDict_Copy(__pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2542, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    } else {
      __pyx_t_1 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_modified_offset_dict); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2541, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }

    /* "pygeoprocessing/routing/routing.pyx":2541
 *             **modified_offset_dict).astype(numpy.int8)
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_25 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_1); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_25);
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_7 = __pyx_t_25;
    __Pyx_INCREF(__pyx_t_7);

    /* "pygeoprocessing/routing/routing.pyx":2542
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(
 *             **modified_offset_dict).astype(numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         # ensure these are set for the complier
*/
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2542, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2542, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_8 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_12};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_25); __pyx_t_25 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2542, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":2541
 *             **modified_offset_dict).astype(numpy.int8)
 * 
 *         flow_dir_buffer_array[ya:yb, xa:xb] = flow_dir_mfd_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *             **modified_offset_dict).astype(numpy.int32)
 * 
*/
    __pyx_t_25 = PySlice_New(__pyx_v_ya, __pyx_v_yb, Py_None); if (unlikely(!__pyx_t_25)) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_25);
    __pyx_t_12 = PySlice_New(__pyx_v_xa, __pyx_v_xb, Py_None); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_GIVEREF(__pyx_t_25);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_25) != (0)) __PYX_ERR(0, 2541, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_12);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_12) != (0)) __PYX_ERR(0, 2541, __pyx_L1_error);
    __pyx_t_25 = 0;
    __pyx_t_12 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_buffer_array), __pyx_t_7, __pyx_t_2) < 0))) __PYX_ERR(0, 2541, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2545
 * 
 *         # ensure these are set for the complier
 *         xi_n = -1             # <<<<<<<<<<<<<<
 *         yi_n = -1
 * 
*/
    __pyx_v_xi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2546
 *         # ensure these are set for the complier
 *         xi_n = -1
 *         yi_n = -1             # <<<<<<<<<<<<<<
 * 
 *         # search block for a pixel that has undefined distance to channel
*/
    __pyx_v_yi_n = -1;

    /* "pygeoprocessing/routing/routing.pyx":2549
 * 
 *         # search block for a pixel that has undefined distance to channel
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 xi_root = xi+xoff-1
*/
    __pyx_t_27 = (__pyx_v_win_ysize + 1);
    __pyx_t_28 = __pyx_t_27;
    for (__pyx_t_19 = 1; __pyx_t_19 < __pyx_t_28; __pyx_t_19+=1) {
      __pyx_v_yi = __pyx_t_19;

      /* "pygeoprocessing/routing/routing.pyx":2550
 *         # search block for a pixel that has undefined distance to channel
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 xi_root = xi+xoff-1
 *                 yi_root = yi+yoff-1
*/
      __pyx_t_29 = (__pyx_v_win_xsize + 1);
      __pyx_t_30 = __pyx_t_29;
      for (__pyx_t_18 = 1; __pyx_t_18 < __pyx_t_30; __pyx_t_18+=1) {
        __pyx_v_xi = __pyx_t_18;

        /* "pygeoprocessing/routing/routing.pyx":2551
 *         for yi in range(1, win_ysize+1):
 *             for xi in range(1, win_xsize+1):
 *                 xi_root = xi+xoff-1             # <<<<<<<<<<<<<<
 *                 yi_root = yi+yoff-1
 * 
*/
        __pyx_v_xi_root = ((__pyx_v_xi + __pyx_v_xoff) - 1);

        /* "pygeoprocessing/routing/routing.pyx":2552
 *             for xi in range(1, win_xsize+1):
 *                 xi_root = xi+xoff-1
 *                 yi_root = yi+yoff-1             # <<<<<<<<<<<<<<
 * 
 *                 # d_i is 0 if pixel i is a stream
*/
        __pyx_v_yi_root = ((__pyx_v_yi + __pyx_v_yoff) - 1);

        /* "pygeoprocessing/routing/routing.pyx":2555
 * 
 *                 # d_i is 0 if pixel i is a stream
 *                 if channel_buffer_array[yi, xi] == 1:             # <<<<<<<<<<<<<<
 *                     distance_to_channel_managed_raster.set(
 *                         xi_root, yi_root, 0)
*/
        __pyx_t_8 = __pyx_v_yi;
        __pyx_t_31 = __pyx_v_xi;
        __pyx_t_15 = -1;
        if (unlikely(__pyx_t_8 >= (size_t)__pyx_pybuffernd_channel_buffer_array.diminfo[0].shape)) __pyx_t_15 = 0;
        if (unlikely(__pyx_t_31 >= (size_t)__pyx_pybuffernd_channel_buffer_array.diminfo[1].shape)) __pyx_t_15 = 1;
        if (unlikely(__pyx_t_15 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_15);
          __PYX_ERR(0, 2555, __pyx_L1_error)
        }
        __pyx_t_4 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_uint8_t *, __pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_channel_buffer_array.diminfo[0].strides, __pyx_t_31, __pyx_pybuffernd_channel_buffer_array.diminfo[1].strides)) == 1);
        if (__pyx_t_4) {

          /* "pygeoprocessing/routing/routing.pyx":2556
 *                 # d_i is 0 if pixel i is a stream
 *                 if channel_buffer_array[yi, xi] == 1:
 *                     distance_to_channel_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         xi_root, yi_root, 0)
 *                     continue
*/
          __pyx_v_distance_to_channel_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 0.0);

          /* "pygeoprocessing/routing/routing.pyx":2558
 *                     distance_to_channel_managed_raster.set(
 *                         xi_root, yi_root, 0)
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 if flow_dir_buffer_array[yi, xi] == 0:
*/
          goto __pyx_L22_continue;

          /* "pygeoprocessing/routing/routing.pyx":2555
 * 
 *                 # d_i is 0 if pixel i is a stream
 *                 if channel_buffer_array[yi, xi] == 1:             # <<<<<<<<<<<<<<
 *                     distance_to_channel_managed_raster.set(
 *                         xi_root, yi_root, 0)
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2560
 *                     continue
 * 
 *                 if flow_dir_buffer_array[yi, xi] == 0:             # <<<<<<<<<<<<<<
 *                     # nodata flow, so we skip
 *                     continue
*/
        __pyx_t_31 = __pyx_v_yi;
        __pyx_t_8 = __pyx_v_xi;
        __pyx_t_15 = -1;
        if (unlikely(__pyx_t_31 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].shape)) __pyx_t_15 = 0;
        if (unlikely(__pyx_t_8 >= (size_t)__pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].shape)) __pyx_t_15 = 1;
        if (unlikely(__pyx_t_15 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_15);
          __PYX_ERR(0, 2560, __pyx_L1_error)
        }
        __pyx_t_4 = ((*__Pyx_BufPtrStrided2d(__pyx_t_5numpy_int32_t *, __pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer.buf, __pyx_t_31, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[0].strides, __pyx_t_8, __pyx_pybuffernd_flow_dir_buffer_array.diminfo[1].strides)) == 0);
        if (__pyx_t_4) {

          /* "pygeoprocessing/routing/routing.pyx":2562
 *                 if flow_dir_buffer_array[yi, xi] == 0:
 *                     # nodata flow, so we skip
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # the algorithm starts from an arbitrary pixel
*/
          goto __pyx_L22_continue;

          /* "pygeoprocessing/routing/routing.pyx":2560
 *                     continue
 * 
 *                 if flow_dir_buffer_array[yi, xi] == 0:             # <<<<<<<<<<<<<<
 *                     # nodata flow, so we skip
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2567
 *                 # it pushes its downstream neighbors to a stack, working depth-first
 *                 # until reaching either a stream or a raster edge
 *                 if visited_managed_raster.get(xi_root, yi_root) == 0:             # <<<<<<<<<<<<<<
 *                     visited_managed_raster.set(xi_root, yi_root, 1)
 *                     distance_to_channel_stack.push(
*/
        __pyx_t_4 = (__pyx_v_visited_managed_raster.get(__pyx_v_xi_root, __pyx_v_yi_root) == 0.0);
        if (__pyx_t_4) {

          /* "pygeoprocessing/routing/routing.pyx":2568
 *                 # until reaching either a stream or a raster edge
 *                 if visited_managed_raster.get(xi_root, yi_root) == 0:
 *                     visited_managed_raster.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 *                     distance_to_channel_stack.push(
 *                         MFDFlowPixelType(xi_root, yi_root, 0, 0, 0))
*/
          __pyx_v_visited_managed_raster.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

          /* "pygeoprocessing/routing/routing.pyx":2570
 *                     visited_managed_raster.set(xi_root, yi_root, 1)
 *                     distance_to_channel_stack.push(
 *                         MFDFlowPixelType(xi_root, yi_root, 0, 0, 0))             # <<<<<<<<<<<<<<
 * 
 *                 while not distance_to_channel_stack.empty():
*/
          __pyx_t_32.xi = __pyx_v_xi_root;
          __pyx_t_32.yi = __pyx_v_yi_root;
          __pyx_t_32.last_flow_dir = 0;
          __pyx_t_32.sum_of_weighted_distances = 0.0;
          __pyx_t_32.sum_of_weights = 0.0;

          /* "pygeoprocessing/routing/routing.pyx":2569
 *                 if visited_managed_raster.get(xi_root, yi_root) == 0:
 *                     visited_managed_raster.set(xi_root, yi_root, 1)
 *                     distance_to_channel_stack.push(             # <<<<<<<<<<<<<<
 *                         MFDFlowPixelType(xi_root, yi_root, 0, 0, 0))
 * 
*/
          try {
            __pyx_v_distance_to_channel_stack.push(__pyx_t_32);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 2569, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":2567
 *                 # it pushes its downstream neighbors to a stack, working depth-first
 *                 # until reaching either a stream or a raster edge
 *                 if visited_managed_raster.get(xi_root, yi_root) == 0:             # <<<<<<<<<<<<<<
 *                     visited_managed_raster.set(xi_root, yi_root, 1)
 *                     distance_to_channel_stack.push(
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2572
 *                         MFDFlowPixelType(xi_root, yi_root, 0, 0, 0))
 * 
 *                 while not distance_to_channel_stack.empty():             # <<<<<<<<<<<<<<
 *                     pixel = distance_to_channel_stack.top()
 *                     distance_to_channel_stack.pop()
*/
        while (1) {
          __pyx_t_4 = (!__pyx_v_distance_to_channel_stack.empty());
          if (!__pyx_t_4) break;

          /* "pygeoprocessing/routing/routing.pyx":2573
 * 
 *                 while not distance_to_channel_stack.empty():
 *                     pixel = distance_to_channel_stack.top()             # <<<<<<<<<<<<<<
 *                     distance_to_channel_stack.pop()
 *                     is_a_channel = (
*/
          __pyx_v_pixel = __pyx_v_distance_to_channel_stack.top();

          /* "pygeoprocessing/routing/routing.pyx":2574
 *                 while not distance_to_channel_stack.empty():
 *                     pixel = distance_to_channel_stack.top()
 *                     distance_to_channel_stack.pop()             # <<<<<<<<<<<<<<
 *                     is_a_channel = (
 *                         channel_managed_raster.get(pixel.xi, pixel.yi) == 1)
*/
          __pyx_v_distance_to_channel_stack.pop();

          /* "pygeoprocessing/routing/routing.pyx":2576
 *                     distance_to_channel_stack.pop()
 *                     is_a_channel = (
 *                         channel_managed_raster.get(pixel.xi, pixel.yi) == 1)             # <<<<<<<<<<<<<<
 *                     if is_a_channel:
 *                         distance_to_channel_managed_raster.set(
*/
          __pyx_v_is_a_channel = (__pyx_v_channel_managed_raster.get(__pyx_v_pixel.xi, __pyx_v_pixel.yi) == 1.0);

          /* "pygeoprocessing/routing/routing.pyx":2577
 *                     is_a_channel = (
 *                         channel_managed_raster.get(pixel.xi, pixel.yi) == 1)
 *                     if is_a_channel:             # <<<<<<<<<<<<<<
 *                         distance_to_channel_managed_raster.set(
 *                             pixel.xi, pixel.yi, 0)
*/
          __pyx_t_4 = (__pyx_v_is_a_channel != 0);
          if (__pyx_t_4) {

            /* "pygeoprocessing/routing/routing.pyx":2578
 *                         channel_managed_raster.get(pixel.xi, pixel.yi) == 1)
 *                     if is_a_channel:
 *                         distance_to_channel_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             pixel.xi, pixel.yi, 0)
 *                         continue
*/
            __pyx_v_distance_to_channel_managed_raster.set(__pyx_v_pixel.xi, __pyx_v_pixel.yi, 0.0);

            /* "pygeoprocessing/routing/routing.pyx":2580
 *                         distance_to_channel_managed_raster.set(
 *                             pixel.xi, pixel.yi, 0)
 *                         continue             # <<<<<<<<<<<<<<
 * 
 *                     mfd_value = (
*/
            goto __pyx_L27_continue;

            /* "pygeoprocessing/routing/routing.pyx":2577
 *                     is_a_channel = (
 *                         channel_managed_raster.get(pixel.xi, pixel.yi) == 1)
 *                     if is_a_channel:             # <<<<<<<<<<<<<<
 *                         distance_to_channel_managed_raster.set(
 *                             pixel.xi, pixel.yi, 0)
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2583
 * 
 *                     mfd_value = (
 *                         <int>flow_dir_mfd_managed_raster.get(             # <<<<<<<<<<<<<<
 *                             pixel.xi, pixel.yi))
 * 
*/
          __pyx_v_mfd_value = ((int)__pyx_v_flow_dir_mfd_managed_raster.get(__pyx_v_pixel.xi, __pyx_v_pixel.yi));

          /* "pygeoprocessing/routing/routing.pyx":2589
 *                     # the stack because not all its downstream neighbors are
 *                     # visited yet
 *                     preempted = 0             # <<<<<<<<<<<<<<
 * 
 *                     # iterate over neighbors
*/
          __pyx_v_preempted = 0;

          /* "pygeoprocessing/routing/routing.pyx":2597
 *                     # the neighbor back onto the stack and exit the loop
 *                     # if all have been visited, we can calculate d_i
 *                     for i_n in range(pixel.last_flow_dir, 8):             # <<<<<<<<<<<<<<
 *                         flow_dir_weight = 0xF & (mfd_value >> (i_n * 4))
 *                         if flow_dir_weight == 0:
*/
          for (__pyx_t_33 = __pyx_v_pixel.last_flow_dir; __pyx_t_33 < 8; __pyx_t_33+=1) {
            __pyx_v_i_n = __pyx_t_33;

            /* "pygeoprocessing/routing/routing.pyx":2598
 *                     # if all have been visited, we can calculate d_i
 *                     for i_n in range(pixel.last_flow_dir, 8):
 *                         flow_dir_weight = 0xF & (mfd_value >> (i_n * 4))             # <<<<<<<<<<<<<<
 *                         if flow_dir_weight == 0:
 *                             continue
*/
            __pyx_v_flow_dir_weight = (0xF & (__pyx_v_mfd_value >> (__pyx_v_i_n * 4)));

            /* "pygeoprocessing/routing/routing.pyx":2599
 *                     for i_n in range(pixel.last_flow_dir, 8):
 *                         flow_dir_weight = 0xF & (mfd_value >> (i_n * 4))
 *                         if flow_dir_weight == 0:             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_4 = (__pyx_v_flow_dir_weight == 0);
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2600
 *                         flow_dir_weight = 0xF & (mfd_value >> (i_n * 4))
 *                         if flow_dir_weight == 0:
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]
*/
              goto __pyx_L30_continue;

              /* "pygeoprocessing/routing/routing.pyx":2599
 *                     for i_n in range(pixel.last_flow_dir, 8):
 *                         flow_dir_weight = 0xF & (mfd_value >> (i_n * 4))
 *                         if flow_dir_weight == 0:             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2602
 *                             continue
 * 
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
*/
            __pyx_v_xi_n = (__pyx_v_pixel.xi + (COL_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2603
 * 
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
*/
            __pyx_v_yi_n = (__pyx_v_pixel.yi + (ROW_OFFSETS[__pyx_v_i_n]));

            /* "pygeoprocessing/routing/routing.pyx":2604
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            __pyx_t_9 = (__pyx_v_xi_n < 0);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L34_bool_binop_done;
            }
            __pyx_t_9 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L34_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":2605
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 * 
*/
            __pyx_t_9 = (__pyx_v_yi_n < 0);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_4 = __pyx_t_9;
              goto __pyx_L34_bool_binop_done;
            }
            __pyx_t_9 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
            __pyx_t_4 = __pyx_t_9;
            __pyx_L34_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":2604
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2606
 *                         if (xi_n < 0 or xi_n >= raster_x_size or
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         # if the pixel has a neighbor that hasn't been visited yet,
*/
              goto __pyx_L30_continue;

              /* "pygeoprocessing/routing/routing.pyx":2604
 *                         xi_n = pixel.xi+COL_OFFSETS[i_n]
 *                         yi_n = pixel.yi+ROW_OFFSETS[i_n]
 *                         if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_n < 0 or yi_n >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2612
 *                         # onto the stack, and exit the loop.
 *                         # we won't calculate d_i until d_n is defined for every n
 *                         if visited_managed_raster.get(xi_n, yi_n) == 0:             # <<<<<<<<<<<<<<
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             preempted = 1
*/
            __pyx_t_4 = (__pyx_v_visited_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n) == 0.0);
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2613
 *                         # we won't calculate d_i until d_n is defined for every n
 *                         if visited_managed_raster.get(xi_n, yi_n) == 0:
 *                             visited_managed_raster.set(xi_n, yi_n, 1)             # <<<<<<<<<<<<<<
 *                             preempted = 1
 *                             pixel.last_flow_dir = i_n
*/
              __pyx_v_visited_managed_raster.set(__pyx_v_xi_n, __pyx_v_yi_n, 1.0);

              /* "pygeoprocessing/routing/routing.pyx":2614
 *                         if visited_managed_raster.get(xi_n, yi_n) == 0:
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             preempted = 1             # <<<<<<<<<<<<<<
 *                             pixel.last_flow_dir = i_n
 *                             distance_to_channel_stack.push(pixel)
*/
              __pyx_v_preempted = 1;

              /* "pygeoprocessing/routing/routing.pyx":2615
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             preempted = 1
 *                             pixel.last_flow_dir = i_n             # <<<<<<<<<<<<<<
 *                             distance_to_channel_stack.push(pixel)
 *                             distance_to_channel_stack.push(
*/
              __pyx_v_pixel.last_flow_dir = __pyx_v_i_n;

              /* "pygeoprocessing/routing/routing.pyx":2616
 *                             preempted = 1
 *                             pixel.last_flow_dir = i_n
 *                             distance_to_channel_stack.push(pixel)             # <<<<<<<<<<<<<<
 *                             distance_to_channel_stack.push(
 *                                 MFDFlowPixelType(xi_n, yi_n, 0, 0, 0))
*/
              try {
                __pyx_v_distance_to_channel_stack.push(__pyx_v_pixel);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 2616, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":2618
 *                             distance_to_channel_stack.push(pixel)
 *                             distance_to_channel_stack.push(
 *                                 MFDFlowPixelType(xi_n, yi_n, 0, 0, 0))             # <<<<<<<<<<<<<<
 *                             break
 * 
*/
              __pyx_t_32.xi = __pyx_v_xi_n;
              __pyx_t_32.yi = __pyx_v_yi_n;
              __pyx_t_32.last_flow_dir = 0;
              __pyx_t_32.sum_of_weighted_distances = 0.0;
              __pyx_t_32.sum_of_weights = 0.0;

              /* "pygeoprocessing/routing/routing.pyx":2617
 *                             pixel.last_flow_dir = i_n
 *                             distance_to_channel_stack.push(pixel)
 *                             distance_to_channel_stack.push(             # <<<<<<<<<<<<<<
 *                                 MFDFlowPixelType(xi_n, yi_n, 0, 0, 0))
 *                             break
*/
              try {
                __pyx_v_distance_to_channel_stack.push(__pyx_t_32);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 2617, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":2619
 *                             distance_to_channel_stack.push(
 *                                 MFDFlowPixelType(xi_n, yi_n, 0, 0, 0))
 *                             break             # <<<<<<<<<<<<<<
 * 
 *                         # at this point, the pixel's downstream neighbor n
*/
              goto __pyx_L31_break;

              /* "pygeoprocessing/routing/routing.pyx":2612
 *                         # onto the stack, and exit the loop.
 *                         # we won't calculate d_i until d_n is defined for every n
 *                         if visited_managed_raster.get(xi_n, yi_n) == 0:             # <<<<<<<<<<<<<<
 *                             visited_managed_raster.set(xi_n, yi_n, 1)
 *                             preempted = 1
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2623
 *                         # at this point, the pixel's downstream neighbor n
 *                         # distance to channel (d_n) will already be calculated
 *                         n_distance = distance_to_channel_managed_raster.get(             # <<<<<<<<<<<<<<
 *                             xi_n, yi_n)
 * 
*/
            __pyx_v_n_distance = __pyx_v_distance_to_channel_managed_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

            /* "pygeoprocessing/routing/routing.pyx":2629
 *                         # never reaches a stream. we don't count this towards
 *                         # the average.
 *                         if n_distance == distance_nodata:             # <<<<<<<<<<<<<<
 *                             # a channel was never found
 *                             continue
*/
            __pyx_t_4 = (__pyx_v_n_distance == __pyx_v_distance_nodata);
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2631
 *                         if n_distance == distance_nodata:
 *                             # a channel was never found
 *                             continue             # <<<<<<<<<<<<<<
 * 
 *                         # if a weight is passed we use it directly and do
*/
              goto __pyx_L30_continue;

              /* "pygeoprocessing/routing/routing.pyx":2629
 *                         # never reaches a stream. we don't count this towards
 *                         # the average.
 *                         if n_distance == distance_nodata:             # <<<<<<<<<<<<<<
 *                             # a channel was never found
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2638
 *                         # then "distance" is being calculated and we account
 *                         # for diagonal distance.
 *                         if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                             weight_val = weight_raster.get(xi_n, yi_n)
 *                             if is_close(weight_val, weight_nodata):
*/
            __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2638, __pyx_L1_error)
            if (__pyx_t_4) {

              /* "pygeoprocessing/routing/routing.pyx":2639
 *                         # for diagonal distance.
 *                         if weight_raster_path_band:
 *                             weight_val = weight_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                             if is_close(weight_val, weight_nodata):
 *                                 weight_val = 0.0
*/
              __pyx_v_weight_val = __pyx_v_weight_raster.get(__pyx_v_xi_n, __pyx_v_yi_n);

              /* "pygeoprocessing/routing/routing.pyx":2640
 *                         if weight_raster_path_band:
 *                             weight_val = weight_raster.get(xi_n, yi_n)
 *                             if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                 weight_val = 0.0
 *                         else:
*/
              __pyx_t_4 = is_close(__pyx_v_weight_val, __pyx_v_weight_nodata);
              if (__pyx_t_4) {

                /* "pygeoprocessing/routing/routing.pyx":2641
 *                             weight_val = weight_raster.get(xi_n, yi_n)
 *                             if is_close(weight_val, weight_nodata):
 *                                 weight_val = 0.0             # <<<<<<<<<<<<<<
 *                         else:
 *                             # neighbors 0, 2, 4, 6 are lateral
*/
                __pyx_v_weight_val = 0.0;

                /* "pygeoprocessing/routing/routing.pyx":2640
 *                         if weight_raster_path_band:
 *                             weight_val = weight_raster.get(xi_n, yi_n)
 *                             if is_close(weight_val, weight_nodata):             # <<<<<<<<<<<<<<
 *                                 weight_val = 0.0
 *                         else:
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":2638
 *                         # then "distance" is being calculated and we account
 *                         # for diagonal distance.
 *                         if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *                             weight_val = weight_raster.get(xi_n, yi_n)
 *                             if is_close(weight_val, weight_nodata):
*/
              goto __pyx_L40;
            }

            /* "pygeoprocessing/routing/routing.pyx":2645
 *                             # neighbors 0, 2, 4, 6 are lateral
 *                             # 1, 3, 5, 7 are diagonal
 *                             weight_val = (SQRT2 if i_n % 2 else 1)             # <<<<<<<<<<<<<<
 * 
 *                         # for only those neighbors which do drain to a stream,
*/
            /*else*/ {
              __pyx_t_4 = (__Pyx_mod_long(__pyx_v_i_n, 2, 1) != 0);
              if (__pyx_t_4) {
                __pyx_t_16 = __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2;
              } else {
                __pyx_t_16 = 1.0;
              }
              __pyx_v_weight_val = __pyx_t_16;
            }
            __pyx_L40:;

            /* "pygeoprocessing/routing/routing.pyx":2649
 *                         # for only those neighbors which do drain to a stream,
 *                         # sum up the MFD values (the denominator in the average)
 *                         pixel.sum_of_weights += flow_dir_weight             # <<<<<<<<<<<<<<
 *                         # and sum up the d_n values weighted by MFD (the numerator)
 *                         pixel.sum_of_weighted_distances += flow_dir_weight * (
*/
            __pyx_v_pixel.sum_of_weights = (__pyx_v_pixel.sum_of_weights + __pyx_v_flow_dir_weight);

            /* "pygeoprocessing/routing/routing.pyx":2651
 *                         pixel.sum_of_weights += flow_dir_weight
 *                         # and sum up the d_n values weighted by MFD (the numerator)
 *                         pixel.sum_of_weighted_distances += flow_dir_weight * (             # <<<<<<<<<<<<<<
 *                             weight_val + n_distance)
 * 
*/
            __pyx_v_pixel.sum_of_weighted_distances = (__pyx_v_pixel.sum_of_weighted_distances + (__pyx_v_flow_dir_weight * (__pyx_v_weight_val + __pyx_v_n_distance)));
            __pyx_L30_continue:;
          }
          __pyx_L31_break:;

          /* "pygeoprocessing/routing/routing.pyx":2657
 *                     # because at least one of its downstream neighbors isn't done
 *                     # and so this pixel isn't ready to be calculated yet
 *                     if preempted:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
          __pyx_t_4 = (__pyx_v_preempted != 0);
          if (__pyx_t_4) {

            /* "pygeoprocessing/routing/routing.pyx":2658
 *                     # and so this pixel isn't ready to be calculated yet
 *                     if preempted:
 *                         continue             # <<<<<<<<<<<<<<
 * 
 *                     # if the sum of flow weights is 0, that means that no
*/
            goto __pyx_L27_continue;

            /* "pygeoprocessing/routing/routing.pyx":2657
 *                     # because at least one of its downstream neighbors isn't done
 *                     # and so this pixel isn't ready to be calculated yet
 *                     if preempted:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2663
 *                     # neighbors drain to a stream, and so d_i is undefined.
 *                     # in that case leave it unset (nodata).
 *                     if pixel.sum_of_weights != 0:             # <<<<<<<<<<<<<<
 *                         # divide to get the average
 *                         distance_to_channel_managed_raster.set(
*/
          __pyx_t_4 = (__pyx_v_pixel.sum_of_weights != 0.0);
          if (__pyx_t_4) {

            /* "pygeoprocessing/routing/routing.pyx":2667
 *                         distance_to_channel_managed_raster.set(
 *                             pixel.xi, pixel.yi,
 *                             pixel.sum_of_weighted_distances / pixel.sum_of_weights)             # <<<<<<<<<<<<<<
 * 
 *     distance_to_channel_managed_raster.close()
*/
            if (unlikely(__pyx_v_pixel.sum_of_weights == 0)) {
              PyErr_SetString(PyExc_ZeroDivisionError, "float division");
              __PYX_ERR(0, 2667, __pyx_L1_error)
            }

            /* "pygeoprocessing/routing/routing.pyx":2665
 *                     if pixel.sum_of_weights != 0:
 *                         # divide to get the average
 *                         distance_to_channel_managed_raster.set(             # <<<<<<<<<<<<<<
 *                             pixel.xi, pixel.yi,
 *                             pixel.sum_of_weighted_distances / pixel.sum_of_weights)
*/
            __pyx_v_distance_to_channel_managed_raster.set(__pyx_v_pixel.xi, __pyx_v_pixel.yi, (__pyx_v_pixel.sum_of_weighted_distances / __pyx_v_pixel.sum_of_weights));

            /* "pygeoprocessing/routing/routing.pyx":2663
 *                     # neighbors drain to a stream, and so d_i is undefined.
 *                     # in that case leave it unset (nodata).
 *                     if pixel.sum_of_weights != 0:             # <<<<<<<<<<<<<<
 *                         # divide to get the average
 *                         distance_to_channel_managed_raster.set(
*/
          }
          __pyx_L27_continue:;
        }
        __pyx_L22_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":2511
 * 
 *     # this outer loop searches for undefined channels
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             channel_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  }
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2669
 *                             pixel.sum_of_weighted_distances / pixel.sum_of_weights)
 * 
 *     distance_to_channel_managed_raster.close()             # <<<<<<<<<<<<<<
 *     channel_managed_raster.close()
 *     flow_dir_mfd_managed_raster.close()
*/
  __pyx_v_distance_to_channel_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2670
 * 
 *     distance_to_channel_managed_raster.close()
 *     channel_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_dir_mfd_managed_raster.close()
 *     if weight_raster_path_band:
*/
  __pyx_v_channel_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2671
 *     distance_to_channel_managed_raster.close()
 *     channel_managed_raster.close()
 *     flow_dir_mfd_managed_raster.close()             # <<<<<<<<<<<<<<
 *     if weight_raster_path_band:
 *         weight_raster.close()
*/
  __pyx_v_flow_dir_mfd_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2672
 *     channel_managed_raster.close()
 *     flow_dir_mfd_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     visited_managed_raster.close()
*/
  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_weight_raster_path_band); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 2672, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":2673
 *     flow_dir_mfd_managed_raster.close()
 *     if weight_raster_path_band:
 *         weight_raster.close()             # <<<<<<<<<<<<<<
 *     visited_managed_raster.close()
 *     shutil.rmtree(tmp_work_dir)
*/
    __pyx_v_weight_raster.close();

    /* "pygeoprocessing/routing/routing.pyx":2672
 *     channel_managed_raster.close()
 *     flow_dir_mfd_managed_raster.close()
 *     if weight_raster_path_band:             # <<<<<<<<<<<<<<
 *         weight_raster.close()
 *     visited_managed_raster.close()
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2674
 *     if weight_raster_path_band:
 *         weight_raster.close()
 *     visited_managed_raster.close()             # <<<<<<<<<<<<<<
 *     shutil.rmtree(tmp_work_dir)
 *     LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0)
*/
  __pyx_v_visited_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":2675
 *         weight_raster.close()
 *     visited_managed_raster.close()
 *     shutil.rmtree(tmp_work_dir)             # <<<<<<<<<<<<<<
 *     LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0)
 * 
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2675, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2675, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_8 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_8 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_tmp_work_dir};
    __pyx_t_11 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2675, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_11);
  }
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2676
 *     visited_managed_raster.close()
 *     shutil.rmtree(tmp_work_dir)
 *     LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2676, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2676, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_mstate_global->__pyx_tuple[3], NULL); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 2676, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2346
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
*/

  /* function exit code */
  __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_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_XDECREF(__pyx_t_25);
  __Pyx_XDECREF(__pyx_t_26);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.distance_to_channel_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_channel_buffer_array.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_buffer_array.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_channel_buffer_array);
  __Pyx_XDECREF((PyObject *)__pyx_v_flow_dir_buffer_array);
  __Pyx_XDECREF(__pyx_v_path);
  __Pyx_XDECREF(__pyx_v_tmp_work_dir);
  __Pyx_XDECREF(__pyx_v_visited_raster_path);
  __Pyx_XDECREF(__pyx_v_channel_raster);
  __Pyx_XDECREF(__pyx_v_channel_band);
  __Pyx_XDECREF(__pyx_v_flow_dir_mfd_raster);
  __Pyx_XDECREF(__pyx_v_flow_dir_mfd_band);
  __Pyx_XDECREF(__pyx_v_raw_weight_nodata);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster_info);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_xa);
  __Pyx_XDECREF(__pyx_v_xb);
  __Pyx_XDECREF(__pyx_v_ya);
  __Pyx_XDECREF(__pyx_v_yb);
  __Pyx_XDECREF(__pyx_v_modified_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":2679
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_streams_mfd(
 *         flow_accum_raster_path_band, flow_dir_mfd_path_band,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_46__defaults__(CYTHON_UNUSED PyObject *__pyx_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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":2683
 *         flow_accum_raster_path_band, flow_dir_mfd_path_band,
 *         double flow_threshold, target_stream_raster_path,
 *         double trace_threshold_proportion=1.0,             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):
 *     """Classify a stream raster from MFD flow accumulation.
*/
  __pyx_t_1 = PyFloat_FromDouble(((double)1.0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2683, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":2679
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_streams_mfd(
 *         flow_accum_raster_path_band, flow_dir_mfd_path_band,
*/
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2679, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 2679, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 2679, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2679, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 2679, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, Py_None) != (0)) __PYX_ERR(0, 2679, __pyx_L1_error);
  __pyx_t_2 = 0;
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_17extract_streams_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_16extract_streams_mfd, "Classify a stream raster from MFD flow accumulation.\n\n    This function classifies pixels as streams that have a flow accumulation\n    value >= ``flow_threshold`` and can trace further upstream with a fuzzy\n    propotion if ``trace_threshold_proportion`` is set < 1.0\n\n    Parameters:\n        flow_accum_raster_path_band (tuple): a string/integer tuple indicating\n            the flow accumulation raster to use as a basis for thresholding\n            a stream. Values in this raster that are >= flow_threshold will\n            be classified as streams. This raster should be derived from\n            ``dem_raster_path_band`` using\n            ``pygeoprocessing.routing.flow_accumulation_mfd``. Paths may use\n            any GDAL-supported scheme, including virtual file system /vsi schemes.\n        flow_dir_mfd_path_band (str): path to multiple flow direction\n            raster, required to join divergent streams. Paths may use any\n            GDAL-supported scheme, including virtual file system /vsi schemes.\n        flow_threshold (float): the value in ``flow_accum_raster_path_band`` to\n            indicate where a stream exists.\n        target_stream_raster_path (str): path to the target stream raster.\n            This raster will be the same dimensions and projection as\n            ``dem_raster_path_band`` and will contain 1s where a stream is\n            defined, 0 where the flow accumulation layer is defined but no\n            stream exists, and nodata otherwise.\n        trace_threshold_proportion (float): this value indicates what\n            proportion of the flow_threshold is enough to classify a pixel\n            as a stream after the stream has been traced from a\n            ``flow_threshold`` drain. Setting this value < 1.0 is useful for\n            classifying streams in regions that have highly divergent flow\n            directions.\n        raster_driver_creation_tuple (tuple): a tuple containing a GDAL driver\n            name strin""g as the first element and a GDAL creation options\n            tuple/list as the second. Defaults to a GTiff driver tuple\n            defined at geoprocessing.DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_17extract_streams_mfd = {"extract_streams_mfd", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_17extract_streams_mfd, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_16extract_streams_mfd};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_17extract_streams_mfd(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_accum_raster_path_band = 0;
  PyObject *__pyx_v_flow_dir_mfd_path_band = 0;
  double __pyx_v_flow_threshold;
  PyObject *__pyx_v_target_stream_raster_path = 0;
  double __pyx_v_trace_threshold_proportion;
  PyObject *__pyx_v_raster_driver_creation_tuple = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[6] = {0,0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("extract_streams_mfd (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_accum_raster_path_band,&__pyx_mstate_global->__pyx_n_u_flow_dir_mfd_path_band,&__pyx_mstate_global->__pyx_n_u_flow_threshold,&__pyx_mstate_global->__pyx_n_u_target_stream_raster_path,&__pyx_mstate_global->__pyx_n_u_trace_threshold_proportion,&__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2679, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "extract_streams_mfd", 0) < (0)) __PYX_ERR(0, 2679, __pyx_L3_error)
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 4; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("extract_streams_mfd", 0, 4, 6, i); __PYX_ERR(0, 2679, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2679, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2679, __pyx_L3_error)
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2679, __pyx_L3_error)
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2679, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2679, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[5]) values[5] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_accum_raster_path_band = values[0];
    __pyx_v_flow_dir_mfd_path_band = values[1];
    __pyx_v_flow_threshold = __Pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_flow_threshold == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 2682, __pyx_L3_error)
    __pyx_v_target_stream_raster_path = values[3];
    if (values[4]) {
      __pyx_v_trace_threshold_proportion = __Pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_trace_threshold_proportion == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 2683, __pyx_L3_error)
    } else {
      __pyx_v_trace_threshold_proportion = ((double)((double)1.0));
    }
    __pyx_v_raster_driver_creation_tuple = values[5];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("extract_streams_mfd", 0, 4, 6, __pyx_nargs); __PYX_ERR(0, 2679, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.extract_streams_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_16extract_streams_mfd(__pyx_self, __pyx_v_flow_accum_raster_path_band, __pyx_v_flow_dir_mfd_path_band, __pyx_v_flow_threshold, __pyx_v_target_stream_raster_path, __pyx_v_trace_threshold_proportion, __pyx_v_raster_driver_creation_tuple);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_16extract_streams_mfd(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_accum_raster_path_band, PyObject *__pyx_v_flow_dir_mfd_path_band, double __pyx_v_flow_threshold, PyObject *__pyx_v_target_stream_raster_path, double __pyx_v_trace_threshold_proportion, PyObject *__pyx_v_raster_driver_creation_tuple) {
  PyObject *__pyx_v_flow_accum_info = NULL;
  double __pyx_v_flow_accum_nodata;
  long __pyx_v_stream_nodata;
  int __pyx_v_raster_x_size;
  int __pyx_v_raster_y_size;
  ManagedRaster __pyx_v_flow_accum_mr;
  ManagedRaster __pyx_v_stream_mr;
  ManagedRaster __pyx_v_flow_dir_mfd_mr;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  unsigned int __pyx_v_i_n;
  unsigned int __pyx_v_xi_n;
  unsigned int __pyx_v_yi_n;
  unsigned int __pyx_v_i_sn;
  unsigned int __pyx_v_xi_sn;
  unsigned int __pyx_v_yi_sn;
  int __pyx_v_flow_dir_mfd;
  double __pyx_v_flow_accum;
  double __pyx_v_trace_flow_threshold;
  unsigned int __pyx_v_n_iterations;
  int __pyx_v_is_outlet;
  int __pyx_v_stream_val;
  unsigned long __pyx_v_current_pixel;
  int __pyx_v_flow_dir_nodata;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_open_set;
  __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateQueueType __pyx_v_backtrace_set;
  int __pyx_v_xi_bn;
  int __pyx_v_yi_bn;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_block_offsets = NULL;
  PyObject *__pyx_v_block_offsets_list = NULL;
  PyObject *__pyx_v_stream_raster = NULL;
  PyObject *__pyx_v_stream_band = NULL;
  PyObject *__pyx_v_stream_array = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  int __pyx_t_2;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  size_t __pyx_t_7;
  double __pyx_t_8;
  PyObject *(*__pyx_t_9)(PyObject *);
  int __pyx_t_10;
  int __pyx_t_11;
  PyObject *__pyx_t_12 = NULL;
  PyObject *__pyx_t_13 = NULL;
  PyObject *__pyx_t_14 = NULL;
  char *__pyx_t_15;
  ManagedRaster __pyx_t_16;
  Py_ssize_t __pyx_t_17;
  PyObject *(*__pyx_t_18)(PyObject *);
  unsigned int __pyx_t_19;
  unsigned int __pyx_t_20;
  unsigned int __pyx_t_21;
  float __pyx_t_22;
  unsigned int __pyx_t_23;
  unsigned int __pyx_t_24;
  unsigned int __pyx_t_25;
  unsigned int __pyx_t_26;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_t_27;
  unsigned int __pyx_t_28;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("extract_streams_mfd", 0);

  /* "pygeoprocessing/routing/routing.pyx":2723
 *         None.
 *     """
 *     if trace_threshold_proportion < 0.or trace_threshold_proportion > 1.0:             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "trace_threshold_proportion should be in the range [0.0, 1.0] "
*/
  __pyx_t_2 = (__pyx_v_trace_threshold_proportion < 0.);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = (__pyx_v_trace_threshold_proportion > 1.0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (unlikely(__pyx_t_1)) {

    /* "pygeoprocessing/routing/routing.pyx":2724
 *     """
 *     if trace_threshold_proportion < 0.or trace_threshold_proportion > 1.0:
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             "trace_threshold_proportion should be in the range [0.0, 1.0] "
 *             "actual value is: %s" % trace_threshold_proportion)
*/
    __pyx_t_4 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":2726
 *         raise ValueError(
 *             "trace_threshold_proportion should be in the range [0.0, 1.0] "
 *             "actual value is: %s" % trace_threshold_proportion)             # <<<<<<<<<<<<<<
 * 
 *     flow_accum_info = pygeoprocessing.get_raster_info(
*/
    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_trace_threshold_proportion); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2726, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_6 = PyUnicode_Format(__pyx_mstate_global->__pyx_kp_u_trace_threshold_proportion_shoul, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2726, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_7 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_6};
      __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2724, __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;
    __PYX_ERR(0, 2724, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":2723
 *         None.
 *     """
 *     if trace_threshold_proportion < 0.or trace_threshold_proportion > 1.0:             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             "trace_threshold_proportion should be in the range [0.0, 1.0] "
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2728
 *             "actual value is: %s" % trace_threshold_proportion)
 * 
 *     flow_accum_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[0])
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2728, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2728, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2729
 * 
 *     flow_accum_info = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][
 *         flow_accum_raster_path_band[1]-1]
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2729, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_4};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2728, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_v_flow_accum_info = __pyx_t_3;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2730
 *     flow_accum_info = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1]-1]
 *     stream_nodata = 255
*/
  __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_accum_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2730, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":2731
 *         flow_accum_raster_path_band[0])
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][
 *         flow_accum_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     stream_nodata = 255
 * 
*/
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2731, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_4 = __Pyx_PyLong_SubtractObjC(__pyx_t_5, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2731, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2730
 *     flow_accum_info = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1]-1]
 *     stream_nodata = 255
*/
  __pyx_t_5 = __Pyx_PyObject_GetItem(__pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2730, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_8 = __Pyx_PyFloat_AsDouble(__pyx_t_5); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 2730, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_flow_accum_nodata = __pyx_t_8;

  /* "pygeoprocessing/routing/routing.pyx":2732
 *     cdef double flow_accum_nodata = flow_accum_info['nodata'][
 *         flow_accum_raster_path_band[1]-1]
 *     stream_nodata = 255             # <<<<<<<<<<<<<<
 * 
 *     cdef int raster_x_size, raster_y_size
*/
  __pyx_v_stream_nodata = 0xFF;

  /* "pygeoprocessing/routing/routing.pyx":2735
 * 
 *     cdef int raster_x_size, raster_y_size
 *     raster_x_size, raster_y_size = flow_accum_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_accum_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2735, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  if ((likely(PyTuple_CheckExact(__pyx_t_5))) || (PyList_CheckExact(__pyx_t_5))) {
    PyObject* sequence = __pyx_t_5;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 2735, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2735, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2735, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2735, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2735, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_6 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2735, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_9 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6);
    index = 0; __pyx_t_4 = __pyx_t_9(__pyx_t_6); if (unlikely(!__pyx_t_4)) goto __pyx_L6_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_4);
    index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_6); if (unlikely(!__pyx_t_3)) goto __pyx_L6_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_6), 2) < (0)) __PYX_ERR(0, 2735, __pyx_L1_error)
    __pyx_t_9 = NULL;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    goto __pyx_L7_unpacking_done;
    __pyx_L6_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_9 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 2735, __pyx_L1_error)
    __pyx_L7_unpacking_done:;
  }
  __pyx_t_10 = __Pyx_PyLong_As_int(__pyx_t_4); if (unlikely((__pyx_t_10 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2735, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2735, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_raster_x_size = __pyx_t_10;
  __pyx_v_raster_y_size = __pyx_t_11;

  /* "pygeoprocessing/routing/routing.pyx":2737
 *     raster_x_size, raster_y_size = flow_accum_info['raster_size']
 * 
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[0], target_stream_raster_path,
 *         gdal.GDT_Byte, [stream_nodata],
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2737, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2737, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2738
 * 
 *     pygeoprocessing.new_raster_from_base(
 *         flow_accum_raster_path_band[0], target_stream_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Byte, [stream_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2738, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);

  /* "pygeoprocessing/routing/routing.pyx":2739
 *     pygeoprocessing.new_raster_from_base(
 *         flow_accum_raster_path_band[0], target_stream_raster_path,
 *         gdal.GDT_Byte, [stream_nodata],             # <<<<<<<<<<<<<<
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2739, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_GDT_Byte); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2739, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_12 = __Pyx_PyLong_From_long(__pyx_v_stream_nodata); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2739, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_14 = PyList_New(1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2739, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_GIVEREF(__pyx_t_12);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_14, 0, __pyx_t_12) != (0)) __PYX_ERR(0, 2739, __pyx_L1_error);
  __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2740
 *         flow_accum_raster_path_band[0], target_stream_raster_path,
 *         gdal.GDT_Byte, [stream_nodata],
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster flow_accum_mr = ManagedRaster(
*/
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_6);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_3, __pyx_t_4, __pyx_v_target_stream_raster_path, __pyx_t_13, __pyx_t_14};
    __pyx_t_12 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2737, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_raster_driver_creation_tuple, __pyx_v_raster_driver_creation_tuple, __pyx_t_12, __pyx_callargs+5, 0) < (0)) __PYX_ERR(0, 2737, __pyx_L1_error)
    __pyx_t_5 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_7, (5-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_12);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2737, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2743
 * 
 *     cdef ManagedRaster flow_accum_mr = ManagedRaster(
 *         flow_accum_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1], False)
 *     cdef ManagedRaster stream_mr = ManagedRaster(
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2743, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_6 = __pyx_t_12;
  __Pyx_INCREF(__pyx_t_6);
  __pyx_t_7 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2743, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }
  __pyx_t_15 = __Pyx_PyObject_AsWritableString(__pyx_t_5); if (unlikely((!__pyx_t_15) && PyErr_Occurred())) __PYX_ERR(0, 2743, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2744
 *     cdef ManagedRaster flow_accum_mr = ManagedRaster(
 *         flow_accum_raster_path_band[0].encode('utf-8'),
 *         flow_accum_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     cdef ManagedRaster stream_mr = ManagedRaster(
 *         target_stream_raster_path.encode('utf-8'), 1, True)
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2744, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_12); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2744, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2742
 *         raster_driver_creation_tuple=raster_driver_creation_tuple)
 * 
 *     cdef ManagedRaster flow_accum_mr = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[0].encode('utf-8'),
 *         flow_accum_raster_path_band[1], False)
*/
  try {
    __pyx_t_16 = ManagedRaster(__pyx_t_15, __pyx_t_11, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2742, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_flow_accum_mr = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_16);

  /* "pygeoprocessing/routing/routing.pyx":2746
 *         flow_accum_raster_path_band[1], False)
 *     cdef ManagedRaster stream_mr = ManagedRaster(
 *         target_stream_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 *     cdef ManagedRaster flow_dir_mfd_mr = ManagedRaster(
 *         flow_dir_mfd_path_band[0].encode('utf-8'),
*/
  __pyx_t_12 = __pyx_v_target_stream_raster_path;
  __Pyx_INCREF(__pyx_t_12);
  __pyx_t_7 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2746, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }
  __pyx_t_15 = __Pyx_PyObject_AsWritableString(__pyx_t_5); if (unlikely((!__pyx_t_15) && PyErr_Occurred())) __PYX_ERR(0, 2746, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2745
 *         flow_accum_raster_path_band[0].encode('utf-8'),
 *         flow_accum_raster_path_band[1], False)
 *     cdef ManagedRaster stream_mr = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_stream_raster_path.encode('utf-8'), 1, True)
 *     cdef ManagedRaster flow_dir_mfd_mr = ManagedRaster(
*/
  try {
    __pyx_t_16 = ManagedRaster(__pyx_t_15, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2745, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_stream_mr = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_16);

  /* "pygeoprocessing/routing/routing.pyx":2748
 *         target_stream_raster_path.encode('utf-8'), 1, True)
 *     cdef ManagedRaster flow_dir_mfd_mr = ManagedRaster(
 *         flow_dir_mfd_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_path_band[1], False)
 * 
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2748, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_12 = __pyx_t_6;
  __Pyx_INCREF(__pyx_t_12);
  __pyx_t_7 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2748, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }
  __pyx_t_15 = __Pyx_PyObject_AsWritableString(__pyx_t_5); if (unlikely((!__pyx_t_15) && PyErr_Occurred())) __PYX_ERR(0, 2748, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2749
 *     cdef ManagedRaster flow_dir_mfd_mr = ManagedRaster(
 *         flow_dir_mfd_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned int xoff, yoff, win_xsize, win_ysize
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2749, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2749, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2747
 *     cdef ManagedRaster stream_mr = ManagedRaster(
 *         target_stream_raster_path.encode('utf-8'), 1, True)
 *     cdef ManagedRaster flow_dir_mfd_mr = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_path_band[0].encode('utf-8'),
 *         flow_dir_mfd_path_band[1], False)
*/
  try {
    __pyx_t_16 = ManagedRaster(__pyx_t_15, __pyx_t_11, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 2747, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_flow_dir_mfd_mr = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_16);

  /* "pygeoprocessing/routing/routing.pyx":2756
 *     cdef double flow_accum
 *     cdef double trace_flow_threshold = (
 *         trace_threshold_proportion * flow_threshold)             # <<<<<<<<<<<<<<
 *     cdef unsigned int n_iterations = 0
 *     cdef int is_outlet, stream_val
*/
  __pyx_v_trace_flow_threshold = (__pyx_v_trace_threshold_proportion * __pyx_v_flow_threshold);

  /* "pygeoprocessing/routing/routing.pyx":2757
 *     cdef double trace_flow_threshold = (
 *         trace_threshold_proportion * flow_threshold)
 *     cdef unsigned int n_iterations = 0             # <<<<<<<<<<<<<<
 *     cdef int is_outlet, stream_val
 *     cdef unsigned long current_pixel
*/
  __pyx_v_n_iterations = 0;

  /* "pygeoprocessing/routing/routing.pyx":2761
 *     cdef unsigned long current_pixel
 * 
 *     cdef int flow_dir_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_mfd_path_band[0])['nodata'][flow_dir_mfd_path_band[1]-1]
 * 
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2761, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2761, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2762
 * 
 *     cdef int flow_dir_nodata = pygeoprocessing.get_raster_info(
 *         flow_dir_mfd_path_band[0])['nodata'][flow_dir_mfd_path_band[1]-1]             # <<<<<<<<<<<<<<
 * 
 *     # this queue is used to march the front from the stream pixel or the
*/
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_14);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_12};
    __pyx_t_5 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2761, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }
  __pyx_t_14 = __Pyx_PyObject_Dict_GetItem(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_flow_dir_mfd_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_12 = __Pyx_PyLong_SubtractObjC(__pyx_t_5, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_PyObject_GetItem(__pyx_t_14, __pyx_t_12); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_5); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2762, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_v_flow_dir_nodata = __pyx_t_11;

  /* "pygeoprocessing/routing/routing.pyx":2769
 *     cdef int xi_bn, yi_bn # used for backtrace neighbor coordinates
 * 
 *     cdef time_t last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     for block_offsets in pygeoprocessing.iterblocks(
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":2771
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             (target_stream_raster_path, 1), offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  __pyx_t_12 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2771, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2771, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2772
 * 
 *     for block_offsets in pygeoprocessing.iterblocks(
 *             (target_stream_raster_path, 1), offset_only=True):             # <<<<<<<<<<<<<<
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']
*/
  __pyx_t_14 = PyTuple_New(2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2772, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_INCREF(__pyx_v_target_stream_raster_path);
  __Pyx_GIVEREF(__pyx_v_target_stream_raster_path);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_14, 0, __pyx_v_target_stream_raster_path) != (0)) __PYX_ERR(0, 2772, __pyx_L1_error);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_1);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_14, 1, __pyx_mstate_global->__pyx_int_1) != (0)) __PYX_ERR(0, 2772, __pyx_L1_error);
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_6);
    assert(__pyx_t_12);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
    __Pyx_INCREF(__pyx_t_12);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_12, __pyx_t_14};
    __pyx_t_13 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2771, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_13, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2771, __pyx_L1_error)
    __pyx_t_5 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_13);
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2771, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
  }

  /* "pygeoprocessing/routing/routing.pyx":2771
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             (target_stream_raster_path, 1), offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  if (likely(PyList_CheckExact(__pyx_t_5)) || PyTuple_CheckExact(__pyx_t_5)) {
    __pyx_t_6 = __pyx_t_5; __Pyx_INCREF(__pyx_t_6);
    __pyx_t_17 = 0;
    __pyx_t_18 = NULL;
  } else {
    __pyx_t_17 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2771, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_18 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 2771, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  for (;;) {
    if (likely(!__pyx_t_18)) {
      if (likely(PyList_CheckExact(__pyx_t_6))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2771, __pyx_L1_error)
          #endif
          if (__pyx_t_17 >= __pyx_temp) break;
        }
        __pyx_t_5 = __Pyx_PyList_GetItemRefFast(__pyx_t_6, __pyx_t_17, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_17;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2771, __pyx_L1_error)
          #endif
          if (__pyx_t_17 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_5 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_17));
        #else
        __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_6, __pyx_t_17);
        #endif
        ++__pyx_t_17;
      }
      if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2771, __pyx_L1_error)
    } else {
      __pyx_t_5 = __pyx_t_18(__pyx_t_6);
      if (unlikely(!__pyx_t_5)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 2771, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_XDECREF_SET(__pyx_v_block_offsets, __pyx_t_5);
    __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2773
 *     for block_offsets in pygeoprocessing.iterblocks(
 *             (target_stream_raster_path, 1), offset_only=True):
 *         xoff = block_offsets['xoff']             # <<<<<<<<<<<<<<
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2773, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_5); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2773, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_xoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2774
 *             (target_stream_raster_path, 1), offset_only=True):
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']             # <<<<<<<<<<<<<<
 *         win_xsize = block_offsets['win_xsize']
 *         win_ysize = block_offsets['win_ysize']
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2774, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_5); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2774, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_yoff = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2775
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = block_offsets['win_ysize']
 *         for yi in range(win_ysize):
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2775, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_5); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2775, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_win_xsize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2776
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']
 *         win_ysize = block_offsets['win_ysize']             # <<<<<<<<<<<<<<
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2776, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_19 = __Pyx_PyLong_As_unsigned_int(__pyx_t_5); if (unlikely((__pyx_t_19 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2776, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_win_ysize = __pyx_t_19;

    /* "pygeoprocessing/routing/routing.pyx":2777
 *         win_xsize = block_offsets['win_xsize']
 *         win_ysize = block_offsets['win_ysize']
 *         for yi in range(win_ysize):             # <<<<<<<<<<<<<<
 *             yi_root = yi+yoff
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_19 = __pyx_v_win_ysize;
    __pyx_t_20 = __pyx_t_19;
    for (__pyx_t_21 = 0; __pyx_t_21 < __pyx_t_20; __pyx_t_21+=1) {
      __pyx_v_yi = __pyx_t_21;

      /* "pygeoprocessing/routing/routing.pyx":2778
 *         win_ysize = block_offsets['win_ysize']
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff             # <<<<<<<<<<<<<<
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *                 last_log_time = ctime(NULL)
*/
      __pyx_v_yi_root = (__pyx_v_yi + __pyx_v_yoff);

      /* "pygeoprocessing/routing/routing.pyx":2779
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
*/
      __pyx_t_1 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
      if (__pyx_t_1) {

        /* "pygeoprocessing/routing/routing.pyx":2780
 *             yi_root = yi+yoff
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *                 last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(
*/
        __pyx_v_last_log_time = time(NULL);

        /* "pygeoprocessing/routing/routing.pyx":2781
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                     raster_x_size * raster_y_size))
*/
        __pyx_v_current_pixel = (__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size));

        /* "pygeoprocessing/routing/routing.pyx":2782
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                     raster_x_size * raster_y_size))
 *             for xi in range(win_xsize):
*/
        __pyx_t_13 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2782, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_14);
        __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2782, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_12);
        __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
        __pyx_t_8 = (100.0 * __pyx_v_current_pixel);

        /* "pygeoprocessing/routing/routing.pyx":2783
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                     raster_x_size * raster_y_size))             # <<<<<<<<<<<<<<
 *             for xi in range(win_xsize):
 *                 xi_root = xi+xoff
*/
        __pyx_t_22 = ((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size));

        /* "pygeoprocessing/routing/routing.pyx":2782
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                     raster_x_size * raster_y_size))
 *             for xi in range(win_xsize):
*/
        if (unlikely(__pyx_t_22 == 0)) {
          PyErr_SetString(PyExc_ZeroDivisionError, "float division");
          __PYX_ERR(0, 2782, __pyx_L1_error)
        }
        __pyx_t_14 = PyFloat_FromDouble((__pyx_t_8 / ((double)__pyx_t_22))); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2782, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_14);
        __pyx_t_7 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_12))) {
          __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_12);
          assert(__pyx_t_13);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
          __Pyx_INCREF(__pyx_t_13);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
          __pyx_t_7 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[3] = {__pyx_t_13, __pyx_mstate_global->__pyx_kp_u_Extract_streams_MFD_1f_complete, __pyx_t_14};
          __pyx_t_5 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_7, (3-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
          __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
          if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2782, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
        }
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

        /* "pygeoprocessing/routing/routing.pyx":2779
 *         for yi in range(win_ysize):
 *             yi_root = yi+yoff
 *             if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":2784
 *                 LOGGER.info('Extract streams MFD %.1f%% complete', 100.0 * current_pixel / <float>(
 *                     raster_x_size * raster_y_size))
 *             for xi in range(win_xsize):             # <<<<<<<<<<<<<<
 *                 xi_root = xi+xoff
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)
*/
      __pyx_t_23 = __pyx_v_win_xsize;
      __pyx_t_24 = __pyx_t_23;
      for (__pyx_t_25 = 0; __pyx_t_25 < __pyx_t_24; __pyx_t_25+=1) {
        __pyx_v_xi = __pyx_t_25;

        /* "pygeoprocessing/routing/routing.pyx":2785
 *                     raster_x_size * raster_y_size))
 *             for xi in range(win_xsize):
 *                 xi_root = xi+xoff             # <<<<<<<<<<<<<<
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)
 *                 if is_close(flow_accum, flow_accum_nodata):
*/
        __pyx_v_xi_root = (__pyx_v_xi + __pyx_v_xoff);

        /* "pygeoprocessing/routing/routing.pyx":2786
 *             for xi in range(win_xsize):
 *                 xi_root = xi+xoff
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                 if is_close(flow_accum, flow_accum_nodata):
 *                     continue
*/
        __pyx_v_flow_accum = __pyx_v_flow_accum_mr.get(__pyx_v_xi_root, __pyx_v_yi_root);

        /* "pygeoprocessing/routing/routing.pyx":2787
 *                 xi_root = xi+xoff
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)
 *                 if is_close(flow_accum, flow_accum_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:
*/
        __pyx_t_1 = is_close(__pyx_v_flow_accum, __pyx_v_flow_accum_nodata);
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":2788
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)
 *                 if is_close(flow_accum, flow_accum_nodata):
 *                     continue             # <<<<<<<<<<<<<<
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:
 *                     continue
*/
          goto __pyx_L13_continue;

          /* "pygeoprocessing/routing/routing.pyx":2787
 *                 xi_root = xi+xoff
 *                 flow_accum = flow_accum_mr.get(xi_root, yi_root)
 *                 if is_close(flow_accum, flow_accum_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2789
 *                 if is_close(flow_accum, flow_accum_nodata):
 *                     continue
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 *                 stream_mr.set(xi_root, yi_root, 0)
*/
        __pyx_t_1 = (__pyx_v_stream_mr.get(__pyx_v_xi_root, __pyx_v_yi_root) != __pyx_v_stream_nodata);
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":2790
 *                     continue
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:
 *                     continue             # <<<<<<<<<<<<<<
 *                 stream_mr.set(xi_root, yi_root, 0)
 *                 if flow_accum < flow_threshold:
*/
          goto __pyx_L13_continue;

          /* "pygeoprocessing/routing/routing.pyx":2789
 *                 if is_close(flow_accum, flow_accum_nodata):
 *                     continue
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 *                 stream_mr.set(xi_root, yi_root, 0)
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2791
 *                 if stream_mr.get(xi_root, yi_root) != stream_nodata:
 *                     continue
 *                 stream_mr.set(xi_root, yi_root, 0)             # <<<<<<<<<<<<<<
 *                 if flow_accum < flow_threshold:
 *                     continue
*/
        __pyx_v_stream_mr.set(__pyx_v_xi_root, __pyx_v_yi_root, 0.0);

        /* "pygeoprocessing/routing/routing.pyx":2792
 *                     continue
 *                 stream_mr.set(xi_root, yi_root, 0)
 *                 if flow_accum < flow_threshold:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_1 = (__pyx_v_flow_accum < __pyx_v_flow_threshold);
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":2793
 *                 stream_mr.set(xi_root, yi_root, 0)
 *                 if flow_accum < flow_threshold:
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_root, yi_root)
*/
          goto __pyx_L13_continue;

          /* "pygeoprocessing/routing/routing.pyx":2792
 *                     continue
 *                 stream_mr.set(xi_root, yi_root, 0)
 *                 if flow_accum < flow_threshold:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2795
 *                     continue
 * 
 *                 flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                 is_outlet = 0
 *                 for i_n in range(8):
*/
        __pyx_v_flow_dir_mfd = ((int)__pyx_v_flow_dir_mfd_mr.get(__pyx_v_xi_root, __pyx_v_yi_root));

        /* "pygeoprocessing/routing/routing.pyx":2796
 * 
 *                 flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_root, yi_root)
 *                 is_outlet = 0             # <<<<<<<<<<<<<<
 *                 for i_n in range(8):
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:
*/
        __pyx_v_is_outlet = 0;

        /* "pygeoprocessing/routing/routing.pyx":2797
 *                 flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_root, yi_root)
 *                 is_outlet = 0
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:
 *                         # no flow in that direction
*/
        for (__pyx_t_26 = 0; __pyx_t_26 < 8; __pyx_t_26+=1) {
          __pyx_v_i_n = __pyx_t_26;

          /* "pygeoprocessing/routing/routing.pyx":2798
 *                 is_outlet = 0
 *                 for i_n in range(8):
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:             # <<<<<<<<<<<<<<
 *                         # no flow in that direction
 *                         continue
*/
          __pyx_t_1 = (((__pyx_v_flow_dir_mfd >> (__pyx_v_i_n * 4)) & 0xF) == 0);
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":2800
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:
 *                         # no flow in that direction
 *                         continue             # <<<<<<<<<<<<<<
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
*/
            goto __pyx_L18_continue;

            /* "pygeoprocessing/routing/routing.pyx":2798
 *                 is_outlet = 0
 *                 for i_n in range(8):
 *                     if ((flow_dir_mfd >> (i_n * 4)) & 0xF) == 0:             # <<<<<<<<<<<<<<
 *                         # no flow in that direction
 *                         continue
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2801
 *                         # no flow in that direction
 *                         continue
 *                     xi_n = xi_root+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
*/
          __pyx_v_xi_n = (__pyx_v_xi_root + (COL_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":2802
 *                         continue
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):
*/
          __pyx_v_yi_n = (__pyx_v_yi_root + (ROW_OFFSETS[__pyx_v_i_n]));

          /* "pygeoprocessing/routing/routing.pyx":2803
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          __pyx_t_2 = (__pyx_v_xi_n < 0);
          if (!__pyx_t_2) {
          } else {
            __pyx_t_1 = __pyx_t_2;
            goto __pyx_L22_bool_binop_done;
          }
          __pyx_t_2 = (__pyx_v_xi_n >= __pyx_v_raster_x_size);
          if (!__pyx_t_2) {
          } else {
            __pyx_t_1 = __pyx_t_2;
            goto __pyx_L22_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":2804
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                         # it'll drain off the edge of the raster
 *                         is_outlet = 1
*/
          __pyx_t_2 = (__pyx_v_yi_n < 0);
          if (!__pyx_t_2) {
          } else {
            __pyx_t_1 = __pyx_t_2;
            goto __pyx_L22_bool_binop_done;
          }
          __pyx_t_2 = (__pyx_v_yi_n >= __pyx_v_raster_y_size);
          __pyx_t_1 = __pyx_t_2;
          __pyx_L22_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":2803
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":2806
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
 *                         is_outlet = 1             # <<<<<<<<<<<<<<
 *                         break
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:
*/
            __pyx_v_is_outlet = 1;

            /* "pygeoprocessing/routing/routing.pyx":2807
 *                         # it'll drain off the edge of the raster
 *                         is_outlet = 1
 *                         break             # <<<<<<<<<<<<<<
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:
 *                         is_outlet = 1
*/
            goto __pyx_L19_break;

            /* "pygeoprocessing/routing/routing.pyx":2803
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":2808
 *                         is_outlet = 1
 *                         break
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:             # <<<<<<<<<<<<<<
 *                         is_outlet = 1
 *                         break
*/
          __pyx_t_1 = (__pyx_v_flow_accum_mr.get(__pyx_v_xi_n, __pyx_v_yi_n) == __pyx_v_flow_accum_nodata);
          if (__pyx_t_1) {

            /* "pygeoprocessing/routing/routing.pyx":2809
 *                         break
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:
 *                         is_outlet = 1             # <<<<<<<<<<<<<<
 *                         break
 *                 if is_outlet:
*/
            __pyx_v_is_outlet = 1;

            /* "pygeoprocessing/routing/routing.pyx":2810
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:
 *                         is_outlet = 1
 *                         break             # <<<<<<<<<<<<<<
 *                 if is_outlet:
 *                     open_set.push(CoordinateType(xi_root, yi_root))
*/
            goto __pyx_L19_break;

            /* "pygeoprocessing/routing/routing.pyx":2808
 *                         is_outlet = 1
 *                         break
 *                     if flow_accum_mr.get(xi_n, yi_n) == flow_accum_nodata:             # <<<<<<<<<<<<<<
 *                         is_outlet = 1
 *                         break
*/
          }
          __pyx_L18_continue:;
        }
        __pyx_L19_break:;

        /* "pygeoprocessing/routing/routing.pyx":2811
 *                         is_outlet = 1
 *                         break
 *                 if is_outlet:             # <<<<<<<<<<<<<<
 *                     open_set.push(CoordinateType(xi_root, yi_root))
 *                     stream_mr.set(xi_root, yi_root, 1)
*/
        __pyx_t_1 = (__pyx_v_is_outlet != 0);
        if (__pyx_t_1) {

          /* "pygeoprocessing/routing/routing.pyx":2812
 *                         break
 *                 if is_outlet:
 *                     open_set.push(CoordinateType(xi_root, yi_root))             # <<<<<<<<<<<<<<
 *                     stream_mr.set(xi_root, yi_root, 1)
 * 
*/
          __pyx_t_27.xi = __pyx_v_xi_root;
          __pyx_t_27.yi = __pyx_v_yi_root;
          __pyx_v_open_set.push(__pyx_t_27);

          /* "pygeoprocessing/routing/routing.pyx":2813
 *                 if is_outlet:
 *                     open_set.push(CoordinateType(xi_root, yi_root))
 *                     stream_mr.set(xi_root, yi_root, 1)             # <<<<<<<<<<<<<<
 * 
 *                 n_iterations = 0
*/
          __pyx_v_stream_mr.set(__pyx_v_xi_root, __pyx_v_yi_root, 1.0);

          /* "pygeoprocessing/routing/routing.pyx":2811
 *                         is_outlet = 1
 *                         break
 *                 if is_outlet:             # <<<<<<<<<<<<<<
 *                     open_set.push(CoordinateType(xi_root, yi_root))
 *                     stream_mr.set(xi_root, yi_root, 1)
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":2815
 *                     stream_mr.set(xi_root, yi_root, 1)
 * 
 *                 n_iterations = 0             # <<<<<<<<<<<<<<
 *                 while open_set.size() > 0:
 *                     xi_n = open_set.front().xi
*/
        __pyx_v_n_iterations = 0;

        /* "pygeoprocessing/routing/routing.pyx":2816
 * 
 *                 n_iterations = 0
 *                 while open_set.size() > 0:             # <<<<<<<<<<<<<<
 *                     xi_n = open_set.front().xi
 *                     yi_n = open_set.front().yi
*/
        while (1) {
          __pyx_t_1 = (__pyx_v_open_set.size() > 0);
          if (!__pyx_t_1) break;

          /* "pygeoprocessing/routing/routing.pyx":2817
 *                 n_iterations = 0
 *                 while open_set.size() > 0:
 *                     xi_n = open_set.front().xi             # <<<<<<<<<<<<<<
 *                     yi_n = open_set.front().yi
 *                     open_set.pop()
*/
          __pyx_t_26 = __pyx_v_open_set.front().xi;
          __pyx_v_xi_n = __pyx_t_26;

          /* "pygeoprocessing/routing/routing.pyx":2818
 *                 while open_set.size() > 0:
 *                     xi_n = open_set.front().xi
 *                     yi_n = open_set.front().yi             # <<<<<<<<<<<<<<
 *                     open_set.pop()
 *                     n_iterations += 1
*/
          __pyx_t_26 = __pyx_v_open_set.front().yi;
          __pyx_v_yi_n = __pyx_t_26;

          /* "pygeoprocessing/routing/routing.pyx":2819
 *                     xi_n = open_set.front().xi
 *                     yi_n = open_set.front().yi
 *                     open_set.pop()             # <<<<<<<<<<<<<<
 *                     n_iterations += 1
 *                     for i_sn in range(8):
*/
          __pyx_v_open_set.pop();

          /* "pygeoprocessing/routing/routing.pyx":2820
 *                     yi_n = open_set.front().yi
 *                     open_set.pop()
 *                     n_iterations += 1             # <<<<<<<<<<<<<<
 *                     for i_sn in range(8):
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
*/
          __pyx_v_n_iterations = (__pyx_v_n_iterations + 1);

          /* "pygeoprocessing/routing/routing.pyx":2821
 *                     open_set.pop()
 *                     n_iterations += 1
 *                     for i_sn in range(8):             # <<<<<<<<<<<<<<
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
*/
          for (__pyx_t_26 = 0; __pyx_t_26 < 8; __pyx_t_26+=1) {
            __pyx_v_i_sn = __pyx_t_26;

            /* "pygeoprocessing/routing/routing.pyx":2822
 *                     n_iterations += 1
 *                     for i_sn in range(8):
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]             # <<<<<<<<<<<<<<
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or
*/
            __pyx_v_xi_sn = (__pyx_v_xi_n + (COL_OFFSETS[__pyx_v_i_sn]));

            /* "pygeoprocessing/routing/routing.pyx":2823
 *                     for i_sn in range(8):
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]             # <<<<<<<<<<<<<<
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
*/
            __pyx_v_yi_sn = (__pyx_v_yi_n + (ROW_OFFSETS[__pyx_v_i_sn]));

            /* "pygeoprocessing/routing/routing.pyx":2824
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
 *                             continue
*/
            __pyx_t_2 = (__pyx_v_xi_sn < 0);
            if (!__pyx_t_2) {
            } else {
              __pyx_t_1 = __pyx_t_2;
              goto __pyx_L33_bool_binop_done;
            }
            __pyx_t_2 = (__pyx_v_xi_sn >= __pyx_v_raster_x_size);
            if (!__pyx_t_2) {
            } else {
              __pyx_t_1 = __pyx_t_2;
              goto __pyx_L33_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":2825
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):             # <<<<<<<<<<<<<<
 *                             continue
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)
*/
            __pyx_t_2 = (__pyx_v_yi_sn < 0);
            if (!__pyx_t_2) {
            } else {
              __pyx_t_1 = __pyx_t_2;
              goto __pyx_L33_bool_binop_done;
            }
            __pyx_t_2 = (__pyx_v_yi_sn >= __pyx_v_raster_y_size);
            __pyx_t_1 = __pyx_t_2;
            __pyx_L33_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":2824
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
 *                             continue
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":2826
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
 *                             continue             # <<<<<<<<<<<<<<
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)
 *                         if flow_dir_mfd == flow_dir_nodata:
*/
              goto __pyx_L30_continue;

              /* "pygeoprocessing/routing/routing.pyx":2824
 *                         xi_sn = xi_n+COL_OFFSETS[i_sn]
 *                         yi_sn = yi_n+ROW_OFFSETS[i_sn]
 *                         if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2827
 *                                 yi_sn < 0 or yi_sn >= raster_y_size):
 *                             continue
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)             # <<<<<<<<<<<<<<
 *                         if flow_dir_mfd == flow_dir_nodata:
 *                             continue
*/
            __pyx_v_flow_dir_mfd = ((int)__pyx_v_flow_dir_mfd_mr.get(__pyx_v_xi_sn, __pyx_v_yi_sn));

            /* "pygeoprocessing/routing/routing.pyx":2828
 *                             continue
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)
 *                         if flow_dir_mfd == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if ((flow_dir_mfd >>
*/
            __pyx_t_1 = (__pyx_v_flow_dir_mfd == __pyx_v_flow_dir_nodata);
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":2829
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)
 *                         if flow_dir_mfd == flow_dir_nodata:
 *                             continue             # <<<<<<<<<<<<<<
 *                         if ((flow_dir_mfd >>
 *                                 (INFLOW_OFFSETS[i_sn] * 4)) & 0xF) > 0:
*/
              goto __pyx_L30_continue;

              /* "pygeoprocessing/routing/routing.pyx":2828
 *                             continue
 *                         flow_dir_mfd = <int>flow_dir_mfd_mr.get(xi_sn, yi_sn)
 *                         if flow_dir_mfd == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if ((flow_dir_mfd >>
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":2831
 *                             continue
 *                         if ((flow_dir_mfd >>
 *                                 (INFLOW_OFFSETS[i_sn] * 4)) & 0xF) > 0:             # <<<<<<<<<<<<<<
 *                             # upstream pixel flows into this one
 *                             stream_val = <int>stream_mr.get(xi_sn, yi_sn)
*/
            __pyx_t_1 = (((__pyx_v_flow_dir_mfd >> ((INFLOW_OFFSETS[__pyx_v_i_sn]) * 4)) & 0xF) > 0);

            /* "pygeoprocessing/routing/routing.pyx":2830
 *                         if flow_dir_mfd == flow_dir_nodata:
 *                             continue
 *                         if ((flow_dir_mfd >>             # <<<<<<<<<<<<<<
 *                                 (INFLOW_OFFSETS[i_sn] * 4)) & 0xF) > 0:
 *                             # upstream pixel flows into this one
*/
            if (__pyx_t_1) {

              /* "pygeoprocessing/routing/routing.pyx":2833
 *                                 (INFLOW_OFFSETS[i_sn] * 4)) & 0xF) > 0:
 *                             # upstream pixel flows into this one
 *                             stream_val = <int>stream_mr.get(xi_sn, yi_sn)             # <<<<<<<<<<<<<<
 *                             if stream_val != 1 and stream_val != 2:
 *                                 flow_accum = flow_accum_mr.get(
*/
              __pyx_v_stream_val = ((int)__pyx_v_stream_mr.get(__pyx_v_xi_sn, __pyx_v_yi_sn));

              /* "pygeoprocessing/routing/routing.pyx":2834
 *                             # upstream pixel flows into this one
 *                             stream_val = <int>stream_mr.get(xi_sn, yi_sn)
 *                             if stream_val != 1 and stream_val != 2:             # <<<<<<<<<<<<<<
 *                                 flow_accum = flow_accum_mr.get(
 *                                     xi_sn, yi_sn)
*/
              switch (__pyx_v_stream_val) {
                case 1:
                case 2:
                __pyx_t_1 = 0;
                break;
                default:
                __pyx_t_1 = 1;
                break;
              }
              if (__pyx_t_1) {

                /* "pygeoprocessing/routing/routing.pyx":2835
 *                             stream_val = <int>stream_mr.get(xi_sn, yi_sn)
 *                             if stream_val != 1 and stream_val != 2:
 *                                 flow_accum = flow_accum_mr.get(             # <<<<<<<<<<<<<<
 *                                     xi_sn, yi_sn)
 *                                 if flow_accum >= flow_threshold:
*/
                __pyx_v_flow_accum = __pyx_v_flow_accum_mr.get(__pyx_v_xi_sn, __pyx_v_yi_sn);

                /* "pygeoprocessing/routing/routing.pyx":2837
 *                                 flow_accum = flow_accum_mr.get(
 *                                     xi_sn, yi_sn)
 *                                 if flow_accum >= flow_threshold:             # <<<<<<<<<<<<<<
 *                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                     open_set.push(
*/
                __pyx_t_1 = (__pyx_v_flow_accum >= __pyx_v_flow_threshold);
                if (__pyx_t_1) {

                  /* "pygeoprocessing/routing/routing.pyx":2838
 *                                     xi_sn, yi_sn)
 *                                 if flow_accum >= flow_threshold:
 *                                     stream_mr.set(xi_sn, yi_sn, 1)             # <<<<<<<<<<<<<<
 *                                     open_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))
*/
                  __pyx_v_stream_mr.set(__pyx_v_xi_sn, __pyx_v_yi_sn, 1.0);

                  /* "pygeoprocessing/routing/routing.pyx":2840
 *                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                     open_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))             # <<<<<<<<<<<<<<
 *                                     # see if we're in a potential stream and
 *                                     # found a connection
*/
                  __pyx_t_27.xi = __pyx_v_xi_sn;
                  __pyx_t_27.yi = __pyx_v_yi_sn;

                  /* "pygeoprocessing/routing/routing.pyx":2839
 *                                 if flow_accum >= flow_threshold:
 *                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                     open_set.push(             # <<<<<<<<<<<<<<
 *                                         CoordinateType(xi_sn, yi_sn))
 *                                     # see if we're in a potential stream and
*/
                  __pyx_v_open_set.push(__pyx_t_27);

                  /* "pygeoprocessing/routing/routing.pyx":2844
 *                                     # found a connection
 *                                     backtrace_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))             # <<<<<<<<<<<<<<
 *                                     while backtrace_set.size() > 0:
 *                                         xi_bn = backtrace_set.front().xi
*/
                  __pyx_t_27.xi = __pyx_v_xi_sn;
                  __pyx_t_27.yi = __pyx_v_yi_sn;

                  /* "pygeoprocessing/routing/routing.pyx":2843
 *                                     # see if we're in a potential stream and
 *                                     # found a connection
 *                                     backtrace_set.push(             # <<<<<<<<<<<<<<
 *                                         CoordinateType(xi_sn, yi_sn))
 *                                     while backtrace_set.size() > 0:
*/
                  __pyx_v_backtrace_set.push(__pyx_t_27);

                  /* "pygeoprocessing/routing/routing.pyx":2845
 *                                     backtrace_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))
 *                                     while backtrace_set.size() > 0:             # <<<<<<<<<<<<<<
 *                                         xi_bn = backtrace_set.front().xi
 *                                         yi_bn = backtrace_set.front().yi
*/
                  while (1) {
                    __pyx_t_1 = (__pyx_v_backtrace_set.size() > 0);
                    if (!__pyx_t_1) break;

                    /* "pygeoprocessing/routing/routing.pyx":2846
 *                                         CoordinateType(xi_sn, yi_sn))
 *                                     while backtrace_set.size() > 0:
 *                                         xi_bn = backtrace_set.front().xi             # <<<<<<<<<<<<<<
 *                                         yi_bn = backtrace_set.front().yi
 *                                         backtrace_set.pop()
*/
                    __pyx_t_28 = __pyx_v_backtrace_set.front().xi;
                    __pyx_v_xi_bn = __pyx_t_28;

                    /* "pygeoprocessing/routing/routing.pyx":2847
 *                                     while backtrace_set.size() > 0:
 *                                         xi_bn = backtrace_set.front().xi
 *                                         yi_bn = backtrace_set.front().yi             # <<<<<<<<<<<<<<
 *                                         backtrace_set.pop()
 *                                         flow_dir_mfd = <int>(
*/
                    __pyx_t_28 = __pyx_v_backtrace_set.front().yi;
                    __pyx_v_yi_bn = __pyx_t_28;

                    /* "pygeoprocessing/routing/routing.pyx":2848
 *                                         xi_bn = backtrace_set.front().xi
 *                                         yi_bn = backtrace_set.front().yi
 *                                         backtrace_set.pop()             # <<<<<<<<<<<<<<
 *                                         flow_dir_mfd = <int>(
 *                                             flow_dir_mfd_mr.get(xi_bn, yi_bn))
*/
                    __pyx_v_backtrace_set.pop();

                    /* "pygeoprocessing/routing/routing.pyx":2849
 *                                         yi_bn = backtrace_set.front().yi
 *                                         backtrace_set.pop()
 *                                         flow_dir_mfd = <int>(             # <<<<<<<<<<<<<<
 *                                             flow_dir_mfd_mr.get(xi_bn, yi_bn))
 *                                         for i_sn in range(8):
*/
                    __pyx_v_flow_dir_mfd = ((int)__pyx_v_flow_dir_mfd_mr.get(__pyx_v_xi_bn, __pyx_v_yi_bn));

                    /* "pygeoprocessing/routing/routing.pyx":2851
 *                                         flow_dir_mfd = <int>(
 *                                             flow_dir_mfd_mr.get(xi_bn, yi_bn))
 *                                         for i_sn in range(8):             # <<<<<<<<<<<<<<
 *                                             if (flow_dir_mfd >> (i_sn*4)) & 0xF > 0:
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
*/
                    for (__pyx_t_28 = 0; __pyx_t_28 < 8; __pyx_t_28+=1) {
                      __pyx_v_i_sn = __pyx_t_28;

                      /* "pygeoprocessing/routing/routing.pyx":2852
 *                                             flow_dir_mfd_mr.get(xi_bn, yi_bn))
 *                                         for i_sn in range(8):
 *                                             if (flow_dir_mfd >> (i_sn*4)) & 0xF > 0:             # <<<<<<<<<<<<<<
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
*/
                      __pyx_t_1 = (((__pyx_v_flow_dir_mfd >> (__pyx_v_i_sn * 4)) & 0xF) > 0);
                      if (__pyx_t_1) {

                        /* "pygeoprocessing/routing/routing.pyx":2853
 *                                         for i_sn in range(8):
 *                                             if (flow_dir_mfd >> (i_sn*4)) & 0xF > 0:
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]             # <<<<<<<<<<<<<<
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or
*/
                        __pyx_v_xi_sn = (__pyx_v_xi_bn + (COL_OFFSETS[__pyx_v_i_sn]));

                        /* "pygeoprocessing/routing/routing.pyx":2854
 *                                             if (flow_dir_mfd >> (i_sn*4)) & 0xF > 0:
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]             # <<<<<<<<<<<<<<
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
*/
                        __pyx_v_yi_sn = (__pyx_v_yi_bn + (ROW_OFFSETS[__pyx_v_i_sn]));

                        /* "pygeoprocessing/routing/routing.pyx":2855
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue
*/
                        __pyx_t_2 = (__pyx_v_xi_sn < 0);
                        if (!__pyx_t_2) {
                        } else {
                          __pyx_t_1 = __pyx_t_2;
                          goto __pyx_L47_bool_binop_done;
                        }
                        __pyx_t_2 = (__pyx_v_xi_sn >= __pyx_v_raster_x_size);
                        if (!__pyx_t_2) {
                        } else {
                          __pyx_t_1 = __pyx_t_2;
                          goto __pyx_L47_bool_binop_done;
                        }

                        /* "pygeoprocessing/routing/routing.pyx":2856
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):             # <<<<<<<<<<<<<<
 *                                                     continue
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:
*/
                        __pyx_t_2 = (__pyx_v_yi_sn < 0);
                        if (!__pyx_t_2) {
                        } else {
                          __pyx_t_1 = __pyx_t_2;
                          goto __pyx_L47_bool_binop_done;
                        }
                        __pyx_t_2 = (__pyx_v_yi_sn >= __pyx_v_raster_y_size);
                        __pyx_t_1 = __pyx_t_2;
                        __pyx_L47_bool_binop_done:;

                        /* "pygeoprocessing/routing/routing.pyx":2855
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue
*/
                        if (__pyx_t_1) {

                          /* "pygeoprocessing/routing/routing.pyx":2857
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue             # <<<<<<<<<<<<<<
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)
*/
                          goto __pyx_L43_continue;

                          /* "pygeoprocessing/routing/routing.pyx":2855
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
 *                                                 if (xi_sn < 0 or xi_sn >= raster_x_size or             # <<<<<<<<<<<<<<
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue
*/
                        }

                        /* "pygeoprocessing/routing/routing.pyx":2858
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:             # <<<<<<<<<<<<<<
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                                     backtrace_set.push(
*/
                        __pyx_t_1 = (__pyx_v_stream_mr.get(__pyx_v_xi_sn, __pyx_v_yi_sn) == 2.0);
                        if (__pyx_t_1) {

                          /* "pygeoprocessing/routing/routing.pyx":2859
 *                                                     continue
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)             # <<<<<<<<<<<<<<
 *                                                     backtrace_set.push(
 *                                                         CoordinateType(xi_sn, yi_sn))
*/
                          __pyx_v_stream_mr.set(__pyx_v_xi_sn, __pyx_v_yi_sn, 1.0);

                          /* "pygeoprocessing/routing/routing.pyx":2861
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                                     backtrace_set.push(
 *                                                         CoordinateType(xi_sn, yi_sn))             # <<<<<<<<<<<<<<
 *                                 elif flow_accum >= trace_flow_threshold:
 *                                     stream_mr.set(xi_sn, yi_sn, 2)
*/
                          __pyx_t_27.xi = __pyx_v_xi_sn;
                          __pyx_t_27.yi = __pyx_v_yi_sn;

                          /* "pygeoprocessing/routing/routing.pyx":2860
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                                     backtrace_set.push(             # <<<<<<<<<<<<<<
 *                                                         CoordinateType(xi_sn, yi_sn))
 *                                 elif flow_accum >= trace_flow_threshold:
*/
                          __pyx_v_backtrace_set.push(__pyx_t_27);

                          /* "pygeoprocessing/routing/routing.pyx":2858
 *                                                         yi_sn < 0 or yi_sn >= raster_y_size):
 *                                                     continue
 *                                                 if stream_mr.get(xi_sn, yi_sn) == 2:             # <<<<<<<<<<<<<<
 *                                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                                     backtrace_set.push(
*/
                        }

                        /* "pygeoprocessing/routing/routing.pyx":2852
 *                                             flow_dir_mfd_mr.get(xi_bn, yi_bn))
 *                                         for i_sn in range(8):
 *                                             if (flow_dir_mfd >> (i_sn*4)) & 0xF > 0:             # <<<<<<<<<<<<<<
 *                                                 xi_sn = xi_bn+COL_OFFSETS[i_sn]
 *                                                 yi_sn = yi_bn+ROW_OFFSETS[i_sn]
*/
                      }
                      __pyx_L43_continue:;
                    }
                  }

                  /* "pygeoprocessing/routing/routing.pyx":2837
 *                                 flow_accum = flow_accum_mr.get(
 *                                     xi_sn, yi_sn)
 *                                 if flow_accum >= flow_threshold:             # <<<<<<<<<<<<<<
 *                                     stream_mr.set(xi_sn, yi_sn, 1)
 *                                     open_set.push(
*/
                  goto __pyx_L40;
                }

                /* "pygeoprocessing/routing/routing.pyx":2862
 *                                                     backtrace_set.push(
 *                                                         CoordinateType(xi_sn, yi_sn))
 *                                 elif flow_accum >= trace_flow_threshold:             # <<<<<<<<<<<<<<
 *                                     stream_mr.set(xi_sn, yi_sn, 2)
 *                                     open_set.push(
*/
                __pyx_t_1 = (__pyx_v_flow_accum >= __pyx_v_trace_flow_threshold);
                if (__pyx_t_1) {

                  /* "pygeoprocessing/routing/routing.pyx":2863
 *                                                         CoordinateType(xi_sn, yi_sn))
 *                                 elif flow_accum >= trace_flow_threshold:
 *                                     stream_mr.set(xi_sn, yi_sn, 2)             # <<<<<<<<<<<<<<
 *                                     open_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))
*/
                  __pyx_v_stream_mr.set(__pyx_v_xi_sn, __pyx_v_yi_sn, 2.0);

                  /* "pygeoprocessing/routing/routing.pyx":2865
 *                                     stream_mr.set(xi_sn, yi_sn, 2)
 *                                     open_set.push(
 *                                         CoordinateType(xi_sn, yi_sn))             # <<<<<<<<<<<<<<
 * 
 *     flow_accum_mr.close()
*/
                  __pyx_t_27.xi = __pyx_v_xi_sn;
                  __pyx_t_27.yi = __pyx_v_yi_sn;

                  /* "pygeoprocessing/routing/routing.pyx":2864
 *                                 elif flow_accum >= trace_flow_threshold:
 *                                     stream_mr.set(xi_sn, yi_sn, 2)
 *                                     open_set.push(             # <<<<<<<<<<<<<<
 *                                         CoordinateType(xi_sn, yi_sn))
 * 
*/
                  __pyx_v_open_set.push(__pyx_t_27);

                  /* "pygeoprocessing/routing/routing.pyx":2862
 *                                                     backtrace_set.push(
 *                                                         CoordinateType(xi_sn, yi_sn))
 *                                 elif flow_accum >= trace_flow_threshold:             # <<<<<<<<<<<<<<
 *                                     stream_mr.set(xi_sn, yi_sn, 2)
 *                                     open_set.push(
*/
                }
                __pyx_L40:;

                /* "pygeoprocessing/routing/routing.pyx":2834
 *                             # upstream pixel flows into this one
 *                             stream_val = <int>stream_mr.get(xi_sn, yi_sn)
 *                             if stream_val != 1 and stream_val != 2:             # <<<<<<<<<<<<<<
 *                                 flow_accum = flow_accum_mr.get(
 *                                     xi_sn, yi_sn)
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":2830
 *                         if flow_dir_mfd == flow_dir_nodata:
 *                             continue
 *                         if ((flow_dir_mfd >>             # <<<<<<<<<<<<<<
 *                                 (INFLOW_OFFSETS[i_sn] * 4)) & 0xF) > 0:
 *                             # upstream pixel flows into this one
*/
            }
            __pyx_L30_continue:;
          }
        }
        __pyx_L13_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":2771
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             (target_stream_raster_path, 1), offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2867
 *                                         CoordinateType(xi_sn, yi_sn))
 * 
 *     flow_accum_mr.close()             # <<<<<<<<<<<<<<
 *     stream_mr.close()
 *     flow_dir_mfd_mr.close()
*/
  __pyx_v_flow_accum_mr.close();

  /* "pygeoprocessing/routing/routing.pyx":2868
 * 
 *     flow_accum_mr.close()
 *     stream_mr.close()             # <<<<<<<<<<<<<<
 *     flow_dir_mfd_mr.close()
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')
*/
  __pyx_v_stream_mr.close();

  /* "pygeoprocessing/routing/routing.pyx":2869
 *     flow_accum_mr.close()
 *     stream_mr.close()
 *     flow_dir_mfd_mr.close()             # <<<<<<<<<<<<<<
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')
 *     block_offsets_list = list(pygeoprocessing.iterblocks(
*/
  __pyx_v_flow_dir_mfd_mr.close();

  /* "pygeoprocessing/routing/routing.pyx":2870
 *     stream_mr.close()
 *     flow_dir_mfd_mr.close()
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')             # <<<<<<<<<<<<<<
 *     block_offsets_list = list(pygeoprocessing.iterblocks(
 *         (target_stream_raster_path, 1), offset_only=True))
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2870, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2870, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_14))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_14);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_kp_u_Extract_streams_MFD_filter_out_i};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2871
 *     flow_dir_mfd_mr.close()
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')
 *     block_offsets_list = list(pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *         (target_stream_raster_path, 1), offset_only=True))
 *     stream_raster = gdal.OpenEx(
*/
  __pyx_t_14 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2871, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2871, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2872
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')
 *     block_offsets_list = list(pygeoprocessing.iterblocks(
 *         (target_stream_raster_path, 1), offset_only=True))             # <<<<<<<<<<<<<<
 *     stream_raster = gdal.OpenEx(
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)
*/
  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2872, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_INCREF(__pyx_v_target_stream_raster_path);
  __Pyx_GIVEREF(__pyx_v_target_stream_raster_path);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_target_stream_raster_path) != (0)) __PYX_ERR(0, 2872, __pyx_L1_error);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_1);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_mstate_global->__pyx_int_1) != (0)) __PYX_ERR(0, 2872, __pyx_L1_error);
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_14);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_14);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_14, __pyx_t_5};
    __pyx_t_13 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2871, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_13, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2871, __pyx_L1_error)
    __pyx_t_6 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_13);
    __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2871, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }

  /* "pygeoprocessing/routing/routing.pyx":2871
 *     flow_dir_mfd_mr.close()
 *     LOGGER.info('Extract streams MFD: filter out incomplete divergent streams')
 *     block_offsets_list = list(pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *         (target_stream_raster_path, 1), offset_only=True))
 *     stream_raster = gdal.OpenEx(
*/
  __pyx_t_12 = __Pyx_PySequence_ListKeepNew(__pyx_t_6); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2871, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_v_block_offsets_list = ((PyObject*)__pyx_t_12);
  __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2873
 *     block_offsets_list = list(pygeoprocessing.iterblocks(
 *         (target_stream_raster_path, 1), offset_only=True))
 *     stream_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     stream_band = stream_raster.GetRasterBand(1)
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2873, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2873, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2874
 *         (target_stream_raster_path, 1), offset_only=True))
 *     stream_raster = gdal.OpenEx(
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)             # <<<<<<<<<<<<<<
 *     stream_band = stream_raster.GetRasterBand(1)
 *     for block_offsets in block_offsets_list:
*/
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2874, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2874, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2874, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_GA_Update); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2874, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __pyx_t_13 = PyNumber_Or(__pyx_t_14, __pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2874, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_6, __pyx_v_target_stream_raster_path, __pyx_t_13};
    __pyx_t_12 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_7, (3-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2873, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
  }
  __pyx_v_stream_raster = __pyx_t_12;
  __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2875
 *     stream_raster = gdal.OpenEx(
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     stream_band = stream_raster.GetRasterBand(1)             # <<<<<<<<<<<<<<
 *     for block_offsets in block_offsets_list:
 *         stream_array = stream_band.ReadAsArray(**block_offsets)
*/
  __pyx_t_5 = __pyx_v_stream_raster;
  __Pyx_INCREF(__pyx_t_5);
  __pyx_t_7 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_int_1};
    __pyx_t_12 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2875, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
  }
  __pyx_v_stream_band = __pyx_t_12;
  __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2876
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     stream_band = stream_raster.GetRasterBand(1)
 *     for block_offsets in block_offsets_list:             # <<<<<<<<<<<<<<
 *         stream_array = stream_band.ReadAsArray(**block_offsets)
 *         stream_array[stream_array == 2] = 0
*/
  __pyx_t_12 = __pyx_v_block_offsets_list; __Pyx_INCREF(__pyx_t_12);
  __pyx_t_17 = 0;
  for (;;) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_12);
      #if !CYTHON_ASSUME_SAFE_SIZE
      if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 2876, __pyx_L1_error)
      #endif
      if (__pyx_t_17 >= __pyx_temp) break;
    }
    __pyx_t_5 = __Pyx_PyList_GetItemRefFast(__pyx_t_12, __pyx_t_17, __Pyx_ReferenceSharing_OwnStrongReference);
    ++__pyx_t_17;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2876, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_XDECREF_SET(__pyx_v_block_offsets, __pyx_t_5);
    __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2877
 *     stream_band = stream_raster.GetRasterBand(1)
 *     for block_offsets in block_offsets_list:
 *         stream_array = stream_band.ReadAsArray(**block_offsets)             # <<<<<<<<<<<<<<
 *         stream_array[stream_array == 2] = 0
 *         stream_band.WriteArray(
*/
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_stream_band, __pyx_mstate_global->__pyx_n_u_ReadAsArray); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2877, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (unlikely(__pyx_v_block_offsets == Py_None)) {
      PyErr_SetString(PyExc_TypeError, "argument after ** must be a mapping, not NoneType");
      __PYX_ERR(0, 2877, __pyx_L1_error)
    }
    if (likely(PyDict_CheckExact(__pyx_v_block_offsets))) {
      __pyx_t_13 = PyDict_Copy(__pyx_v_block_offsets); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2877, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_13);
    } else {
      __pyx_t_13 = __Pyx_PyObject_CallOneArg((PyObject*)&PyDict_Type, __pyx_v_block_offsets); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2877, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_13);
    }
    __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_mstate_global->__pyx_empty_tuple, __pyx_t_13); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2877, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_XDECREF_SET(__pyx_v_stream_array, __pyx_t_6);
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2878
 *     for block_offsets in block_offsets_list:
 *         stream_array = stream_band.ReadAsArray(**block_offsets)
 *         stream_array[stream_array == 2] = 0             # <<<<<<<<<<<<<<
 *         stream_band.WriteArray(
 *             stream_array, xoff=block_offsets['xoff'],
*/
    __pyx_t_6 = __Pyx_PyLong_EqObjC(__pyx_v_stream_array, __pyx_mstate_global->__pyx_int_2, 2, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2878, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    if (unlikely((PyObject_SetItem(__pyx_v_stream_array, __pyx_t_6, __pyx_mstate_global->__pyx_int_0) < 0))) __PYX_ERR(0, 2878, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2879
 *         stream_array = stream_band.ReadAsArray(**block_offsets)
 *         stream_array[stream_array == 2] = 0
 *         stream_band.WriteArray(             # <<<<<<<<<<<<<<
 *             stream_array, xoff=block_offsets['xoff'],
 *             yoff=block_offsets['yoff'])
*/
    __pyx_t_13 = __pyx_v_stream_band;
    __Pyx_INCREF(__pyx_t_13);

    /* "pygeoprocessing/routing/routing.pyx":2880
 *         stream_array[stream_array == 2] = 0
 *         stream_band.WriteArray(
 *             stream_array, xoff=block_offsets['xoff'],             # <<<<<<<<<<<<<<
 *             yoff=block_offsets['yoff'])
 *     stream_band = None
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2880, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);

    /* "pygeoprocessing/routing/routing.pyx":2881
 *         stream_band.WriteArray(
 *             stream_array, xoff=block_offsets['xoff'],
 *             yoff=block_offsets['yoff'])             # <<<<<<<<<<<<<<
 *     stream_band = None
 *     stream_raster = None
*/
    __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2881, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_7 = 0;
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_13, __pyx_v_stream_array};
      __pyx_t_14 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2879, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_14);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_xoff, __pyx_t_5, __pyx_t_14, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 2879, __pyx_L1_error)
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_yoff, __pyx_t_4, __pyx_t_14, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 2879, __pyx_L1_error)
      __pyx_t_6 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_WriteArray, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_14);
      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2879, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2876
 *         target_stream_raster_path, gdal.OF_RASTER | gdal.GA_Update)
 *     stream_band = stream_raster.GetRasterBand(1)
 *     for block_offsets in block_offsets_list:             # <<<<<<<<<<<<<<
 *         stream_array = stream_band.ReadAsArray(**block_offsets)
 *         stream_array[stream_array == 2] = 0
*/
  }
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2882
 *             stream_array, xoff=block_offsets['xoff'],
 *             yoff=block_offsets['yoff'])
 *     stream_band = None             # <<<<<<<<<<<<<<
 *     stream_raster = None
 *     LOGGER.info('Extract streams MFD: 100.0% complete')
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_stream_band, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":2883
 *             yoff=block_offsets['yoff'])
 *     stream_band = None
 *     stream_raster = None             # <<<<<<<<<<<<<<
 *     LOGGER.info('Extract streams MFD: 100.0% complete')
 * 
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_stream_raster, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":2884
 *     stream_band = None
 *     stream_raster = None
 *     LOGGER.info('Extract streams MFD: 100.0% complete')             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 2884, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2884, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
  __pyx_t_7 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_7 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_kp_u_Extract_streams_MFD_100_0_comple};
    __pyx_t_12 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_7, (2-__pyx_t_7) | (__pyx_t_7*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2884, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
  }
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2679
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_streams_mfd(
 *         flow_accum_raster_path_band, flow_dir_mfd_path_band,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_XDECREF(__pyx_t_13);
  __Pyx_XDECREF(__pyx_t_14);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.extract_streams_mfd", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_flow_accum_info);
  __Pyx_XDECREF(__pyx_v_block_offsets);
  __Pyx_XDECREF(__pyx_v_block_offsets_list);
  __Pyx_XDECREF(__pyx_v_stream_raster);
  __Pyx_XDECREF(__pyx_v_stream_band);
  __Pyx_XDECREF(__pyx_v_stream_array);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":2887
 * 
 * 
 * def _is_raster_path_band_formatted(raster_path_band):             # <<<<<<<<<<<<<<
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_19_is_raster_path_band_formatted(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_18_is_raster_path_band_formatted, "Return true if raster path band is a (str, int) tuple/list.");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_19_is_raster_path_band_formatted = {"_is_raster_path_band_formatted", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_19_is_raster_path_band_formatted, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_18_is_raster_path_band_formatted};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_19_is_raster_path_band_formatted(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_raster_path_band = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[1] = {0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_is_raster_path_band_formatted (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_raster_path_band,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2887, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2887, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "_is_raster_path_band_formatted", 0) < (0)) __PYX_ERR(0, 2887, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 1; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("_is_raster_path_band_formatted", 1, 1, 1, i); __PYX_ERR(0, 2887, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 1)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2887, __pyx_L3_error)
    }
    __pyx_v_raster_path_band = values[0];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("_is_raster_path_band_formatted", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 2887, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._is_raster_path_band_formatted", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_18_is_raster_path_band_formatted(__pyx_self, __pyx_v_raster_path_band);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_18_is_raster_path_band_formatted(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_raster_path_band) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  int __pyx_t_1;
  int __pyx_t_2;
  Py_ssize_t __pyx_t_3;
  PyObject *__pyx_t_4 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_is_raster_path_band_formatted", 0);

  /* "pygeoprocessing/routing/routing.pyx":2889
 * def _is_raster_path_band_formatted(raster_path_band):
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):             # <<<<<<<<<<<<<<
 *         return False
 *     elif len(raster_path_band) != 2:
*/
  __pyx_t_2 = PyList_Check(__pyx_v_raster_path_band); 
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = PyTuple_Check(__pyx_v_raster_path_band); 
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  __pyx_t_2 = (!__pyx_t_1);
  if (__pyx_t_2) {

    /* "pygeoprocessing/routing/routing.pyx":2890
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):
 *         return False             # <<<<<<<<<<<<<<
 *     elif len(raster_path_band) != 2:
 *         return False
*/
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(Py_False);
    __pyx_r = Py_False;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":2889
 * def _is_raster_path_band_formatted(raster_path_band):
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):             # <<<<<<<<<<<<<<
 *         return False
 *     elif len(raster_path_band) != 2:
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2891
 *     if not isinstance(raster_path_band, (list, tuple)):
 *         return False
 *     elif len(raster_path_band) != 2:             # <<<<<<<<<<<<<<
 *         return False
 *     elif not isinstance(raster_path_band[0], basestring):
*/
  __pyx_t_3 = PyObject_Length(__pyx_v_raster_path_band); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(0, 2891, __pyx_L1_error)
  __pyx_t_2 = (__pyx_t_3 != 2);
  if (__pyx_t_2) {

    /* "pygeoprocessing/routing/routing.pyx":2892
 *         return False
 *     elif len(raster_path_band) != 2:
 *         return False             # <<<<<<<<<<<<<<
 *     elif not isinstance(raster_path_band[0], basestring):
 *         return False
*/
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(Py_False);
    __pyx_r = Py_False;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":2891
 *     if not isinstance(raster_path_band, (list, tuple)):
 *         return False
 *     elif len(raster_path_band) != 2:             # <<<<<<<<<<<<<<
 *         return False
 *     elif not isinstance(raster_path_band[0], basestring):
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2893
 *     elif len(raster_path_band) != 2:
 *         return False
 *     elif not isinstance(raster_path_band[0], basestring):             # <<<<<<<<<<<<<<
 *         return False
 *     elif not isinstance(raster_path_band[1], int):
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2893, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = PyUnicode_Check(__pyx_t_4); 
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_1 = (!__pyx_t_2);
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":2894
 *         return False
 *     elif not isinstance(raster_path_band[0], basestring):
 *         return False             # <<<<<<<<<<<<<<
 *     elif not isinstance(raster_path_band[1], int):
 *         return False
*/
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(Py_False);
    __pyx_r = Py_False;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":2893
 *     elif len(raster_path_band) != 2:
 *         return False
 *     elif not isinstance(raster_path_band[0], basestring):             # <<<<<<<<<<<<<<
 *         return False
 *     elif not isinstance(raster_path_band[1], int):
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2895
 *     elif not isinstance(raster_path_band[0], basestring):
 *         return False
 *     elif not isinstance(raster_path_band[1], int):             # <<<<<<<<<<<<<<
 *         return False
 *     else:
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2895, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = PyLong_Check(__pyx_t_4); 
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_2 = (!__pyx_t_1);
  if (__pyx_t_2) {

    /* "pygeoprocessing/routing/routing.pyx":2896
 *         return False
 *     elif not isinstance(raster_path_band[1], int):
 *         return False             # <<<<<<<<<<<<<<
 *     else:
 *         return True
*/
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(Py_False);
    __pyx_r = Py_False;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":2895
 *     elif not isinstance(raster_path_band[0], basestring):
 *         return False
 *     elif not isinstance(raster_path_band[1], int):             # <<<<<<<<<<<<<<
 *         return False
 *     else:
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":2898
 *         return False
 *     else:
 *         return True             # <<<<<<<<<<<<<<
 * 
 * 
*/
  /*else*/ {
    __Pyx_XDECREF(__pyx_r);
    __Pyx_INCREF(Py_True);
    __pyx_r = Py_True;
    goto __pyx_L0;
  }

  /* "pygeoprocessing/routing/routing.pyx":2887
 * 
 * 
 * def _is_raster_path_band_formatted(raster_path_band):             # <<<<<<<<<<<<<<
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._is_raster_path_band_formatted", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":2901
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_strahler_streams_d8(
 *         flow_dir_d8_raster_path_band, flow_accum_raster_path_band,
*/

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_48__defaults__(CYTHON_UNUSED PyObject *__pyx_self) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  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("__defaults__", 0);
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":2906
 *         dem_raster_path_band,
 *         target_stream_vector_path,
 *         long min_flow_accum_threshold=100,             # <<<<<<<<<<<<<<
 *         int river_order=5,
 *         float min_p_val=0.05,
*/
  __pyx_t_1 = __Pyx_PyLong_From_long(((long)0x64)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2906, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":2907
 *         target_stream_vector_path,
 *         long min_flow_accum_threshold=100,
 *         int river_order=5,             # <<<<<<<<<<<<<<
 *         float min_p_val=0.05,
 *         autotune_flow_accumulation=False,
*/
  __pyx_t_2 = __Pyx_PyLong_From_int(((int)5)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2907, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":2908
 *         long min_flow_accum_threshold=100,
 *         int river_order=5,
 *         float min_p_val=0.05,             # <<<<<<<<<<<<<<
 *         autotune_flow_accumulation=False,
 *         osr_axis_mapping_strategy=DEFAULT_OSR_AXIS_MAPPING_STRATEGY):
*/
  __pyx_t_3 = PyFloat_FromDouble(((double)0.05)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2908, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":2901
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_strahler_streams_d8(
 *         flow_dir_d8_raster_path_band, flow_accum_raster_path_band,
*/
  __pyx_t_4 = PyTuple_New(5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2901, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_3);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __Pyx_INCREF(((PyObject*)Py_False));
  __Pyx_GIVEREF(((PyObject*)Py_False));
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 3, ((PyObject*)Py_False)) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __Pyx_INCREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  __Pyx_GIVEREF(__Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 4, __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self)->arg0) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_2 = 0;
  __pyx_t_3 = 0;
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2901, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_4);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __Pyx_INCREF(Py_None);
  __Pyx_GIVEREF(Py_None);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, Py_None) != (0)) __PYX_ERR(0, 2901, __pyx_L1_error);
  __pyx_t_4 = 0;
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;

  /* 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_AddTraceback("pygeoprocessing.routing.routing.__defaults__", __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_15pygeoprocessing_7routing_7routing_21extract_strahler_streams_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_20extract_strahler_streams_d8, "Extract Strahler order stream geometry from flow accumulation.\n\n    Creates a Strahler ordered stream vector containing line segments\n    representing each separate stream fragment. The final vector contains\n    at least the fields:\n\n        * \"order\" (int): an integer representing the stream order\n        * \"river_id\" (int): unique ID used by all stream segments that\n            connect to the same outlet.\n        * \"drop_distance\" (float): this is the drop distance in DEM units\n            from the upstream to downstream component of this stream\n            segment.\n        * \"outlet\" (int): 1 if this segment is an outlet, 0 if not.\n        * \"us_fa\" (int): flow accumulation value at the upstream end of\n            the stream segment.\n        * \"ds_fa\" (int): flow accumulation value at the downstream end of\n            the stream segment\n        * \"thresh_fa\" (int): the final threshold flow accumulation value\n            used to determine the river segments.\n        * \"upstream_d8_dir\" (int): a bookkeeping parameter from stream\n            calculations that is left in due to the overhead\n            of deleting a field.\n        * \"ds_x\" (int): the raster x coordinate for the outlet.\n        * \"ds_y\" (int): the raster y coordinate for the outlet.\n        * \"ds_x_1\" (int): the x raster space coordinate that is 1 pixel\n            upstream from the outlet.\n        * \"ds_y_1\" (int): the y raster space coordinate that is 1 pixel\n            upstream from the outlet.\n        * \"us_x\" (int): the raster x coordinate for the upstream inlet.\n        * \"us_y\" (int): the raster y coordinate for the upstream inlet.\n\n    Args:\n        flow_dir_d8_raster_path_band (tuple): a path/band representing the D8\n            flow direction raster. Paths may use any GDAL-supported scheme,\n            including virtual file system /vsi schemes.\n        flow_accum_raster_path_band (tuple): a path/band representing the D8\n      ""      flow accumulation raster represented by\n            ``flow_dir_d8_raster_path_band``. Paths may use any GDAL-supported\n            scheme, including virtual file system /vsi schemes.\n        dem_raster_path_band (tuple): a path/band representing the DEM used to\n            derive flow dir. Paths may use any GDAL-supported scheme, including\n            virtual file system /vsi schemes.\n        target_stream_vector_path (tuple): a single layer line vector created\n            by this function representing the stream segments extracted from\n            the above arguments. Contains the fields \"order\" and \"parent\" as\n            described above.\n        min_flow_accum_threshold (int): minimum number of upstream pixels\n            required to create a stream. If ``autotune_flow_accumulation``\n            is True, then the final value may be adjusted based on\n            significant differences in 1st and 2nd order streams.\n        river_order (int): what stream order to define as a river in terms of\n            automatically determining flow accumulation threshold for that\n            stream collection.\n        min_p_val (float): minimum p_value test for significance\n        autotune_flow_accumulation (bool): If true, uses a t-test to test for\n            significant distances in order 1 and order 2 streams. If it is\n            significant the flow accumulation parameter is adjusted upwards\n            until the drop distances are insignificant.\n        osr_axis_mapping_strategy (int): OSR axis mapping strategy for\n            ``SpatialReference`` objects. Defaults to\n            ``geoprocessing.DEFAULT_OSR_AXIS_MAPPING_STRATEGY``. This parameter\n            should not be changed unless you know what you are doing.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_21extract_strahler_streams_d8 = {"extract_strahler_streams_d8", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_21extract_strahler_streams_d8, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_20extract_strahler_streams_d8};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_21extract_strahler_streams_d8(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_d8_raster_path_band = 0;
  PyObject *__pyx_v_flow_accum_raster_path_band = 0;
  PyObject *__pyx_v_dem_raster_path_band = 0;
  PyObject *__pyx_v_target_stream_vector_path = 0;
  long __pyx_v_min_flow_accum_threshold;
  int __pyx_v_river_order;
  float __pyx_v_min_p_val;
  PyObject *__pyx_v_autotune_flow_accumulation = 0;
  PyObject *__pyx_v_osr_axis_mapping_strategy = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[9] = {0,0,0,0,0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("extract_strahler_streams_d8 (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_d8_raster_path_band,&__pyx_mstate_global->__pyx_n_u_flow_accum_raster_path_band,&__pyx_mstate_global->__pyx_n_u_dem_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_stream_vector_path,&__pyx_mstate_global->__pyx_n_u_min_flow_accum_threshold,&__pyx_mstate_global->__pyx_n_u_river_order,&__pyx_mstate_global->__pyx_n_u_min_p_val,&__pyx_mstate_global->__pyx_n_u_autotune_flow_accumulation,&__pyx_mstate_global->__pyx_n_u_osr_axis_mapping_strategy,0};
    struct __pyx_defaults *__pyx_dynamic_args = __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_self);
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 2901, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  9:
        values[8] = __Pyx_ArgRef_FASTCALL(__pyx_args, 8);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[8])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  8:
        values[7] = __Pyx_ArgRef_FASTCALL(__pyx_args, 7);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[7])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  7:
        values[6] = __Pyx_ArgRef_FASTCALL(__pyx_args, 6);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[6])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "extract_strahler_streams_d8", 0) < (0)) __PYX_ERR(0, 2901, __pyx_L3_error)
      if (!values[7]) values[7] = __Pyx_NewRef(((PyObject *)((PyObject*)Py_False)));
      if (!values[8]) values[8] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
      for (Py_ssize_t i = __pyx_nargs; i < 4; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("extract_strahler_streams_d8", 0, 4, 9, i); __PYX_ERR(0, 2901, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  9:
        values[8] = __Pyx_ArgRef_FASTCALL(__pyx_args, 8);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[8])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  8:
        values[7] = __Pyx_ArgRef_FASTCALL(__pyx_args, 7);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[7])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  7:
        values[6] = __Pyx_ArgRef_FASTCALL(__pyx_args, 6);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[6])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  6:
        values[5] = __Pyx_ArgRef_FASTCALL(__pyx_args, 5);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[5])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 2901, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 2901, __pyx_L3_error)
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 2901, __pyx_L3_error)
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 2901, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 2901, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[7]) values[7] = __Pyx_NewRef(((PyObject *)((PyObject*)Py_False)));
      if (!values[8]) values[8] = __Pyx_NewRef(__pyx_dynamic_args->arg0);
    }
    __pyx_v_flow_dir_d8_raster_path_band = values[0];
    __pyx_v_flow_accum_raster_path_band = values[1];
    __pyx_v_dem_raster_path_band = values[2];
    __pyx_v_target_stream_vector_path = values[3];
    if (values[4]) {
      __pyx_v_min_flow_accum_threshold = __Pyx_PyLong_As_long(values[4]); if (unlikely((__pyx_v_min_flow_accum_threshold == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 2906, __pyx_L3_error)
    } else {
      __pyx_v_min_flow_accum_threshold = ((long)((long)0x64));
    }
    if (values[5]) {
      __pyx_v_river_order = __Pyx_PyLong_As_int(values[5]); if (unlikely((__pyx_v_river_order == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 2907, __pyx_L3_error)
    } else {
      __pyx_v_river_order = ((int)((int)5));
    }
    if (values[6]) {
      __pyx_v_min_p_val = __Pyx_PyFloat_AsFloat(values[6]); if (unlikely((__pyx_v_min_p_val == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 2908, __pyx_L3_error)
    } else {
      __pyx_v_min_p_val = ((float)((double)0.05));
    }
    __pyx_v_autotune_flow_accumulation = values[7];
    __pyx_v_osr_axis_mapping_strategy = values[8];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("extract_strahler_streams_d8", 0, 4, 9, __pyx_nargs); __PYX_ERR(0, 2901, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.extract_strahler_streams_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_20extract_strahler_streams_d8(__pyx_self, __pyx_v_flow_dir_d8_raster_path_band, __pyx_v_flow_accum_raster_path_band, __pyx_v_dem_raster_path_band, __pyx_v_target_stream_vector_path, __pyx_v_min_flow_accum_threshold, __pyx_v_river_order, __pyx_v_min_p_val, __pyx_v_autotune_flow_accumulation, __pyx_v_osr_axis_mapping_strategy);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_20extract_strahler_streams_d8(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_flow_accum_raster_path_band, PyObject *__pyx_v_dem_raster_path_band, PyObject *__pyx_v_target_stream_vector_path, long __pyx_v_min_flow_accum_threshold, int __pyx_v_river_order, float __pyx_v_min_p_val, PyObject *__pyx_v_autotune_flow_accumulation, PyObject *__pyx_v_osr_axis_mapping_strategy) {
  PyObject *__pyx_v_flow_dir_info = NULL;
  PyObject *__pyx_v_flow_dir_srs = NULL;
  PyObject *__pyx_v_gpkg_driver = NULL;
  PyObject *__pyx_v_stream_vector = NULL;
  PyObject *__pyx_v_stream_basename = NULL;
  PyObject *__pyx_v_stream_layer = NULL;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  ManagedRaster __pyx_v_flow_accum_managed_raster;
  ManagedRaster __pyx_v_dem_managed_raster;
  int __pyx_v_flow_nodata;
  double __pyx_v_flow_accum_nodata;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_i;
  unsigned int __pyx_v_j;
  unsigned int __pyx_v_d;
  unsigned int __pyx_v_d_n;
  unsigned int __pyx_v_n_cols;
  unsigned int __pyx_v_n_rows;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_win_ysize;
  unsigned long __pyx_v_n_pixels;
  long __pyx_v_n_processed;
  time_t __pyx_v_last_log_time;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_StreamConnectivityPoint>  __pyx_v_source_point_stack;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_StreamConnectivityPoint __pyx_v_source_stream_point;
  unsigned int __pyx_v_x_l;
  unsigned int __pyx_v_y_l;
  unsigned int __pyx_v_x_n;
  unsigned int __pyx_v_y_n;
  unsigned int __pyx_v_upstream_count;
  unsigned int __pyx_v_upstream_index;
  int *__pyx_v_upstream_dirs;
  double __pyx_v_local_flow_accum;
  int __pyx_v_is_drain;
  PyObject *__pyx_v_coord_to_stream_ids = NULL;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_stream_feature = NULL;
  PyObject *__pyx_v_stream_fid = NULL;
  PyObject *__pyx_v_n_points = NULL;
  PyObject *__pyx_v_downstream_to_upstream_ids = NULL;
  PyObject *__pyx_v_upstream_to_downstream_id = NULL;
  PyObject *__pyx_v_payload = NULL;
  PyObject *__pyx_v_x_u = NULL;
  PyObject *__pyx_v_y_u = NULL;
  PyObject *__pyx_v_ds_x_1 = NULL;
  PyObject *__pyx_v_ds_y_1 = NULL;
  PyObject *__pyx_v_upstream_id_list = NULL;
  PyObject *__pyx_v_stream_line = NULL;
  double __pyx_v_downstream_dem;
  PyObject *__pyx_v_upstream_id = NULL;
  double __pyx_v_upstream_dem;
  double __pyx_v_drop_distance;
  PyObject *__pyx_v_streams_to_process = NULL;
  PyObject *__pyx_v_base_feature_count = NULL;
  PyObject *__pyx_v_outlet_fid_list = NULL;
  PyObject *__pyx_v_downstream_fid = NULL;
  PyObject *__pyx_v_downstream_feature = NULL;
  PyObject *__pyx_v_connected_upstream_fids = NULL;
  PyObject *__pyx_v_stream_order_list = NULL;
  int __pyx_v_all_defined;
  PyObject *__pyx_v_upstream_fid = NULL;
  PyObject *__pyx_v_upstream_feature = NULL;
  PyObject *__pyx_v_upstream_order = NULL;
  PyObject *__pyx_v_sorted_stream_order_list = NULL;
  PyObject *__pyx_v_downstream_order = NULL;
  PyObject *__pyx_v_working_river_id = NULL;
  PyObject *__pyx_v_outlet_index = NULL;
  PyObject *__pyx_v_outlet_fid = NULL;
  PyObject *__pyx_v_search_stack = NULL;
  PyObject *__pyx_v_feature_id = NULL;
  PyObject *__pyx_v_stream_order = NULL;
  PyObject *__pyx_v_upstream_stack = NULL;
  PyObject *__pyx_v_streams_by_order = NULL;
  PyObject *__pyx_v_drop_distance_collection = NULL;
  PyObject *__pyx_v_max_upstream_flow_accum = NULL;
  PyObject *__pyx_v_order = NULL;
  PyObject *__pyx_v_working_flow_accum_threshold = NULL;
  PyObject *__pyx_v_test_order = NULL;
  CYTHON_UNUSED PyObject *__pyx_v__ = NULL;
  PyObject *__pyx_v_p_val = NULL;
  PyObject *__pyx_v_streams_to_retest = NULL;
  PyObject *__pyx_v_ds_x = NULL;
  PyObject *__pyx_v_ds_y = NULL;
  PyObject *__pyx_v_upstream_d8_dir = NULL;
  PyObject *__pyx_v_working_stack = NULL;
  PyObject *__pyx_v_fid_to_order = NULL;
  PyObject *__pyx_v_processed_segments = NULL;
  Py_ssize_t __pyx_v_segments_to_process;
  PyObject *__pyx_v_deleted_set = NULL;
  PyObject *__pyx_v_working_fid = NULL;
  PyObject *__pyx_v_upstream_fid_list = NULL;
  PyObject *__pyx_v_order_count = NULL;
  PyObject *__pyx_v_working_order = NULL;
  PyObject *__pyx_v_working_feature = NULL;
  PyObject *__pyx_v_connected_fids = NULL;
  PyObject *__pyx_v_downstream_geom = NULL;
  PyObject *__pyx_v_working_geom = NULL;
  PyObject *__pyx_v_multi_line = NULL;
  PyObject *__pyx_v_joined_line = NULL;
  int __pyx_v_upstream_all_defined;
  PyObject *__pyx_v_connected_fid = NULL;
  PyObject *__pyx_7genexpr__pyx_v_stream_feature = NULL;
  PyObject *__pyx_8genexpr1__pyx_v_fid = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  size_t __pyx_t_5;
  int __pyx_t_6;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  char *__pyx_t_10;
  int __pyx_t_11;
  ManagedRaster __pyx_t_12;
  double __pyx_t_13;
  PyObject *(*__pyx_t_14)(PyObject *);
  unsigned int __pyx_t_15;
  unsigned int __pyx_t_16;
  int __pyx_t_17[8];
  Py_ssize_t __pyx_t_18;
  PyObject *(*__pyx_t_19)(PyObject *);
  PyObject *__pyx_t_20[5];
  unsigned int __pyx_t_21;
  unsigned int __pyx_t_22;
  unsigned int __pyx_t_23;
  unsigned int __pyx_t_24;
  int __pyx_t_25;
  unsigned int __pyx_t_26;
  unsigned int __pyx_t_27;
  unsigned int __pyx_t_28;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_StreamConnectivityPoint __pyx_t_29;
  unsigned int __pyx_t_30;
  int __pyx_t_31;
  PyObject *__pyx_t_32[6];
  long __pyx_t_33;
  long __pyx_t_34;
  Py_ssize_t __pyx_t_35;
  PyObject *__pyx_t_36 = NULL;
  int __pyx_t_37;
  int __pyx_t_38;
  int __pyx_t_39;
  PyObject *__pyx_t_40 = NULL;
  PyObject *__pyx_t_41 = NULL;
  PyObject *__pyx_t_42 = NULL;
  PyObject *__pyx_t_43 = NULL;
  PyObject *__pyx_t_44 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("extract_strahler_streams_d8", 0);

  /* "pygeoprocessing/routing/routing.pyx":2977
 *         None.
 *     """
 *     flow_dir_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0])
 *     if flow_dir_info['projection_wkt']:
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2977, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2977, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2978
 *     """
 *     flow_dir_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     if flow_dir_info['projection_wkt']:
 *         flow_dir_srs = osr.SpatialReference()
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2978, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2977, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2979
 *     flow_dir_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])
 *     if flow_dir_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         flow_dir_srs = osr.SpatialReference()
 *         flow_dir_srs.ImportFromWkt(flow_dir_info['projection_wkt'])
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2979, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 2979, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (__pyx_t_6) {

    /* "pygeoprocessing/routing/routing.pyx":2980
 *         flow_dir_d8_raster_path_band[0])
 *     if flow_dir_info['projection_wkt']:
 *         flow_dir_srs = osr.SpatialReference()             # <<<<<<<<<<<<<<
 *         flow_dir_srs.ImportFromWkt(flow_dir_info['projection_wkt'])
 *         flow_dir_srs.SetAxisMappingStrategy(osr_axis_mapping_strategy)
*/
    __pyx_t_4 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_osr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2980, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_SpatialReference); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2980, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_5 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_4);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_5 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2980, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_v_flow_dir_srs = __pyx_t_1;
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2981
 *     if flow_dir_info['projection_wkt']:
 *         flow_dir_srs = osr.SpatialReference()
 *         flow_dir_srs.ImportFromWkt(flow_dir_info['projection_wkt'])             # <<<<<<<<<<<<<<
 *         flow_dir_srs.SetAxisMappingStrategy(osr_axis_mapping_strategy)
 *     else:
*/
    __pyx_t_2 = __pyx_v_flow_dir_srs;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2981, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_ImportFromWkt, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2981, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2982
 *         flow_dir_srs = osr.SpatialReference()
 *         flow_dir_srs.ImportFromWkt(flow_dir_info['projection_wkt'])
 *         flow_dir_srs.SetAxisMappingStrategy(osr_axis_mapping_strategy)             # <<<<<<<<<<<<<<
 *     else:
 *         flow_dir_srs = None
*/
    __pyx_t_4 = __pyx_v_flow_dir_srs;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_osr_axis_mapping_strategy};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetAxisMappingStrategy, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2982, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":2979
 *     flow_dir_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])
 *     if flow_dir_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         flow_dir_srs = osr.SpatialReference()
 *         flow_dir_srs.ImportFromWkt(flow_dir_info['projection_wkt'])
*/
    goto __pyx_L3;
  }

  /* "pygeoprocessing/routing/routing.pyx":2984
 *         flow_dir_srs.SetAxisMappingStrategy(osr_axis_mapping_strategy)
 *     else:
 *         flow_dir_srs = None             # <<<<<<<<<<<<<<
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
*/
  /*else*/ {
    __Pyx_INCREF(Py_None);
    __pyx_v_flow_dir_srs = Py_None;
  }
  __pyx_L3:;

  /* "pygeoprocessing/routing/routing.pyx":2985
 *     else:
 *         flow_dir_srs = None
 *     gpkg_driver = gdal.GetDriverByName('GPKG')             # <<<<<<<<<<<<<<
 * 
 *     stream_vector = gpkg_driver.Create(
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2985, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_GetDriverByName); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2985, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_GPKG};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2985, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_gpkg_driver = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2987
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
 *     stream_vector = gpkg_driver.Create(             # <<<<<<<<<<<<<<
 *         target_stream_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     stream_basename = os.path.basename(
*/
  __pyx_t_3 = __pyx_v_gpkg_driver;
  __Pyx_INCREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":2988
 * 
 *     stream_vector = gpkg_driver.Create(
 *         target_stream_vector_path, 0, 0, 0, gdal.GDT_Unknown)             # <<<<<<<<<<<<<<
 *     stream_basename = os.path.basename(
 *         os.path.splitext(target_stream_vector_path)[0])
*/
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2988, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_GDT_Unknown); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2988, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[6] = {__pyx_t_3, __pyx_v_target_stream_vector_path, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_Create, __pyx_callargs+__pyx_t_5, (6-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2987, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_stream_vector = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2989
 *     stream_vector = gpkg_driver.Create(
 *         target_stream_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     stream_basename = os.path.basename(             # <<<<<<<<<<<<<<
 *         os.path.splitext(target_stream_vector_path)[0])
 *     stream_layer = stream_vector.CreateLayer(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2989, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2989, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_2 = __pyx_t_4;
  __Pyx_INCREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":2990
 *         target_stream_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     stream_basename = os.path.basename(
 *         os.path.splitext(target_stream_vector_path)[0])             # <<<<<<<<<<<<<<
 *     stream_layer = stream_vector.CreateLayer(
 *         stream_basename, flow_dir_srs, ogr.wkbLineString)
*/
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2990, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2990, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_7 = __pyx_t_9;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_v_target_stream_vector_path};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_splitext, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2990, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_9 = __Pyx_GetItemInt(__pyx_t_3, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2990, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_9};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_basename, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2989, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_stream_basename = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2991
 *     stream_basename = os.path.basename(
 *         os.path.splitext(target_stream_vector_path)[0])
 *     stream_layer = stream_vector.CreateLayer(             # <<<<<<<<<<<<<<
 *         stream_basename, flow_dir_srs, ogr.wkbLineString)
 *     stream_layer.CreateField(ogr.FieldDefn('order', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_vector;
  __Pyx_INCREF(__pyx_t_4);

  /* "pygeoprocessing/routing/routing.pyx":2992
 *         os.path.splitext(target_stream_vector_path)[0])
 *     stream_layer = stream_vector.CreateLayer(
 *         stream_basename, flow_dir_srs, ogr.wkbLineString)             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('order', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('drop_distance', ogr.OFTReal))
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2992, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_wkbLineString); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2992, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[4] = {__pyx_t_4, __pyx_v_stream_basename, __pyx_v_flow_dir_srs, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateLayer, __pyx_callargs+__pyx_t_5, (4-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2991, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_stream_layer = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2993
 *     stream_layer = stream_vector.CreateLayer(
 *         stream_basename, flow_dir_srs, ogr.wkbLineString)
 *     stream_layer.CreateField(ogr.FieldDefn('order', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('drop_distance', ogr.OFTReal))
 *     stream_layer.CreateField(ogr.FieldDefn('outlet', ogr.OFTInteger))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2993, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2993, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2993, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2993, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_order, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2993, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2993, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2994
 *         stream_basename, flow_dir_srs, ogr.wkbLineString)
 *     stream_layer.CreateField(ogr.FieldDefn('order', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('drop_distance', ogr.OFTReal))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('outlet', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('river_id', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2994, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2994, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2994, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTReal); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2994, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_drop_distance, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2994, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2994, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2995
 *     stream_layer.CreateField(ogr.FieldDefn('order', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('drop_distance', ogr.OFTReal))
 *     stream_layer.CreateField(ogr.FieldDefn('outlet', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('river_id', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_fa', ogr.OFTInteger64))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2995, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2995, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2995, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2995, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_outlet, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2995, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2995, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2996
 *     stream_layer.CreateField(ogr.FieldDefn('drop_distance', ogr.OFTReal))
 *     stream_layer.CreateField(ogr.FieldDefn('outlet', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('river_id', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('us_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_fa', ogr.OFTInteger64))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2996, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2996, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2996, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2996, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_river_id, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2996, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2996, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2997
 *     stream_layer.CreateField(ogr.FieldDefn('outlet', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('river_id', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_fa', ogr.OFTInteger64))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('ds_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('thresh_fa', ogr.OFTInteger64))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2997, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2997, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2997, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger64); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2997, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_us_fa, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2997, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2997, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2998
 *     stream_layer.CreateField(ogr.FieldDefn('river_id', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_fa', ogr.OFTInteger64))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('thresh_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('upstream_d8_dir', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2998, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2998, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2998, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger64); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2998, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_ds_fa, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2998, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2998, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2999
 *     stream_layer.CreateField(ogr.FieldDefn('us_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('thresh_fa', ogr.OFTInteger64))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('upstream_d8_dir', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x', ogr.OFTInteger))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2999, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2999, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 2999, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger64); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 2999, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_thresh_fa, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2999, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2999, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3000
 *     stream_layer.CreateField(ogr.FieldDefn('ds_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('thresh_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('upstream_d8_dir', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3000, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3000, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3000, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3000, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_upstream_d8_dir, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3000, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3000, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3001
 *     stream_layer.CreateField(ogr.FieldDefn('thresh_fa', ogr.OFTInteger64))
 *     stream_layer.CreateField(ogr.FieldDefn('upstream_d8_dir', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x_1', ogr.OFTInteger))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3001, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_ds_x, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3001, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3001, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3002
 *     stream_layer.CreateField(ogr.FieldDefn('upstream_d8_dir', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y_1', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3002, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3002, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3002, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3002, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_ds_y, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3002, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3002, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3003
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x_1', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_x', ogr.OFTInteger))
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3003, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3003, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3003, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3003, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_ds_x_1, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3003, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3003, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3004
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y_1', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('us_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_y', ogr.OFTInteger))
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3004, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3004, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3004, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3004, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_ds_y_1, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3004, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3004, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3005
 *     stream_layer.CreateField(ogr.FieldDefn('ds_x_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_x', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     stream_layer.CreateField(ogr.FieldDefn('us_y', ogr.OFTInteger))
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3005, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3005, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3005, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3005, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_us_x, __pyx_t_8};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3005, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3005, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3006
 *     stream_layer.CreateField(ogr.FieldDefn('ds_y_1', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_y', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_4 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3006, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3006, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3006, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3006, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_us_y, __pyx_t_3};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3006, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3006, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3008
 *     stream_layer.CreateField(ogr.FieldDefn('us_y', ogr.OFTInteger))
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[1], False)
 * 
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3008, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __pyx_t_4;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3008, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_10 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 3008, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3009
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     flow_accum_managed_raster = ManagedRaster(
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3009, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_4); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3009, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3007
 *     stream_layer.CreateField(ogr.FieldDefn('us_x', ogr.OFTInteger))
 *     stream_layer.CreateField(ogr.FieldDefn('us_y', ogr.OFTInteger))
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)
*/
  try {
    __pyx_t_12 = ManagedRaster(__pyx_t_10, __pyx_t_11, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3007, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_12);

  /* "pygeoprocessing/routing/routing.pyx":3012
 * 
 *     flow_accum_managed_raster = ManagedRaster(
 *         flow_accum_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1], False)
 * 
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3012, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = __pyx_t_2;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3012, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_10 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 3012, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3013
 *     flow_accum_managed_raster = ManagedRaster(
 *         flow_accum_raster_path_band[0].encode('utf-8'),
 *         flow_accum_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     dem_managed_raster = ManagedRaster(
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3013, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_2); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3013, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3011
 *         flow_dir_d8_raster_path_band[1], False)
 * 
 *     flow_accum_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[0].encode('utf-8'),
 *         flow_accum_raster_path_band[1], False)
*/
  try {
    __pyx_t_12 = ManagedRaster(__pyx_t_10, __pyx_t_11, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3011, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_accum_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_12);

  /* "pygeoprocessing/routing/routing.pyx":3016
 * 
 *     dem_managed_raster = ManagedRaster(
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     cdef int flow_nodata = pygeoprocessing.get_raster_info(
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3016, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __pyx_t_4;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3016, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_10 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 3016, __pyx_L1_error)
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3016, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_4); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3016, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3015
 *         flow_accum_raster_path_band[1], False)
 * 
 *     dem_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)
 * 
*/
  try {
    __pyx_t_12 = ManagedRaster(__pyx_t_10, __pyx_t_11, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3015, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_dem_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_12);

  /* "pygeoprocessing/routing/routing.pyx":3018
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)
 * 
 *     cdef int flow_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0])['nodata'][
 *             flow_dir_d8_raster_path_band[1]-1]
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3018, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3018, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3019
 * 
 *     cdef int flow_nodata = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band[1]-1]
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3019, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3018, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_9 = __Pyx_PyObject_Dict_GetItem(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3019, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3020
 *     cdef int flow_nodata = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])['nodata'][
 *             flow_dir_d8_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])['nodata'][
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3020, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyLong_SubtractObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3020, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3019
 * 
 *     cdef int flow_nodata = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band[1]-1]
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
*/
  __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_9, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3019, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_t_1); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3019, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_nodata = __pyx_t_11;

  /* "pygeoprocessing/routing/routing.pyx":3021
 *         flow_dir_d8_raster_path_band[0])['nodata'][
 *             flow_dir_d8_raster_path_band[1]-1]
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[0])['nodata'][
 *         flow_accum_raster_path_band[1]-1]
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3021, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3021, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3022
 *             flow_dir_d8_raster_path_band[1]-1]
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1]-1]
 * 
*/
  __pyx_t_9 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3022, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_9};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3021, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3022, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3023
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])['nodata'][
 *         flow_accum_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 * 
 *     # D8 flow directions encoded as
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_flow_accum_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3023, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_9 = __Pyx_PyLong_SubtractObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3023, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3022
 *             flow_dir_d8_raster_path_band[1]-1]
 *     cdef double flow_accum_nodata = pygeoprocessing.get_raster_info(
 *         flow_accum_raster_path_band[0])['nodata'][             # <<<<<<<<<<<<<<
 *         flow_accum_raster_path_band[1]-1]
 * 
*/
  __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_t_4, __pyx_t_9); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3022, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_13 = __Pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_13 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3022, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_flow_accum_nodata = __pyx_t_13;

  /* "pygeoprocessing/routing/routing.pyx":3032
 *     cdef unsigned int win_xsize, win_ysize
 * 
 *     n_cols, n_rows = flow_dir_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     LOGGER.info('(extract_strahler_streams_d8): seed the drains')
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3032, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 3032, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_9 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_4);
    } else {
      __pyx_t_9 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3032, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_9);
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3032, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
    }
    #else
    __pyx_t_9 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3032, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_9);
    __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3032, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3032, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_14 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2);
    index = 0; __pyx_t_9 = __pyx_t_14(__pyx_t_2); if (unlikely(!__pyx_t_9)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_9);
    index = 1; __pyx_t_4 = __pyx_t_14(__pyx_t_2); if (unlikely(!__pyx_t_4)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_2), 2) < (0)) __PYX_ERR(0, 3032, __pyx_L1_error)
    __pyx_t_14 = NULL;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L5_unpacking_done;
    __pyx_L4_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_14 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 3032, __pyx_L1_error)
    __pyx_L5_unpacking_done:;
  }
  __pyx_t_15 = __Pyx_PyLong_As_unsigned_int(__pyx_t_9); if (unlikely((__pyx_t_15 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3032, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_16 = __Pyx_PyLong_As_unsigned_int(__pyx_t_4); if (unlikely((__pyx_t_16 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3032, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_n_cols = __pyx_t_15;
  __pyx_v_n_rows = __pyx_t_16;

  /* "pygeoprocessing/routing/routing.pyx":3034
 *     n_cols, n_rows = flow_dir_info['raster_size']
 * 
 *     LOGGER.info('(extract_strahler_streams_d8): seed the drains')             # <<<<<<<<<<<<<<
 *     cdef unsigned long n_pixels = n_cols * n_rows
 *     cdef long n_processed = 0
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3034, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3034, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_see};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3034, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3035
 * 
 *     LOGGER.info('(extract_strahler_streams_d8): seed the drains')
 *     cdef unsigned long n_pixels = n_cols * n_rows             # <<<<<<<<<<<<<<
 *     cdef long n_processed = 0
 *     cdef time_t last_log_time
*/
  __pyx_v_n_pixels = (__pyx_v_n_cols * __pyx_v_n_rows);

  /* "pygeoprocessing/routing/routing.pyx":3036
 *     LOGGER.info('(extract_strahler_streams_d8): seed the drains')
 *     cdef unsigned long n_pixels = n_cols * n_rows
 *     cdef long n_processed = 0             # <<<<<<<<<<<<<<
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)
*/
  __pyx_v_n_processed = 0;

  /* "pygeoprocessing/routing/routing.pyx":3038
 *     cdef long n_processed = 0
 *     cdef time_t last_log_time
 *     last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *     cdef stack[StreamConnectivityPoint] source_point_stack
 *     cdef StreamConnectivityPoint source_stream_point
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":3042
 *     cdef StreamConnectivityPoint source_stream_point
 * 
 *     cdef unsigned int x_l=-1, y_l=-1  # the _l is for "local" aka "current" pixel             # <<<<<<<<<<<<<<
 * 
 *     # D8 backflow directions encoded as
*/
  __pyx_v_x_l = -1;
  __pyx_v_y_l = -1;

  /* "pygeoprocessing/routing/routing.pyx":3049
 *     # 123
 *     cdef unsigned int x_n, y_n  # the _n is for "neighbor"
 *     cdef unsigned int upstream_count=0, upstream_index             # <<<<<<<<<<<<<<
 *     # this array is filled out as upstream directions are calculated and
 *     # indexed by `upstream_count`
*/
  __pyx_v_upstream_count = 0;

  /* "pygeoprocessing/routing/routing.pyx":3052
 *     # this array is filled out as upstream directions are calculated and
 *     # indexed by `upstream_count`
 *     cdef int *upstream_dirs = [0, 0, 0, 0, 0, 0, 0, 0]             # <<<<<<<<<<<<<<
 *     cdef double local_flow_accum
 *     # used to determine if source is a drain and should be tracked
*/
  __pyx_t_17[0] = 0;
  __pyx_t_17[1] = 0;
  __pyx_t_17[2] = 0;
  __pyx_t_17[3] = 0;
  __pyx_t_17[4] = 0;
  __pyx_t_17[5] = 0;
  __pyx_t_17[6] = 0;
  __pyx_t_17[7] = 0;
  __pyx_v_upstream_dirs = __pyx_t_17;

  /* "pygeoprocessing/routing/routing.pyx":3059
 *     # map x/y tuple to list of streams originating from that point
 *     # 2 tuple -> list of int
 *     coord_to_stream_ids = collections.defaultdict(list)             # <<<<<<<<<<<<<<
 * 
 *     # First pass - search for bifurcating stream points
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3059, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3059, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, ((PyObject *)(&PyList_Type))};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3059, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_coord_to_stream_ids = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3068
 *     #       * drains to edge or nodata pixel
 *     #   record a seed point for that bifurcation for later processing.
 *     stream_layer.StartTransaction()             # <<<<<<<<<<<<<<
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_d8_raster_path_band, offset_only=True):
*/
  __pyx_t_9 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_9);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_9, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3068, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3069
 *     #   record a seed point for that bifurcation for later processing.
 *     stream_layer.StartTransaction()
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3069, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3069, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3070
 *     stream_layer.StartTransaction()
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_d8_raster_path_band, offset_only=True):             # <<<<<<<<<<<<<<
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_9, __pyx_v_flow_dir_d8_raster_path_band};
    __pyx_t_2 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3069, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_2, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 3069, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_2);
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3069, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }

  /* "pygeoprocessing/routing/routing.pyx":3069
 *     #   record a seed point for that bifurcation for later processing.
 *     stream_layer.StartTransaction()
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
*/
  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_18 = 0;
    __pyx_t_19 = NULL;
  } else {
    __pyx_t_18 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3069, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_4); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3069, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_19)) {
      if (likely(PyList_CheckExact(__pyx_t_4))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_4);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3069, __pyx_L1_error)
          #endif
          if (__pyx_t_18 >= __pyx_temp) break;
        }
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(__pyx_t_4, __pyx_t_18, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_18;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_4);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3069, __pyx_L1_error)
          #endif
          if (__pyx_t_18 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_18));
        #else
        __pyx_t_1 = __Pyx_PySequence_ITEM(__pyx_t_4, __pyx_t_18);
        #endif
        ++__pyx_t_18;
      }
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3069, __pyx_L1_error)
    } else {
      __pyx_t_1 = __pyx_t_19(__pyx_t_4);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3069, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3071
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): drain seeding '
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3072
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(extract_strahler_streams_d8): drain seeding '
 *                 f'{n_processed} of {n_pixels} pixels complete')
*/
      __pyx_t_2 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3072, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3072, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3074
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): drain seeding '
 *                 f'{n_processed} of {n_pixels} pixels complete')             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']
*/
      __pyx_t_9 = __Pyx_PyUnicode_From_long(__pyx_v_n_processed, 0, ' ', 'd'); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3074, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_7 = __Pyx_PyUnicode_From_unsigned_long(__pyx_v_n_pixels, 0, ' ', 'd'); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3074, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_20[0] = __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_dra;
      __pyx_t_20[1] = __pyx_t_9;
      __pyx_t_20[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_20[3] = __pyx_t_7;
      __pyx_t_20[4] = __pyx_mstate_global->__pyx_kp_u_pixels_complete;

      /* "pygeoprocessing/routing/routing.pyx":3073
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): drain seeding '             # <<<<<<<<<<<<<<
 *                 f'{n_processed} of {n_pixels} pixels complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_8 = __Pyx_PyUnicode_Join(__pyx_t_20, 5, 45 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7) + 16, 127);
      if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3073, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_3))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
        assert(__pyx_t_2);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_8};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3072, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3075
 *                 '(extract_strahler_streams_d8): drain seeding '
 *                 f'{n_processed} of {n_pixels} pixels complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3071
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): drain seeding '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3076
 *                 f'{n_processed} of {n_pixels} pixels complete')
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3076, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_16 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_16 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3076, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_xoff = __pyx_t_16;

    /* "pygeoprocessing/routing/routing.pyx":3077
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3077, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_16 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_16 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3077, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_yoff = __pyx_t_16;

    /* "pygeoprocessing/routing/routing.pyx":3078
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         n_processed += win_xsize * win_ysize
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3078, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_16 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_16 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3078, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_win_xsize = __pyx_t_16;

    /* "pygeoprocessing/routing/routing.pyx":3079
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         n_processed += win_xsize * win_ysize
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3079, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_16 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_16 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3079, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_win_ysize = __pyx_t_16;

    /* "pygeoprocessing/routing/routing.pyx":3080
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         n_processed += win_xsize * win_ysize             # <<<<<<<<<<<<<<
 * 
 *         for i in range(win_xsize):
*/
    __pyx_v_n_processed = (__pyx_v_n_processed + (__pyx_v_win_xsize * __pyx_v_win_ysize));

    /* "pygeoprocessing/routing/routing.pyx":3082
 *         n_processed += win_xsize * win_ysize
 * 
 *         for i in range(win_xsize):             # <<<<<<<<<<<<<<
 *             for j in range(win_ysize):
 *                 is_drain = 0
*/
    __pyx_t_16 = __pyx_v_win_xsize;
    __pyx_t_15 = __pyx_t_16;
    for (__pyx_t_21 = 0; __pyx_t_21 < __pyx_t_15; __pyx_t_21+=1) {
      __pyx_v_i = __pyx_t_21;

      /* "pygeoprocessing/routing/routing.pyx":3083
 * 
 *         for i in range(win_xsize):
 *             for j in range(win_ysize):             # <<<<<<<<<<<<<<
 *                 is_drain = 0
 *                 x_l = xoff + i
*/
      __pyx_t_22 = __pyx_v_win_ysize;
      __pyx_t_23 = __pyx_t_22;
      for (__pyx_t_24 = 0; __pyx_t_24 < __pyx_t_23; __pyx_t_24+=1) {
        __pyx_v_j = __pyx_t_24;

        /* "pygeoprocessing/routing/routing.pyx":3084
 *         for i in range(win_xsize):
 *             for j in range(win_ysize):
 *                 is_drain = 0             # <<<<<<<<<<<<<<
 *                 x_l = xoff + i
 *                 y_l = yoff + j
*/
        __pyx_v_is_drain = 0;

        /* "pygeoprocessing/routing/routing.pyx":3085
 *             for j in range(win_ysize):
 *                 is_drain = 0
 *                 x_l = xoff + i             # <<<<<<<<<<<<<<
 *                 y_l = yoff + j
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(
*/
        __pyx_v_x_l = (__pyx_v_xoff + __pyx_v_i);

        /* "pygeoprocessing/routing/routing.pyx":3086
 *                 is_drain = 0
 *                 x_l = xoff + i
 *                 y_l = yoff + j             # <<<<<<<<<<<<<<
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(
 *                     x_l, y_l)
*/
        __pyx_v_y_l = (__pyx_v_yoff + __pyx_v_j);

        /* "pygeoprocessing/routing/routing.pyx":3087
 *                 x_l = xoff + i
 *                 y_l = yoff + j
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(             # <<<<<<<<<<<<<<
 *                     x_l, y_l)
 *                 if (local_flow_accum < min_flow_accum_threshold or
*/
        __pyx_v_local_flow_accum = ((double)__pyx_v_flow_accum_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

        /* "pygeoprocessing/routing/routing.pyx":3089
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(
 *                     x_l, y_l)
 *                 if (local_flow_accum < min_flow_accum_threshold or             # <<<<<<<<<<<<<<
 *                         is_close(local_flow_accum, flow_accum_nodata)):
 *                     continue
*/
        __pyx_t_25 = (__pyx_v_local_flow_accum < __pyx_v_min_flow_accum_threshold);
        if (!__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L14_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":3090
 *                     x_l, y_l)
 *                 if (local_flow_accum < min_flow_accum_threshold or
 *                         is_close(local_flow_accum, flow_accum_nodata)):             # <<<<<<<<<<<<<<
 *                     continue
 *                 # check to see if it's a drain
*/
        __pyx_t_25 = is_close(__pyx_v_local_flow_accum, __pyx_v_flow_accum_nodata);
        __pyx_t_6 = __pyx_t_25;
        __pyx_L14_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":3089
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(
 *                     x_l, y_l)
 *                 if (local_flow_accum < min_flow_accum_threshold or             # <<<<<<<<<<<<<<
 *                         is_close(local_flow_accum, flow_accum_nodata)):
 *                     continue
*/
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":3091
 *                 if (local_flow_accum < min_flow_accum_threshold or
 *                         is_close(local_flow_accum, flow_accum_nodata)):
 *                     continue             # <<<<<<<<<<<<<<
 *                 # check to see if it's a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
*/
          goto __pyx_L11_continue;

          /* "pygeoprocessing/routing/routing.pyx":3089
 *                 local_flow_accum = <double>flow_accum_managed_raster.get(
 *                     x_l, y_l)
 *                 if (local_flow_accum < min_flow_accum_threshold or             # <<<<<<<<<<<<<<
 *                         is_close(local_flow_accum, flow_accum_nodata)):
 *                     continue
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3093
 *                     continue
 *                 # check to see if it's a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)             # <<<<<<<<<<<<<<
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]
*/
        __pyx_v_d_n = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

        /* "pygeoprocessing/routing/routing.pyx":3094
 *                 # check to see if it's a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
 *                 x_n = x_l + COL_OFFSETS[d_n]             # <<<<<<<<<<<<<<
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or
*/
        __pyx_v_x_n = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_d_n]));

        /* "pygeoprocessing/routing/routing.pyx":3095
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]             # <<<<<<<<<<<<<<
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or
 *                         <int>flow_dir_managed_raster.get(
*/
        __pyx_v_y_n = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_d_n]));

        /* "pygeoprocessing/routing/routing.pyx":3096
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_nodata):
*/
        __pyx_t_25 = (__pyx_v_x_n < 0);
        if (!__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L17_bool_binop_done;
        }
        __pyx_t_25 = (__pyx_v_y_n < 0);
        if (!__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L17_bool_binop_done;
        }
        __pyx_t_25 = (__pyx_v_x_n >= __pyx_v_n_cols);
        if (!__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L17_bool_binop_done;
        }
        __pyx_t_25 = (__pyx_v_y_n >= __pyx_v_n_rows);
        if (!__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L17_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":3098
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_nodata):             # <<<<<<<<<<<<<<
 *                     is_drain = 1
 * 
*/
        __pyx_t_25 = (((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n)) == __pyx_v_flow_nodata);
        __pyx_t_6 = __pyx_t_25;
        __pyx_L17_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":3096
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_nodata):
*/
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":3099
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_nodata):
 *                     is_drain = 1             # <<<<<<<<<<<<<<
 * 
 *                 if not is_drain and (
*/
          __pyx_v_is_drain = 1;

          /* "pygeoprocessing/routing/routing.pyx":3096
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_nodata):
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3101
 *                     is_drain = 1
 * 
 *                 if not is_drain and (             # <<<<<<<<<<<<<<
 *                         local_flow_accum < 2*min_flow_accum_threshold):
 *                     # if current pixel is < 2*flow threshold then it can't
*/
        __pyx_t_25 = (!(__pyx_v_is_drain != 0));
        if (__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L23_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":3102
 * 
 *                 if not is_drain and (
 *                         local_flow_accum < 2*min_flow_accum_threshold):             # <<<<<<<<<<<<<<
 *                     # if current pixel is < 2*flow threshold then it can't
 *                     # bifurcate into two pixels == flow threshold
*/
        __pyx_t_25 = (__pyx_v_local_flow_accum < (2 * __pyx_v_min_flow_accum_threshold));
        __pyx_t_6 = __pyx_t_25;
        __pyx_L23_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":3101
 *                     is_drain = 1
 * 
 *                 if not is_drain and (             # <<<<<<<<<<<<<<
 *                         local_flow_accum < 2*min_flow_accum_threshold):
 *                     # if current pixel is < 2*flow threshold then it can't
*/
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":3105
 *                     # if current pixel is < 2*flow threshold then it can't
 *                     # bifurcate into two pixels == flow threshold
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 upstream_count = 0
*/
          goto __pyx_L11_continue;

          /* "pygeoprocessing/routing/routing.pyx":3101
 *                     is_drain = 1
 * 
 *                 if not is_drain and (             # <<<<<<<<<<<<<<
 *                         local_flow_accum < 2*min_flow_accum_threshold):
 *                     # if current pixel is < 2*flow threshold then it can't
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3107
 *                     continue
 * 
 *                 upstream_count = 0             # <<<<<<<<<<<<<<
 *                 for d in range(8):
 *                     x_n = x_l + COL_OFFSETS[d]
*/
        __pyx_v_upstream_count = 0;

        /* "pygeoprocessing/routing/routing.pyx":3108
 * 
 *                 upstream_count = 0
 *                 for d in range(8):             # <<<<<<<<<<<<<<
 *                     x_n = x_l + COL_OFFSETS[d]
 *                     y_n = y_l + ROW_OFFSETS[d]
*/
        for (__pyx_t_26 = 0; __pyx_t_26 < 8; __pyx_t_26+=1) {
          __pyx_v_d = __pyx_t_26;

          /* "pygeoprocessing/routing/routing.pyx":3109
 *                 upstream_count = 0
 *                 for d in range(8):
 *                     x_n = x_l + COL_OFFSETS[d]             # <<<<<<<<<<<<<<
 *                     y_n = y_l + ROW_OFFSETS[d]
 *                     # check if on border
*/
          __pyx_v_x_n = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_d]));

          /* "pygeoprocessing/routing/routing.pyx":3110
 *                 for d in range(8):
 *                     x_n = x_l + COL_OFFSETS[d]
 *                     y_n = y_l + ROW_OFFSETS[d]             # <<<<<<<<<<<<<<
 *                     # check if on border
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
*/
          __pyx_v_y_n = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_d]));

          /* "pygeoprocessing/routing/routing.pyx":3112
 *                     y_n = y_l + ROW_OFFSETS[d]
 *                     # check if on border
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *                         continue
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
*/
          __pyx_t_25 = (__pyx_v_x_n < 0);
          if (!__pyx_t_25) {
          } else {
            __pyx_t_6 = __pyx_t_25;
            goto __pyx_L28_bool_binop_done;
          }
          __pyx_t_25 = (__pyx_v_y_n < 0);
          if (!__pyx_t_25) {
          } else {
            __pyx_t_6 = __pyx_t_25;
            goto __pyx_L28_bool_binop_done;
          }
          __pyx_t_25 = (__pyx_v_x_n >= __pyx_v_n_cols);
          if (!__pyx_t_25) {
          } else {
            __pyx_t_6 = __pyx_t_25;
            goto __pyx_L28_bool_binop_done;
          }
          __pyx_t_25 = (__pyx_v_y_n >= __pyx_v_n_rows);
          __pyx_t_6 = __pyx_t_25;
          __pyx_L28_bool_binop_done:;
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":3113
 *                     # check if on border
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *                         continue             # <<<<<<<<<<<<<<
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_nodata:
*/
            goto __pyx_L25_continue;

            /* "pygeoprocessing/routing/routing.pyx":3112
 *                     y_n = y_l + ROW_OFFSETS[d]
 *                     # check if on border
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *                         continue
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":3114
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *                         continue
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)             # <<<<<<<<<<<<<<
 *                     if d_n == flow_nodata:
 *                         continue
*/
          __pyx_v_d_n = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n));

          /* "pygeoprocessing/routing/routing.pyx":3115
 *                         continue
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_nodata:             # <<<<<<<<<<<<<<
 *                         continue
 *                     if (INFLOW_OFFSETS[d] == d_n and
*/
          __pyx_t_6 = (__pyx_v_d_n == __pyx_v_flow_nodata);
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":3116
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_nodata:
 *                         continue             # <<<<<<<<<<<<<<
 *                     if (INFLOW_OFFSETS[d] == d_n and
 *                             <double>flow_accum_managed_raster.get(
*/
            goto __pyx_L25_continue;

            /* "pygeoprocessing/routing/routing.pyx":3115
 *                         continue
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_nodata:             # <<<<<<<<<<<<<<
 *                         continue
 *                     if (INFLOW_OFFSETS[d] == d_n and
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":3117
 *                     if d_n == flow_nodata:
 *                         continue
 *                     if (INFLOW_OFFSETS[d] == d_n and             # <<<<<<<<<<<<<<
 *                             <double>flow_accum_managed_raster.get(
 *                                 x_n, y_n) >= min_flow_accum_threshold):
*/
          __pyx_t_25 = ((INFLOW_OFFSETS[__pyx_v_d]) == __pyx_v_d_n);
          if (__pyx_t_25) {
          } else {
            __pyx_t_6 = __pyx_t_25;
            goto __pyx_L34_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":3119
 *                     if (INFLOW_OFFSETS[d] == d_n and
 *                             <double>flow_accum_managed_raster.get(
 *                                 x_n, y_n) >= min_flow_accum_threshold):             # <<<<<<<<<<<<<<
 *                         upstream_dirs[upstream_count] = d
 *                         upstream_count += 1
*/
          __pyx_t_25 = (((double)__pyx_v_flow_accum_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n)) >= __pyx_v_min_flow_accum_threshold);
          __pyx_t_6 = __pyx_t_25;
          __pyx_L34_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":3117
 *                     if d_n == flow_nodata:
 *                         continue
 *                     if (INFLOW_OFFSETS[d] == d_n and             # <<<<<<<<<<<<<<
 *                             <double>flow_accum_managed_raster.get(
 *                                 x_n, y_n) >= min_flow_accum_threshold):
*/
          if (__pyx_t_6) {

            /* "pygeoprocessing/routing/routing.pyx":3120
 *                             <double>flow_accum_managed_raster.get(
 *                                 x_n, y_n) >= min_flow_accum_threshold):
 *                         upstream_dirs[upstream_count] = d             # <<<<<<<<<<<<<<
 *                         upstream_count += 1
 *                 if upstream_count <= 1 and not is_drain:
*/
            (__pyx_v_upstream_dirs[__pyx_v_upstream_count]) = __pyx_v_d;

            /* "pygeoprocessing/routing/routing.pyx":3121
 *                                 x_n, y_n) >= min_flow_accum_threshold):
 *                         upstream_dirs[upstream_count] = d
 *                         upstream_count += 1             # <<<<<<<<<<<<<<
 *                 if upstream_count <= 1 and not is_drain:
 *                     continue
*/
            __pyx_v_upstream_count = (__pyx_v_upstream_count + 1);

            /* "pygeoprocessing/routing/routing.pyx":3117
 *                     if d_n == flow_nodata:
 *                         continue
 *                     if (INFLOW_OFFSETS[d] == d_n and             # <<<<<<<<<<<<<<
 *                             <double>flow_accum_managed_raster.get(
 *                                 x_n, y_n) >= min_flow_accum_threshold):
*/
          }
          __pyx_L25_continue:;
        }

        /* "pygeoprocessing/routing/routing.pyx":3122
 *                         upstream_dirs[upstream_count] = d
 *                         upstream_count += 1
 *                 if upstream_count <= 1 and not is_drain:             # <<<<<<<<<<<<<<
 *                     continue
 *                 for upstream_index in range(upstream_count):
*/
        __pyx_t_25 = (__pyx_v_upstream_count <= 1);
        if (__pyx_t_25) {
        } else {
          __pyx_t_6 = __pyx_t_25;
          goto __pyx_L37_bool_binop_done;
        }
        __pyx_t_25 = (!(__pyx_v_is_drain != 0));
        __pyx_t_6 = __pyx_t_25;
        __pyx_L37_bool_binop_done:;
        if (__pyx_t_6) {

          /* "pygeoprocessing/routing/routing.pyx":3123
 *                         upstream_count += 1
 *                 if upstream_count <= 1 and not is_drain:
 *                     continue             # <<<<<<<<<<<<<<
 *                 for upstream_index in range(upstream_count):
 *                     # hit a branch!
*/
          goto __pyx_L11_continue;

          /* "pygeoprocessing/routing/routing.pyx":3122
 *                         upstream_dirs[upstream_count] = d
 *                         upstream_count += 1
 *                 if upstream_count <= 1 and not is_drain:             # <<<<<<<<<<<<<<
 *                     continue
 *                 for upstream_index in range(upstream_count):
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3124
 *                 if upstream_count <= 1 and not is_drain:
 *                     continue
 *                 for upstream_index in range(upstream_count):             # <<<<<<<<<<<<<<
 *                     # hit a branch!
 *                     stream_feature = ogr.Feature(
*/
        __pyx_t_26 = __pyx_v_upstream_count;
        __pyx_t_27 = __pyx_t_26;
        for (__pyx_t_28 = 0; __pyx_t_28 < __pyx_t_27; __pyx_t_28+=1) {
          __pyx_v_upstream_index = __pyx_t_28;

          /* "pygeoprocessing/routing/routing.pyx":3126
 *                 for upstream_index in range(upstream_count):
 *                     # hit a branch!
 *                     stream_feature = ogr.Feature(             # <<<<<<<<<<<<<<
 *                         stream_layer.GetLayerDefn())
 *                     stream_feature.SetField('outlet', 0)
*/
          __pyx_t_3 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3126, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_8);
          __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_Feature); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3126, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3127
 *                     # hit a branch!
 *                     stream_feature = ogr.Feature(
 *                         stream_layer.GetLayerDefn())             # <<<<<<<<<<<<<<
 *                     stream_feature.SetField('outlet', 0)
 *                     stream_layer.CreateFeature(stream_feature)
*/
          __pyx_t_7 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_7);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_7, NULL};
            __pyx_t_8 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetLayerDefn, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
            if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3127, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_8);
          }
          __pyx_t_5 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_2))) {
            __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
            assert(__pyx_t_3);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
            __Pyx_INCREF(__pyx_t_3);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
            __pyx_t_5 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_8};
            __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
            if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3126, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_1);
          }
          __Pyx_XDECREF_SET(__pyx_v_stream_feature, __pyx_t_1);
          __pyx_t_1 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3128
 *                     stream_feature = ogr.Feature(
 *                         stream_layer.GetLayerDefn())
 *                     stream_feature.SetField('outlet', 0)             # <<<<<<<<<<<<<<
 *                     stream_layer.CreateFeature(stream_feature)
 *                     stream_fid = stream_feature.GetFID()
*/
          __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_stream_feature, __pyx_mstate_global->__pyx_n_u_SetField); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3128, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_mstate_global->__pyx_tuple[4], NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3128, __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;

          /* "pygeoprocessing/routing/routing.pyx":3129
 *                         stream_layer.GetLayerDefn())
 *                     stream_feature.SetField('outlet', 0)
 *                     stream_layer.CreateFeature(stream_feature)             # <<<<<<<<<<<<<<
 *                     stream_fid = stream_feature.GetFID()
 *                     source_point_stack.push(StreamConnectivityPoint(
*/
          __pyx_t_1 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_1);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_v_stream_feature};
            __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
            if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3129, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_2);
          }
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3130
 *                     stream_feature.SetField('outlet', 0)
 *                     stream_layer.CreateFeature(stream_feature)
 *                     stream_fid = stream_feature.GetFID()             # <<<<<<<<<<<<<<
 *                     source_point_stack.push(StreamConnectivityPoint(
 *                         x_l, y_l, upstream_dirs[upstream_index], stream_fid))
*/
          __pyx_t_1 = __pyx_v_stream_feature;
          __Pyx_INCREF(__pyx_t_1);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_1, NULL};
            __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
            if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3130, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_2);
          }
          __Pyx_XDECREF_SET(__pyx_v_stream_fid, __pyx_t_2);
          __pyx_t_2 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3132
 *                     stream_fid = stream_feature.GetFID()
 *                     source_point_stack.push(StreamConnectivityPoint(
 *                         x_l, y_l, upstream_dirs[upstream_index], stream_fid))             # <<<<<<<<<<<<<<
 *                     coord_to_stream_ids[(x_l, y_l)].append(stream_fid)
 *     LOGGER.info(
*/
          __pyx_t_29.xi = __pyx_v_x_l;
          __pyx_t_29.yi = __pyx_v_y_l;
          __pyx_t_29.upstream_d8_dir = (__pyx_v_upstream_dirs[__pyx_v_upstream_index]);
          __pyx_t_30 = __Pyx_PyLong_As_unsigned_int(__pyx_v_stream_fid); if (unlikely((__pyx_t_30 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3132, __pyx_L1_error)
          __pyx_t_29.source_id = __pyx_t_30;

          /* "pygeoprocessing/routing/routing.pyx":3131
 *                     stream_layer.CreateFeature(stream_feature)
 *                     stream_fid = stream_feature.GetFID()
 *                     source_point_stack.push(StreamConnectivityPoint(             # <<<<<<<<<<<<<<
 *                         x_l, y_l, upstream_dirs[upstream_index], stream_fid))
 *                     coord_to_stream_ids[(x_l, y_l)].append(stream_fid)
*/
          try {
            __pyx_v_source_point_stack.push(__pyx_t_29);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 3131, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":3133
 *                     source_point_stack.push(StreamConnectivityPoint(
 *                         x_l, y_l, upstream_dirs[upstream_index], stream_fid))
 *                     coord_to_stream_ids[(x_l, y_l)].append(stream_fid)             # <<<<<<<<<<<<<<
 *     LOGGER.info(
 *         '(extract_strahler_streams_d8): '
*/
          __pyx_t_2 = __Pyx_PyLong_From_unsigned_int(__pyx_v_x_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3133, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __pyx_t_1 = __Pyx_PyLong_From_unsigned_int(__pyx_v_y_l); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3133, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3133, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_8);
          __Pyx_GIVEREF(__pyx_t_2);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 3133, __pyx_L1_error);
          __Pyx_GIVEREF(__pyx_t_1);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1) != (0)) __PYX_ERR(0, 3133, __pyx_L1_error);
          __pyx_t_2 = 0;
          __pyx_t_1 = 0;
          __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_v_coord_to_stream_ids, __pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3133, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          __pyx_t_31 = __Pyx_PyObject_Append(__pyx_t_1, __pyx_v_stream_fid); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3133, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        }
        __pyx_L11_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":3069
 *     #   record a seed point for that bifurcation for later processing.
 *     stream_layer.StartTransaction()
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
*/
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3134
 *                         x_l, y_l, upstream_dirs[upstream_index], stream_fid))
 *                     coord_to_stream_ids[(x_l, y_l)].append(stream_fid)
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): '
 *         f'drain seeding complete')
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3134, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3134, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_dra_2};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3134, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3137
 *         '(extract_strahler_streams_d8): '
 *         f'drain seeding complete')
 *     LOGGER.info('(extract_strahler_streams_d8): starting upstream walk')             # <<<<<<<<<<<<<<
 *     n_points = source_point_stack.size()
 * 
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3137, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3137, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_8);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_sta};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3137, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3138
 *         f'drain seeding complete')
 *     LOGGER.info('(extract_strahler_streams_d8): starting upstream walk')
 *     n_points = source_point_stack.size()             # <<<<<<<<<<<<<<
 * 
 *     # map downstream ids to list of upstream connected streams
*/
  __pyx_t_4 = __Pyx_PyLong_FromSize_t(__pyx_v_source_point_stack.size()); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3138, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_n_points = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3142
 *     # map downstream ids to list of upstream connected streams
 *     # id -> list of ids
 *     downstream_to_upstream_ids = {}             # <<<<<<<<<<<<<<
 * 
 *     # map upstream id to downstream connected stream id -> id
*/
  __pyx_t_4 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3142, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_downstream_to_upstream_ids = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3145
 * 
 *     # map upstream id to downstream connected stream id -> id
 *     upstream_to_downstream_id = {}             # <<<<<<<<<<<<<<
 * 
 *     while not source_point_stack.empty():
*/
  __pyx_t_4 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3145, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_upstream_to_downstream_id = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3147
 *     upstream_to_downstream_id = {}
 * 
 *     while not source_point_stack.empty():             # <<<<<<<<<<<<<<
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
*/
  while (1) {
    __pyx_t_6 = (!__pyx_v_source_point_stack.empty());
    if (!__pyx_t_6) break;

    /* "pygeoprocessing/routing/routing.pyx":3148
 * 
 *     while not source_point_stack.empty():
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3149
 *     while not source_point_stack.empty():
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(extract_strahler_streams_d8): '
 *                 'stream segment creation '
*/
      __pyx_t_8 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3149, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3149, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3152
 *                 '(extract_strahler_streams_d8): '
 *                 'stream segment creation '
 *                 f'{n_points-source_point_stack.size()} of {n_points} '             # <<<<<<<<<<<<<<
 *                 'source points complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_2 = __Pyx_PyLong_FromSize_t(__pyx_v_source_point_stack.size()); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3152, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_3 = PyNumber_Subtract(__pyx_v_n_points, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3152, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = __Pyx_PyObject_FormatSimple(__pyx_t_3, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3152, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_3 = __Pyx_PyObject_FormatSimple(__pyx_v_n_points, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3152, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_20[0] = __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_str;
      __pyx_t_20[1] = __pyx_t_2;
      __pyx_t_20[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_20[3] = __pyx_t_3;
      __pyx_t_20[4] = __pyx_mstate_global->__pyx_kp_u_source_points_complete;

      /* "pygeoprocessing/routing/routing.pyx":3150
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '             # <<<<<<<<<<<<<<
 *                 'stream segment creation '
 *                 f'{n_points-source_point_stack.size()} of {n_points} '
*/
      __pyx_t_7 = __Pyx_PyUnicode_Join(__pyx_t_20, 5, 55 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 23, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_2) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_3));
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3150, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_1);
        assert(__pyx_t_8);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_8);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_7};
        __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3149, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3154
 *                 f'{n_points-source_point_stack.size()} of {n_points} '
 *                 'source points complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *         # This coordinate is the downstream end of the stream
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3148
 * 
 *     while not source_point_stack.empty():
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3157
 * 
 *         # This coordinate is the downstream end of the stream
 *         source_stream_point = source_point_stack.top()             # <<<<<<<<<<<<<<
 *         source_point_stack.pop()
 * 
*/
    __pyx_v_source_stream_point = __pyx_v_source_point_stack.top();

    /* "pygeoprocessing/routing/routing.pyx":3158
 *         # This coordinate is the downstream end of the stream
 *         source_stream_point = source_point_stack.top()
 *         source_point_stack.pop()             # <<<<<<<<<<<<<<
 * 
 *         payload = _calculate_stream_geometry(
*/
    __pyx_v_source_point_stack.pop();

    /* "pygeoprocessing/routing/routing.pyx":3163
 *             source_stream_point.xi, source_stream_point.yi,
 *             source_stream_point.upstream_d8_dir,
 *             flow_dir_info['geotransform'], n_cols, n_rows,             # <<<<<<<<<<<<<<
 *             flow_accum_managed_raster, flow_dir_managed_raster, flow_nodata,
 *             min_flow_accum_threshold, coord_to_stream_ids)
*/
    __pyx_t_4 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_geotransform); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3163, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);

    /* "pygeoprocessing/routing/routing.pyx":3160
 *         source_point_stack.pop()
 * 
 *         payload = _calculate_stream_geometry(             # <<<<<<<<<<<<<<
 *             source_stream_point.xi, source_stream_point.yi,
 *             source_stream_point.upstream_d8_dir,
*/
    __pyx_t_1 = __pyx_f_15pygeoprocessing_7routing_7routing__calculate_stream_geometry(__pyx_v_source_stream_point.xi, __pyx_v_source_stream_point.yi, __pyx_v_source_stream_point.upstream_d8_dir, __pyx_t_4, __pyx_v_n_cols, __pyx_v_n_rows, __pyx_v_flow_accum_managed_raster, __pyx_v_flow_dir_managed_raster, __pyx_v_flow_nodata, __pyx_v_min_flow_accum_threshold, __pyx_v_coord_to_stream_ids); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3160, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_payload, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3166
 *             flow_accum_managed_raster, flow_dir_managed_raster, flow_nodata,
 *             min_flow_accum_threshold, coord_to_stream_ids)
 *         if payload is None:             # <<<<<<<<<<<<<<
 *             LOGGER.debug(
 *                 f'no geometry for source point at '
*/
    __pyx_t_6 = (__pyx_v_payload == Py_None);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3167
 *             min_flow_accum_threshold, coord_to_stream_ids)
 *         if payload is None:
 *             LOGGER.debug(             # <<<<<<<<<<<<<<
 *                 f'no geometry for source point at '
 *                 f'{source_stream_point.xi}, {source_stream_point.yi} '
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3167, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_debug); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3167, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3169
 *             LOGGER.debug(
 *                 f'no geometry for source point at '
 *                 f'{source_stream_point.xi}, {source_stream_point.yi} '             # <<<<<<<<<<<<<<
 *                 f'upstream direction: {source_stream_point.upstream_d8_dir}')
 *             continue
*/
      __pyx_t_7 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_source_stream_point.xi, 0, ' ', 'd'); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3169, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_3 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_source_stream_point.yi, 0, ' ', 'd'); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3169, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);

      /* "pygeoprocessing/routing/routing.pyx":3170
 *                 f'no geometry for source point at '
 *                 f'{source_stream_point.xi}, {source_stream_point.yi} '
 *                 f'upstream direction: {source_stream_point.upstream_d8_dir}')             # <<<<<<<<<<<<<<
 *             continue
 *         x_u, y_u, ds_x_1, ds_y_1, upstream_id_list, stream_line = payload
*/
      __pyx_t_2 = __Pyx_PyUnicode_From_int(__pyx_v_source_stream_point.upstream_d8_dir, 0, ' ', 'd'); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3170, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_32[0] = __pyx_mstate_global->__pyx_kp_u_no_geometry_for_source_point_at;
      __pyx_t_32[1] = __pyx_t_7;
      __pyx_t_32[2] = __pyx_mstate_global->__pyx_kp_u_;
      __pyx_t_32[3] = __pyx_t_3;
      __pyx_t_32[4] = __pyx_mstate_global->__pyx_kp_u_upstream_direction;
      __pyx_t_32[5] = __pyx_t_2;

      /* "pygeoprocessing/routing/routing.pyx":3168
 *         if payload is None:
 *             LOGGER.debug(
 *                 f'no geometry for source point at '             # <<<<<<<<<<<<<<
 *                 f'{source_stream_point.xi}, {source_stream_point.yi} '
 *                 f'upstream direction: {source_stream_point.upstream_d8_dir}')
*/
      __pyx_t_9 = __Pyx_PyUnicode_Join(__pyx_t_32, 6, 32 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7) + 2 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_3) + 21 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2), 127);
      if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3168, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_8))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_8);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_9};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3167, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3171
 *                 f'{source_stream_point.xi}, {source_stream_point.yi} '
 *                 f'upstream direction: {source_stream_point.upstream_d8_dir}')
 *             continue             # <<<<<<<<<<<<<<
 *         x_u, y_u, ds_x_1, ds_y_1, upstream_id_list, stream_line = payload
 * 
*/
      goto __pyx_L42_continue;

      /* "pygeoprocessing/routing/routing.pyx":3166
 *             flow_accum_managed_raster, flow_dir_managed_raster, flow_nodata,
 *             min_flow_accum_threshold, coord_to_stream_ids)
 *         if payload is None:             # <<<<<<<<<<<<<<
 *             LOGGER.debug(
 *                 f'no geometry for source point at '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3172
 *                 f'upstream direction: {source_stream_point.upstream_d8_dir}')
 *             continue
 *         x_u, y_u, ds_x_1, ds_y_1, upstream_id_list, stream_line = payload             # <<<<<<<<<<<<<<
 * 
 *         downstream_dem = dem_managed_raster.get(
*/
    if ((likely(PyTuple_CheckExact(__pyx_v_payload))) || (PyList_CheckExact(__pyx_v_payload))) {
      PyObject* sequence = __pyx_v_payload;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 6)) {
        if (size > 6) __Pyx_RaiseTooManyValuesError(6);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 3172, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_8);
        __pyx_t_9 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_9);
        __pyx_t_4 = PyTuple_GET_ITEM(sequence, 3);
        __Pyx_INCREF(__pyx_t_4);
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 4);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 5);
        __Pyx_INCREF(__pyx_t_3);
      } else {
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_8);
        __pyx_t_9 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_9);
        __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_4);
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 4, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 5, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3172, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
      }
      #else
      {
        Py_ssize_t i;
        PyObject** temps[6] = {&__pyx_t_1,&__pyx_t_8,&__pyx_t_9,&__pyx_t_4,&__pyx_t_2,&__pyx_t_3};
        for (i=0; i < 6; i++) {
          PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 3172, __pyx_L1_error)
          __Pyx_GOTREF(item);
          *(temps[i]) = item;
        }
      }
      #endif
    } else {
      Py_ssize_t index = -1;
      PyObject** temps[6] = {&__pyx_t_1,&__pyx_t_8,&__pyx_t_9,&__pyx_t_4,&__pyx_t_2,&__pyx_t_3};
      __pyx_t_7 = PyObject_GetIter(__pyx_v_payload); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3172, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __pyx_t_14 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
      for (index=0; index < 6; index++) {
        PyObject* item = __pyx_t_14(__pyx_t_7); if (unlikely(!item)) goto __pyx_L46_unpacking_failed;
        __Pyx_GOTREF(item);
        *(temps[index]) = item;
      }
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_7), 6) < (0)) __PYX_ERR(0, 3172, __pyx_L1_error)
      __pyx_t_14 = NULL;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      goto __pyx_L47_unpacking_done;
      __pyx_L46_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_14 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 3172, __pyx_L1_error)
      __pyx_L47_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_x_u, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_XDECREF_SET(__pyx_v_y_u, __pyx_t_8);
    __pyx_t_8 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ds_x_1, __pyx_t_9);
    __pyx_t_9 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ds_y_1, __pyx_t_4);
    __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_upstream_id_list, __pyx_t_2);
    __pyx_t_2 = 0;
    __Pyx_XDECREF_SET(__pyx_v_stream_line, __pyx_t_3);
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3174
 *         x_u, y_u, ds_x_1, ds_y_1, upstream_id_list, stream_line = payload
 * 
 *         downstream_dem = dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *             source_stream_point.xi, source_stream_point.yi)
 * 
*/
    __pyx_v_downstream_dem = __pyx_v_dem_managed_raster.get(__pyx_v_source_stream_point.xi, __pyx_v_source_stream_point.yi);

    /* "pygeoprocessing/routing/routing.pyx":3177
 *             source_stream_point.xi, source_stream_point.yi)
 * 
 *         stream_feature = stream_layer.GetFeature(             # <<<<<<<<<<<<<<
 *             source_stream_point.source_id)
 *         stream_feature.SetField(
*/
    __pyx_t_2 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":3178
 * 
 *         stream_feature = stream_layer.GetFeature(
 *             source_stream_point.source_id)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField(
 *             'ds_fa', flow_accum_managed_raster.get(
*/
    __pyx_t_4 = __Pyx_PyLong_From_unsigned_int(__pyx_v_source_stream_point.source_id); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3178, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3177, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_XDECREF_SET(__pyx_v_stream_feature, __pyx_t_3);
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3179
 *         stream_feature = stream_layer.GetFeature(
 *             source_stream_point.source_id)
 *         stream_feature.SetField(             # <<<<<<<<<<<<<<
 *             'ds_fa', flow_accum_managed_raster.get(
 *                 source_stream_point.xi, source_stream_point.yi))
*/
    __pyx_t_4 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_4);

    /* "pygeoprocessing/routing/routing.pyx":3180
 *             source_stream_point.source_id)
 *         stream_feature.SetField(
 *             'ds_fa', flow_accum_managed_raster.get(             # <<<<<<<<<<<<<<
 *                 source_stream_point.xi, source_stream_point.yi))
 *         stream_feature.SetField('ds_x', source_stream_point.xi)
*/
    __pyx_t_2 = PyFloat_FromDouble(__pyx_v_flow_accum_managed_raster.get(__pyx_v_source_stream_point.xi, __pyx_v_source_stream_point.yi)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3180, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_ds_fa, __pyx_t_2};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3179, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3182
 *             'ds_fa', flow_accum_managed_raster.get(
 *                 source_stream_point.xi, source_stream_point.yi))
 *         stream_feature.SetField('ds_x', source_stream_point.xi)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('ds_y', source_stream_point.yi)
 *         stream_feature.SetField('ds_x_1', ds_x_1)
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_4 = __Pyx_PyLong_From_unsigned_int(__pyx_v_source_stream_point.xi); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3182, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ds_x, __pyx_t_4};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3182, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3183
 *                 source_stream_point.xi, source_stream_point.yi))
 *         stream_feature.SetField('ds_x', source_stream_point.xi)
 *         stream_feature.SetField('ds_y', source_stream_point.yi)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('ds_x_1', ds_x_1)
 *         stream_feature.SetField('ds_y_1', ds_y_1)
*/
    __pyx_t_4 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_2 = __Pyx_PyLong_From_unsigned_int(__pyx_v_source_stream_point.yi); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3183, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_ds_y, __pyx_t_2};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3183, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3184
 *         stream_feature.SetField('ds_x', source_stream_point.xi)
 *         stream_feature.SetField('ds_y', source_stream_point.yi)
 *         stream_feature.SetField('ds_x_1', ds_x_1)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('ds_y_1', ds_y_1)
 *         stream_feature.SetField('us_x', x_u)
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ds_x_1, __pyx_v_ds_x_1};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3184, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3185
 *         stream_feature.SetField('ds_y', source_stream_point.yi)
 *         stream_feature.SetField('ds_x_1', ds_x_1)
 *         stream_feature.SetField('ds_y_1', ds_y_1)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('us_x', x_u)
 *         stream_feature.SetField('us_y', y_u)
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ds_y_1, __pyx_v_ds_y_1};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3185, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3186
 *         stream_feature.SetField('ds_x_1', ds_x_1)
 *         stream_feature.SetField('ds_y_1', ds_y_1)
 *         stream_feature.SetField('us_x', x_u)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('us_y', y_u)
 *         stream_feature.SetField(
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_x, __pyx_v_x_u};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3186, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3187
 *         stream_feature.SetField('ds_y_1', ds_y_1)
 *         stream_feature.SetField('us_x', x_u)
 *         stream_feature.SetField('us_y', y_u)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField(
 *             'upstream_d8_dir', source_stream_point.upstream_d8_dir)
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_y, __pyx_v_y_u};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3187, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3188
 *         stream_feature.SetField('us_x', x_u)
 *         stream_feature.SetField('us_y', y_u)
 *         stream_feature.SetField(             # <<<<<<<<<<<<<<
 *             'upstream_d8_dir', source_stream_point.upstream_d8_dir)
 * 
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":3189
 *         stream_feature.SetField('us_y', y_u)
 *         stream_feature.SetField(
 *             'upstream_d8_dir', source_stream_point.upstream_d8_dir)             # <<<<<<<<<<<<<<
 * 
 *         # record the downstream connected component for all the upstream
*/
    __pyx_t_4 = __Pyx_PyLong_From_int(__pyx_v_source_stream_point.upstream_d8_dir); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3189, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_upstream_d8_dir, __pyx_t_4};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3188, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3193
 *         # record the downstream connected component for all the upstream
 *         # connected components
 *         for upstream_id in upstream_id_list:             # <<<<<<<<<<<<<<
 *             upstream_to_downstream_id[upstream_id] = (
 *                 source_stream_point.source_id)
*/
    if (likely(PyList_CheckExact(__pyx_v_upstream_id_list)) || PyTuple_CheckExact(__pyx_v_upstream_id_list)) {
      __pyx_t_3 = __pyx_v_upstream_id_list; __Pyx_INCREF(__pyx_t_3);
      __pyx_t_18 = 0;
      __pyx_t_19 = NULL;
    } else {
      __pyx_t_18 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_upstream_id_list); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3193, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3193, __pyx_L1_error)
    }
    for (;;) {
      if (likely(!__pyx_t_19)) {
        if (likely(PyList_CheckExact(__pyx_t_3))) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3193, __pyx_L1_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          __pyx_t_4 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_18, __Pyx_ReferenceSharing_OwnStrongReference);
          ++__pyx_t_18;
        } else {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3193, __pyx_L1_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_4 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_18));
          #else
          __pyx_t_4 = __Pyx_PySequence_ITEM(__pyx_t_3, __pyx_t_18);
          #endif
          ++__pyx_t_18;
        }
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3193, __pyx_L1_error)
      } else {
        __pyx_t_4 = __pyx_t_19(__pyx_t_3);
        if (unlikely(!__pyx_t_4)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3193, __pyx_L1_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_XDECREF_SET(__pyx_v_upstream_id, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3195
 *         for upstream_id in upstream_id_list:
 *             upstream_to_downstream_id[upstream_id] = (
 *                 source_stream_point.source_id)             # <<<<<<<<<<<<<<
 * 
 *         # record the upstream connected components for the downstream component
*/
      __pyx_t_4 = __Pyx_PyLong_From_unsigned_int(__pyx_v_source_stream_point.source_id); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3195, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);

      /* "pygeoprocessing/routing/routing.pyx":3194
 *         # connected components
 *         for upstream_id in upstream_id_list:
 *             upstream_to_downstream_id[upstream_id] = (             # <<<<<<<<<<<<<<
 *                 source_stream_point.source_id)
 * 
*/
      if (unlikely((PyDict_SetItem(__pyx_v_upstream_to_downstream_id, __pyx_v_upstream_id, __pyx_t_4) < 0))) __PYX_ERR(0, 3194, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3193
 *         # record the downstream connected component for all the upstream
 *         # connected components
 *         for upstream_id in upstream_id_list:             # <<<<<<<<<<<<<<
 *             upstream_to_downstream_id[upstream_id] = (
 *                 source_stream_point.source_id)
*/
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3198
 * 
 *         # record the upstream connected components for the downstream component
 *         downstream_to_upstream_ids[source_stream_point.source_id] = (             # <<<<<<<<<<<<<<
 *             upstream_id_list)
 * 
*/
    __pyx_t_3 = __Pyx_PyLong_From_unsigned_int(__pyx_v_source_stream_point.source_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3198, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    if (unlikely((PyDict_SetItem(__pyx_v_downstream_to_upstream_ids, __pyx_t_3, __pyx_v_upstream_id_list) < 0))) __PYX_ERR(0, 3198, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3202
 * 
 *         # if no upstream it means it is an order 1 source stream
 *         if not upstream_id_list:             # <<<<<<<<<<<<<<
 *             stream_feature.SetField('order', 1)
 *         stream_feature.SetGeometry(stream_line)
*/
    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_upstream_id_list); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3202, __pyx_L1_error)
    __pyx_t_25 = (!__pyx_t_6);
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3203
 *         # if no upstream it means it is an order 1 source stream
 *         if not upstream_id_list:
 *             stream_feature.SetField('order', 1)             # <<<<<<<<<<<<<<
 *         stream_feature.SetGeometry(stream_line)
 * 
*/
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_stream_feature, __pyx_mstate_global->__pyx_n_u_SetField); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3203, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_mstate_global->__pyx_tuple[5], NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3203, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3202
 * 
 *         # if no upstream it means it is an order 1 source stream
 *         if not upstream_id_list:             # <<<<<<<<<<<<<<
 *             stream_feature.SetField('order', 1)
 *         stream_feature.SetGeometry(stream_line)
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3204
 *         if not upstream_id_list:
 *             stream_feature.SetField('order', 1)
 *         stream_feature.SetGeometry(stream_line)             # <<<<<<<<<<<<<<
 * 
 *         # calculate the drop distance
*/
    __pyx_t_3 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_3);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_stream_line};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetGeometry, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3204, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3207
 * 
 *         # calculate the drop distance
 *         upstream_dem = dem_managed_raster.get(x_u, y_u)             # <<<<<<<<<<<<<<
 *         drop_distance = upstream_dem - downstream_dem
 *         stream_feature.SetField('drop_distance', drop_distance)
*/
    __pyx_t_33 = __Pyx_PyLong_As_long(__pyx_v_x_u); if (unlikely((__pyx_t_33 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3207, __pyx_L1_error)
    __pyx_t_34 = __Pyx_PyLong_As_long(__pyx_v_y_u); if (unlikely((__pyx_t_34 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3207, __pyx_L1_error)
    __pyx_v_upstream_dem = __pyx_v_dem_managed_raster.get(__pyx_t_33, __pyx_t_34);

    /* "pygeoprocessing/routing/routing.pyx":3208
 *         # calculate the drop distance
 *         upstream_dem = dem_managed_raster.get(x_u, y_u)
 *         drop_distance = upstream_dem - downstream_dem             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('drop_distance', drop_distance)
 *         stream_feature.SetField(
*/
    __pyx_v_drop_distance = (__pyx_v_upstream_dem - __pyx_v_downstream_dem);

    /* "pygeoprocessing/routing/routing.pyx":3209
 *         upstream_dem = dem_managed_raster.get(x_u, y_u)
 *         drop_distance = upstream_dem - downstream_dem
 *         stream_feature.SetField('drop_distance', drop_distance)             # <<<<<<<<<<<<<<
 *         stream_feature.SetField(
 *             'us_fa', flow_accum_managed_raster.get(x_u, y_u))
*/
    __pyx_t_3 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_3);
    __pyx_t_2 = PyFloat_FromDouble(__pyx_v_drop_distance); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3209, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_drop_distance, __pyx_t_2};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3209, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3210
 *         drop_distance = upstream_dem - downstream_dem
 *         stream_feature.SetField('drop_distance', drop_distance)
 *         stream_feature.SetField(             # <<<<<<<<<<<<<<
 *             'us_fa', flow_accum_managed_raster.get(x_u, y_u))
 *         stream_feature.SetField('thresh_fa', min_flow_accum_threshold)
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":3211
 *         stream_feature.SetField('drop_distance', drop_distance)
 *         stream_feature.SetField(
 *             'us_fa', flow_accum_managed_raster.get(x_u, y_u))             # <<<<<<<<<<<<<<
 *         stream_feature.SetField('thresh_fa', min_flow_accum_threshold)
 *         stream_layer.SetFeature(stream_feature)
*/
    __pyx_t_34 = __Pyx_PyLong_As_long(__pyx_v_x_u); if (unlikely((__pyx_t_34 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3211, __pyx_L1_error)
    __pyx_t_33 = __Pyx_PyLong_As_long(__pyx_v_y_u); if (unlikely((__pyx_t_33 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3211, __pyx_L1_error)
    __pyx_t_3 = PyFloat_FromDouble(__pyx_v_flow_accum_managed_raster.get(__pyx_t_34, __pyx_t_33)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3211, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_fa, __pyx_t_3};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3210, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3212
 *         stream_feature.SetField(
 *             'us_fa', flow_accum_managed_raster.get(x_u, y_u))
 *         stream_feature.SetField('thresh_fa', min_flow_accum_threshold)             # <<<<<<<<<<<<<<
 *         stream_layer.SetFeature(stream_feature)
 * 
*/
    __pyx_t_3 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_3);
    __pyx_t_2 = __Pyx_PyLong_From_long(__pyx_v_min_flow_accum_threshold); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3212, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_thresh_fa, __pyx_t_2};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3212, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3213
 *             'us_fa', flow_accum_managed_raster.get(x_u, y_u))
 *         stream_feature.SetField('thresh_fa', min_flow_accum_threshold)
 *         stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 * 
 *     LOGGER.info(
*/
    __pyx_t_2 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_stream_feature};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3213, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_L42_continue:;
  }

  /* "pygeoprocessing/routing/routing.pyx":3215
 *         stream_layer.SetFeature(stream_feature)
 * 
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): stream segment creation complete')
 * 
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3215, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3215, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_str_2};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3215, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3218
 *         '(extract_strahler_streams_d8): stream segment creation complete')
 * 
 *     LOGGER.info('(extract_strahler_streams_d8): determining stream order')             # <<<<<<<<<<<<<<
 *     # seed the list with all order 1 streams
 *     stream_layer.SetAttributeFilter('"order"=1')
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3218, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_det};
    __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3218, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3220
 *     LOGGER.info('(extract_strahler_streams_d8): determining stream order')
 *     # seed the list with all order 1 streams
 *     stream_layer.SetAttributeFilter('"order"=1')             # <<<<<<<<<<<<<<
 *     streams_to_process = [stream_feature for stream_feature in stream_layer]
 *     base_feature_count = len(streams_to_process)
*/
  __pyx_t_3 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_order_1};
    __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetAttributeFilter, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3220, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
  }
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3221
 *     # seed the list with all order 1 streams
 *     stream_layer.SetAttributeFilter('"order"=1')
 *     streams_to_process = [stream_feature for stream_feature in stream_layer]             # <<<<<<<<<<<<<<
 *     base_feature_count = len(streams_to_process)
 *     outlet_fid_list = []
*/
  { /* enter inner scope */
    __pyx_t_4 = PyList_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3221, __pyx_L54_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (likely(PyList_CheckExact(__pyx_v_stream_layer)) || PyTuple_CheckExact(__pyx_v_stream_layer)) {
      __pyx_t_3 = __pyx_v_stream_layer; __Pyx_INCREF(__pyx_t_3);
      __pyx_t_18 = 0;
      __pyx_t_19 = NULL;
    } else {
      __pyx_t_18 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_stream_layer); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3221, __pyx_L54_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3221, __pyx_L54_error)
    }
    for (;;) {
      if (likely(!__pyx_t_19)) {
        if (likely(PyList_CheckExact(__pyx_t_3))) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3221, __pyx_L54_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          __pyx_t_9 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_18, __Pyx_ReferenceSharing_OwnStrongReference);
          ++__pyx_t_18;
        } else {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3221, __pyx_L54_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_9 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_18));
          #else
          __pyx_t_9 = __Pyx_PySequence_ITEM(__pyx_t_3, __pyx_t_18);
          #endif
          ++__pyx_t_18;
        }
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3221, __pyx_L54_error)
      } else {
        __pyx_t_9 = __pyx_t_19(__pyx_t_3);
        if (unlikely(!__pyx_t_9)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3221, __pyx_L54_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_XDECREF_SET(__pyx_7genexpr__pyx_v_stream_feature, __pyx_t_9);
      __pyx_t_9 = 0;
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_4, (PyObject*)__pyx_7genexpr__pyx_v_stream_feature))) __PYX_ERR(0, 3221, __pyx_L54_error)
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_stream_feature); __pyx_7genexpr__pyx_v_stream_feature = 0;
    goto __pyx_L58_exit_scope;
    __pyx_L54_error:;
    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_stream_feature); __pyx_7genexpr__pyx_v_stream_feature = 0;
    goto __pyx_L1_error;
    __pyx_L58_exit_scope:;
  } /* exit inner scope */
  __pyx_v_streams_to_process = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3222
 *     stream_layer.SetAttributeFilter('"order"=1')
 *     streams_to_process = [stream_feature for stream_feature in stream_layer]
 *     base_feature_count = len(streams_to_process)             # <<<<<<<<<<<<<<
 *     outlet_fid_list = []
 *     while streams_to_process:
*/
  __pyx_t_18 = __Pyx_PyList_GET_SIZE(__pyx_v_streams_to_process); if (unlikely(__pyx_t_18 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3222, __pyx_L1_error)
  __pyx_t_4 = PyLong_FromSsize_t(__pyx_t_18); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3222, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_base_feature_count = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3223
 *     streams_to_process = [stream_feature for stream_feature in stream_layer]
 *     base_feature_count = len(streams_to_process)
 *     outlet_fid_list = []             # <<<<<<<<<<<<<<
 *     while streams_to_process:
 *         if ctime(NULL)-last_log_time > 2.0:
*/
  __pyx_t_4 = PyList_New(0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3223, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_v_outlet_fid_list = ((PyObject*)__pyx_t_4);
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3224
 *     base_feature_count = len(streams_to_process)
 *     outlet_fid_list = []
 *     while streams_to_process:             # <<<<<<<<<<<<<<
 *         if ctime(NULL)-last_log_time > 2.0:
 *             LOGGER.info(
*/
  while (1) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_streams_to_process);
      if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3224, __pyx_L1_error)
      __pyx_t_25 = (__pyx_temp != 0);
    }

    if (!__pyx_t_25) break;

    /* "pygeoprocessing/routing/routing.pyx":3225
 *     outlet_fid_list = []
 *     while streams_to_process:
 *         if ctime(NULL)-last_log_time > 2.0:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    __pyx_t_25 = ((time(NULL) - __pyx_v_last_log_time) > 2.0);
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3226
 *     while streams_to_process:
 *         if ctime(NULL)-last_log_time > 2.0:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(extract_strahler_streams_d8): '
 *                 'stream order processing: '
*/
      __pyx_t_3 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3226, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3226, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3229
 *                 '(extract_strahler_streams_d8): '
 *                 'stream order processing: '
 *                 f'{base_feature_count-len(streams_to_process)} of '             # <<<<<<<<<<<<<<
 *                 f'{base_feature_count} stream fragments complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_18 = __Pyx_PyList_GET_SIZE(__pyx_v_streams_to_process); if (unlikely(__pyx_t_18 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3229, __pyx_L1_error)
      __pyx_t_9 = PyLong_FromSsize_t(__pyx_t_18); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3229, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __pyx_t_8 = PyNumber_Subtract(__pyx_v_base_feature_count, __pyx_t_9); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3229, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __pyx_t_9 = __Pyx_PyObject_FormatSimple(__pyx_t_8, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3229, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3230
 *                 'stream order processing: '
 *                 f'{base_feature_count-len(streams_to_process)} of '
 *                 f'{base_feature_count} stream fragments complete')             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *         # fetch the downstream and connected upstream ids
*/
      __pyx_t_8 = __Pyx_PyObject_FormatSimple(__pyx_v_base_feature_count, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3230, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_20[0] = __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_str_3;
      __pyx_t_20[1] = __pyx_t_9;
      __pyx_t_20[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_20[3] = __pyx_t_8;
      __pyx_t_20[4] = __pyx_mstate_global->__pyx_kp_u_stream_fragments_complete;

      /* "pygeoprocessing/routing/routing.pyx":3227
 *         if ctime(NULL)-last_log_time > 2.0:
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '             # <<<<<<<<<<<<<<
 *                 'stream order processing: '
 *                 f'{base_feature_count-len(streams_to_process)} of '
*/
      __pyx_t_1 = __Pyx_PyUnicode_Join(__pyx_t_20, 5, 56 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_8) + 26, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_8));
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3227, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
        assert(__pyx_t_3);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_1};
        __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3226, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3231
 *                 f'{base_feature_count-len(streams_to_process)} of '
 *                 f'{base_feature_count} stream fragments complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         # fetch the downstream and connected upstream ids
 *         stream_feature = streams_to_process.pop(0)
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3225
 *     outlet_fid_list = []
 *     while streams_to_process:
 *         if ctime(NULL)-last_log_time > 2.0:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3233
 *             last_log_time = ctime(NULL)
 *         # fetch the downstream and connected upstream ids
 *         stream_feature = streams_to_process.pop(0)             # <<<<<<<<<<<<<<
 *         stream_fid = stream_feature.GetFID()
 *         if stream_fid not in upstream_to_downstream_id:
*/
    __pyx_t_4 = __Pyx_PyList_PopIndex(__pyx_v_streams_to_process, __pyx_mstate_global->__pyx_int_0, 0, 1, Py_ssize_t, PyLong_FromSsize_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3233, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_XDECREF_SET(__pyx_v_stream_feature, __pyx_t_4);
    __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3234
 *         # fetch the downstream and connected upstream ids
 *         stream_feature = streams_to_process.pop(0)
 *         stream_fid = stream_feature.GetFID()             # <<<<<<<<<<<<<<
 *         if stream_fid not in upstream_to_downstream_id:
 *             # it's an outlet so no downstream to process
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
      __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3234, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __Pyx_XDECREF_SET(__pyx_v_stream_fid, __pyx_t_4);
    __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3235
 *         stream_feature = streams_to_process.pop(0)
 *         stream_fid = stream_feature.GetFID()
 *         if stream_fid not in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *             # it's an outlet so no downstream to process
 *             stream_feature.SetField('outlet', 1)
*/
    __pyx_t_25 = (__Pyx_PyDict_ContainsTF(__pyx_v_stream_fid, __pyx_v_upstream_to_downstream_id, Py_NE)); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3235, __pyx_L1_error)
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3237
 *         if stream_fid not in upstream_to_downstream_id:
 *             # it's an outlet so no downstream to process
 *             stream_feature.SetField('outlet', 1)             # <<<<<<<<<<<<<<
 *             stream_layer.SetFeature(stream_feature)
 *             outlet_fid_list.append(stream_feature.GetFID())
*/
      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_stream_feature, __pyx_mstate_global->__pyx_n_u_SetField); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3237, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_mstate_global->__pyx_tuple[6], NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3237, __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;

      /* "pygeoprocessing/routing/routing.pyx":3238
 *             # it's an outlet so no downstream to process
 *             stream_feature.SetField('outlet', 1)
 *             stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 *             outlet_fid_list.append(stream_feature.GetFID())
 *             stream_feature = None
*/
      __pyx_t_4 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_stream_feature};
        __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3238, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3239
 *             stream_feature.SetField('outlet', 1)
 *             stream_layer.SetFeature(stream_feature)
 *             outlet_fid_list.append(stream_feature.GetFID())             # <<<<<<<<<<<<<<
 *             stream_feature = None
 *             continue
*/
      __pyx_t_4 = __pyx_v_stream_feature;
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};
        __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3239, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_outlet_fid_list, __pyx_t_2); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3239, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3240
 *             stream_layer.SetFeature(stream_feature)
 *             outlet_fid_list.append(stream_feature.GetFID())
 *             stream_feature = None             # <<<<<<<<<<<<<<
 *             continue
 *         downstream_fid = upstream_to_downstream_id[stream_fid]
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_stream_feature, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3241
 *             outlet_fid_list.append(stream_feature.GetFID())
 *             stream_feature = None
 *             continue             # <<<<<<<<<<<<<<
 *         downstream_fid = upstream_to_downstream_id[stream_fid]
 *         downstream_feature = stream_layer.GetFeature(downstream_fid)
*/
      goto __pyx_L59_continue;

      /* "pygeoprocessing/routing/routing.pyx":3235
 *         stream_feature = streams_to_process.pop(0)
 *         stream_fid = stream_feature.GetFID()
 *         if stream_fid not in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *             # it's an outlet so no downstream to process
 *             stream_feature.SetField('outlet', 1)
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3242
 *             stream_feature = None
 *             continue
 *         downstream_fid = upstream_to_downstream_id[stream_fid]             # <<<<<<<<<<<<<<
 *         downstream_feature = stream_layer.GetFeature(downstream_fid)
 *         if downstream_feature.GetField('order') is not None:
*/
    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_upstream_to_downstream_id, __pyx_v_stream_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3242, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_downstream_fid, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3243
 *             continue
 *         downstream_fid = upstream_to_downstream_id[stream_fid]
 *         downstream_feature = stream_layer.GetFeature(downstream_fid)             # <<<<<<<<<<<<<<
 *         if downstream_feature.GetField('order') is not None:
 *             # downstream component already processed
*/
    __pyx_t_4 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_downstream_fid};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3243, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_downstream_feature, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3244
 *         downstream_fid = upstream_to_downstream_id[stream_fid]
 *         downstream_feature = stream_layer.GetFeature(downstream_fid)
 *         if downstream_feature.GetField('order') is not None:             # <<<<<<<<<<<<<<
 *             # downstream component already processed
 *             downstream_feature = None
*/
    __pyx_t_4 = __pyx_v_downstream_feature;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_order};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3244, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_25 = (__pyx_t_2 != Py_None);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3246
 *         if downstream_feature.GetField('order') is not None:
 *             # downstream component already processed
 *             downstream_feature = None             # <<<<<<<<<<<<<<
 *             continue
 *         connected_upstream_fids = downstream_to_upstream_ids[downstream_fid]
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_downstream_feature, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3247
 *             # downstream component already processed
 *             downstream_feature = None
 *             continue             # <<<<<<<<<<<<<<
 *         connected_upstream_fids = downstream_to_upstream_ids[downstream_fid]
 *         # check that all upstream IDs are defined and construct stream order
*/
      goto __pyx_L59_continue;

      /* "pygeoprocessing/routing/routing.pyx":3244
 *         downstream_fid = upstream_to_downstream_id[stream_fid]
 *         downstream_feature = stream_layer.GetFeature(downstream_fid)
 *         if downstream_feature.GetField('order') is not None:             # <<<<<<<<<<<<<<
 *             # downstream component already processed
 *             downstream_feature = None
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3248
 *             downstream_feature = None
 *             continue
 *         connected_upstream_fids = downstream_to_upstream_ids[downstream_fid]             # <<<<<<<<<<<<<<
 *         # check that all upstream IDs are defined and construct stream order
 *         # list
*/
    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_downstream_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3248, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_connected_upstream_fids, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3251
 *         # check that all upstream IDs are defined and construct stream order
 *         # list
 *         stream_order_list = []             # <<<<<<<<<<<<<<
 *         all_defined = True
 *         for upstream_fid in connected_upstream_fids:
*/
    __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3251, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_stream_order_list, ((PyObject*)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3252
 *         # list
 *         stream_order_list = []
 *         all_defined = True             # <<<<<<<<<<<<<<
 *         for upstream_fid in connected_upstream_fids:
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
*/
    __pyx_v_all_defined = 1;

    /* "pygeoprocessing/routing/routing.pyx":3253
 *         stream_order_list = []
 *         all_defined = True
 *         for upstream_fid in connected_upstream_fids:             # <<<<<<<<<<<<<<
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
 *             upstream_order = upstream_feature.GetField('order')
*/
    if (likely(PyList_CheckExact(__pyx_v_connected_upstream_fids)) || PyTuple_CheckExact(__pyx_v_connected_upstream_fids)) {
      __pyx_t_2 = __pyx_v_connected_upstream_fids; __Pyx_INCREF(__pyx_t_2);
      __pyx_t_18 = 0;
      __pyx_t_19 = NULL;
    } else {
      __pyx_t_18 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_connected_upstream_fids); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3253, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3253, __pyx_L1_error)
    }
    for (;;) {
      if (likely(!__pyx_t_19)) {
        if (likely(PyList_CheckExact(__pyx_t_2))) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3253, __pyx_L1_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          __pyx_t_4 = __Pyx_PyList_GetItemRefFast(__pyx_t_2, __pyx_t_18, __Pyx_ReferenceSharing_OwnStrongReference);
          ++__pyx_t_18;
        } else {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_2);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3253, __pyx_L1_error)
            #endif
            if (__pyx_t_18 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_4 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_18));
          #else
          __pyx_t_4 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_18);
          #endif
          ++__pyx_t_18;
        }
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3253, __pyx_L1_error)
      } else {
        __pyx_t_4 = __pyx_t_19(__pyx_t_2);
        if (unlikely(!__pyx_t_4)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3253, __pyx_L1_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_XDECREF_SET(__pyx_v_upstream_fid, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3254
 *         all_defined = True
 *         for upstream_fid in connected_upstream_fids:
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)             # <<<<<<<<<<<<<<
 *             upstream_order = upstream_feature.GetField('order')
 *             if upstream_order is not None:
*/
      __pyx_t_1 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_1);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_v_upstream_fid};
        __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3254, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __Pyx_XDECREF_SET(__pyx_v_upstream_feature, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3255
 *         for upstream_fid in connected_upstream_fids:
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
 *             upstream_order = upstream_feature.GetField('order')             # <<<<<<<<<<<<<<
 *             if upstream_order is not None:
 *                 stream_order_list.append(upstream_order)
*/
      __pyx_t_1 = __pyx_v_upstream_feature;
      __Pyx_INCREF(__pyx_t_1);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_mstate_global->__pyx_n_u_order};
        __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3255, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __Pyx_XDECREF_SET(__pyx_v_upstream_order, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3256
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
 *             upstream_order = upstream_feature.GetField('order')
 *             if upstream_order is not None:             # <<<<<<<<<<<<<<
 *                 stream_order_list.append(upstream_order)
 *             else:
*/
      __pyx_t_25 = (__pyx_v_upstream_order != Py_None);
      if (__pyx_t_25) {

        /* "pygeoprocessing/routing/routing.pyx":3257
 *             upstream_order = upstream_feature.GetField('order')
 *             if upstream_order is not None:
 *                 stream_order_list.append(upstream_order)             # <<<<<<<<<<<<<<
 *             else:
 *                 # found an upstream not defined, that means it'll be processed
*/
        __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_stream_order_list, __pyx_v_upstream_order); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3257, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":3256
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
 *             upstream_order = upstream_feature.GetField('order')
 *             if upstream_order is not None:             # <<<<<<<<<<<<<<
 *                 stream_order_list.append(upstream_order)
 *             else:
*/
        goto __pyx_L66;
      }

      /* "pygeoprocessing/routing/routing.pyx":3261
 *                 # found an upstream not defined, that means it'll be processed
 *                 # later
 *                 all_defined = False             # <<<<<<<<<<<<<<
 *                 break
 *         if not all_defined:
*/
      /*else*/ {
        __pyx_v_all_defined = 0;

        /* "pygeoprocessing/routing/routing.pyx":3262
 *                 # later
 *                 all_defined = False
 *                 break             # <<<<<<<<<<<<<<
 *         if not all_defined:
 *             # we'll revisit this stream later when the other connected
*/
        goto __pyx_L65_break;
      }
      __pyx_L66:;

      /* "pygeoprocessing/routing/routing.pyx":3253
 *         stream_order_list = []
 *         all_defined = True
 *         for upstream_fid in connected_upstream_fids:             # <<<<<<<<<<<<<<
 *             upstream_feature = stream_layer.GetFeature(upstream_fid)
 *             upstream_order = upstream_feature.GetField('order')
*/
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L67_for_end;
    __pyx_L65_break:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L67_for_end;
    __pyx_L67_for_end:;

    /* "pygeoprocessing/routing/routing.pyx":3263
 *                 all_defined = False
 *                 break
 *         if not all_defined:             # <<<<<<<<<<<<<<
 *             # we'll revisit this stream later when the other connected
 *             # components are processed
*/
    __pyx_t_25 = (!__pyx_v_all_defined);
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3266
 *             # we'll revisit this stream later when the other connected
 *             # components are processed
 *             continue             # <<<<<<<<<<<<<<
 *         sorted_stream_order_list = sorted(stream_order_list)
 *         downstream_order = sorted_stream_order_list[-1]
*/
      goto __pyx_L59_continue;

      /* "pygeoprocessing/routing/routing.pyx":3263
 *                 all_defined = False
 *                 break
 *         if not all_defined:             # <<<<<<<<<<<<<<
 *             # we'll revisit this stream later when the other connected
 *             # components are processed
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3267
 *             # components are processed
 *             continue
 *         sorted_stream_order_list = sorted(stream_order_list)             # <<<<<<<<<<<<<<
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (
*/
    __pyx_t_2 = PySequence_List(__pyx_v_stream_order_list); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3267, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    if (unlikely((PyList_Sort(__pyx_t_2) < 0))) __PYX_ERR(0, 3267, __pyx_L1_error)
    __Pyx_XDECREF_SET(__pyx_v_sorted_stream_order_list, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3268
 *             continue
 *         sorted_stream_order_list = sorted(stream_order_list)
 *         downstream_order = sorted_stream_order_list[-1]             # <<<<<<<<<<<<<<
 *         if len(sorted_stream_order_list) > 1 and (
 *                 sorted_stream_order_list[-1] ==
*/
    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_sorted_stream_order_list, -1L, long, 1, __Pyx_PyLong_From_long, 1, 1, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3268, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_downstream_order, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3269
 *         sorted_stream_order_list = sorted(stream_order_list)
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (             # <<<<<<<<<<<<<<
 *                 sorted_stream_order_list[-1] ==
 *                 sorted_stream_order_list[-2]):
*/
    __pyx_t_18 = __Pyx_PyList_GET_SIZE(__pyx_v_sorted_stream_order_list); if (unlikely(__pyx_t_18 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3269, __pyx_L1_error)
    __pyx_t_6 = (__pyx_t_18 > 1);
    if (__pyx_t_6) {
    } else {
      __pyx_t_25 = __pyx_t_6;
      goto __pyx_L70_bool_binop_done;
    }

    /* "pygeoprocessing/routing/routing.pyx":3270
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (
 *                 sorted_stream_order_list[-1] ==             # <<<<<<<<<<<<<<
 *                 sorted_stream_order_list[-2]):
 *             # if there are at least two equal order streams feeding in,
*/
    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_sorted_stream_order_list, -1L, long, 1, __Pyx_PyLong_From_long, 1, 1, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3270, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":3271
 *         if len(sorted_stream_order_list) > 1 and (
 *                 sorted_stream_order_list[-1] ==
 *                 sorted_stream_order_list[-2]):             # <<<<<<<<<<<<<<
 *             # if there are at least two equal order streams feeding in,
 *             # we go up one order
*/
    __pyx_t_4 = __Pyx_GetItemInt_List(__pyx_v_sorted_stream_order_list, -2L, long, 1, __Pyx_PyLong_From_long, 1, 1, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3271, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3270, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3270
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (
 *                 sorted_stream_order_list[-1] ==             # <<<<<<<<<<<<<<
 *                 sorted_stream_order_list[-2]):
 *             # if there are at least two equal order streams feeding in,
*/
    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3270, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_25 = __pyx_t_6;
    __pyx_L70_bool_binop_done:;

    /* "pygeoprocessing/routing/routing.pyx":3269
 *         sorted_stream_order_list = sorted(stream_order_list)
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (             # <<<<<<<<<<<<<<
 *                 sorted_stream_order_list[-1] ==
 *                 sorted_stream_order_list[-2]):
*/
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3274
 *             # if there are at least two equal order streams feeding in,
 *             # we go up one order
 *             downstream_order += 1             # <<<<<<<<<<<<<<
 *         downstream_feature.SetField('order', downstream_order)
 *         stream_layer.SetFeature(downstream_feature)
*/
      __pyx_t_1 = __Pyx_PyLong_AddObjC(__pyx_v_downstream_order, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3274, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF_SET(__pyx_v_downstream_order, __pyx_t_1);
      __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3269
 *         sorted_stream_order_list = sorted(stream_order_list)
 *         downstream_order = sorted_stream_order_list[-1]
 *         if len(sorted_stream_order_list) > 1 and (             # <<<<<<<<<<<<<<
 *                 sorted_stream_order_list[-1] ==
 *                 sorted_stream_order_list[-2]):
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3275
 *             # we go up one order
 *             downstream_order += 1
 *         downstream_feature.SetField('order', downstream_order)             # <<<<<<<<<<<<<<
 *         stream_layer.SetFeature(downstream_feature)
 *         streams_to_process.append(downstream_feature)
*/
    __pyx_t_4 = __pyx_v_downstream_feature;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_order, __pyx_v_downstream_order};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3275, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3276
 *             downstream_order += 1
 *         downstream_feature.SetField('order', downstream_order)
 *         stream_layer.SetFeature(downstream_feature)             # <<<<<<<<<<<<<<
 *         streams_to_process.append(downstream_feature)
 *         downstream_feature = None
*/
    __pyx_t_4 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_downstream_feature};
      __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3276, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3277
 *         downstream_feature.SetField('order', downstream_order)
 *         stream_layer.SetFeature(downstream_feature)
 *         streams_to_process.append(downstream_feature)             # <<<<<<<<<<<<<<
 *         downstream_feature = None
 *     LOGGER.info(
*/
    __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_streams_to_process, __pyx_v_downstream_feature); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3277, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":3278
 *         stream_layer.SetFeature(downstream_feature)
 *         streams_to_process.append(downstream_feature)
 *         downstream_feature = None             # <<<<<<<<<<<<<<
 *     LOGGER.info(
 *         '(extract_strahler_streams_d8): stream order processing complete')
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_downstream_feature, Py_None);
    __pyx_L59_continue:;
  }

  /* "pygeoprocessing/routing/routing.pyx":3279
 *         streams_to_process.append(downstream_feature)
 *         downstream_feature = None
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): stream order processing complete')
 * 
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3279, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3279, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_str_4};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3279, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3282
 *         '(extract_strahler_streams_d8): stream order processing complete')
 * 
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): determine rivers')
 *     working_river_id = 0
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3282, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3282, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_det_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3284
 *     LOGGER.info(
 *         '(extract_strahler_streams_d8): determine rivers')
 *     working_river_id = 0             # <<<<<<<<<<<<<<
 *     for outlet_index, outlet_fid in enumerate(outlet_fid_list):
 *         # walk upstream starting from this outlet to search for rivers
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __pyx_v_working_river_id = __pyx_mstate_global->__pyx_int_0;

  /* "pygeoprocessing/routing/routing.pyx":3285
 *         '(extract_strahler_streams_d8): determine rivers')
 *     working_river_id = 0
 *     for outlet_index, outlet_fid in enumerate(outlet_fid_list):             # <<<<<<<<<<<<<<
 *         # walk upstream starting from this outlet to search for rivers
 *         # defined as stream segments whose order is <= river_order. Note it
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __pyx_t_1 = __pyx_mstate_global->__pyx_int_0;
  __pyx_t_2 = __pyx_v_outlet_fid_list; __Pyx_INCREF(__pyx_t_2);
  __pyx_t_18 = 0;
  for (;;) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2);
      #if !CYTHON_ASSUME_SAFE_SIZE
      if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3285, __pyx_L1_error)
      #endif
      if (__pyx_t_18 >= __pyx_temp) break;
    }
    __pyx_t_3 = __Pyx_PyList_GetItemRefFast(__pyx_t_2, __pyx_t_18, __Pyx_ReferenceSharing_OwnStrongReference);
    ++__pyx_t_18;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3285, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_XDECREF_SET(__pyx_v_outlet_fid, __pyx_t_3);
    __pyx_t_3 = 0;
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_outlet_index, __pyx_t_1);
    __pyx_t_3 = __Pyx_PyLong_AddObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3285, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_1);
    __pyx_t_1 = __pyx_t_3;
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3290
 *         # can be < river_order because we may have some streams that have
 *         # outlets for shorter rivers that can't get to river_order.
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    __pyx_t_25 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_25) {

      /* "pygeoprocessing/routing/routing.pyx":3291
 *         # outlets for shorter rivers that can't get to river_order.
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(extract_strahler_streams_d8): '
 *                 'flow accumulation adjustment '
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3291, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3291, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3294
 *                 '(extract_strahler_streams_d8): '
 *                 'flow accumulation adjustment '
 *                 f'{outlet_index+1} of {len(outlet_fid_list)} '             # <<<<<<<<<<<<<<
 *                 'outlets complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_8 = __Pyx_PyLong_AddObjC(__pyx_v_outlet_index, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3294, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_t_8, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3294, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_35 = __Pyx_PyList_GET_SIZE(__pyx_v_outlet_fid_list); if (unlikely(__pyx_t_35 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3294, __pyx_L1_error)
      __pyx_t_8 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_t_35, 0, ' ', 'd'); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3294, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_20[0] = __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_flo;
      __pyx_t_20[1] = __pyx_t_7;
      __pyx_t_20[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_20[3] = __pyx_t_8;
      __pyx_t_20[4] = __pyx_mstate_global->__pyx_kp_u_outlets_complete;

      /* "pygeoprocessing/routing/routing.pyx":3292
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '             # <<<<<<<<<<<<<<
 *                 'flow accumulation adjustment '
 *                 f'{outlet_index+1} of {len(outlet_fid_list)} '
*/
      __pyx_t_36 = __Pyx_PyUnicode_Join(__pyx_t_20, 5, 60 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_8) + 17, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7));
      if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3292, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_36);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_9);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_36};
        __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3291, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3296
 *                 f'{outlet_index+1} of {len(outlet_fid_list)} '
 *                 'outlets complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         search_stack = [outlet_fid]
 *         while search_stack:
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3290
 *         # can be < river_order because we may have some streams that have
 *         # outlets for shorter rivers that can't get to river_order.
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3297
 *                 'outlets complete')
 *             last_log_time = ctime(NULL)
 *         search_stack = [outlet_fid]             # <<<<<<<<<<<<<<
 *         while search_stack:
 *             stream_layer.CommitTransaction()
*/
    __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3297, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_INCREF(__pyx_v_outlet_fid);
    __Pyx_GIVEREF(__pyx_v_outlet_fid);
    if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 0, __pyx_v_outlet_fid) != (0)) __PYX_ERR(0, 3297, __pyx_L1_error);
    __Pyx_XDECREF_SET(__pyx_v_search_stack, ((PyObject*)__pyx_t_3));
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3298
 *             last_log_time = ctime(NULL)
 *         search_stack = [outlet_fid]
 *         while search_stack:             # <<<<<<<<<<<<<<
 *             stream_layer.CommitTransaction()
 *             stream_layer.StartTransaction()
*/
    while (1) {
      {
        Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_search_stack);
        if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3298, __pyx_L1_error)
        __pyx_t_25 = (__pyx_temp != 0);
      }

      if (!__pyx_t_25) break;

      /* "pygeoprocessing/routing/routing.pyx":3299
 *         search_stack = [outlet_fid]
 *         while search_stack:
 *             stream_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *             stream_layer.StartTransaction()
 *             feature_id = search_stack.pop()
*/
      __pyx_t_9 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, NULL};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3299, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3300
 *         while search_stack:
 *             stream_layer.CommitTransaction()
 *             stream_layer.StartTransaction()             # <<<<<<<<<<<<<<
 *             feature_id = search_stack.pop()
 *             stream_feature = stream_layer.GetFeature(feature_id)
*/
      __pyx_t_9 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, NULL};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3300, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3301
 *             stream_layer.CommitTransaction()
 *             stream_layer.StartTransaction()
 *             feature_id = search_stack.pop()             # <<<<<<<<<<<<<<
 *             stream_feature = stream_layer.GetFeature(feature_id)
 *             stream_order = stream_feature.GetField('order')
*/
      __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_search_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3301, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_XDECREF_SET(__pyx_v_feature_id, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3302
 *             stream_layer.StartTransaction()
 *             feature_id = search_stack.pop()
 *             stream_feature = stream_layer.GetFeature(feature_id)             # <<<<<<<<<<<<<<
 *             stream_order = stream_feature.GetField('order')
 * 
*/
      __pyx_t_9 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_feature_id};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3302, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_stream_feature, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3303
 *             feature_id = search_stack.pop()
 *             stream_feature = stream_layer.GetFeature(feature_id)
 *             stream_order = stream_feature.GetField('order')             # <<<<<<<<<<<<<<
 * 
 *             if (stream_order > river_order or
*/
      __pyx_t_9 = __pyx_v_stream_feature;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_order};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3303, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_stream_order, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3305
 *             stream_order = stream_feature.GetField('order')
 * 
 *             if (stream_order > river_order or             # <<<<<<<<<<<<<<
 *                     stream_feature.GetField('river_id') is not None):
 *                 # keep walking upstream until there's an order <= river_order
*/
      __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_river_order); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3305, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_9 = PyObject_RichCompare(__pyx_v_stream_order, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3305, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3305, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      if (!__pyx_t_6) {
      } else {
        __pyx_t_25 = __pyx_t_6;
        goto __pyx_L78_bool_binop_done;
      }

      /* "pygeoprocessing/routing/routing.pyx":3306
 * 
 *             if (stream_order > river_order or
 *                     stream_feature.GetField('river_id') is not None):             # <<<<<<<<<<<<<<
 *                 # keep walking upstream until there's an order <= river_order
 *                 search_stack.extend(
*/
      __pyx_t_3 = __pyx_v_stream_feature;
      __Pyx_INCREF(__pyx_t_3);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_river_id};
        __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3306, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
      }
      __pyx_t_6 = (__pyx_t_9 != Py_None);
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      __pyx_t_25 = __pyx_t_6;
      __pyx_L78_bool_binop_done:;

      /* "pygeoprocessing/routing/routing.pyx":3305
 *             stream_order = stream_feature.GetField('order')
 * 
 *             if (stream_order > river_order or             # <<<<<<<<<<<<<<
 *                     stream_feature.GetField('river_id') is not None):
 *                 # keep walking upstream until there's an order <= river_order
*/
      if (__pyx_t_25) {

        /* "pygeoprocessing/routing/routing.pyx":3309
 *                 # keep walking upstream until there's an order <= river_order
 *                 search_stack.extend(
 *                     downstream_to_upstream_ids[feature_id])             # <<<<<<<<<<<<<<
 *             else:
 *                 # walk up the stream setting every upstream segment's
*/
        __pyx_t_9 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_feature_id); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3309, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);

        /* "pygeoprocessing/routing/routing.pyx":3308
 *                     stream_feature.GetField('river_id') is not None):
 *                 # keep walking upstream until there's an order <= river_order
 *                 search_stack.extend(             # <<<<<<<<<<<<<<
 *                     downstream_to_upstream_ids[feature_id])
 *             else:
*/
        __pyx_t_31 = __Pyx_PyList_Extend(__pyx_v_search_stack, __pyx_t_9); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3308, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3305
 *             stream_order = stream_feature.GetField('order')
 * 
 *             if (stream_order > river_order or             # <<<<<<<<<<<<<<
 *                     stream_feature.GetField('river_id') is not None):
 *                 # keep walking upstream until there's an order <= river_order
*/
        goto __pyx_L77;
      }

      /* "pygeoprocessing/routing/routing.pyx":3313
 *                 # walk up the stream setting every upstream segment's
 *                 # river_id to working_river_id
 *                 stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 *                 upstream_stack = [feature_id]
 * 
*/
      /*else*/ {
        __pyx_t_3 = __pyx_v_stream_layer;
        __Pyx_INCREF(__pyx_t_3);
        __pyx_t_5 = 0;
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_stream_feature};
          __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
          if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3313, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
        }
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3314
 *                 # river_id to working_river_id
 *                 stream_layer.SetFeature(stream_feature)
 *                 upstream_stack = [feature_id]             # <<<<<<<<<<<<<<
 * 
 *                 streams_by_order = collections.defaultdict(list)
*/
        __pyx_t_9 = PyList_New(1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3314, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
        __Pyx_INCREF(__pyx_v_feature_id);
        __Pyx_GIVEREF(__pyx_v_feature_id);
        if (__Pyx_PyList_SET_ITEM(__pyx_t_9, 0, __pyx_v_feature_id) != (0)) __PYX_ERR(0, 3314, __pyx_L1_error);
        __Pyx_XDECREF_SET(__pyx_v_upstream_stack, ((PyObject*)__pyx_t_9));
        __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3316
 *                 upstream_stack = [feature_id]
 * 
 *                 streams_by_order = collections.defaultdict(list)             # <<<<<<<<<<<<<<
 *                 drop_distance_collection = collections.defaultdict(list)
 *                 max_upstream_flow_accum = collections.defaultdict(int)
*/
        __pyx_t_3 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3316, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_36);
        __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3316, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
        __pyx_t_5 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_4))) {
          __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
          assert(__pyx_t_3);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
          __Pyx_INCREF(__pyx_t_3);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
          __pyx_t_5 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_3, ((PyObject *)(&PyList_Type))};
          __pyx_t_9 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3316, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
        }
        __Pyx_XDECREF_SET(__pyx_v_streams_by_order, __pyx_t_9);
        __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3317
 * 
 *                 streams_by_order = collections.defaultdict(list)
 *                 drop_distance_collection = collections.defaultdict(list)             # <<<<<<<<<<<<<<
 *                 max_upstream_flow_accum = collections.defaultdict(int)
 *                 while upstream_stack:
*/
        __pyx_t_4 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3317, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_36 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3317, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_36);
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_t_5 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_36))) {
          __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_36);
          assert(__pyx_t_4);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_36);
          __Pyx_INCREF(__pyx_t_4);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_36, __pyx__function);
          __pyx_t_5 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_4, ((PyObject *)(&PyList_Type))};
          __pyx_t_9 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_36, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
          __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
          if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3317, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
        }
        __Pyx_XDECREF_SET(__pyx_v_drop_distance_collection, __pyx_t_9);
        __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3318
 *                 streams_by_order = collections.defaultdict(list)
 *                 drop_distance_collection = collections.defaultdict(list)
 *                 max_upstream_flow_accum = collections.defaultdict(int)             # <<<<<<<<<<<<<<
 *                 while upstream_stack:
 *                     feature_id = upstream_stack.pop()
*/
        __pyx_t_36 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3318, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3318, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_t_5 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_3))) {
          __pyx_t_36 = PyMethod_GET_SELF(__pyx_t_3);
          assert(__pyx_t_36);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
          __Pyx_INCREF(__pyx_t_36);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
          __pyx_t_5 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_36, ((PyObject *)(&PyLong_Type))};
          __pyx_t_9 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3318, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
        }
        __Pyx_XDECREF_SET(__pyx_v_max_upstream_flow_accum, __pyx_t_9);
        __pyx_t_9 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3319
 *                 drop_distance_collection = collections.defaultdict(list)
 *                 max_upstream_flow_accum = collections.defaultdict(int)
 *                 while upstream_stack:             # <<<<<<<<<<<<<<
 *                     feature_id = upstream_stack.pop()
 *                     stream_feature = stream_layer.GetFeature(feature_id)
*/
        while (1) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_upstream_stack);
            if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3319, __pyx_L1_error)
            __pyx_t_25 = (__pyx_temp != 0);
          }

          if (!__pyx_t_25) break;

          /* "pygeoprocessing/routing/routing.pyx":3320
 *                 max_upstream_flow_accum = collections.defaultdict(int)
 *                 while upstream_stack:
 *                     feature_id = upstream_stack.pop()             # <<<<<<<<<<<<<<
 *                     stream_feature = stream_layer.GetFeature(feature_id)
 *                     stream_feature.SetField('river_id', working_river_id)
*/
          __pyx_t_9 = __Pyx_PyList_Pop(__pyx_v_upstream_stack); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3320, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
          __Pyx_DECREF_SET(__pyx_v_feature_id, __pyx_t_9);
          __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3321
 *                 while upstream_stack:
 *                     feature_id = upstream_stack.pop()
 *                     stream_feature = stream_layer.GetFeature(feature_id)             # <<<<<<<<<<<<<<
 *                     stream_feature.SetField('river_id', working_river_id)
 *                     stream_layer.SetFeature(stream_feature)
*/
          __pyx_t_3 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_3);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_feature_id};
            __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3321, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);
          }
          __Pyx_DECREF_SET(__pyx_v_stream_feature, __pyx_t_9);
          __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3322
 *                     feature_id = upstream_stack.pop()
 *                     stream_feature = stream_layer.GetFeature(feature_id)
 *                     stream_feature.SetField('river_id', working_river_id)             # <<<<<<<<<<<<<<
 *                     stream_layer.SetFeature(stream_feature)
 *                     order = stream_feature.GetField('order')
*/
          __pyx_t_3 = __pyx_v_stream_feature;
          __Pyx_INCREF(__pyx_t_3);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_river_id, __pyx_v_working_river_id};
            __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3322, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);
          }
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3323
 *                     stream_feature = stream_layer.GetFeature(feature_id)
 *                     stream_feature.SetField('river_id', working_river_id)
 *                     stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 *                     order = stream_feature.GetField('order')
 *                     streams_by_order[order].append(stream_feature)
*/
          __pyx_t_3 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_3);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_stream_feature};
            __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3323, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);
          }
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3324
 *                     stream_feature.SetField('river_id', working_river_id)
 *                     stream_layer.SetFeature(stream_feature)
 *                     order = stream_feature.GetField('order')             # <<<<<<<<<<<<<<
 *                     streams_by_order[order].append(stream_feature)
 *                     drop_distance_collection[order].append(
*/
          __pyx_t_3 = __pyx_v_stream_feature;
          __Pyx_INCREF(__pyx_t_3);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_order};
            __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3324, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);
          }
          __Pyx_XDECREF_SET(__pyx_v_order, __pyx_t_9);
          __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3325
 *                     stream_layer.SetFeature(stream_feature)
 *                     order = stream_feature.GetField('order')
 *                     streams_by_order[order].append(stream_feature)             # <<<<<<<<<<<<<<
 *                     drop_distance_collection[order].append(
 *                         stream_feature.GetField('drop_distance'))
*/
          __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_streams_by_order, __pyx_v_order); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3325, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
          __pyx_t_31 = __Pyx_PyObject_Append(__pyx_t_9, __pyx_v_stream_feature); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3325, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3326
 *                     order = stream_feature.GetField('order')
 *                     streams_by_order[order].append(stream_feature)
 *                     drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                         stream_feature.GetField('drop_distance'))
 *                     max_upstream_flow_accum[order] = max(
*/
          __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_v_order); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3326, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);

          /* "pygeoprocessing/routing/routing.pyx":3327
 *                     streams_by_order[order].append(stream_feature)
 *                     drop_distance_collection[order].append(
 *                         stream_feature.GetField('drop_distance'))             # <<<<<<<<<<<<<<
 *                     max_upstream_flow_accum[order] = max(
 *                         max_upstream_flow_accum[order],
*/
          __pyx_t_36 = __pyx_v_stream_feature;
          __Pyx_INCREF(__pyx_t_36);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_36, __pyx_mstate_global->__pyx_n_u_drop_distance};
            __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
            if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3327, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
          }

          /* "pygeoprocessing/routing/routing.pyx":3326
 *                     order = stream_feature.GetField('order')
 *                     streams_by_order[order].append(stream_feature)
 *                     drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                         stream_feature.GetField('drop_distance'))
 *                     max_upstream_flow_accum[order] = max(
*/
          __pyx_t_31 = __Pyx_PyObject_Append(__pyx_t_9, __pyx_t_3); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3326, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3330
 *                     max_upstream_flow_accum[order] = max(
 *                         max_upstream_flow_accum[order],
 *                         stream_feature.GetField('us_fa'))             # <<<<<<<<<<<<<<
 *                     stream_feature = None
 *                     upstream_stack.extend(
*/
          __pyx_t_9 = __pyx_v_stream_feature;
          __Pyx_INCREF(__pyx_t_9);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_us_fa};
            __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
            if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3330, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
          }

          /* "pygeoprocessing/routing/routing.pyx":3329
 *                         stream_feature.GetField('drop_distance'))
 *                     max_upstream_flow_accum[order] = max(
 *                         max_upstream_flow_accum[order],             # <<<<<<<<<<<<<<
 *                         stream_feature.GetField('us_fa'))
 *                     stream_feature = None
*/
          __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_max_upstream_flow_accum, __pyx_v_order); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3329, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);

          /* "pygeoprocessing/routing/routing.pyx":3330
 *                     max_upstream_flow_accum[order] = max(
 *                         max_upstream_flow_accum[order],
 *                         stream_feature.GetField('us_fa'))             # <<<<<<<<<<<<<<
 *                     stream_feature = None
 *                     upstream_stack.extend(
*/
          __pyx_t_4 = PyObject_RichCompare(__pyx_t_3, __pyx_t_9, Py_GT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3330, __pyx_L1_error)
          __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3330, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (__pyx_t_25) {
            __Pyx_INCREF(__pyx_t_3);
            __pyx_t_36 = __pyx_t_3;
          } else {
            __Pyx_INCREF(__pyx_t_9);
            __pyx_t_36 = __pyx_t_9;
          }
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
          __pyx_t_3 = __pyx_t_36;
          __Pyx_INCREF(__pyx_t_3);
          __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3328
 *                     drop_distance_collection[order].append(
 *                         stream_feature.GetField('drop_distance'))
 *                     max_upstream_flow_accum[order] = max(             # <<<<<<<<<<<<<<
 *                         max_upstream_flow_accum[order],
 *                         stream_feature.GetField('us_fa'))
*/
          if (unlikely((PyObject_SetItem(__pyx_v_max_upstream_flow_accum, __pyx_v_order, __pyx_t_3) < 0))) __PYX_ERR(0, 3328, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3331
 *                         max_upstream_flow_accum[order],
 *                         stream_feature.GetField('us_fa'))
 *                     stream_feature = None             # <<<<<<<<<<<<<<
 *                     upstream_stack.extend(
 *                         downstream_to_upstream_ids[feature_id])
*/
          __Pyx_INCREF(Py_None);
          __Pyx_DECREF_SET(__pyx_v_stream_feature, Py_None);

          /* "pygeoprocessing/routing/routing.pyx":3333
 *                     stream_feature = None
 *                     upstream_stack.extend(
 *                         downstream_to_upstream_ids[feature_id])             # <<<<<<<<<<<<<<
 * 
 *                 working_flow_accum_threshold = min_flow_accum_threshold
*/
          __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_feature_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3333, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_3);

          /* "pygeoprocessing/routing/routing.pyx":3332
 *                         stream_feature.GetField('us_fa'))
 *                     stream_feature = None
 *                     upstream_stack.extend(             # <<<<<<<<<<<<<<
 *                         downstream_to_upstream_ids[feature_id])
 * 
*/
          __pyx_t_31 = __Pyx_PyList_Extend(__pyx_v_upstream_stack, __pyx_t_3); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3332, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        }

        /* "pygeoprocessing/routing/routing.pyx":3335
 *                         downstream_to_upstream_ids[feature_id])
 * 
 *                 working_flow_accum_threshold = min_flow_accum_threshold             # <<<<<<<<<<<<<<
 *                 while drop_distance_collection and autotune_flow_accumulation:
 *                     stream_layer.CommitTransaction()
*/
        __pyx_t_3 = __Pyx_PyLong_From_long(__pyx_v_min_flow_accum_threshold); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3335, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_XDECREF_SET(__pyx_v_working_flow_accum_threshold, __pyx_t_3);
        __pyx_t_3 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3336
 * 
 *                 working_flow_accum_threshold = min_flow_accum_threshold
 *                 while drop_distance_collection and autotune_flow_accumulation:             # <<<<<<<<<<<<<<
 *                     stream_layer.CommitTransaction()
 *                     stream_layer.StartTransaction()
*/
        while (1) {
          __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_drop_distance_collection); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3336, __pyx_L1_error)
          if (__pyx_t_6) {
          } else {
            __pyx_t_25 = __pyx_t_6;
            goto __pyx_L84_bool_binop_done;
          }
          __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_autotune_flow_accumulation); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3336, __pyx_L1_error)
          __pyx_t_25 = __pyx_t_6;
          __pyx_L84_bool_binop_done:;
          if (!__pyx_t_25) break;

          /* "pygeoprocessing/routing/routing.pyx":3337
 *                 working_flow_accum_threshold = min_flow_accum_threshold
 *                 while drop_distance_collection and autotune_flow_accumulation:
 *                     stream_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *                     stream_layer.StartTransaction()
 *                     # decide how much bigger to make the flow_accum
*/
          __pyx_t_36 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_36);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_36, NULL};
            __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
            if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3337, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
          }
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3338
 *                 while drop_distance_collection and autotune_flow_accumulation:
 *                     stream_layer.CommitTransaction()
 *                     stream_layer.StartTransaction()             # <<<<<<<<<<<<<<
 *                     # decide how much bigger to make the flow_accum
 *                     # find a test_order that tests p_val > 0.5 then retest
*/
          __pyx_t_36 = __pyx_v_stream_layer;
          __Pyx_INCREF(__pyx_t_36);
          __pyx_t_5 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_36, NULL};
            __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
            if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3338, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
          }
          __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3341
 *                     # decide how much bigger to make the flow_accum
 *                     # find a test_order that tests p_val > 0.5 then retest
 *                     test_order = min(drop_distance_collection)             # <<<<<<<<<<<<<<
 *                     while test_order+1 <= max(drop_distance_collection):
 *                         if (len(drop_distance_collection[test_order]) < 3 or
*/
          __pyx_t_36 = NULL;
          __pyx_t_5 = 1;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_36, __pyx_v_drop_distance_collection};
            __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_min, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
            if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3341, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
          }
          __Pyx_XDECREF_SET(__pyx_v_test_order, __pyx_t_3);
          __pyx_t_3 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3342
 *                     # find a test_order that tests p_val > 0.5 then retest
 *                     test_order = min(drop_distance_collection)
 *                     while test_order+1 <= max(drop_distance_collection):             # <<<<<<<<<<<<<<
 *                         if (len(drop_distance_collection[test_order]) < 3 or
 *                                 len(drop_distance_collection[
*/
          while (1) {
            __pyx_t_3 = __Pyx_PyLong_AddObjC(__pyx_v_test_order, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3342, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_9 = NULL;
            __pyx_t_5 = 1;
            {
              PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_drop_distance_collection};
              __pyx_t_36 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_max, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
              __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
              if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3342, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_36);
            }
            __pyx_t_9 = PyObject_RichCompare(__pyx_t_3, __pyx_t_36, Py_LE); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3342, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
            __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3342, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
            if (!__pyx_t_25) break;

            /* "pygeoprocessing/routing/routing.pyx":3343
 *                     test_order = min(drop_distance_collection)
 *                     while test_order+1 <= max(drop_distance_collection):
 *                         if (len(drop_distance_collection[test_order]) < 3 or             # <<<<<<<<<<<<<<
 *                                 len(drop_distance_collection[
 *                                     test_order+1]) < 3):
*/
            __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_v_test_order); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3343, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);
            __pyx_t_35 = PyObject_Length(__pyx_t_9); if (unlikely(__pyx_t_35 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3343, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
            __pyx_t_6 = (__pyx_t_35 < 3);
            if (!__pyx_t_6) {
            } else {
              __pyx_t_25 = __pyx_t_6;
              goto __pyx_L89_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":3345
 *                         if (len(drop_distance_collection[test_order]) < 3 or
 *                                 len(drop_distance_collection[
 *                                     test_order+1]) < 3):             # <<<<<<<<<<<<<<
 *                             # too small to test so it's not significant
 *                             break
*/
            __pyx_t_9 = __Pyx_PyLong_AddObjC(__pyx_v_test_order, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3345, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_9);

            /* "pygeoprocessing/routing/routing.pyx":3344
 *                     while test_order+1 <= max(drop_distance_collection):
 *                         if (len(drop_distance_collection[test_order]) < 3 or
 *                                 len(drop_distance_collection[             # <<<<<<<<<<<<<<
 *                                     test_order+1]) < 3):
 *                             # too small to test so it's not significant
*/
            __pyx_t_36 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_t_9); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3344, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_36);
            __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
            __pyx_t_35 = PyObject_Length(__pyx_t_36); if (unlikely(__pyx_t_35 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3344, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3345
 *                         if (len(drop_distance_collection[test_order]) < 3 or
 *                                 len(drop_distance_collection[
 *                                     test_order+1]) < 3):             # <<<<<<<<<<<<<<
 *                             # too small to test so it's not significant
 *                             break
*/
            __pyx_t_6 = (__pyx_t_35 < 3);
            __pyx_t_25 = __pyx_t_6;
            __pyx_L89_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":3343
 *                     test_order = min(drop_distance_collection)
 *                     while test_order+1 <= max(drop_distance_collection):
 *                         if (len(drop_distance_collection[test_order]) < 3 or             # <<<<<<<<<<<<<<
 *                                 len(drop_distance_collection[
 *                                     test_order+1]) < 3):
*/
            if (__pyx_t_25) {

              /* "pygeoprocessing/routing/routing.pyx":3347
 *                                     test_order+1]) < 3):
 *                             # too small to test so it's not significant
 *                             break             # <<<<<<<<<<<<<<
 *                         _, p_val = scipy.stats.ttest_ind(
 *                             drop_distance_collection[test_order],
*/
              goto __pyx_L87_break;

              /* "pygeoprocessing/routing/routing.pyx":3343
 *                     test_order = min(drop_distance_collection)
 *                     while test_order+1 <= max(drop_distance_collection):
 *                         if (len(drop_distance_collection[test_order]) < 3 or             # <<<<<<<<<<<<<<
 *                                 len(drop_distance_collection[
 *                                     test_order+1]) < 3):
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3348
 *                             # too small to test so it's not significant
 *                             break
 *                         _, p_val = scipy.stats.ttest_ind(             # <<<<<<<<<<<<<<
 *                             drop_distance_collection[test_order],
 *                             drop_distance_collection[test_order+1],
*/
            __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_scipy); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3348, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_stats); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3348, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            __pyx_t_9 = __pyx_t_4;
            __Pyx_INCREF(__pyx_t_9);

            /* "pygeoprocessing/routing/routing.pyx":3349
 *                             break
 *                         _, p_val = scipy.stats.ttest_ind(
 *                             drop_distance_collection[test_order],             # <<<<<<<<<<<<<<
 *                             drop_distance_collection[test_order+1],
 *                             equal_var=True)
*/
            __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_v_test_order); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3349, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_3);

            /* "pygeoprocessing/routing/routing.pyx":3350
 *                         _, p_val = scipy.stats.ttest_ind(
 *                             drop_distance_collection[test_order],
 *                             drop_distance_collection[test_order+1],             # <<<<<<<<<<<<<<
 *                             equal_var=True)
 *                         if p_val > min_p_val or numpy.isnan(p_val):
*/
            __pyx_t_8 = __Pyx_PyLong_AddObjC(__pyx_v_test_order, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3350, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_8);
            __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3350, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3351
 *                             drop_distance_collection[test_order],
 *                             drop_distance_collection[test_order+1],
 *                             equal_var=True)             # <<<<<<<<<<<<<<
 *                         if p_val > min_p_val or numpy.isnan(p_val):
 *                             # not too big or just too few elements
*/
            __pyx_t_5 = 0;
            {
              PyObject *__pyx_callargs[3 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_9, __pyx_t_3, __pyx_t_7};
              __pyx_t_8 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_8);
              if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_equal_var, Py_True, __pyx_t_8, __pyx_callargs+3, 0) < (0)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __pyx_t_36 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_ttest_ind, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_8);
              __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
              __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
              if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_36);
            }
            if ((likely(PyTuple_CheckExact(__pyx_t_36))) || (PyList_CheckExact(__pyx_t_36))) {
              PyObject* sequence = __pyx_t_36;
              Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
              if (unlikely(size != 2)) {
                if (size > 2) __Pyx_RaiseTooManyValuesError(2);
                else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
                __PYX_ERR(0, 3348, __pyx_L1_error)
              }
              #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
              if (likely(PyTuple_CheckExact(sequence))) {
                __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0);
                __Pyx_INCREF(__pyx_t_4);
                __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1);
                __Pyx_INCREF(__pyx_t_8);
              } else {
                __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
                if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3348, __pyx_L1_error)
                __Pyx_XGOTREF(__pyx_t_4);
                __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
                if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3348, __pyx_L1_error)
                __Pyx_XGOTREF(__pyx_t_8);
              }
              #else
              __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_4);
              __pyx_t_8 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_8);
              #endif
              __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
            } else {
              Py_ssize_t index = -1;
              __pyx_t_7 = PyObject_GetIter(__pyx_t_36); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_7);
              __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
              __pyx_t_14 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
              index = 0; __pyx_t_4 = __pyx_t_14(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L91_unpacking_failed;
              __Pyx_GOTREF(__pyx_t_4);
              index = 1; __pyx_t_8 = __pyx_t_14(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L91_unpacking_failed;
              __Pyx_GOTREF(__pyx_t_8);
              if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_7), 2) < (0)) __PYX_ERR(0, 3348, __pyx_L1_error)
              __pyx_t_14 = NULL;
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              goto __pyx_L92_unpacking_done;
              __pyx_L91_unpacking_failed:;
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              __pyx_t_14 = NULL;
              if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
              __PYX_ERR(0, 3348, __pyx_L1_error)
              __pyx_L92_unpacking_done:;
            }

            /* "pygeoprocessing/routing/routing.pyx":3348
 *                             # too small to test so it's not significant
 *                             break
 *                         _, p_val = scipy.stats.ttest_ind(             # <<<<<<<<<<<<<<
 *                             drop_distance_collection[test_order],
 *                             drop_distance_collection[test_order+1],
*/
            __Pyx_XDECREF_SET(__pyx_v__, __pyx_t_4);
            __pyx_t_4 = 0;
            __Pyx_XDECREF_SET(__pyx_v_p_val, __pyx_t_8);
            __pyx_t_8 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3352
 *                             drop_distance_collection[test_order+1],
 *                             equal_var=True)
 *                         if p_val > min_p_val or numpy.isnan(p_val):             # <<<<<<<<<<<<<<
 *                             # not too big or just too few elements
 *                             break
*/
            __pyx_t_36 = PyFloat_FromDouble(__pyx_v_min_p_val); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_36);
            __pyx_t_8 = PyObject_RichCompare(__pyx_v_p_val, __pyx_t_36, Py_GT); __Pyx_XGOTREF(__pyx_t_8); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
            __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
            if (!__pyx_t_6) {
            } else {
              __pyx_t_25 = __pyx_t_6;
              goto __pyx_L94_bool_binop_done;
            }
            __pyx_t_36 = NULL;
            __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_4);
            __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_isnan); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
            __pyx_t_5 = 1;
            #if CYTHON_UNPACK_METHODS
            if (unlikely(PyMethod_Check(__pyx_t_7))) {
              __pyx_t_36 = PyMethod_GET_SELF(__pyx_t_7);
              assert(__pyx_t_36);
              PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
              __Pyx_INCREF(__pyx_t_36);
              __Pyx_INCREF(__pyx__function);
              __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
              __pyx_t_5 = 0;
            }
            #endif
            {
              PyObject *__pyx_callargs[2] = {__pyx_t_36, __pyx_v_p_val};
              __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
              __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3352, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_8);
            }
            __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_8); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3352, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
            __pyx_t_25 = __pyx_t_6;
            __pyx_L94_bool_binop_done:;
            if (__pyx_t_25) {

              /* "pygeoprocessing/routing/routing.pyx":3354
 *                         if p_val > min_p_val or numpy.isnan(p_val):
 *                             # not too big or just too few elements
 *                             break             # <<<<<<<<<<<<<<
 *                         test_order += 1
 *                     if test_order == min(drop_distance_collection):
*/
              goto __pyx_L87_break;

              /* "pygeoprocessing/routing/routing.pyx":3352
 *                             drop_distance_collection[test_order+1],
 *                             equal_var=True)
 *                         if p_val > min_p_val or numpy.isnan(p_val):             # <<<<<<<<<<<<<<
 *                             # not too big or just too few elements
 *                             break
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3355
 *                             # not too big or just too few elements
 *                             break
 *                         test_order += 1             # <<<<<<<<<<<<<<
 *                     if test_order == min(drop_distance_collection):
 *                         # order 1/2 streams are not statistically different
*/
            __pyx_t_8 = __Pyx_PyLong_AddObjC(__pyx_v_test_order, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3355, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_8);
            __Pyx_DECREF_SET(__pyx_v_test_order, __pyx_t_8);
            __pyx_t_8 = 0;
          }
          __pyx_L87_break:;

          /* "pygeoprocessing/routing/routing.pyx":3356
 *                             break
 *                         test_order += 1
 *                     if test_order == min(drop_distance_collection):             # <<<<<<<<<<<<<<
 *                         # order 1/2 streams are not statistically different
 *                         break
*/
          __pyx_t_7 = NULL;
          __pyx_t_5 = 1;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_v_drop_distance_collection};
            __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_min, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
            if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3356, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_8);
          }
          __pyx_t_7 = PyObject_RichCompare(__pyx_v_test_order, __pyx_t_8, Py_EQ); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3356, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3356, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
          if (__pyx_t_25) {

            /* "pygeoprocessing/routing/routing.pyx":3358
 *                     if test_order == min(drop_distance_collection):
 *                         # order 1/2 streams are not statistically different
 *                         break             # <<<<<<<<<<<<<<
 *                     # try to make a reasonable estimate for flow accum
 *                     working_flow_accum_threshold *= 1.25
*/
            goto __pyx_L83_break;

            /* "pygeoprocessing/routing/routing.pyx":3356
 *                             break
 *                         test_order += 1
 *                     if test_order == min(drop_distance_collection):             # <<<<<<<<<<<<<<
 *                         # order 1/2 streams are not statistically different
 *                         break
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":3360
 *                         break
 *                     # try to make a reasonable estimate for flow accum
 *                     working_flow_accum_threshold *= 1.25             # <<<<<<<<<<<<<<
 *                     # reconstruct stream segments of <= test_order
 *                     for order in range(1, test_order+1):
*/
          __pyx_t_7 = PyNumber_InPlaceMultiply(__pyx_v_working_flow_accum_threshold, __pyx_mstate_global->__pyx_float_1_25); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3360, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_7);
          __Pyx_DECREF_SET(__pyx_v_working_flow_accum_threshold, __pyx_t_7);
          __pyx_t_7 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3362
 *                     working_flow_accum_threshold *= 1.25
 *                     # reconstruct stream segments of <= test_order
 *                     for order in range(1, test_order+1):             # <<<<<<<<<<<<<<
 *                         # This will build up a list of kept or reconstructed
 *                         # streams. Other streams will be deleted.
*/
          __pyx_t_8 = NULL;
          __pyx_t_36 = __Pyx_PyLong_AddObjC(__pyx_v_test_order, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3362, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_36);
          __pyx_t_5 = 1;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_8, __pyx_mstate_global->__pyx_int_1, __pyx_t_36};
            __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)(&PyRange_Type), __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
            __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
            if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3362, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
          }
          __pyx_t_36 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3362, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_36);
          __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_36); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3362, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
          for (;;) {
            {
              __pyx_t_7 = __pyx_t_19(__pyx_t_36);
              if (unlikely(!__pyx_t_7)) {
                PyObject* exc_type = PyErr_Occurred();
                if (exc_type) {
                  if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3362, __pyx_L1_error)
                  PyErr_Clear();
                }
                break;
              }
            }
            __Pyx_GOTREF(__pyx_t_7);
            __Pyx_XDECREF_SET(__pyx_v_order, __pyx_t_7);
            __pyx_t_7 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3365
 *                         # This will build up a list of kept or reconstructed
 *                         # streams. Other streams will be deleted.
 *                         streams_to_retest = []             # <<<<<<<<<<<<<<
 *                         # The drop distance set will be recalculated
 *                         # dynamically for the next loop
*/
            __pyx_t_7 = PyList_New(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3365, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_7);
            __Pyx_XDECREF_SET(__pyx_v_streams_to_retest, ((PyObject*)__pyx_t_7));
            __pyx_t_7 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3368
 *                         # The drop distance set will be recalculated
 *                         # dynamically for the next loop
 *                         if order in max_upstream_flow_accum:             # <<<<<<<<<<<<<<
 *                             del max_upstream_flow_accum[order]
 *                         if order in drop_distance_collection:
*/
            __pyx_t_25 = (__Pyx_PySequence_ContainsTF(__pyx_v_order, __pyx_v_max_upstream_flow_accum, Py_EQ)); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3368, __pyx_L1_error)
            if (__pyx_t_25) {

              /* "pygeoprocessing/routing/routing.pyx":3369
 *                         # dynamically for the next loop
 *                         if order in max_upstream_flow_accum:
 *                             del max_upstream_flow_accum[order]             # <<<<<<<<<<<<<<
 *                         if order in drop_distance_collection:
 *                             del drop_distance_collection[order]
*/
              if (unlikely((PyObject_DelItem(__pyx_v_max_upstream_flow_accum, __pyx_v_order) < 0))) __PYX_ERR(0, 3369, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3368
 *                         # The drop distance set will be recalculated
 *                         # dynamically for the next loop
 *                         if order in max_upstream_flow_accum:             # <<<<<<<<<<<<<<
 *                             del max_upstream_flow_accum[order]
 *                         if order in drop_distance_collection:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3370
 *                         if order in max_upstream_flow_accum:
 *                             del max_upstream_flow_accum[order]
 *                         if order in drop_distance_collection:             # <<<<<<<<<<<<<<
 *                             del drop_distance_collection[order]
 *                         while streams_by_order[order]:
*/
            __pyx_t_25 = (__Pyx_PySequence_ContainsTF(__pyx_v_order, __pyx_v_drop_distance_collection, Py_EQ)); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3370, __pyx_L1_error)
            if (__pyx_t_25) {

              /* "pygeoprocessing/routing/routing.pyx":3371
 *                             del max_upstream_flow_accum[order]
 *                         if order in drop_distance_collection:
 *                             del drop_distance_collection[order]             # <<<<<<<<<<<<<<
 *                         while streams_by_order[order]:
 *                             stream_feature = streams_by_order[order].pop()
*/
              if (unlikely((PyObject_DelItem(__pyx_v_drop_distance_collection, __pyx_v_order) < 0))) __PYX_ERR(0, 3371, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3370
 *                         if order in max_upstream_flow_accum:
 *                             del max_upstream_flow_accum[order]
 *                         if order in drop_distance_collection:             # <<<<<<<<<<<<<<
 *                             del drop_distance_collection[order]
 *                         while streams_by_order[order]:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3372
 *                         if order in drop_distance_collection:
 *                             del drop_distance_collection[order]
 *                         while streams_by_order[order]:             # <<<<<<<<<<<<<<
 *                             stream_feature = streams_by_order[order].pop()
 *                             if (stream_feature.GetField('ds_fa') <
*/
            while (1) {
              __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_v_streams_by_order, __pyx_v_order); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3372, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_7);
              __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3372, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              if (!__pyx_t_25) break;

              /* "pygeoprocessing/routing/routing.pyx":3373
 *                             del drop_distance_collection[order]
 *                         while streams_by_order[order]:
 *                             stream_feature = streams_by_order[order].pop()             # <<<<<<<<<<<<<<
 *                             if (stream_feature.GetField('ds_fa') <
 *                                     working_flow_accum_threshold):
*/
              __pyx_t_7 = __Pyx_PyObject_GetItem(__pyx_v_streams_by_order, __pyx_v_order); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3373, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_7);
              __pyx_t_8 = __Pyx_PyObject_Pop(__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3373, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_8);
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              __Pyx_DECREF_SET(__pyx_v_stream_feature, __pyx_t_8);
              __pyx_t_8 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3374
 *                         while streams_by_order[order]:
 *                             stream_feature = streams_by_order[order].pop()
 *                             if (stream_feature.GetField('ds_fa') <             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this flow accumulation is too small, it's
*/
              __pyx_t_7 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_7);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_ds_fa};
                __pyx_t_8 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
                if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3374, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_8);
              }

              /* "pygeoprocessing/routing/routing.pyx":3375
 *                             stream_feature = streams_by_order[order].pop()
 *                             if (stream_feature.GetField('ds_fa') <
 *                                     working_flow_accum_threshold):             # <<<<<<<<<<<<<<
 *                                 # this flow accumulation is too small, it's
 *                                 # not relevant anymore
*/
              __pyx_t_7 = PyObject_RichCompare(__pyx_t_8, __pyx_v_working_flow_accum_threshold, Py_LT); __Pyx_XGOTREF(__pyx_t_7); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3374, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3374
 *                         while streams_by_order[order]:
 *                             stream_feature = streams_by_order[order].pop()
 *                             if (stream_feature.GetField('ds_fa') <             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this flow accumulation is too small, it's
*/
              __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_7); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3374, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              if (__pyx_t_25) {

                /* "pygeoprocessing/routing/routing.pyx":3379
 *                                 # not relevant anymore
 *                                 # remove from connectivity and delete
 *                                 _delete_feature(             # <<<<<<<<<<<<<<
 *                                     stream_feature, stream_layer,
 *                                     upstream_to_downstream_id,
*/
                __pyx_t_8 = NULL;
                __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_delete_feature); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3379, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_4);

                /* "pygeoprocessing/routing/routing.pyx":3382
 *                                     stream_feature, stream_layer,
 *                                     upstream_to_downstream_id,
 *                                     downstream_to_upstream_ids)             # <<<<<<<<<<<<<<
 *                                 continue
 *                             if (stream_feature.GetField('us_fa') >=
*/
                __pyx_t_5 = 1;
                #if CYTHON_UNPACK_METHODS
                if (unlikely(PyMethod_Check(__pyx_t_4))) {
                  __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_4);
                  assert(__pyx_t_8);
                  PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
                  __Pyx_INCREF(__pyx_t_8);
                  __Pyx_INCREF(__pyx__function);
                  __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
                  __pyx_t_5 = 0;
                }
                #endif
                {
                  PyObject *__pyx_callargs[5] = {__pyx_t_8, __pyx_v_stream_feature, __pyx_v_stream_layer, __pyx_v_upstream_to_downstream_id, __pyx_v_downstream_to_upstream_ids};
                  __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
                  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3379, __pyx_L1_error)
                  __Pyx_GOTREF(__pyx_t_7);
                }
                __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3383
 *                                     upstream_to_downstream_id,
 *                                     downstream_to_upstream_ids)
 *                                 continue             # <<<<<<<<<<<<<<
 *                             if (stream_feature.GetField('us_fa') >=
 *                                     working_flow_accum_threshold):
*/
                goto __pyx_L101_continue;

                /* "pygeoprocessing/routing/routing.pyx":3374
 *                         while streams_by_order[order]:
 *                             stream_feature = streams_by_order[order].pop()
 *                             if (stream_feature.GetField('ds_fa') <             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this flow accumulation is too small, it's
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":3384
 *                                     downstream_to_upstream_ids)
 *                                 continue
 *                             if (stream_feature.GetField('us_fa') >=             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this whole stream still fits in the
*/
              __pyx_t_4 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_4);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_us_fa};
                __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
                if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3384, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_7);
              }

              /* "pygeoprocessing/routing/routing.pyx":3385
 *                                 continue
 *                             if (stream_feature.GetField('us_fa') >=
 *                                     working_flow_accum_threshold):             # <<<<<<<<<<<<<<
 *                                 # this whole stream still fits in the
 *                                 # threshold so keep it
*/
              __pyx_t_4 = PyObject_RichCompare(__pyx_t_7, __pyx_v_working_flow_accum_threshold, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3384, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3384
 *                                     downstream_to_upstream_ids)
 *                                 continue
 *                             if (stream_feature.GetField('us_fa') >=             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this whole stream still fits in the
*/
              __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3384, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
              if (__pyx_t_25) {

                /* "pygeoprocessing/routing/routing.pyx":3389
 *                                 # threshold so keep it
 *                                 # add drop distance to working set
 *                                 drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                                     stream_feature.GetField('drop_distance'))
 *                                 max_upstream_flow_accum[order] = max(
*/
                __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_v_order); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3389, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_4);

                /* "pygeoprocessing/routing/routing.pyx":3390
 *                                 # add drop distance to working set
 *                                 drop_distance_collection[order].append(
 *                                     stream_feature.GetField('drop_distance'))             # <<<<<<<<<<<<<<
 *                                 max_upstream_flow_accum[order] = max(
 *                                     max_upstream_flow_accum[order],
*/
                __pyx_t_8 = __pyx_v_stream_feature;
                __Pyx_INCREF(__pyx_t_8);
                __pyx_t_5 = 0;
                {
                  PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_drop_distance};
                  __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3390, __pyx_L1_error)
                  __Pyx_GOTREF(__pyx_t_7);
                }

                /* "pygeoprocessing/routing/routing.pyx":3389
 *                                 # threshold so keep it
 *                                 # add drop distance to working set
 *                                 drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                                     stream_feature.GetField('drop_distance'))
 *                                 max_upstream_flow_accum[order] = max(
*/
                __pyx_t_31 = __Pyx_PyObject_Append(__pyx_t_4, __pyx_t_7); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3389, __pyx_L1_error)
                __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
                __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3393
 *                                 max_upstream_flow_accum[order] = max(
 *                                     max_upstream_flow_accum[order],
 *                                     stream_feature.GetField('us_fa'))             # <<<<<<<<<<<<<<
 *                                 stream_layer.SetFeature(stream_feature)
 *                                 streams_to_retest.append(stream_feature)
*/
                __pyx_t_4 = __pyx_v_stream_feature;
                __Pyx_INCREF(__pyx_t_4);
                __pyx_t_5 = 0;
                {
                  PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_us_fa};
                  __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
                  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3393, __pyx_L1_error)
                  __Pyx_GOTREF(__pyx_t_7);
                }

                /* "pygeoprocessing/routing/routing.pyx":3392
 *                                     stream_feature.GetField('drop_distance'))
 *                                 max_upstream_flow_accum[order] = max(
 *                                     max_upstream_flow_accum[order],             # <<<<<<<<<<<<<<
 *                                     stream_feature.GetField('us_fa'))
 *                                 stream_layer.SetFeature(stream_feature)
*/
                __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_max_upstream_flow_accum, __pyx_v_order); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3392, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_4);

                /* "pygeoprocessing/routing/routing.pyx":3393
 *                                 max_upstream_flow_accum[order] = max(
 *                                     max_upstream_flow_accum[order],
 *                                     stream_feature.GetField('us_fa'))             # <<<<<<<<<<<<<<
 *                                 stream_layer.SetFeature(stream_feature)
 *                                 streams_to_retest.append(stream_feature)
*/
                __pyx_t_3 = PyObject_RichCompare(__pyx_t_7, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3393, __pyx_L1_error)
                __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3393, __pyx_L1_error)
                __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
                if (__pyx_t_25) {
                  __Pyx_INCREF(__pyx_t_7);
                  __pyx_t_8 = __pyx_t_7;
                } else {
                  __Pyx_INCREF(__pyx_t_4);
                  __pyx_t_8 = __pyx_t_4;
                }
                __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
                __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
                __pyx_t_7 = __pyx_t_8;
                __Pyx_INCREF(__pyx_t_7);
                __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3391
 *                                 drop_distance_collection[order].append(
 *                                     stream_feature.GetField('drop_distance'))
 *                                 max_upstream_flow_accum[order] = max(             # <<<<<<<<<<<<<<
 *                                     max_upstream_flow_accum[order],
 *                                     stream_feature.GetField('us_fa'))
*/
                if (unlikely((PyObject_SetItem(__pyx_v_max_upstream_flow_accum, __pyx_v_order, __pyx_t_7) < 0))) __PYX_ERR(0, 3391, __pyx_L1_error)
                __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3394
 *                                     max_upstream_flow_accum[order],
 *                                     stream_feature.GetField('us_fa'))
 *                                 stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 *                                 streams_to_retest.append(stream_feature)
 *                                 continue
*/
                __pyx_t_8 = __pyx_v_stream_layer;
                __Pyx_INCREF(__pyx_t_8);
                __pyx_t_5 = 0;
                {
                  PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_v_stream_feature};
                  __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                  __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3394, __pyx_L1_error)
                  __Pyx_GOTREF(__pyx_t_7);
                }
                __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3395
 *                                     stream_feature.GetField('us_fa'))
 *                                 stream_layer.SetFeature(stream_feature)
 *                                 streams_to_retest.append(stream_feature)             # <<<<<<<<<<<<<<
 *                                 continue
 *                             # recalculate stream geometry
*/
                __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_streams_to_retest, __pyx_v_stream_feature); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3395, __pyx_L1_error)

                /* "pygeoprocessing/routing/routing.pyx":3396
 *                                 stream_layer.SetFeature(stream_feature)
 *                                 streams_to_retest.append(stream_feature)
 *                                 continue             # <<<<<<<<<<<<<<
 *                             # recalculate stream geometry
 *                             ds_x = stream_feature.GetField('ds_x')
*/
                goto __pyx_L101_continue;

                /* "pygeoprocessing/routing/routing.pyx":3384
 *                                     downstream_to_upstream_ids)
 *                                 continue
 *                             if (stream_feature.GetField('us_fa') >=             # <<<<<<<<<<<<<<
 *                                     working_flow_accum_threshold):
 *                                 # this whole stream still fits in the
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":3398
 *                                 continue
 *                             # recalculate stream geometry
 *                             ds_x = stream_feature.GetField('ds_x')             # <<<<<<<<<<<<<<
 *                             ds_y = stream_feature.GetField('ds_y')
 *                             upstream_d8_dir = stream_feature.GetField(
*/
              __pyx_t_8 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_8);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ds_x};
                __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3398, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_7);
              }
              __Pyx_XDECREF_SET(__pyx_v_ds_x, __pyx_t_7);
              __pyx_t_7 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3399
 *                             # recalculate stream geometry
 *                             ds_x = stream_feature.GetField('ds_x')
 *                             ds_y = stream_feature.GetField('ds_y')             # <<<<<<<<<<<<<<
 *                             upstream_d8_dir = stream_feature.GetField(
 *                                 'upstream_d8_dir')
*/
              __pyx_t_8 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_8);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_ds_y};
                __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3399, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_7);
              }
              __Pyx_XDECREF_SET(__pyx_v_ds_y, __pyx_t_7);
              __pyx_t_7 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3400
 *                             ds_x = stream_feature.GetField('ds_x')
 *                             ds_y = stream_feature.GetField('ds_y')
 *                             upstream_d8_dir = stream_feature.GetField(             # <<<<<<<<<<<<<<
 *                                 'upstream_d8_dir')
 *                             payload = _calculate_stream_geometry(
*/
              __pyx_t_8 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_8);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_upstream_d8_dir};
                __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
                if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3400, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_7);
              }
              __Pyx_XDECREF_SET(__pyx_v_upstream_d8_dir, __pyx_t_7);
              __pyx_t_7 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3403
 *                                 'upstream_d8_dir')
 *                             payload = _calculate_stream_geometry(
 *                                 ds_x, ds_y, upstream_d8_dir,             # <<<<<<<<<<<<<<
 *                                 flow_dir_info['geotransform'], n_cols, n_rows,
 *                                 flow_accum_managed_raster,
*/
              __pyx_t_11 = __Pyx_PyLong_As_int(__pyx_v_ds_x); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3403, __pyx_L1_error)
              __pyx_t_37 = __Pyx_PyLong_As_int(__pyx_v_ds_y); if (unlikely((__pyx_t_37 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3403, __pyx_L1_error)
              __pyx_t_38 = __Pyx_PyLong_As_int(__pyx_v_upstream_d8_dir); if (unlikely((__pyx_t_38 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3403, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3404
 *                             payload = _calculate_stream_geometry(
 *                                 ds_x, ds_y, upstream_d8_dir,
 *                                 flow_dir_info['geotransform'], n_cols, n_rows,             # <<<<<<<<<<<<<<
 *                                 flow_accum_managed_raster,
 *                                 flow_dir_managed_raster, flow_nodata,
*/
              __pyx_t_7 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_geotransform); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3404, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_7);

              /* "pygeoprocessing/routing/routing.pyx":3407
 *                                 flow_accum_managed_raster,
 *                                 flow_dir_managed_raster, flow_nodata,
 *                                 working_flow_accum_threshold,             # <<<<<<<<<<<<<<
 *                                 coord_to_stream_ids)
 *                             if payload is None:
*/
              __pyx_t_39 = __Pyx_PyLong_As_int(__pyx_v_working_flow_accum_threshold); if (unlikely((__pyx_t_39 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3407, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3402
 *                             upstream_d8_dir = stream_feature.GetField(
 *                                 'upstream_d8_dir')
 *                             payload = _calculate_stream_geometry(             # <<<<<<<<<<<<<<
 *                                 ds_x, ds_y, upstream_d8_dir,
 *                                 flow_dir_info['geotransform'], n_cols, n_rows,
*/
              __pyx_t_8 = __pyx_f_15pygeoprocessing_7routing_7routing__calculate_stream_geometry(__pyx_t_11, __pyx_t_37, __pyx_t_38, __pyx_t_7, __pyx_v_n_cols, __pyx_v_n_rows, __pyx_v_flow_accum_managed_raster, __pyx_v_flow_dir_managed_raster, __pyx_v_flow_nodata, __pyx_t_39, __pyx_v_coord_to_stream_ids); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3402, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_8);
              __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
              __Pyx_XDECREF_SET(__pyx_v_payload, __pyx_t_8);
              __pyx_t_8 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3409
 *                                 working_flow_accum_threshold,
 *                                 coord_to_stream_ids)
 *                             if payload is None:             # <<<<<<<<<<<<<<
 *                                 _delete_feature(
 *                                     stream_feature, stream_layer,
*/
              __pyx_t_25 = (__pyx_v_payload == Py_None);
              if (__pyx_t_25) {

                /* "pygeoprocessing/routing/routing.pyx":3410
 *                                 coord_to_stream_ids)
 *                             if payload is None:
 *                                 _delete_feature(             # <<<<<<<<<<<<<<
 *                                     stream_feature, stream_layer,
 *                                     upstream_to_downstream_id,
*/
                __pyx_t_7 = NULL;
                __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_delete_feature); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3410, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_4);

                /* "pygeoprocessing/routing/routing.pyx":3413
 *                                     stream_feature, stream_layer,
 *                                     upstream_to_downstream_id,
 *                                     downstream_to_upstream_ids)             # <<<<<<<<<<<<<<
 *                                 continue
 *                             (x_u, y_u, ds_x_1, ds_y_1, upstream_id_list,
*/
                __pyx_t_5 = 1;
                #if CYTHON_UNPACK_METHODS
                if (unlikely(PyMethod_Check(__pyx_t_4))) {
                  __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
                  assert(__pyx_t_7);
                  PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
                  __Pyx_INCREF(__pyx_t_7);
                  __Pyx_INCREF(__pyx__function);
                  __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
                  __pyx_t_5 = 0;
                }
                #endif
                {
                  PyObject *__pyx_callargs[5] = {__pyx_t_7, __pyx_v_stream_feature, __pyx_v_stream_layer, __pyx_v_upstream_to_downstream_id, __pyx_v_downstream_to_upstream_ids};
                  __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
                  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
                  if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3410, __pyx_L1_error)
                  __Pyx_GOTREF(__pyx_t_8);
                }
                __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;

                /* "pygeoprocessing/routing/routing.pyx":3414
 *                                     upstream_to_downstream_id,
 *                                     downstream_to_upstream_ids)
 *                                 continue             # <<<<<<<<<<<<<<
 *                             (x_u, y_u, ds_x_1, ds_y_1, upstream_id_list,
 *                                 stream_line) = payload
*/
                goto __pyx_L101_continue;

                /* "pygeoprocessing/routing/routing.pyx":3409
 *                                 working_flow_accum_threshold,
 *                                 coord_to_stream_ids)
 *                             if payload is None:             # <<<<<<<<<<<<<<
 *                                 _delete_feature(
 *                                     stream_feature, stream_layer,
*/
              }

              /* "pygeoprocessing/routing/routing.pyx":3416
 *                                 continue
 *                             (x_u, y_u, ds_x_1, ds_y_1, upstream_id_list,
 *                                 stream_line) = payload             # <<<<<<<<<<<<<<
 *                             # recalculate the drop distance set
 *                             stream_feature.SetGeometry(stream_line)
*/
              if ((likely(PyTuple_CheckExact(__pyx_v_payload))) || (PyList_CheckExact(__pyx_v_payload))) {
                PyObject* sequence = __pyx_v_payload;
                Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
                if (unlikely(size != 6)) {
                  if (size > 6) __Pyx_RaiseTooManyValuesError(6);
                  else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
                  __PYX_ERR(0, 3415, __pyx_L1_error)
                }
                #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
                if (likely(PyTuple_CheckExact(sequence))) {
                  __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0);
                  __Pyx_INCREF(__pyx_t_8);
                  __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
                  __Pyx_INCREF(__pyx_t_4);
                  __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2);
                  __Pyx_INCREF(__pyx_t_7);
                  __pyx_t_3 = PyTuple_GET_ITEM(sequence, 3);
                  __Pyx_INCREF(__pyx_t_3);
                  __pyx_t_9 = PyTuple_GET_ITEM(sequence, 4);
                  __Pyx_INCREF(__pyx_t_9);
                  __pyx_t_40 = PyTuple_GET_ITEM(sequence, 5);
                  __Pyx_INCREF(__pyx_t_40);
                } else {
                  __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_8);
                  __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_4);
                  __pyx_t_7 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_7);
                  __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_3);
                  __pyx_t_9 = __Pyx_PyList_GetItemRefFast(sequence, 4, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_9);
                  __pyx_t_40 = __Pyx_PyList_GetItemRefFast(sequence, 5, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_40)) __PYX_ERR(0, 3415, __pyx_L1_error)
                  __Pyx_XGOTREF(__pyx_t_40);
                }
                #else
                {
                  Py_ssize_t i;
                  PyObject** temps[6] = {&__pyx_t_8,&__pyx_t_4,&__pyx_t_7,&__pyx_t_3,&__pyx_t_9,&__pyx_t_40};
                  for (i=0; i < 6; i++) {
                    PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 3415, __pyx_L1_error)
                    __Pyx_GOTREF(item);
                    *(temps[i]) = item;
                  }
                }
                #endif
              } else {
                Py_ssize_t index = -1;
                PyObject** temps[6] = {&__pyx_t_8,&__pyx_t_4,&__pyx_t_7,&__pyx_t_3,&__pyx_t_9,&__pyx_t_40};
                __pyx_t_41 = PyObject_GetIter(__pyx_v_payload); if (unlikely(!__pyx_t_41)) __PYX_ERR(0, 3415, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_41);
                __pyx_t_14 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_41);
                for (index=0; index < 6; index++) {
                  PyObject* item = __pyx_t_14(__pyx_t_41); if (unlikely(!item)) goto __pyx_L106_unpacking_failed;
                  __Pyx_GOTREF(item);
                  *(temps[index]) = item;
                }
                if (__Pyx_IternextUnpackEndCheck(__pyx_t_14(__pyx_t_41), 6) < (0)) __PYX_ERR(0, 3415, __pyx_L1_error)
                __pyx_t_14 = NULL;
                __Pyx_DECREF(__pyx_t_41); __pyx_t_41 = 0;
                goto __pyx_L107_unpacking_done;
                __pyx_L106_unpacking_failed:;
                __Pyx_DECREF(__pyx_t_41); __pyx_t_41 = 0;
                __pyx_t_14 = NULL;
                if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
                __PYX_ERR(0, 3415, __pyx_L1_error)
                __pyx_L107_unpacking_done:;
              }

              /* "pygeoprocessing/routing/routing.pyx":3415
 *                                     downstream_to_upstream_ids)
 *                                 continue
 *                             (x_u, y_u, ds_x_1, ds_y_1, upstream_id_list,             # <<<<<<<<<<<<<<
 *                                 stream_line) = payload
 *                             # recalculate the drop distance set
*/
              __Pyx_XDECREF_SET(__pyx_v_x_u, __pyx_t_8);
              __pyx_t_8 = 0;
              __Pyx_XDECREF_SET(__pyx_v_y_u, __pyx_t_4);
              __pyx_t_4 = 0;
              __Pyx_XDECREF_SET(__pyx_v_ds_x_1, __pyx_t_7);
              __pyx_t_7 = 0;
              __Pyx_XDECREF_SET(__pyx_v_ds_y_1, __pyx_t_3);
              __pyx_t_3 = 0;
              __Pyx_XDECREF_SET(__pyx_v_upstream_id_list, __pyx_t_9);
              __pyx_t_9 = 0;
              __Pyx_XDECREF_SET(__pyx_v_stream_line, __pyx_t_40);
              __pyx_t_40 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3418
 *                                 stream_line) = payload
 *                             # recalculate the drop distance set
 *                             stream_feature.SetGeometry(stream_line)             # <<<<<<<<<<<<<<
 *                             upstream_dem = dem_managed_raster.get(x_u, y_u)
 *                             downstream_dem = dem_managed_raster.get(
*/
              __pyx_t_9 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_9);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_stream_line};
                __pyx_t_40 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetGeometry, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
                if (unlikely(!__pyx_t_40)) __PYX_ERR(0, 3418, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_40);
              }
              __Pyx_DECREF(__pyx_t_40); __pyx_t_40 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3419
 *                             # recalculate the drop distance set
 *                             stream_feature.SetGeometry(stream_line)
 *                             upstream_dem = dem_managed_raster.get(x_u, y_u)             # <<<<<<<<<<<<<<
 *                             downstream_dem = dem_managed_raster.get(
 *                                 ds_x, ds_y)
*/
              __pyx_t_33 = __Pyx_PyLong_As_long(__pyx_v_x_u); if (unlikely((__pyx_t_33 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3419, __pyx_L1_error)
              __pyx_t_34 = __Pyx_PyLong_As_long(__pyx_v_y_u); if (unlikely((__pyx_t_34 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3419, __pyx_L1_error)
              __pyx_v_upstream_dem = __pyx_v_dem_managed_raster.get(__pyx_t_33, __pyx_t_34);

              /* "pygeoprocessing/routing/routing.pyx":3421
 *                             upstream_dem = dem_managed_raster.get(x_u, y_u)
 *                             downstream_dem = dem_managed_raster.get(
 *                                 ds_x, ds_y)             # <<<<<<<<<<<<<<
 *                             drop_distance = upstream_dem - downstream_dem
 *                             drop_distance_collection[order].append(
*/
              __pyx_t_34 = __Pyx_PyLong_As_long(__pyx_v_ds_x); if (unlikely((__pyx_t_34 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3421, __pyx_L1_error)
              __pyx_t_33 = __Pyx_PyLong_As_long(__pyx_v_ds_y); if (unlikely((__pyx_t_33 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3421, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3420
 *                             stream_feature.SetGeometry(stream_line)
 *                             upstream_dem = dem_managed_raster.get(x_u, y_u)
 *                             downstream_dem = dem_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                 ds_x, ds_y)
 *                             drop_distance = upstream_dem - downstream_dem
*/
              __pyx_v_downstream_dem = __pyx_v_dem_managed_raster.get(__pyx_t_34, __pyx_t_33);

              /* "pygeoprocessing/routing/routing.pyx":3422
 *                             downstream_dem = dem_managed_raster.get(
 *                                 ds_x, ds_y)
 *                             drop_distance = upstream_dem - downstream_dem             # <<<<<<<<<<<<<<
 *                             drop_distance_collection[order].append(
 *                                 drop_distance)
*/
              __pyx_v_drop_distance = (__pyx_v_upstream_dem - __pyx_v_downstream_dem);

              /* "pygeoprocessing/routing/routing.pyx":3423
 *                                 ds_x, ds_y)
 *                             drop_distance = upstream_dem - downstream_dem
 *                             drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                                 drop_distance)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __Pyx_PyObject_GetItem(__pyx_v_drop_distance_collection, __pyx_v_order); if (unlikely(!__pyx_t_40)) __PYX_ERR(0, 3423, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3424
 *                             drop_distance = upstream_dem - downstream_dem
 *                             drop_distance_collection[order].append(
 *                                 drop_distance)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'drop_distance', drop_distance)
*/
              __pyx_t_9 = PyFloat_FromDouble(__pyx_v_drop_distance); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3424, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_9);

              /* "pygeoprocessing/routing/routing.pyx":3423
 *                                 ds_x, ds_y)
 *                             drop_distance = upstream_dem - downstream_dem
 *                             drop_distance_collection[order].append(             # <<<<<<<<<<<<<<
 *                                 drop_distance)
 *                             stream_feature.SetField(
*/
              __pyx_t_31 = __Pyx_PyObject_Append(__pyx_t_40, __pyx_t_9); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3423, __pyx_L1_error)
              __Pyx_DECREF(__pyx_t_40); __pyx_t_40 = 0;
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3425
 *                             drop_distance_collection[order].append(
 *                                 drop_distance)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'drop_distance', drop_distance)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3426
 *                                 drop_distance)
 *                             stream_feature.SetField(
 *                                 'drop_distance', drop_distance)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'us_fa', flow_accum_managed_raster.get(
*/
              __pyx_t_3 = PyFloat_FromDouble(__pyx_v_drop_distance); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3426, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_3);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_drop_distance, __pyx_t_3};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3425, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3427
 *                             stream_feature.SetField(
 *                                 'drop_distance', drop_distance)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'us_fa', flow_accum_managed_raster.get(
 *                                     x_u, y_u))
*/
              __pyx_t_3 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_3);

              /* "pygeoprocessing/routing/routing.pyx":3429
 *                             stream_feature.SetField(
 *                                 'us_fa', flow_accum_managed_raster.get(
 *                                     x_u, y_u))             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'thresh_fa', working_flow_accum_threshold)
*/
              __pyx_t_33 = __Pyx_PyLong_As_long(__pyx_v_x_u); if (unlikely((__pyx_t_33 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3429, __pyx_L1_error)
              __pyx_t_34 = __Pyx_PyLong_As_long(__pyx_v_y_u); if (unlikely((__pyx_t_34 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3429, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3428
 *                                 'drop_distance', drop_distance)
 *                             stream_feature.SetField(
 *                                 'us_fa', flow_accum_managed_raster.get(             # <<<<<<<<<<<<<<
 *                                     x_u, y_u))
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = PyFloat_FromDouble(__pyx_v_flow_accum_managed_raster.get(__pyx_t_33, __pyx_t_34)); if (unlikely(!__pyx_t_40)) __PYX_ERR(0, 3428, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_40);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_mstate_global->__pyx_n_u_us_fa, __pyx_t_40};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
                __Pyx_DECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3427, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3430
 *                                 'us_fa', flow_accum_managed_raster.get(
 *                                     x_u, y_u))
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'thresh_fa', working_flow_accum_threshold)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3431
 *                                     x_u, y_u))
 *                             stream_feature.SetField(
 *                                 'thresh_fa', working_flow_accum_threshold)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'ds_x', ds_x)
*/
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_thresh_fa, __pyx_v_working_flow_accum_threshold};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3430, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3432
 *                             stream_feature.SetField(
 *                                 'thresh_fa', working_flow_accum_threshold)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'ds_x', ds_x)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3433
 *                                 'thresh_fa', working_flow_accum_threshold)
 *                             stream_feature.SetField(
 *                                 'ds_x', ds_x)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'ds_y', ds_y)
*/
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_ds_x, __pyx_v_ds_x};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3432, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3434
 *                             stream_feature.SetField(
 *                                 'ds_x', ds_x)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'ds_y', ds_y)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3435
 *                                 'ds_x', ds_x)
 *                             stream_feature.SetField(
 *                                 'ds_y', ds_y)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'ds_x_1', ds_x_1)
*/
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_ds_y, __pyx_v_ds_y};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3434, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3436
 *                             stream_feature.SetField(
 *                                 'ds_y', ds_y)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'ds_x_1', ds_x_1)
 *                             stream_feature.SetField(
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3437
 *                                 'ds_y', ds_y)
 *                             stream_feature.SetField(
 *                                 'ds_x_1', ds_x_1)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField(
 *                                 'ds_y_1', ds_y_1)
*/
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_ds_x_1, __pyx_v_ds_x_1};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3436, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3438
 *                             stream_feature.SetField(
 *                                 'ds_x_1', ds_x_1)
 *                             stream_feature.SetField(             # <<<<<<<<<<<<<<
 *                                 'ds_y_1', ds_y_1)
 *                             stream_feature.SetField('us_x', x_u)
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);

              /* "pygeoprocessing/routing/routing.pyx":3439
 *                                 'ds_x_1', ds_x_1)
 *                             stream_feature.SetField(
 *                                 'ds_y_1', ds_y_1)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField('us_x', x_u)
 *                             stream_feature.SetField('us_y', y_u)
*/
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_ds_y_1, __pyx_v_ds_y_1};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3438, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3440
 *                             stream_feature.SetField(
 *                                 'ds_y_1', ds_y_1)
 *                             stream_feature.SetField('us_x', x_u)             # <<<<<<<<<<<<<<
 *                             stream_feature.SetField('us_y', y_u)
 * 
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_us_x, __pyx_v_x_u};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3440, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3441
 *                                 'ds_y_1', ds_y_1)
 *                             stream_feature.SetField('us_x', x_u)
 *                             stream_feature.SetField('us_y', y_u)             # <<<<<<<<<<<<<<
 * 
 *                             streams_to_retest.append(stream_feature)
*/
              __pyx_t_40 = __pyx_v_stream_feature;
              __Pyx_INCREF(__pyx_t_40);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_40, __pyx_mstate_global->__pyx_n_u_us_y, __pyx_v_y_u};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3441, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;

              /* "pygeoprocessing/routing/routing.pyx":3443
 *                             stream_feature.SetField('us_y', y_u)
 * 
 *                             streams_to_retest.append(stream_feature)             # <<<<<<<<<<<<<<
 *                             stream_layer.SetFeature(stream_feature)
 * 
*/
              __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_streams_to_retest, __pyx_v_stream_feature); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3443, __pyx_L1_error)

              /* "pygeoprocessing/routing/routing.pyx":3444
 * 
 *                             streams_to_retest.append(stream_feature)
 *                             stream_layer.SetFeature(stream_feature)             # <<<<<<<<<<<<<<
 * 
 *                         streams_by_order[order] = streams_to_retest
*/
              __pyx_t_40 = __pyx_v_stream_layer;
              __Pyx_INCREF(__pyx_t_40);
              __pyx_t_5 = 0;
              {
                PyObject *__pyx_callargs[2] = {__pyx_t_40, __pyx_v_stream_feature};
                __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
                if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3444, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_9);
              }
              __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
              __pyx_L101_continue:;
            }

            /* "pygeoprocessing/routing/routing.pyx":3446
 *                             stream_layer.SetFeature(stream_feature)
 * 
 *                         streams_by_order[order] = streams_to_retest             # <<<<<<<<<<<<<<
 *                 working_river_id += 1
 * 
*/
            if (unlikely((PyObject_SetItem(__pyx_v_streams_by_order, __pyx_v_order, __pyx_v_streams_to_retest) < 0))) __PYX_ERR(0, 3446, __pyx_L1_error)

            /* "pygeoprocessing/routing/routing.pyx":3362
 *                     working_flow_accum_threshold *= 1.25
 *                     # reconstruct stream segments of <= test_order
 *                     for order in range(1, test_order+1):             # <<<<<<<<<<<<<<
 *                         # This will build up a list of kept or reconstructed
 *                         # streams. Other streams will be deleted.
*/
          }
          __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
        }
        __pyx_L83_break:;

        /* "pygeoprocessing/routing/routing.pyx":3447
 * 
 *                         streams_by_order[order] = streams_to_retest
 *                 working_river_id += 1             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_managed_raster.close()
*/
        __pyx_t_36 = __Pyx_PyLong_AddObjC(__pyx_v_working_river_id, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3447, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_36);
        __Pyx_DECREF_SET(__pyx_v_working_river_id, __pyx_t_36);
        __pyx_t_36 = 0;
      }
      __pyx_L77:;
    }

    /* "pygeoprocessing/routing/routing.pyx":3285
 *         '(extract_strahler_streams_d8): determine rivers')
 *     working_river_id = 0
 *     for outlet_index, outlet_fid in enumerate(outlet_fid_list):             # <<<<<<<<<<<<<<
 *         # walk upstream starting from this outlet to search for rivers
 *         # defined as stream segments whose order is <= river_order. Note it
*/
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3449
 *                 working_river_id += 1
 * 
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     flow_accum_managed_raster.close()
 *     dem_managed_raster.close()
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3450
 * 
 *     flow_dir_managed_raster.close()
 *     flow_accum_managed_raster.close()             # <<<<<<<<<<<<<<
 *     dem_managed_raster.close()
 *     LOGGER.info(
*/
  __pyx_v_flow_accum_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3451
 *     flow_dir_managed_raster.close()
 *     flow_accum_managed_raster.close()
 *     dem_managed_raster.close()             # <<<<<<<<<<<<<<
 *     LOGGER.info(
 *         '(extract_strahler_streams_d8): '
*/
  __pyx_v_dem_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3452
 *     flow_accum_managed_raster.close()
 *     dem_managed_raster.close()
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): '
 *         'flow accumulation adjustment complete')
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3452, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_36);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3452, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_flo_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3452, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3456
 *         'flow accumulation adjustment complete')
 * 
 *     stream_layer.DeleteField(             # <<<<<<<<<<<<<<
 *         stream_layer.FindFieldIndex('upstream_d8_dir', 1))
 *     stream_layer.CommitTransaction()
*/
  __pyx_t_9 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_9);

  /* "pygeoprocessing/routing/routing.pyx":3457
 * 
 *     stream_layer.DeleteField(
 *         stream_layer.FindFieldIndex('upstream_d8_dir', 1))             # <<<<<<<<<<<<<<
 *     stream_layer.CommitTransaction()
 *     stream_layer.StartTransaction()
*/
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_stream_layer, __pyx_mstate_global->__pyx_n_u_FindFieldIndex); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3457, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_36 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_mstate_global->__pyx_tuple[7], NULL); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3457, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_36);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_t_36};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_DeleteField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3456, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3458
 *     stream_layer.DeleteField(
 *         stream_layer.FindFieldIndex('upstream_d8_dir', 1))
 *     stream_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *     stream_layer.StartTransaction()
 *     LOGGER.info(
*/
  __pyx_t_36 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_36);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_36, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3459
 *         stream_layer.FindFieldIndex('upstream_d8_dir', 1))
 *     stream_layer.CommitTransaction()
 *     stream_layer.StartTransaction()             # <<<<<<<<<<<<<<
 *     LOGGER.info(
 *         '(extract_strahler_streams_d8): '
*/
  __pyx_t_36 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_36);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_36, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3459, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3460
 *     stream_layer.CommitTransaction()
 *     stream_layer.StartTransaction()
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): '
 *         'final pass on stream order and geometry')
*/
  __pyx_t_36 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3460, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3460, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_36 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_36);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_36);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_36, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_fin};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_36); __pyx_t_36 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3460, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3465
 * 
 *     # seed the stack with all the upstream orders
 *     working_stack = [             # <<<<<<<<<<<<<<
 *         fid for fid in downstream_to_upstream_ids if
 *         not downstream_to_upstream_ids[fid]]
*/
  { /* enter inner scope */
    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3465, __pyx_L112_error)
    __Pyx_GOTREF(__pyx_t_1);

    /* "pygeoprocessing/routing/routing.pyx":3466
 *     # seed the stack with all the upstream orders
 *     working_stack = [
 *         fid for fid in downstream_to_upstream_ids if             # <<<<<<<<<<<<<<
 *         not downstream_to_upstream_ids[fid]]
 *     fid_to_order = {}
*/
    __pyx_t_18 = 0;
    __pyx_t_36 = __Pyx_dict_iterator(__pyx_v_downstream_to_upstream_ids, 1, ((PyObject *)NULL), (&__pyx_t_35), (&__pyx_t_39)); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3466, __pyx_L112_error)
    __Pyx_GOTREF(__pyx_t_36);
    __Pyx_XDECREF(__pyx_t_2);
    __pyx_t_2 = __pyx_t_36;
    __pyx_t_36 = 0;
    while (1) {
      __pyx_t_38 = __Pyx_dict_iter_next(__pyx_t_2, __pyx_t_35, &__pyx_t_18, &__pyx_t_36, NULL, NULL, __pyx_t_39);
      if (unlikely(__pyx_t_38 == 0)) break;
      if (unlikely(__pyx_t_38 == -1)) __PYX_ERR(0, 3466, __pyx_L112_error)
      __Pyx_GOTREF(__pyx_t_36);
      __Pyx_XDECREF_SET(__pyx_8genexpr1__pyx_v_fid, __pyx_t_36);
      __pyx_t_36 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3467
 *     working_stack = [
 *         fid for fid in downstream_to_upstream_ids if
 *         not downstream_to_upstream_ids[fid]]             # <<<<<<<<<<<<<<
 *     fid_to_order = {}
 *     processed_segments = 0
*/
      __pyx_t_36 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_8genexpr1__pyx_v_fid); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3467, __pyx_L112_error)
      __Pyx_GOTREF(__pyx_t_36);
      __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_36); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3467, __pyx_L112_error)
      __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
      __pyx_t_6 = (!__pyx_t_25);

      /* "pygeoprocessing/routing/routing.pyx":3466
 *     # seed the stack with all the upstream orders
 *     working_stack = [
 *         fid for fid in downstream_to_upstream_ids if             # <<<<<<<<<<<<<<
 *         not downstream_to_upstream_ids[fid]]
 *     fid_to_order = {}
*/
      if (__pyx_t_6) {
        if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_8genexpr1__pyx_v_fid))) __PYX_ERR(0, 3465, __pyx_L112_error)
      }
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_fid); __pyx_8genexpr1__pyx_v_fid = 0;
    goto __pyx_L116_exit_scope;
    __pyx_L112_error:;
    __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_fid); __pyx_8genexpr1__pyx_v_fid = 0;
    goto __pyx_L1_error;
    __pyx_L116_exit_scope:;
  } /* exit inner scope */
  __pyx_v_working_stack = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3468
 *         fid for fid in downstream_to_upstream_ids if
 *         not downstream_to_upstream_ids[fid]]
 *     fid_to_order = {}             # <<<<<<<<<<<<<<
 *     processed_segments = 0
 *     segments_to_process = len(downstream_to_upstream_ids)
*/
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3468, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_fid_to_order = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3469
 *         not downstream_to_upstream_ids[fid]]
 *     fid_to_order = {}
 *     processed_segments = 0             # <<<<<<<<<<<<<<
 *     segments_to_process = len(downstream_to_upstream_ids)
 *     deleted_set = set()
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __pyx_v_processed_segments = __pyx_mstate_global->__pyx_int_0;

  /* "pygeoprocessing/routing/routing.pyx":3470
 *     fid_to_order = {}
 *     processed_segments = 0
 *     segments_to_process = len(downstream_to_upstream_ids)             # <<<<<<<<<<<<<<
 *     deleted_set = set()
 *     while working_stack:
*/
  __pyx_t_35 = PyDict_Size(__pyx_v_downstream_to_upstream_ids); if (unlikely(__pyx_t_35 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3470, __pyx_L1_error)
  __pyx_v_segments_to_process = __pyx_t_35;

  /* "pygeoprocessing/routing/routing.pyx":3471
 *     processed_segments = 0
 *     segments_to_process = len(downstream_to_upstream_ids)
 *     deleted_set = set()             # <<<<<<<<<<<<<<
 *     while working_stack:
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
*/
  __pyx_t_1 = PySet_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3471, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_deleted_set = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3472
 *     segments_to_process = len(downstream_to_upstream_ids)
 *     deleted_set = set()
 *     while working_stack:             # <<<<<<<<<<<<<<
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
*/
  while (1) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_working_stack);
      if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3472, __pyx_L1_error)
      __pyx_t_6 = (__pyx_temp != 0);
    }

    if (!__pyx_t_6) break;

    /* "pygeoprocessing/routing/routing.pyx":3473
 *     deleted_set = set()
 *     while working_stack:
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    __pyx_t_6 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3474
 *     while working_stack:
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(extract_strahler_streams_d8): '
 *                 'final pass on stream order '
*/
      __pyx_t_2 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3474, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_36);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3474, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3477
 *                 '(extract_strahler_streams_d8): '
 *                 'final pass on stream order '
 *                 f'{processed_segments} of {segments_to_process} '             # <<<<<<<<<<<<<<
 *                 'segments complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_36 = __Pyx_PyObject_FormatSimple(__pyx_v_processed_segments, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3477, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_36);
      __pyx_t_40 = __Pyx_PyUnicode_From_Py_ssize_t(__pyx_v_segments_to_process, 0, ' ', 'd'); if (unlikely(!__pyx_t_40)) __PYX_ERR(0, 3477, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_40);
      __pyx_t_20[0] = __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_fin_2;
      __pyx_t_20[1] = __pyx_t_36;
      __pyx_t_20[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_20[3] = __pyx_t_40;
      __pyx_t_20[4] = __pyx_mstate_global->__pyx_kp_u_segments_complete;

      /* "pygeoprocessing/routing/routing.pyx":3475
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '             # <<<<<<<<<<<<<<
 *                 'final pass on stream order '
 *                 f'{processed_segments} of {segments_to_process} '
*/
      __pyx_t_3 = __Pyx_PyUnicode_Join(__pyx_t_20, 5, 58 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_36) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_40) + 18, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_36));
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3475, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
      __Pyx_DECREF(__pyx_t_40); __pyx_t_40 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
        assert(__pyx_t_2);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3474, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3479
 *                 f'{processed_segments} of {segments_to_process} '
 *                 'segments complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         processed_segments += 1
 * 
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3473
 *     deleted_set = set()
 *     while working_stack:
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(extract_strahler_streams_d8): '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3480
 *                 'segments complete')
 *             last_log_time = ctime(NULL)
 *         processed_segments += 1             # <<<<<<<<<<<<<<
 * 
 *         working_fid = working_stack.pop()
*/
    __pyx_t_1 = __Pyx_PyLong_AddObjC(__pyx_v_processed_segments, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3480, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF_SET(__pyx_v_processed_segments, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3482
 *         processed_segments += 1
 * 
 *         working_fid = working_stack.pop()             # <<<<<<<<<<<<<<
 *         # invariant: working_fid and all upstream are processed, order not set
 * 
*/
    __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_working_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3482, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_working_fid, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3485
 *         # invariant: working_fid and all upstream are processed, order not set
 * 
 *         upstream_fid_list = downstream_to_upstream_ids[working_fid]             # <<<<<<<<<<<<<<
 *         if upstream_fid_list:
 *             order_count = collections.defaultdict(int)
*/
    __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_working_fid); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3485, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_upstream_fid_list, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3486
 * 
 *         upstream_fid_list = downstream_to_upstream_ids[working_fid]
 *         if upstream_fid_list:             # <<<<<<<<<<<<<<
 *             order_count = collections.defaultdict(int)
 *             for upstream_fid in upstream_fid_list:
*/
    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_upstream_fid_list); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3486, __pyx_L1_error)
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3487
 *         upstream_fid_list = downstream_to_upstream_ids[working_fid]
 *         if upstream_fid_list:
 *             order_count = collections.defaultdict(int)             # <<<<<<<<<<<<<<
 *             for upstream_fid in upstream_fid_list:
 *                 order_count[fid_to_order[upstream_fid]] += 1
*/
      __pyx_t_9 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3487, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3487, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_2);
        assert(__pyx_t_9);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_9);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, ((PyObject *)(&PyLong_Type))};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3487, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_XDECREF_SET(__pyx_v_order_count, __pyx_t_1);
      __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3488
 *         if upstream_fid_list:
 *             order_count = collections.defaultdict(int)
 *             for upstream_fid in upstream_fid_list:             # <<<<<<<<<<<<<<
 *                 order_count[fid_to_order[upstream_fid]] += 1
 *             working_order = max(order_count)
*/
      if (likely(PyList_CheckExact(__pyx_v_upstream_fid_list)) || PyTuple_CheckExact(__pyx_v_upstream_fid_list)) {
        __pyx_t_1 = __pyx_v_upstream_fid_list; __Pyx_INCREF(__pyx_t_1);
        __pyx_t_35 = 0;
        __pyx_t_19 = NULL;
      } else {
        __pyx_t_35 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_upstream_fid_list); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3488, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
        __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3488, __pyx_L1_error)
      }
      for (;;) {
        if (likely(!__pyx_t_19)) {
          if (likely(PyList_CheckExact(__pyx_t_1))) {
            {
              Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
              #if !CYTHON_ASSUME_SAFE_SIZE
              if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3488, __pyx_L1_error)
              #endif
              if (__pyx_t_35 >= __pyx_temp) break;
            }
            __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_35, __Pyx_ReferenceSharing_OwnStrongReference);
            ++__pyx_t_35;
          } else {
            {
              Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
              #if !CYTHON_ASSUME_SAFE_SIZE
              if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3488, __pyx_L1_error)
              #endif
              if (__pyx_t_35 >= __pyx_temp) break;
            }
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_35));
            #else
            __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_35);
            #endif
            ++__pyx_t_35;
          }
          if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3488, __pyx_L1_error)
        } else {
          __pyx_t_2 = __pyx_t_19(__pyx_t_1);
          if (unlikely(!__pyx_t_2)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3488, __pyx_L1_error)
              PyErr_Clear();
            }
            break;
          }
        }
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_XDECREF_SET(__pyx_v_upstream_fid, __pyx_t_2);
        __pyx_t_2 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3489
 *             order_count = collections.defaultdict(int)
 *             for upstream_fid in upstream_fid_list:
 *                 order_count[fid_to_order[upstream_fid]] += 1             # <<<<<<<<<<<<<<
 *             working_order = max(order_count)
 *             if order_count[working_order] > 1:
*/
        __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_fid_to_order, __pyx_v_upstream_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3489, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_order_count, __pyx_t_2); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3489, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
        __pyx_t_3 = __Pyx_PyLong_AddObjC(__pyx_t_9, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3489, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely((PyObject_SetItem(__pyx_v_order_count, __pyx_t_2, __pyx_t_3) < 0))) __PYX_ERR(0, 3489, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3488
 *         if upstream_fid_list:
 *             order_count = collections.defaultdict(int)
 *             for upstream_fid in upstream_fid_list:             # <<<<<<<<<<<<<<
 *                 order_count[fid_to_order[upstream_fid]] += 1
 *             working_order = max(order_count)
*/
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3490
 *             for upstream_fid in upstream_fid_list:
 *                 order_count[fid_to_order[upstream_fid]] += 1
 *             working_order = max(order_count)             # <<<<<<<<<<<<<<
 *             if order_count[working_order] > 1:
 *                 working_order += 1
*/
      __pyx_t_2 = NULL;
      __pyx_t_5 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_order_count};
        __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_builtin_max, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3490, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_XDECREF_SET(__pyx_v_working_order, __pyx_t_1);
      __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3491
 *                 order_count[fid_to_order[upstream_fid]] += 1
 *             working_order = max(order_count)
 *             if order_count[working_order] > 1:             # <<<<<<<<<<<<<<
 *                 working_order += 1
 *             fid_to_order[working_fid] = working_order
*/
      __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_v_order_count, __pyx_v_working_order); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3491, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, Py_GT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3491, __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_ERR(0, 3491, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (__pyx_t_6) {

        /* "pygeoprocessing/routing/routing.pyx":3492
 *             working_order = max(order_count)
 *             if order_count[working_order] > 1:
 *                 working_order += 1             # <<<<<<<<<<<<<<
 *             fid_to_order[working_fid] = working_order
 *         else:
*/
        __pyx_t_2 = __Pyx_PyLong_AddObjC(__pyx_v_working_order, __pyx_mstate_global->__pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3492, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_DECREF_SET(__pyx_v_working_order, __pyx_t_2);
        __pyx_t_2 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3491
 *                 order_count[fid_to_order[upstream_fid]] += 1
 *             working_order = max(order_count)
 *             if order_count[working_order] > 1:             # <<<<<<<<<<<<<<
 *                 working_order += 1
 *             fid_to_order[working_fid] = working_order
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":3493
 *             if order_count[working_order] > 1:
 *                 working_order += 1
 *             fid_to_order[working_fid] = working_order             # <<<<<<<<<<<<<<
 *         else:
 *             fid_to_order[working_fid] = 1
*/
      if (unlikely((PyDict_SetItem(__pyx_v_fid_to_order, __pyx_v_working_fid, __pyx_v_working_order) < 0))) __PYX_ERR(0, 3493, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3486
 * 
 *         upstream_fid_list = downstream_to_upstream_ids[working_fid]
 *         if upstream_fid_list:             # <<<<<<<<<<<<<<
 *             order_count = collections.defaultdict(int)
 *             for upstream_fid in upstream_fid_list:
*/
      goto __pyx_L120;
    }

    /* "pygeoprocessing/routing/routing.pyx":3495
 *             fid_to_order[working_fid] = working_order
 *         else:
 *             fid_to_order[working_fid] = 1             # <<<<<<<<<<<<<<
 * 
 *         working_feature = stream_layer.GetFeature(working_fid)
*/
    /*else*/ {
      if (unlikely((PyDict_SetItem(__pyx_v_fid_to_order, __pyx_v_working_fid, __pyx_mstate_global->__pyx_int_1) < 0))) __PYX_ERR(0, 3495, __pyx_L1_error)
    }
    __pyx_L120:;

    /* "pygeoprocessing/routing/routing.pyx":3497
 *             fid_to_order[working_fid] = 1
 * 
 *         working_feature = stream_layer.GetFeature(working_fid)             # <<<<<<<<<<<<<<
 *         working_feature.SetField('order', fid_to_order[working_fid])
 *         stream_layer.SetFeature(working_feature)
*/
    __pyx_t_1 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_1);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_v_working_fid};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3497, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_working_feature, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3498
 * 
 *         working_feature = stream_layer.GetFeature(working_fid)
 *         working_feature.SetField('order', fid_to_order[working_fid])             # <<<<<<<<<<<<<<
 *         stream_layer.SetFeature(working_feature)
 *         working_feature = None
*/
    __pyx_t_1 = __pyx_v_working_feature;
    __Pyx_INCREF(__pyx_t_1);
    __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v_fid_to_order, __pyx_v_working_fid); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3498, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_mstate_global->__pyx_n_u_order, __pyx_t_3};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3498, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3499
 *         working_feature = stream_layer.GetFeature(working_fid)
 *         working_feature.SetField('order', fid_to_order[working_fid])
 *         stream_layer.SetFeature(working_feature)             # <<<<<<<<<<<<<<
 *         working_feature = None
 * 
*/
    __pyx_t_3 = __pyx_v_stream_layer;
    __Pyx_INCREF(__pyx_t_3);
    __pyx_t_5 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_working_feature};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3499, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3500
 *         working_feature.SetField('order', fid_to_order[working_fid])
 *         stream_layer.SetFeature(working_feature)
 *         working_feature = None             # <<<<<<<<<<<<<<
 * 
 *         if working_fid not in upstream_to_downstream_id:
*/
    __Pyx_INCREF(Py_None);
    __Pyx_DECREF_SET(__pyx_v_working_feature, Py_None);

    /* "pygeoprocessing/routing/routing.pyx":3502
 *         working_feature = None
 * 
 *         if working_fid not in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *             # nothing downstream so it's done
 *             continue
*/
    __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_working_fid, __pyx_v_upstream_to_downstream_id, Py_NE)); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3502, __pyx_L1_error)
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3504
 *         if working_fid not in upstream_to_downstream_id:
 *             # nothing downstream so it's done
 *             continue             # <<<<<<<<<<<<<<
 * 
 *         downstream_fid = upstream_to_downstream_id[working_fid]
*/
      goto __pyx_L117_continue;

      /* "pygeoprocessing/routing/routing.pyx":3502
 *         working_feature = None
 * 
 *         if working_fid not in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *             # nothing downstream so it's done
 *             continue
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3506
 *             continue
 * 
 *         downstream_fid = upstream_to_downstream_id[working_fid]             # <<<<<<<<<<<<<<
 *         connected_fids = downstream_to_upstream_ids[downstream_fid]
 *         if len(connected_fids) == 1:
*/
    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_upstream_to_downstream_id, __pyx_v_working_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3506, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_downstream_fid, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3507
 * 
 *         downstream_fid = upstream_to_downstream_id[working_fid]
 *         connected_fids = downstream_to_upstream_ids[downstream_fid]             # <<<<<<<<<<<<<<
 *         if len(connected_fids) == 1:
 *             # There's only one downstream, join it.
*/
    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_downstream_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3507, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_connected_fids, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3508
 *         downstream_fid = upstream_to_downstream_id[working_fid]
 *         connected_fids = downstream_to_upstream_ids[downstream_fid]
 *         if len(connected_fids) == 1:             # <<<<<<<<<<<<<<
 *             # There's only one downstream, join it.
 *             # Downstream order is the same as upstream
*/
    __pyx_t_35 = PyObject_Length(__pyx_v_connected_fids); if (unlikely(__pyx_t_35 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3508, __pyx_L1_error)
    __pyx_t_6 = (__pyx_t_35 == 1);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3511
 *             # There's only one downstream, join it.
 *             # Downstream order is the same as upstream
 *             fid_to_order[downstream_fid] = fid_to_order[working_fid]             # <<<<<<<<<<<<<<
 *             del fid_to_order[working_fid]
 * 
*/
      __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_fid_to_order, __pyx_v_working_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3511, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      if (unlikely((PyDict_SetItem(__pyx_v_fid_to_order, __pyx_v_downstream_fid, __pyx_t_2) < 0))) __PYX_ERR(0, 3511, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3512
 *             # Downstream order is the same as upstream
 *             fid_to_order[downstream_fid] = fid_to_order[working_fid]
 *             del fid_to_order[working_fid]             # <<<<<<<<<<<<<<
 * 
 *             # set downstream order to working order
*/
      if (unlikely((PyDict_DelItem(__pyx_v_fid_to_order, __pyx_v_working_fid) < 0))) __PYX_ERR(0, 3512, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3516
 *             # set downstream order to working order
 *             downstream_to_upstream_ids[downstream_fid] = (
 *                 downstream_to_upstream_ids[working_fid])             # <<<<<<<<<<<<<<
 *             # since we're deleting the upstream segment we need upstream
 *             # connecting segments to connect to the new downstream
*/
      __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_working_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3516, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);

      /* "pygeoprocessing/routing/routing.pyx":3515
 * 
 *             # set downstream order to working order
 *             downstream_to_upstream_ids[downstream_fid] = (             # <<<<<<<<<<<<<<
 *                 downstream_to_upstream_ids[working_fid])
 *             # since we're deleting the upstream segment we need upstream
*/
      if (unlikely((PyDict_SetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_downstream_fid, __pyx_t_2) < 0))) __PYX_ERR(0, 3515, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3519
 *             # since we're deleting the upstream segment we need upstream
 *             # connecting segments to connect to the new downstream
 *             for upstream_fid in downstream_to_upstream_ids[downstream_fid]:             # <<<<<<<<<<<<<<
 *                 upstream_to_downstream_id[upstream_fid] = downstream_fid
 *             del downstream_to_upstream_ids[working_fid]
*/
      __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_downstream_fid); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3519, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
        __pyx_t_3 = __pyx_t_2; __Pyx_INCREF(__pyx_t_3);
        __pyx_t_35 = 0;
        __pyx_t_19 = NULL;
      } else {
        __pyx_t_35 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3519, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3519, __pyx_L1_error)
      }
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      for (;;) {
        if (likely(!__pyx_t_19)) {
          if (likely(PyList_CheckExact(__pyx_t_3))) {
            {
              Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
              #if !CYTHON_ASSUME_SAFE_SIZE
              if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3519, __pyx_L1_error)
              #endif
              if (__pyx_t_35 >= __pyx_temp) break;
            }
            __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_35, __Pyx_ReferenceSharing_OwnStrongReference);
            ++__pyx_t_35;
          } else {
            {
              Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_3);
              #if !CYTHON_ASSUME_SAFE_SIZE
              if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3519, __pyx_L1_error)
              #endif
              if (__pyx_t_35 >= __pyx_temp) break;
            }
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_35));
            #else
            __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_3, __pyx_t_35);
            #endif
            ++__pyx_t_35;
          }
          if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3519, __pyx_L1_error)
        } else {
          __pyx_t_2 = __pyx_t_19(__pyx_t_3);
          if (unlikely(!__pyx_t_2)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3519, __pyx_L1_error)
              PyErr_Clear();
            }
            break;
          }
        }
        __Pyx_GOTREF(__pyx_t_2);
        __Pyx_XDECREF_SET(__pyx_v_upstream_fid, __pyx_t_2);
        __pyx_t_2 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3520
 *             # connecting segments to connect to the new downstream
 *             for upstream_fid in downstream_to_upstream_ids[downstream_fid]:
 *                 upstream_to_downstream_id[upstream_fid] = downstream_fid             # <<<<<<<<<<<<<<
 *             del downstream_to_upstream_ids[working_fid]
 *             del upstream_to_downstream_id[working_fid]
*/
        if (unlikely((PyDict_SetItem(__pyx_v_upstream_to_downstream_id, __pyx_v_upstream_fid, __pyx_v_downstream_fid) < 0))) __PYX_ERR(0, 3520, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":3519
 *             # since we're deleting the upstream segment we need upstream
 *             # connecting segments to connect to the new downstream
 *             for upstream_fid in downstream_to_upstream_ids[downstream_fid]:             # <<<<<<<<<<<<<<
 *                 upstream_to_downstream_id[upstream_fid] = downstream_fid
 *             del downstream_to_upstream_ids[working_fid]
*/
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3521
 *             for upstream_fid in downstream_to_upstream_ids[downstream_fid]:
 *                 upstream_to_downstream_id[upstream_fid] = downstream_fid
 *             del downstream_to_upstream_ids[working_fid]             # <<<<<<<<<<<<<<
 *             del upstream_to_downstream_id[working_fid]
 * 
*/
      if (unlikely((PyDict_DelItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_working_fid) < 0))) __PYX_ERR(0, 3521, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3522
 *                 upstream_to_downstream_id[upstream_fid] = downstream_fid
 *             del downstream_to_upstream_ids[working_fid]
 *             del upstream_to_downstream_id[working_fid]             # <<<<<<<<<<<<<<
 * 
 *             # join working line with downstream line
*/
      if (unlikely((PyDict_DelItem(__pyx_v_upstream_to_downstream_id, __pyx_v_working_fid) < 0))) __PYX_ERR(0, 3522, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3525
 * 
 *             # join working line with downstream line
 *             working_feature = stream_layer.GetFeature(working_fid)             # <<<<<<<<<<<<<<
 *             downstream_feature = stream_layer.GetFeature(downstream_fid)
 *             downstream_geom = downstream_feature.GetGeometryRef()
*/
      __pyx_t_2 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_working_fid};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3525, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF_SET(__pyx_v_working_feature, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3526
 *             # join working line with downstream line
 *             working_feature = stream_layer.GetFeature(working_fid)
 *             downstream_feature = stream_layer.GetFeature(downstream_fid)             # <<<<<<<<<<<<<<
 *             downstream_geom = downstream_feature.GetGeometryRef()
 *             working_geom = working_feature.GetGeometryRef()
*/
      __pyx_t_2 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_downstream_fid};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3526, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_downstream_feature, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3527
 *             working_feature = stream_layer.GetFeature(working_fid)
 *             downstream_feature = stream_layer.GetFeature(downstream_fid)
 *             downstream_geom = downstream_feature.GetGeometryRef()             # <<<<<<<<<<<<<<
 *             working_geom = working_feature.GetGeometryRef()
 * 
*/
      __pyx_t_2 = __pyx_v_downstream_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetGeometryRef, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3527, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_downstream_geom, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3528
 *             downstream_feature = stream_layer.GetFeature(downstream_fid)
 *             downstream_geom = downstream_feature.GetGeometryRef()
 *             working_geom = working_feature.GetGeometryRef()             # <<<<<<<<<<<<<<
 * 
 *             # Union creates a multiline string by default but we know it's
*/
      __pyx_t_2 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetGeometryRef, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3528, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_working_geom, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3533
 *             # connected only at one point, so the next step ensures it's a
 *             # regular linestring
 *             multi_line = working_geom.Union(downstream_geom)             # <<<<<<<<<<<<<<
 *             joined_line = ogr.CreateGeometryFromWkb(
 *                 shapely.ops.linemerge(shapely.wkb.loads(
*/
      __pyx_t_2 = __pyx_v_working_geom;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_downstream_geom};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_Union, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3533, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_multi_line, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3534
 *             # regular linestring
 *             multi_line = working_geom.Union(downstream_geom)
 *             joined_line = ogr.CreateGeometryFromWkb(             # <<<<<<<<<<<<<<
 *                 shapely.ops.linemerge(shapely.wkb.loads(
 *                     bytes(multi_line.ExportToWkb()))).wkb)
*/
      __pyx_t_2 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3534, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_CreateGeometryFromWkb); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3534, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3535
 *             multi_line = working_geom.Union(downstream_geom)
 *             joined_line = ogr.CreateGeometryFromWkb(
 *                 shapely.ops.linemerge(shapely.wkb.loads(             # <<<<<<<<<<<<<<
 *                     bytes(multi_line.ExportToWkb()))).wkb)
 * 
*/
      __Pyx_GetModuleGlobalName(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_shapely); if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3535, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_36);
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_36, __pyx_mstate_global->__pyx_n_u_ops); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3535, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
      __pyx_t_40 = __pyx_t_7;
      __Pyx_INCREF(__pyx_t_40);
      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_shapely); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3535, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __pyx_t_41 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_mstate_global->__pyx_n_u_wkb); if (unlikely(!__pyx_t_41)) __PYX_ERR(0, 3535, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_41);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __pyx_t_4 = __pyx_t_41;
      __Pyx_INCREF(__pyx_t_4);

      /* "pygeoprocessing/routing/routing.pyx":3536
 *             joined_line = ogr.CreateGeometryFromWkb(
 *                 shapely.ops.linemerge(shapely.wkb.loads(
 *                     bytes(multi_line.ExportToWkb()))).wkb)             # <<<<<<<<<<<<<<
 * 
 *             downstream_feature.SetGeometry(joined_line)
*/
      __pyx_t_42 = NULL;
      __pyx_t_44 = __pyx_v_multi_line;
      __Pyx_INCREF(__pyx_t_44);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_44, NULL};
        __pyx_t_43 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_ExportToWkb, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_44); __pyx_t_44 = 0;
        if (unlikely(!__pyx_t_43)) __PYX_ERR(0, 3536, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_43);
      }
      __pyx_t_5 = 1;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_42, __pyx_t_43};
        __pyx_t_8 = __Pyx_PyObject_FastCall((PyObject*)(&PyBytes_Type), __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_42); __pyx_t_42 = 0;
        __Pyx_DECREF(__pyx_t_43); __pyx_t_43 = 0;
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3536, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
      }
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_8};
        __pyx_t_36 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_loads, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        __Pyx_DECREF(__pyx_t_41); __pyx_t_41 = 0;
        if (unlikely(!__pyx_t_36)) __PYX_ERR(0, 3535, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_36);
      }
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_40, __pyx_t_36};
        __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_linemerge, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_40); __pyx_t_40 = 0;
        __Pyx_DECREF(__pyx_t_36); __pyx_t_36 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3535, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_wkb); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3536, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_9))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_9);
        assert(__pyx_t_2);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7};
        __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3534, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_XDECREF_SET(__pyx_v_joined_line, __pyx_t_3);
      __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3538
 *                     bytes(multi_line.ExportToWkb()))).wkb)
 * 
 *             downstream_feature.SetGeometry(joined_line)             # <<<<<<<<<<<<<<
 *             downstream_feature.SetField(
 *                 'us_x', working_feature.GetField('us_x'))
*/
      __pyx_t_9 = __pyx_v_downstream_feature;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_joined_line};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetGeometry, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3538, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3539
 * 
 *             downstream_feature.SetGeometry(joined_line)
 *             downstream_feature.SetField(             # <<<<<<<<<<<<<<
 *                 'us_x', working_feature.GetField('us_x'))
 *             downstream_feature.SetField(
*/
      __pyx_t_9 = __pyx_v_downstream_feature;
      __Pyx_INCREF(__pyx_t_9);

      /* "pygeoprocessing/routing/routing.pyx":3540
 *             downstream_feature.SetGeometry(joined_line)
 *             downstream_feature.SetField(
 *                 'us_x', working_feature.GetField('us_x'))             # <<<<<<<<<<<<<<
 *             downstream_feature.SetField(
 *                 'us_y', working_feature.GetField('us_y'))
*/
      __pyx_t_2 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_x};
        __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3540, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
      }
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_9, __pyx_mstate_global->__pyx_n_u_us_x, __pyx_t_7};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3539, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3541
 *             downstream_feature.SetField(
 *                 'us_x', working_feature.GetField('us_x'))
 *             downstream_feature.SetField(             # <<<<<<<<<<<<<<
 *                 'us_y', working_feature.GetField('us_y'))
 *             stream_layer.SetFeature(downstream_feature)
*/
      __pyx_t_7 = __pyx_v_downstream_feature;
      __Pyx_INCREF(__pyx_t_7);

      /* "pygeoprocessing/routing/routing.pyx":3542
 *                 'us_x', working_feature.GetField('us_x'))
 *             downstream_feature.SetField(
 *                 'us_y', working_feature.GetField('us_y'))             # <<<<<<<<<<<<<<
 *             stream_layer.SetFeature(downstream_feature)
 *             working_feature = None
*/
      __pyx_t_2 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_y};
        __pyx_t_9 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3542, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_9);
      }
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_us_y, __pyx_t_9};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_5, (3-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3541, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3543
 *             downstream_feature.SetField(
 *                 'us_y', working_feature.GetField('us_y'))
 *             stream_layer.SetFeature(downstream_feature)             # <<<<<<<<<<<<<<
 *             working_feature = None
 *             downstream_feature = None
*/
      __pyx_t_9 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_downstream_feature};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3543, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3544
 *                 'us_y', working_feature.GetField('us_y'))
 *             stream_layer.SetFeature(downstream_feature)
 *             working_feature = None             # <<<<<<<<<<<<<<
 *             downstream_feature = None
 *             multi_line = None
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_working_feature, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3545
 *             stream_layer.SetFeature(downstream_feature)
 *             working_feature = None
 *             downstream_feature = None             # <<<<<<<<<<<<<<
 *             multi_line = None
 *             joined_line = None
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_downstream_feature, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3546
 *             working_feature = None
 *             downstream_feature = None
 *             multi_line = None             # <<<<<<<<<<<<<<
 *             joined_line = None
 * 
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_multi_line, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3547
 *             downstream_feature = None
 *             multi_line = None
 *             joined_line = None             # <<<<<<<<<<<<<<
 * 
 *             # delete working line
*/
      __Pyx_INCREF(Py_None);
      __Pyx_DECREF_SET(__pyx_v_joined_line, Py_None);

      /* "pygeoprocessing/routing/routing.pyx":3550
 * 
 *             # delete working line
 *             stream_layer.DeleteFeature(working_fid)             # <<<<<<<<<<<<<<
 *             deleted_set.add(working_fid)
 * 
*/
      __pyx_t_9 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_9);
      __pyx_t_5 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_v_working_fid};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_DeleteFeature, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3550, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3551
 *             # delete working line
 *             stream_layer.DeleteFeature(working_fid)
 *             deleted_set.add(working_fid)             # <<<<<<<<<<<<<<
 * 
 *             # push downstream line for processing
*/
      __pyx_t_31 = PySet_Add(__pyx_v_deleted_set, __pyx_v_working_fid); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3551, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3554
 * 
 *             # push downstream line for processing
 *             working_stack.append(downstream_fid)             # <<<<<<<<<<<<<<
 *             continue
 * 
*/
      __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_working_stack, __pyx_v_downstream_fid); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3554, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3555
 *             # push downstream line for processing
 *             working_stack.append(downstream_fid)
 *             continue             # <<<<<<<<<<<<<<
 * 
 *         # otherwise check if connected streams are all defined and if so
*/
      goto __pyx_L117_continue;

      /* "pygeoprocessing/routing/routing.pyx":3508
 *         downstream_fid = upstream_to_downstream_id[working_fid]
 *         connected_fids = downstream_to_upstream_ids[downstream_fid]
 *         if len(connected_fids) == 1:             # <<<<<<<<<<<<<<
 *             # There's only one downstream, join it.
 *             # Downstream order is the same as upstream
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3559
 *         # otherwise check if connected streams are all defined and if so
 *         # set a new downstream order
 *         upstream_all_defined = True             # <<<<<<<<<<<<<<
 *         for connected_fid in connected_fids:
 *             if connected_fid == working_fid:
*/
    __pyx_v_upstream_all_defined = 1;

    /* "pygeoprocessing/routing/routing.pyx":3560
 *         # set a new downstream order
 *         upstream_all_defined = True
 *         for connected_fid in connected_fids:             # <<<<<<<<<<<<<<
 *             if connected_fid == working_fid:
 *                 # skip current
*/
    if (likely(PyList_CheckExact(__pyx_v_connected_fids)) || PyTuple_CheckExact(__pyx_v_connected_fids)) {
      __pyx_t_3 = __pyx_v_connected_fids; __Pyx_INCREF(__pyx_t_3);
      __pyx_t_35 = 0;
      __pyx_t_19 = NULL;
    } else {
      __pyx_t_35 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_connected_fids); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3560, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 3560, __pyx_L1_error)
    }
    for (;;) {
      if (likely(!__pyx_t_19)) {
        if (likely(PyList_CheckExact(__pyx_t_3))) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3560, __pyx_L1_error)
            #endif
            if (__pyx_t_35 >= __pyx_temp) break;
          }
          __pyx_t_9 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_35, __Pyx_ReferenceSharing_OwnStrongReference);
          ++__pyx_t_35;
        } else {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_3);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3560, __pyx_L1_error)
            #endif
            if (__pyx_t_35 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_9 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_35));
          #else
          __pyx_t_9 = __Pyx_PySequence_ITEM(__pyx_t_3, __pyx_t_35);
          #endif
          ++__pyx_t_35;
        }
        if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3560, __pyx_L1_error)
      } else {
        __pyx_t_9 = __pyx_t_19(__pyx_t_3);
        if (unlikely(!__pyx_t_9)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3560, __pyx_L1_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_9);
      __Pyx_XDECREF_SET(__pyx_v_connected_fid, __pyx_t_9);
      __pyx_t_9 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3561
 *         upstream_all_defined = True
 *         for connected_fid in connected_fids:
 *             if connected_fid == working_fid:             # <<<<<<<<<<<<<<
 *                 # skip current
 *                 continue
*/
      __pyx_t_9 = PyObject_RichCompare(__pyx_v_connected_fid, __pyx_v_working_fid, Py_EQ); __Pyx_XGOTREF(__pyx_t_9); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3561, __pyx_L1_error)
      __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_t_9); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3561, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
      if (__pyx_t_6) {

        /* "pygeoprocessing/routing/routing.pyx":3563
 *             if connected_fid == working_fid:
 *                 # skip current
 *                 continue             # <<<<<<<<<<<<<<
 *             if connected_fid not in fid_to_order:
 *                 # upstream not defined so skip it and it will be processed
*/
        goto __pyx_L130_continue;

        /* "pygeoprocessing/routing/routing.pyx":3561
 *         upstream_all_defined = True
 *         for connected_fid in connected_fids:
 *             if connected_fid == working_fid:             # <<<<<<<<<<<<<<
 *                 # skip current
 *                 continue
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":3564
 *                 # skip current
 *                 continue
 *             if connected_fid not in fid_to_order:             # <<<<<<<<<<<<<<
 *                 # upstream not defined so skip it and it will be processed
 *                 # on another iteration
*/
      __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_connected_fid, __pyx_v_fid_to_order, Py_NE)); if (unlikely((__pyx_t_6 < 0))) __PYX_ERR(0, 3564, __pyx_L1_error)
      if (__pyx_t_6) {

        /* "pygeoprocessing/routing/routing.pyx":3567
 *                 # upstream not defined so skip it and it will be processed
 *                 # on another iteration
 *                 upstream_all_defined = False             # <<<<<<<<<<<<<<
 *                 break
 * 
*/
        __pyx_v_upstream_all_defined = 0;

        /* "pygeoprocessing/routing/routing.pyx":3568
 *                 # on another iteration
 *                 upstream_all_defined = False
 *                 break             # <<<<<<<<<<<<<<
 * 
 *         if not upstream_all_defined:
*/
        goto __pyx_L131_break;

        /* "pygeoprocessing/routing/routing.pyx":3564
 *                 # skip current
 *                 continue
 *             if connected_fid not in fid_to_order:             # <<<<<<<<<<<<<<
 *                 # upstream not defined so skip it and it will be processed
 *                 # on another iteration
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":3560
 *         # set a new downstream order
 *         upstream_all_defined = True
 *         for connected_fid in connected_fids:             # <<<<<<<<<<<<<<
 *             if connected_fid == working_fid:
 *                 # skip current
*/
      __pyx_L130_continue:;
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    goto __pyx_L134_for_end;
    __pyx_L131_break:;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    goto __pyx_L134_for_end;
    __pyx_L134_for_end:;

    /* "pygeoprocessing/routing/routing.pyx":3570
 *                 break
 * 
 *         if not upstream_all_defined:             # <<<<<<<<<<<<<<
 *             # wait for other upstream components to be defined
 *             continue
*/
    __pyx_t_6 = (!__pyx_v_upstream_all_defined);
    if (__pyx_t_6) {

      /* "pygeoprocessing/routing/routing.pyx":3572
 *         if not upstream_all_defined:
 *             # wait for other upstream components to be defined
 *             continue             # <<<<<<<<<<<<<<
 * 
 *         # all upstream components of this fid are calculated so it can be
*/
      goto __pyx_L117_continue;

      /* "pygeoprocessing/routing/routing.pyx":3570
 *                 break
 * 
 *         if not upstream_all_defined:             # <<<<<<<<<<<<<<
 *             # wait for other upstream components to be defined
 *             continue
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3576
 *         # all upstream components of this fid are calculated so it can be
 *         # calculated now too
 *         working_stack.append(downstream_fid)             # <<<<<<<<<<<<<<
 * 
 *     LOGGER.info(
*/
    __pyx_t_31 = __Pyx_PyList_Append(__pyx_v_working_stack, __pyx_v_downstream_fid); if (unlikely(__pyx_t_31 == ((int)-1))) __PYX_ERR(0, 3576, __pyx_L1_error)
    __pyx_L117_continue:;
  }

  /* "pygeoprocessing/routing/routing.pyx":3578
 *         working_stack.append(downstream_fid)
 * 
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): '
 *         'final pass on stream order complete')
*/
  __pyx_t_9 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3578, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3578, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_9);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_fin_3};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3578, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3581
 *         '(extract_strahler_streams_d8): '
 *         'final pass on stream order complete')
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(extract_strahler_streams_d8): '
 *         'commit transaction due to stream joining')
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3581, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3581, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_com};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3581, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3584
 *         '(extract_strahler_streams_d8): '
 *         'commit transaction due to stream joining')
 *     stream_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *     stream_layer = None
 *     stream_vector = None
*/
  __pyx_t_7 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, NULL};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_5, (1-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3584, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3585
 *         'commit transaction due to stream joining')
 *     stream_layer.CommitTransaction()
 *     stream_layer = None             # <<<<<<<<<<<<<<
 *     stream_vector = None
 *     LOGGER.info('(extract_strahler_streams_d8): all done')
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_stream_layer, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":3586
 *     stream_layer.CommitTransaction()
 *     stream_layer = None
 *     stream_vector = None             # <<<<<<<<<<<<<<
 *     LOGGER.info('(extract_strahler_streams_d8): all done')
 * 
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_stream_vector, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":3587
 *     stream_layer = None
 *     stream_vector = None
 *     LOGGER.info('(extract_strahler_streams_d8): all done')             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3587, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3587, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_9))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_9);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_9, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_extract_strahler_streams_d8_all};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_9, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3587, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2901
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_strahler_streams_d8(
 *         flow_dir_d8_raster_path_band, flow_accum_raster_path_band,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_36);
  __Pyx_XDECREF(__pyx_t_40);
  __Pyx_XDECREF(__pyx_t_41);
  __Pyx_XDECREF(__pyx_t_42);
  __Pyx_XDECREF(__pyx_t_43);
  __Pyx_XDECREF(__pyx_t_44);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.extract_strahler_streams_d8", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_flow_dir_info);
  __Pyx_XDECREF(__pyx_v_flow_dir_srs);
  __Pyx_XDECREF(__pyx_v_gpkg_driver);
  __Pyx_XDECREF(__pyx_v_stream_vector);
  __Pyx_XDECREF(__pyx_v_stream_basename);
  __Pyx_XDECREF(__pyx_v_stream_layer);
  __Pyx_XDECREF(__pyx_v_coord_to_stream_ids);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_stream_feature);
  __Pyx_XDECREF(__pyx_v_stream_fid);
  __Pyx_XDECREF(__pyx_v_n_points);
  __Pyx_XDECREF(__pyx_v_downstream_to_upstream_ids);
  __Pyx_XDECREF(__pyx_v_upstream_to_downstream_id);
  __Pyx_XDECREF(__pyx_v_payload);
  __Pyx_XDECREF(__pyx_v_x_u);
  __Pyx_XDECREF(__pyx_v_y_u);
  __Pyx_XDECREF(__pyx_v_ds_x_1);
  __Pyx_XDECREF(__pyx_v_ds_y_1);
  __Pyx_XDECREF(__pyx_v_upstream_id_list);
  __Pyx_XDECREF(__pyx_v_stream_line);
  __Pyx_XDECREF(__pyx_v_upstream_id);
  __Pyx_XDECREF(__pyx_v_streams_to_process);
  __Pyx_XDECREF(__pyx_v_base_feature_count);
  __Pyx_XDECREF(__pyx_v_outlet_fid_list);
  __Pyx_XDECREF(__pyx_v_downstream_fid);
  __Pyx_XDECREF(__pyx_v_downstream_feature);
  __Pyx_XDECREF(__pyx_v_connected_upstream_fids);
  __Pyx_XDECREF(__pyx_v_stream_order_list);
  __Pyx_XDECREF(__pyx_v_upstream_fid);
  __Pyx_XDECREF(__pyx_v_upstream_feature);
  __Pyx_XDECREF(__pyx_v_upstream_order);
  __Pyx_XDECREF(__pyx_v_sorted_stream_order_list);
  __Pyx_XDECREF(__pyx_v_downstream_order);
  __Pyx_XDECREF(__pyx_v_working_river_id);
  __Pyx_XDECREF(__pyx_v_outlet_index);
  __Pyx_XDECREF(__pyx_v_outlet_fid);
  __Pyx_XDECREF(__pyx_v_search_stack);
  __Pyx_XDECREF(__pyx_v_feature_id);
  __Pyx_XDECREF(__pyx_v_stream_order);
  __Pyx_XDECREF(__pyx_v_upstream_stack);
  __Pyx_XDECREF(__pyx_v_streams_by_order);
  __Pyx_XDECREF(__pyx_v_drop_distance_collection);
  __Pyx_XDECREF(__pyx_v_max_upstream_flow_accum);
  __Pyx_XDECREF(__pyx_v_order);
  __Pyx_XDECREF(__pyx_v_working_flow_accum_threshold);
  __Pyx_XDECREF(__pyx_v_test_order);
  __Pyx_XDECREF(__pyx_v__);
  __Pyx_XDECREF(__pyx_v_p_val);
  __Pyx_XDECREF(__pyx_v_streams_to_retest);
  __Pyx_XDECREF(__pyx_v_ds_x);
  __Pyx_XDECREF(__pyx_v_ds_y);
  __Pyx_XDECREF(__pyx_v_upstream_d8_dir);
  __Pyx_XDECREF(__pyx_v_working_stack);
  __Pyx_XDECREF(__pyx_v_fid_to_order);
  __Pyx_XDECREF(__pyx_v_processed_segments);
  __Pyx_XDECREF(__pyx_v_deleted_set);
  __Pyx_XDECREF(__pyx_v_working_fid);
  __Pyx_XDECREF(__pyx_v_upstream_fid_list);
  __Pyx_XDECREF(__pyx_v_order_count);
  __Pyx_XDECREF(__pyx_v_working_order);
  __Pyx_XDECREF(__pyx_v_working_feature);
  __Pyx_XDECREF(__pyx_v_connected_fids);
  __Pyx_XDECREF(__pyx_v_downstream_geom);
  __Pyx_XDECREF(__pyx_v_working_geom);
  __Pyx_XDECREF(__pyx_v_multi_line);
  __Pyx_XDECREF(__pyx_v_joined_line);
  __Pyx_XDECREF(__pyx_v_connected_fid);
  __Pyx_XDECREF(__pyx_7genexpr__pyx_v_stream_feature);
  __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_fid);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":3590
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _build_discovery_finish_rasters(
 *         flow_dir_d8_raster_path_band, target_discovery_raster_path,
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_23_build_discovery_finish_rasters(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_22_build_discovery_finish_rasters, "Generates a discovery and finish time raster for a given d8 flow path.\n\n    Args:\n        flow_dir_d8_raster_path_band (tuple): a D8 flow raster path band tuple.\n            Paths may use any GDAL-supported scheme, including virtual file\n            system /vsi schemes.\n        target_discovery_raster_path (str): path to a generated raster that\n            creates discovery time (i.e. what count the pixel is visited in)\n        target_finish_raster_path (str): path to generated raster that creates\n            maximum upstream finish time.\n\n    Returns:\n        None\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_23_build_discovery_finish_rasters = {"_build_discovery_finish_rasters", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_23_build_discovery_finish_rasters, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_22_build_discovery_finish_rasters};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_23_build_discovery_finish_rasters(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_d8_raster_path_band = 0;
  PyObject *__pyx_v_target_discovery_raster_path = 0;
  PyObject *__pyx_v_target_finish_raster_path = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[3] = {0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_build_discovery_finish_rasters (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_d8_raster_path_band,&__pyx_mstate_global->__pyx_n_u_target_discovery_raster_path,&__pyx_mstate_global->__pyx_n_u_target_finish_raster_path,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 3590, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 3590, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 3590, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 3590, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "_build_discovery_finish_rasters", 0) < (0)) __PYX_ERR(0, 3590, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("_build_discovery_finish_rasters", 1, 3, 3, i); __PYX_ERR(0, 3590, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 3)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 3590, __pyx_L3_error)
      values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 3590, __pyx_L3_error)
      values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 3590, __pyx_L3_error)
    }
    __pyx_v_flow_dir_d8_raster_path_band = values[0];
    __pyx_v_target_discovery_raster_path = values[1];
    __pyx_v_target_finish_raster_path = values[2];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("_build_discovery_finish_rasters", 1, 3, 3, __pyx_nargs); __PYX_ERR(0, 3590, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._build_discovery_finish_rasters", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_22_build_discovery_finish_rasters(__pyx_self, __pyx_v_flow_dir_d8_raster_path_band, __pyx_v_target_discovery_raster_path, __pyx_v_target_finish_raster_path);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_22_build_discovery_finish_rasters(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_d8_raster_path_band, PyObject *__pyx_v_target_discovery_raster_path, PyObject *__pyx_v_target_finish_raster_path) {
  PyObject *__pyx_v_flow_dir_info = NULL;
  int __pyx_v_n_cols;
  int __pyx_v_n_rows;
  int __pyx_v_flow_dir_nodata;
  ManagedRaster __pyx_v_flow_dir_managed_raster;
  ManagedRaster __pyx_v_discovery_managed_raster;
  ManagedRaster __pyx_v_finish_managed_raster;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType>  __pyx_v_discovery_stack;
  std::stack<struct __pyx_t_15pygeoprocessing_7routing_7routing_FinishType>  __pyx_v_finish_stack;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_v_raster_coord;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_FinishType __pyx_v_finish_coordinate;
  long __pyx_v_discovery_count;
  int __pyx_v_n_processed;
  int __pyx_v_n_pixels;
  time_t __pyx_v_last_log_time;
  int __pyx_v_n_pushed;
  int __pyx_v_i;
  int __pyx_v_j;
  int __pyx_v_xoff;
  int __pyx_v_yoff;
  int __pyx_v_win_xsize;
  int __pyx_v_win_ysize;
  int __pyx_v_x_l;
  int __pyx_v_y_l;
  int __pyx_v_x_n;
  int __pyx_v_y_n;
  int __pyx_v_n_dir;
  int __pyx_v_test_dir;
  PyObject *__pyx_v_offset_dict = NULL;
  int __pyx_v_d_n;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  size_t __pyx_t_5;
  PyObject *(*__pyx_t_6)(PyObject *);
  int __pyx_t_7;
  int __pyx_t_8;
  char *__pyx_t_9;
  ManagedRaster __pyx_t_10;
  PyObject *__pyx_t_11 = NULL;
  PyObject *__pyx_t_12 = NULL;
  Py_ssize_t __pyx_t_13;
  PyObject *(*__pyx_t_14)(PyObject *);
  int __pyx_t_15;
  PyObject *__pyx_t_16[3];
  int __pyx_t_17;
  int __pyx_t_18;
  int __pyx_t_19;
  int __pyx_t_20;
  int __pyx_t_21;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_CoordinateType __pyx_t_22;
  struct __pyx_t_15pygeoprocessing_7routing_7routing_FinishType __pyx_t_23;
  int __pyx_t_24;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_build_discovery_finish_rasters", 0);

  /* "pygeoprocessing/routing/routing.pyx":3608
 *         None
 *     """
 *     flow_dir_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0])
 *     cdef int n_cols, n_rows
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3608, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3608, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3609
 *     """
 *     flow_dir_info = pygeoprocessing.get_raster_info(
 *         flow_dir_d8_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     cdef int n_cols, n_rows
 *     n_cols, n_rows = flow_dir_info['raster_size']
*/
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3609, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3608, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_flow_dir_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3611
 *         flow_dir_d8_raster_path_band[0])
 *     cdef int n_cols, n_rows
 *     n_cols, n_rows = flow_dir_info['raster_size']             # <<<<<<<<<<<<<<
 *     cdef int flow_dir_nodata = (
 *         flow_dir_info['nodata'][flow_dir_d8_raster_path_band[1]-1])
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3611, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 3611, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_3);
    } else {
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3611, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3611, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
    }
    #else
    __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3611, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3611, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3611, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_6 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2);
    index = 0; __pyx_t_4 = __pyx_t_6(__pyx_t_2); if (unlikely(!__pyx_t_4)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_4);
    index = 1; __pyx_t_3 = __pyx_t_6(__pyx_t_2); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_3);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_6(__pyx_t_2), 2) < (0)) __PYX_ERR(0, 3611, __pyx_L1_error)
    __pyx_t_6 = NULL;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L4_unpacking_done;
    __pyx_L3_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_6 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 3611, __pyx_L1_error)
    __pyx_L4_unpacking_done:;
  }
  __pyx_t_7 = __Pyx_PyLong_As_int(__pyx_t_4); if (unlikely((__pyx_t_7 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3611, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3611, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_n_cols = __pyx_t_7;
  __pyx_v_n_rows = __pyx_t_8;

  /* "pygeoprocessing/routing/routing.pyx":3613
 *     n_cols, n_rows = flow_dir_info['raster_size']
 *     cdef int flow_dir_nodata = (
 *         flow_dir_info['nodata'][flow_dir_d8_raster_path_band[1]-1])             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_flow_dir_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3613, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3613, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyLong_SubtractObjC(__pyx_t_3, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3613, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3613, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3613, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_flow_dir_nodata = __pyx_t_8;

  /* "pygeoprocessing/routing/routing.pyx":3616
 * 
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[1], False)
 *     pygeoprocessing.new_raster_from_base(
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3616, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __pyx_t_1;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3616, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_t_3); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 3616, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3617
 *     flow_dir_managed_raster = ManagedRaster(
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_discovery_raster_path,
*/
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3617, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3617, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3615
 *         flow_dir_info['nodata'][flow_dir_d8_raster_path_band[1]-1])
 * 
 *     flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)
*/
  try {
    __pyx_t_10 = ManagedRaster(__pyx_t_9, __pyx_t_8, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3615, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_10);

  /* "pygeoprocessing/routing/routing.pyx":3618
 *         flow_dir_d8_raster_path_band[0].encode('utf-8'),
 *         flow_dir_d8_raster_path_band[1], False)
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0], target_discovery_raster_path,
 *         gdal.GDT_Float64, [-1])
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3618, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3618, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3619
 *         flow_dir_d8_raster_path_band[1], False)
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_discovery_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Float64, [-1])
 *     discovery_managed_raster = ManagedRaster(
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3619, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);

  /* "pygeoprocessing/routing/routing.pyx":3620
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_discovery_raster_path,
 *         gdal.GDT_Float64, [-1])             # <<<<<<<<<<<<<<
 *     discovery_managed_raster = ManagedRaster(
 *         target_discovery_raster_path.encode('utf-8'), 1, True)
*/
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 3620, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 3620, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = PyList_New(1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 3620, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_neg_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_11, 0, __pyx_mstate_global->__pyx_int_neg_1) != (0)) __PYX_ERR(0, 3620, __pyx_L1_error);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5] = {__pyx_t_1, __pyx_t_4, __pyx_v_target_discovery_raster_path, __pyx_t_12, __pyx_t_11};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 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;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3618, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3622
 *         gdal.GDT_Float64, [-1])
 *     discovery_managed_raster = ManagedRaster(
 *         target_discovery_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_finish_raster_path,
*/
  __pyx_t_2 = __pyx_v_target_discovery_raster_path;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3622, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_t_3); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 3622, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3621
 *         flow_dir_d8_raster_path_band[0], target_discovery_raster_path,
 *         gdal.GDT_Float64, [-1])
 *     discovery_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_discovery_raster_path.encode('utf-8'), 1, True)
 *     pygeoprocessing.new_raster_from_base(
*/
  try {
    __pyx_t_10 = ManagedRaster(__pyx_t_9, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3621, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_discovery_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_10);

  /* "pygeoprocessing/routing/routing.pyx":3623
 *     discovery_managed_raster = ManagedRaster(
 *         target_discovery_raster_path.encode('utf-8'), 1, True)
 *     pygeoprocessing.new_raster_from_base(             # <<<<<<<<<<<<<<
 *         flow_dir_d8_raster_path_band[0], target_finish_raster_path,
 *         gdal.GDT_Float64, [-1])
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 3623, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_new_raster_from_base); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 3623, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3624
 *         target_discovery_raster_path.encode('utf-8'), 1, True)
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_finish_raster_path,             # <<<<<<<<<<<<<<
 *         gdal.GDT_Float64, [-1])
 *     finish_managed_raster = ManagedRaster(
*/
  __pyx_t_11 = __Pyx_GetItemInt(__pyx_v_flow_dir_d8_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 3624, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);

  /* "pygeoprocessing/routing/routing.pyx":3625
 *     pygeoprocessing.new_raster_from_base(
 *         flow_dir_d8_raster_path_band[0], target_finish_raster_path,
 *         gdal.GDT_Float64, [-1])             # <<<<<<<<<<<<<<
 *     finish_managed_raster = ManagedRaster(
 *         target_finish_raster_path.encode('utf-8'), 1, True)
*/
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3625, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_GDT_Float64); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3625, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = PyList_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3625, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_neg_1);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_int_neg_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_4, 0, __pyx_mstate_global->__pyx_int_neg_1) != (0)) __PYX_ERR(0, 3625, __pyx_L1_error);
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[5] = {__pyx_t_2, __pyx_t_11, __pyx_v_target_finish_raster_path, __pyx_t_1, __pyx_t_4};
    __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_5, (5-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3623, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3627
 *         gdal.GDT_Float64, [-1])
 *     finish_managed_raster = ManagedRaster(
 *         target_finish_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 * 
 *     cdef stack[CoordinateType] discovery_stack
*/
  __pyx_t_12 = __pyx_v_target_finish_raster_path;
  __Pyx_INCREF(__pyx_t_12);
  __pyx_t_5 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3627, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_t_3); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 3627, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3626
 *         flow_dir_d8_raster_path_band[0], target_finish_raster_path,
 *         gdal.GDT_Float64, [-1])
 *     finish_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         target_finish_raster_path.encode('utf-8'), 1, True)
 * 
*/
  try {
    __pyx_t_10 = ManagedRaster(__pyx_t_9, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3626, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_finish_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_10);

  /* "pygeoprocessing/routing/routing.pyx":3634
 *     cdef FinishType finish_coordinate
 * 
 *     cdef long discovery_count = 0             # <<<<<<<<<<<<<<
 *     cdef int n_processed, n_pixels
 *     n_pixels = n_rows * n_cols
*/
  __pyx_v_discovery_count = 0;

  /* "pygeoprocessing/routing/routing.pyx":3636
 *     cdef long discovery_count = 0
 *     cdef int n_processed, n_pixels
 *     n_pixels = n_rows * n_cols             # <<<<<<<<<<<<<<
 *     n_processed = 0
 *     cdef time_t last_log_time = ctime(NULL)
*/
  __pyx_v_n_pixels = (__pyx_v_n_rows * __pyx_v_n_cols);

  /* "pygeoprocessing/routing/routing.pyx":3637
 *     cdef int n_processed, n_pixels
 *     n_pixels = n_rows * n_cols
 *     n_processed = 0             # <<<<<<<<<<<<<<
 *     cdef time_t last_log_time = ctime(NULL)
 *     cdef int n_pushed
*/
  __pyx_v_n_processed = 0;

  /* "pygeoprocessing/routing/routing.pyx":3638
 *     n_pixels = n_rows * n_cols
 *     n_processed = 0
 *     cdef time_t last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *     cdef int n_pushed
 * 
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":3644
 *     cdef int n_dir, test_dir
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         # search raster block by raster block
*/
  __pyx_t_12 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3644, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3644, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3645
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             flow_dir_d8_raster_path_band, offset_only=True):             # <<<<<<<<<<<<<<
 *         # search raster block by raster block
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
*/
  __pyx_t_5 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_12);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_12);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_5 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_12, __pyx_v_flow_dir_d8_raster_path_band};
    __pyx_t_4 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3644, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_4, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 3644, __pyx_L1_error)
    __pyx_t_3 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_4);
    __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3644, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }

  /* "pygeoprocessing/routing/routing.pyx":3644
 *     cdef int n_dir, test_dir
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         # search raster block by raster block
*/
  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
    __pyx_t_1 = __pyx_t_3; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_13 = 0;
    __pyx_t_14 = NULL;
  } else {
    __pyx_t_13 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3644, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_14 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 3644, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  for (;;) {
    if (likely(!__pyx_t_14)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3644, __pyx_L1_error)
          #endif
          if (__pyx_t_13 >= __pyx_temp) break;
        }
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_13, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_13;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3644, __pyx_L1_error)
          #endif
          if (__pyx_t_13 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_3 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_13));
        #else
        __pyx_t_3 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_13);
        #endif
        ++__pyx_t_13;
      }
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3644, __pyx_L1_error)
    } else {
      __pyx_t_3 = __pyx_t_14(__pyx_t_1);
      if (unlikely(!__pyx_t_3)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3644, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_3);
    __pyx_t_3 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3647
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         # search raster block by raster block
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 f'(discovery time processing): '
*/
    __pyx_t_15 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_15) {

      /* "pygeoprocessing/routing/routing.pyx":3648
 *         # search raster block by raster block
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 f'(discovery time processing): '
 *                 f'{n_processed/n_pixels*100:.1f}% complete')
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 3648, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 3648, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_11);
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3650
 *             LOGGER.info(
 *                 f'(discovery time processing): '
 *                 f'{n_processed/n_pixels*100:.1f}% complete')             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']
*/
      if (unlikely(__pyx_v_n_pixels == 0)) {
        PyErr_SetString(PyExc_ZeroDivisionError, "float division");
        __PYX_ERR(0, 3650, __pyx_L1_error)
      }
      __pyx_t_12 = PyFloat_FromDouble(((((double)__pyx_v_n_processed) / ((double)__pyx_v_n_pixels)) * 100.0)); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 3650, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      __pyx_t_2 = __Pyx_PyObject_Format(__pyx_t_12, __pyx_mstate_global->__pyx_kp_u_1f); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3650, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      __pyx_t_16[0] = __pyx_mstate_global->__pyx_kp_u_discovery_time_processing;
      __pyx_t_16[1] = __pyx_t_2;
      __pyx_t_16[2] = __pyx_mstate_global->__pyx_kp_u_complete;

      /* "pygeoprocessing/routing/routing.pyx":3649
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 f'(discovery time processing): '             # <<<<<<<<<<<<<<
 *                 f'{n_processed/n_pixels*100:.1f}% complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_12 = __Pyx_PyUnicode_Join(__pyx_t_16, 3, 29 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 10, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_2));
      if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 3649, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_12);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_5 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_11))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_11);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
        __pyx_t_5 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_12};
        __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_5, (2-__pyx_t_5) | (__pyx_t_5*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__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;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3648, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3651
 *                 f'(discovery time processing): '
 *                 f'{n_processed/n_pixels*100:.1f}% complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3647
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         # search raster block by raster block
 *         if ctime(NULL)-last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 f'(discovery time processing): '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3652
 *                 f'{n_processed/n_pixels*100:.1f}% complete')
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3652, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3652, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_xoff = __pyx_t_8;

    /* "pygeoprocessing/routing/routing.pyx":3653
 *             last_log_time = ctime(NULL)
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3653, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3653, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_yoff = __pyx_t_8;

    /* "pygeoprocessing/routing/routing.pyx":3654
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         n_processed += win_xsize * win_ysize
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3654, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3654, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_xsize = __pyx_t_8;

    /* "pygeoprocessing/routing/routing.pyx":3655
 *         yoff = offset_dict['yoff']
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         n_processed += win_xsize * win_ysize
 * 
*/
    __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3655, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_3); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3655, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_v_win_ysize = __pyx_t_8;

    /* "pygeoprocessing/routing/routing.pyx":3656
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         n_processed += win_xsize * win_ysize             # <<<<<<<<<<<<<<
 * 
 *         for i in range(win_xsize):
*/
    __pyx_v_n_processed = (__pyx_v_n_processed + (__pyx_v_win_xsize * __pyx_v_win_ysize));

    /* "pygeoprocessing/routing/routing.pyx":3658
 *         n_processed += win_xsize * win_ysize
 * 
 *         for i in range(win_xsize):             # <<<<<<<<<<<<<<
 *             for j in range(win_ysize):
 *                 x_l = xoff + i
*/
    __pyx_t_8 = __pyx_v_win_xsize;
    __pyx_t_7 = __pyx_t_8;
    for (__pyx_t_17 = 0; __pyx_t_17 < __pyx_t_7; __pyx_t_17+=1) {
      __pyx_v_i = __pyx_t_17;

      /* "pygeoprocessing/routing/routing.pyx":3659
 * 
 *         for i in range(win_xsize):
 *             for j in range(win_ysize):             # <<<<<<<<<<<<<<
 *                 x_l = xoff + i
 *                 y_l = yoff + j
*/
      __pyx_t_18 = __pyx_v_win_ysize;
      __pyx_t_19 = __pyx_t_18;
      for (__pyx_t_20 = 0; __pyx_t_20 < __pyx_t_19; __pyx_t_20+=1) {
        __pyx_v_j = __pyx_t_20;

        /* "pygeoprocessing/routing/routing.pyx":3660
 *         for i in range(win_xsize):
 *             for j in range(win_ysize):
 *                 x_l = xoff + i             # <<<<<<<<<<<<<<
 *                 y_l = yoff + j
 *                 # check to see if this pixel is a drain
*/
        __pyx_v_x_l = (__pyx_v_xoff + __pyx_v_i);

        /* "pygeoprocessing/routing/routing.pyx":3661
 *             for j in range(win_ysize):
 *                 x_l = xoff + i
 *                 y_l = yoff + j             # <<<<<<<<<<<<<<
 *                 # check to see if this pixel is a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
*/
        __pyx_v_y_l = (__pyx_v_yoff + __pyx_v_j);

        /* "pygeoprocessing/routing/routing.pyx":3663
 *                 y_l = yoff + j
 *                 # check to see if this pixel is a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)             # <<<<<<<<<<<<<<
 *                 if d_n == flow_dir_nodata:
 *                     continue
*/
        __pyx_v_d_n = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

        /* "pygeoprocessing/routing/routing.pyx":3664
 *                 # check to see if this pixel is a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
 *                 if d_n == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_15 = (__pyx_v_d_n == __pyx_v_flow_dir_nodata);
        if (__pyx_t_15) {

          /* "pygeoprocessing/routing/routing.pyx":3665
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
 *                 if d_n == flow_dir_nodata:
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # check if downstream neighbor runs off raster or is nodata
*/
          goto __pyx_L10_continue;

          /* "pygeoprocessing/routing/routing.pyx":3664
 *                 # check to see if this pixel is a drain
 *                 d_n = <int>flow_dir_managed_raster.get(x_l, y_l)
 *                 if d_n == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3668
 * 
 *                 # check if downstream neighbor runs off raster or is nodata
 *                 x_n = x_l + COL_OFFSETS[d_n]             # <<<<<<<<<<<<<<
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 * 
*/
        __pyx_v_x_n = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_d_n]));

        /* "pygeoprocessing/routing/routing.pyx":3669
 *                 # check if downstream neighbor runs off raster or is nodata
 *                 x_n = x_l + COL_OFFSETS[d_n]
 *                 y_n = y_l + ROW_OFFSETS[d_n]             # <<<<<<<<<<<<<<
 * 
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or
*/
        __pyx_v_y_n = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_d_n]));

        /* "pygeoprocessing/routing/routing.pyx":3671
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 * 
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_dir_nodata):
*/
        __pyx_t_21 = (__pyx_v_x_n < 0);
        if (!__pyx_t_21) {
        } else {
          __pyx_t_15 = __pyx_t_21;
          goto __pyx_L14_bool_binop_done;
        }
        __pyx_t_21 = (__pyx_v_y_n < 0);
        if (!__pyx_t_21) {
        } else {
          __pyx_t_15 = __pyx_t_21;
          goto __pyx_L14_bool_binop_done;
        }
        __pyx_t_21 = (__pyx_v_x_n >= __pyx_v_n_cols);
        if (!__pyx_t_21) {
        } else {
          __pyx_t_15 = __pyx_t_21;
          goto __pyx_L14_bool_binop_done;
        }
        __pyx_t_21 = (__pyx_v_y_n >= __pyx_v_n_rows);
        if (!__pyx_t_21) {
        } else {
          __pyx_t_15 = __pyx_t_21;
          goto __pyx_L14_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":3673
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_dir_nodata):             # <<<<<<<<<<<<<<
 *                     discovery_stack.push(CoordinateType(x_l, y_l))
 *                     finish_stack.push(FinishType(x_l, y_l, 1))
*/
        __pyx_t_21 = (((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n)) == __pyx_v_flow_dir_nodata);
        __pyx_t_15 = __pyx_t_21;
        __pyx_L14_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":3671
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 * 
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_dir_nodata):
*/
        if (__pyx_t_15) {

          /* "pygeoprocessing/routing/routing.pyx":3674
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_dir_nodata):
 *                     discovery_stack.push(CoordinateType(x_l, y_l))             # <<<<<<<<<<<<<<
 *                     finish_stack.push(FinishType(x_l, y_l, 1))
 * 
*/
          __pyx_t_22.xi = __pyx_v_x_l;
          __pyx_t_22.yi = __pyx_v_y_l;
          try {
            __pyx_v_discovery_stack.push(__pyx_t_22);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 3674, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":3675
 *                             x_n, y_n) == flow_dir_nodata):
 *                     discovery_stack.push(CoordinateType(x_l, y_l))
 *                     finish_stack.push(FinishType(x_l, y_l, 1))             # <<<<<<<<<<<<<<
 * 
 *                 while not discovery_stack.empty():
*/
          __pyx_t_23.xi = __pyx_v_x_l;
          __pyx_t_23.yi = __pyx_v_y_l;
          __pyx_t_23.n_pushed = 1;
          try {
            __pyx_v_finish_stack.push(__pyx_t_23);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 3675, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":3671
 *                 y_n = y_l + ROW_OFFSETS[d_n]
 * 
 *                 if (x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows or             # <<<<<<<<<<<<<<
 *                         <int>flow_dir_managed_raster.get(
 *                             x_n, y_n) == flow_dir_nodata):
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3677
 *                     finish_stack.push(FinishType(x_l, y_l, 1))
 * 
 *                 while not discovery_stack.empty():             # <<<<<<<<<<<<<<
 *                     # This coordinate is the downstream end of the stream
 *                     raster_coord = discovery_stack.top()
*/
        while (1) {
          __pyx_t_15 = (!__pyx_v_discovery_stack.empty());
          if (!__pyx_t_15) break;

          /* "pygeoprocessing/routing/routing.pyx":3679
 *                 while not discovery_stack.empty():
 *                     # This coordinate is the downstream end of the stream
 *                     raster_coord = discovery_stack.top()             # <<<<<<<<<<<<<<
 *                     discovery_stack.pop()
 * 
*/
          __pyx_v_raster_coord = __pyx_v_discovery_stack.top();

          /* "pygeoprocessing/routing/routing.pyx":3680
 *                     # This coordinate is the downstream end of the stream
 *                     raster_coord = discovery_stack.top()
 *                     discovery_stack.pop()             # <<<<<<<<<<<<<<
 * 
 *                     discovery_managed_raster.set(
*/
          __pyx_v_discovery_stack.pop();

          /* "pygeoprocessing/routing/routing.pyx":3682
 *                     discovery_stack.pop()
 * 
 *                     discovery_managed_raster.set(             # <<<<<<<<<<<<<<
 *                         raster_coord.xi, raster_coord.yi, discovery_count)
 *                     discovery_count += 1
*/
          __pyx_v_discovery_managed_raster.set(__pyx_v_raster_coord.xi, __pyx_v_raster_coord.yi, __pyx_v_discovery_count);

          /* "pygeoprocessing/routing/routing.pyx":3684
 *                     discovery_managed_raster.set(
 *                         raster_coord.xi, raster_coord.yi, discovery_count)
 *                     discovery_count += 1             # <<<<<<<<<<<<<<
 * 
 *                     n_pushed = 0
*/
          __pyx_v_discovery_count = (__pyx_v_discovery_count + 1);

          /* "pygeoprocessing/routing/routing.pyx":3686
 *                     discovery_count += 1
 * 
 *                     n_pushed = 0             # <<<<<<<<<<<<<<
 *                     # check each neighbor to see if it drains to this cell
 *                     # if so, it's on the traversal path
*/
          __pyx_v_n_pushed = 0;

          /* "pygeoprocessing/routing/routing.pyx":3689
 *                     # check each neighbor to see if it drains to this cell
 *                     # if so, it's on the traversal path
 *                     for test_dir in range(8):             # <<<<<<<<<<<<<<
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
*/
          for (__pyx_t_24 = 0; __pyx_t_24 < 8; __pyx_t_24+=1) {
            __pyx_v_test_dir = __pyx_t_24;

            /* "pygeoprocessing/routing/routing.pyx":3690
 *                     # if so, it's on the traversal path
 *                     for test_dir in range(8):
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]             # <<<<<<<<<<<<<<
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
 *                         if x_n < 0 or y_n < 0 or \
*/
            __pyx_v_x_n = (__pyx_v_raster_coord.xi + (COL_OFFSETS[__Pyx_mod_long(__pyx_v_test_dir, 8, 1)]));

            /* "pygeoprocessing/routing/routing.pyx":3691
 *                     for test_dir in range(8):
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]             # <<<<<<<<<<<<<<
 *                         if x_n < 0 or y_n < 0 or \
 *                                 x_n >= n_cols or y_n >= n_rows:
*/
            __pyx_v_y_n = (__pyx_v_raster_coord.yi + (ROW_OFFSETS[__Pyx_mod_long(__pyx_v_test_dir, 8, 1)]));

            /* "pygeoprocessing/routing/routing.pyx":3692
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
 *                         if x_n < 0 or y_n < 0 or \             # <<<<<<<<<<<<<<
 *                                 x_n >= n_cols or y_n >= n_rows:
 *                             continue
*/
            __pyx_t_21 = (__pyx_v_x_n < 0);
            if (!__pyx_t_21) {
            } else {
              __pyx_t_15 = __pyx_t_21;
              goto __pyx_L24_bool_binop_done;
            }
            __pyx_t_21 = (__pyx_v_y_n < 0);
            if (!__pyx_t_21) {
            } else {
              __pyx_t_15 = __pyx_t_21;
              goto __pyx_L24_bool_binop_done;
            }

            /* "pygeoprocessing/routing/routing.pyx":3693
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
 *                         if x_n < 0 or y_n < 0 or \
 *                                 x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *                             continue
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)
*/
            __pyx_t_21 = (__pyx_v_x_n >= __pyx_v_n_cols);
            if (!__pyx_t_21) {
            } else {
              __pyx_t_15 = __pyx_t_21;
              goto __pyx_L24_bool_binop_done;
            }
            __pyx_t_21 = (__pyx_v_y_n >= __pyx_v_n_rows);
            __pyx_t_15 = __pyx_t_21;
            __pyx_L24_bool_binop_done:;

            /* "pygeoprocessing/routing/routing.pyx":3692
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
 *                         if x_n < 0 or y_n < 0 or \             # <<<<<<<<<<<<<<
 *                                 x_n >= n_cols or y_n >= n_rows:
 *                             continue
*/
            if (__pyx_t_15) {

              /* "pygeoprocessing/routing/routing.pyx":3694
 *                         if x_n < 0 or y_n < 0 or \
 *                                 x_n >= n_cols or y_n >= n_rows:
 *                             continue             # <<<<<<<<<<<<<<
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                         if n_dir == flow_dir_nodata:
*/
              goto __pyx_L21_continue;

              /* "pygeoprocessing/routing/routing.pyx":3692
 *                         x_n = raster_coord.xi + COL_OFFSETS[test_dir % 8]
 *                         y_n = raster_coord.yi + ROW_OFFSETS[test_dir % 8]
 *                         if x_n < 0 or y_n < 0 or \             # <<<<<<<<<<<<<<
 *                                 x_n >= n_cols or y_n >= n_rows:
 *                             continue
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3695
 *                                 x_n >= n_cols or y_n >= n_rows:
 *                             continue
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)             # <<<<<<<<<<<<<<
 *                         if n_dir == flow_dir_nodata:
 *                             continue
*/
            __pyx_v_n_dir = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n));

            /* "pygeoprocessing/routing/routing.pyx":3696
 *                             continue
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                         if n_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:
*/
            __pyx_t_15 = (__pyx_v_n_dir == __pyx_v_flow_dir_nodata);
            if (__pyx_t_15) {

              /* "pygeoprocessing/routing/routing.pyx":3697
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                         if n_dir == flow_dir_nodata:
 *                             continue             # <<<<<<<<<<<<<<
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:
 *                             discovery_stack.push(CoordinateType(x_n, y_n))
*/
              goto __pyx_L21_continue;

              /* "pygeoprocessing/routing/routing.pyx":3696
 *                             continue
 *                         n_dir = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                         if n_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             continue
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3698
 *                         if n_dir == flow_dir_nodata:
 *                             continue
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:             # <<<<<<<<<<<<<<
 *                             discovery_stack.push(CoordinateType(x_n, y_n))
 *                             n_pushed += 1
*/
            __pyx_t_15 = ((INFLOW_OFFSETS[__pyx_v_test_dir]) == __pyx_v_n_dir);
            if (__pyx_t_15) {

              /* "pygeoprocessing/routing/routing.pyx":3699
 *                             continue
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:
 *                             discovery_stack.push(CoordinateType(x_n, y_n))             # <<<<<<<<<<<<<<
 *                             n_pushed += 1
 *                     # this reference is for the previous top and represents
*/
              __pyx_t_22.xi = __pyx_v_x_n;
              __pyx_t_22.yi = __pyx_v_y_n;
              try {
                __pyx_v_discovery_stack.push(__pyx_t_22);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 3699, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":3700
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:
 *                             discovery_stack.push(CoordinateType(x_n, y_n))
 *                             n_pushed += 1             # <<<<<<<<<<<<<<
 *                     # this reference is for the previous top and represents
 *                     # how many elements must be processed before finish
*/
              __pyx_v_n_pushed = (__pyx_v_n_pushed + 1);

              /* "pygeoprocessing/routing/routing.pyx":3698
 *                         if n_dir == flow_dir_nodata:
 *                             continue
 *                         if INFLOW_OFFSETS[test_dir] == n_dir:             # <<<<<<<<<<<<<<
 *                             discovery_stack.push(CoordinateType(x_n, y_n))
 *                             n_pushed += 1
*/
            }
            __pyx_L21_continue:;
          }

          /* "pygeoprocessing/routing/routing.pyx":3706
 *                     finish_stack.push(
 *                         FinishType(
 *                             raster_coord.xi, raster_coord.yi, n_pushed))             # <<<<<<<<<<<<<<
 * 
 *                     # pop the finish stack until n_pushed > 1
*/
          __pyx_t_23.xi = __pyx_v_raster_coord.xi;
          __pyx_t_23.yi = __pyx_v_raster_coord.yi;
          __pyx_t_23.n_pushed = __pyx_v_n_pushed;

          /* "pygeoprocessing/routing/routing.pyx":3704
 *                     # how many elements must be processed before finish
 *                     # time can be defined
 *                     finish_stack.push(             # <<<<<<<<<<<<<<
 *                         FinishType(
 *                             raster_coord.xi, raster_coord.yi, n_pushed))
*/
          try {
            __pyx_v_finish_stack.push(__pyx_t_23);
          } catch(...) {
            __Pyx_CppExn2PyErr();
            __PYX_ERR(0, 3704, __pyx_L1_error)
          }

          /* "pygeoprocessing/routing/routing.pyx":3709
 * 
 *                     # pop the finish stack until n_pushed > 1
 *                     if n_pushed == 0:             # <<<<<<<<<<<<<<
 *                         while (not finish_stack.empty() and
 *                                finish_stack.top().n_pushed <= 1):
*/
          __pyx_t_15 = (__pyx_v_n_pushed == 0);
          if (__pyx_t_15) {

            /* "pygeoprocessing/routing/routing.pyx":3710
 *                     # pop the finish stack until n_pushed > 1
 *                     if n_pushed == 0:
 *                         while (not finish_stack.empty() and             # <<<<<<<<<<<<<<
 *                                finish_stack.top().n_pushed <= 1):
 *                             finish_coordinate = finish_stack.top()
*/
            while (1) {
              __pyx_t_21 = (!__pyx_v_finish_stack.empty());
              if (__pyx_t_21) {
              } else {
                __pyx_t_15 = __pyx_t_21;
                goto __pyx_L33_bool_binop_done;
              }

              /* "pygeoprocessing/routing/routing.pyx":3711
 *                     if n_pushed == 0:
 *                         while (not finish_stack.empty() and
 *                                finish_stack.top().n_pushed <= 1):             # <<<<<<<<<<<<<<
 *                             finish_coordinate = finish_stack.top()
 *                             finish_stack.pop()
*/
              __pyx_t_21 = (__pyx_v_finish_stack.top().n_pushed <= 1);
              __pyx_t_15 = __pyx_t_21;
              __pyx_L33_bool_binop_done:;
              if (!__pyx_t_15) break;

              /* "pygeoprocessing/routing/routing.pyx":3712
 *                         while (not finish_stack.empty() and
 *                                finish_stack.top().n_pushed <= 1):
 *                             finish_coordinate = finish_stack.top()             # <<<<<<<<<<<<<<
 *                             finish_stack.pop()
 *                             finish_managed_raster.set(
*/
              __pyx_v_finish_coordinate = __pyx_v_finish_stack.top();

              /* "pygeoprocessing/routing/routing.pyx":3713
 *                                finish_stack.top().n_pushed <= 1):
 *                             finish_coordinate = finish_stack.top()
 *                             finish_stack.pop()             # <<<<<<<<<<<<<<
 *                             finish_managed_raster.set(
 *                                 finish_coordinate.xi, finish_coordinate.yi,
*/
              __pyx_v_finish_stack.pop();

              /* "pygeoprocessing/routing/routing.pyx":3714
 *                             finish_coordinate = finish_stack.top()
 *                             finish_stack.pop()
 *                             finish_managed_raster.set(             # <<<<<<<<<<<<<<
 *                                 finish_coordinate.xi, finish_coordinate.yi,
 *                                 discovery_count-1)
*/
              __pyx_v_finish_managed_raster.set(__pyx_v_finish_coordinate.xi, __pyx_v_finish_coordinate.yi, (__pyx_v_discovery_count - 1));
            }

            /* "pygeoprocessing/routing/routing.pyx":3717
 *                                 finish_coordinate.xi, finish_coordinate.yi,
 *                                 discovery_count-1)
 *                         if not finish_stack.empty():             # <<<<<<<<<<<<<<
 *                             # then take one more because one branch is done
 *                             finish_coordinate = finish_stack.top()
*/
            __pyx_t_15 = (!__pyx_v_finish_stack.empty());
            if (__pyx_t_15) {

              /* "pygeoprocessing/routing/routing.pyx":3719
 *                         if not finish_stack.empty():
 *                             # then take one more because one branch is done
 *                             finish_coordinate = finish_stack.top()             # <<<<<<<<<<<<<<
 *                             finish_stack.pop()
 *                             finish_coordinate.n_pushed -= 1
*/
              __pyx_v_finish_coordinate = __pyx_v_finish_stack.top();

              /* "pygeoprocessing/routing/routing.pyx":3720
 *                             # then take one more because one branch is done
 *                             finish_coordinate = finish_stack.top()
 *                             finish_stack.pop()             # <<<<<<<<<<<<<<
 *                             finish_coordinate.n_pushed -= 1
 *                             finish_stack.push(finish_coordinate)
*/
              __pyx_v_finish_stack.pop();

              /* "pygeoprocessing/routing/routing.pyx":3721
 *                             finish_coordinate = finish_stack.top()
 *                             finish_stack.pop()
 *                             finish_coordinate.n_pushed -= 1             # <<<<<<<<<<<<<<
 *                             finish_stack.push(finish_coordinate)
 * 
*/
              __pyx_v_finish_coordinate.n_pushed = (__pyx_v_finish_coordinate.n_pushed - 1);

              /* "pygeoprocessing/routing/routing.pyx":3722
 *                             finish_stack.pop()
 *                             finish_coordinate.n_pushed -= 1
 *                             finish_stack.push(finish_coordinate)             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_managed_raster.close()
*/
              try {
                __pyx_v_finish_stack.push(__pyx_v_finish_coordinate);
              } catch(...) {
                __Pyx_CppExn2PyErr();
                __PYX_ERR(0, 3722, __pyx_L1_error)
              }

              /* "pygeoprocessing/routing/routing.pyx":3717
 *                                 finish_coordinate.xi, finish_coordinate.yi,
 *                                 discovery_count-1)
 *                         if not finish_stack.empty():             # <<<<<<<<<<<<<<
 *                             # then take one more because one branch is done
 *                             finish_coordinate = finish_stack.top()
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":3709
 * 
 *                     # pop the finish stack until n_pushed > 1
 *                     if n_pushed == 0:             # <<<<<<<<<<<<<<
 *                         while (not finish_stack.empty() and
 *                                finish_stack.top().n_pushed <= 1):
*/
          }
        }
        __pyx_L10_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":3644
 *     cdef int n_dir, test_dir
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_d8_raster_path_band, offset_only=True):
 *         # search raster block by raster block
*/
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3724
 *                             finish_stack.push(finish_coordinate)
 * 
 *     flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     discovery_managed_raster.close()
 *     finish_managed_raster.close()
*/
  __pyx_v_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3725
 * 
 *     flow_dir_managed_raster.close()
 *     discovery_managed_raster.close()             # <<<<<<<<<<<<<<
 *     finish_managed_raster.close()
 * 
*/
  __pyx_v_discovery_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3726
 *     flow_dir_managed_raster.close()
 *     discovery_managed_raster.close()
 *     finish_managed_raster.close()             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_v_finish_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":3590
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _build_discovery_finish_rasters(
 *         flow_dir_d8_raster_path_band, target_discovery_raster_path,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._build_discovery_finish_rasters", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_flow_dir_info);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":3729
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def calculate_subwatershed_boundary(
 *         d8_flow_dir_raster_path_band,
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_25calculate_subwatershed_boundary(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_24calculate_subwatershed_boundary, "Calculate a linestring boundary around all subwatersheds.\n\n    Subwatersheds start where the ``strahler_stream_vector`` has a junction\n    starting at this highest upstream to lowest and ending at the outlet of\n    a river.\n\n    Args:\n        d8_flow_dir_raster_path_band (tuple): raster/path band for d8 flow dir\n            raster. Paths may use any GDAL-supported scheme, including virtual\n            file system /vsi schemes.\n        strahler_stream_vector_path (str): path to stream segment vector. Paths\n            may use any GDAL-supported scheme, including virtual file system\n            /vsi schemes.\n        target_watershed_boundary_vector_path (str): path to created vector\n            of linestring for watershed boundaries. Contains the fields:\n\n            * \"stream_id\": this is the stream ID from the\n              ``strahler_stream_vector_path`` that corresponds to this\n              subwatershed.\n            * \"terminated_early\": if set to 1 this watershed generation was\n              terminated before it could be complete. This value should\n              always be 0 unless something is wrong as a software bug\n              or some degenerate case of data.\n            * \"outlet_x\", \"outlet_y\": this is the x/y coordinate in raster\n              space of the outlet of the watershed. It can be useful when\n              determining other properties about the watershed when indexed\n              with underlying raster data that created the streams in\n              ``strahler_stream_vector_path``.\n\n            Paths may use any GDAL-supported scheme, including virtual file\n            system /vsi schemes.\n        max_steps_per_watershed (int): maximum number of steps to take when\n            defining a watershed boundary. Useful if the DEM is large and\n            degenerate or some other user known condition to limit long large\n            polygons. Defaults to 1000000.\n        outlet_at_confluence (bool): If True the"" outlet of subwatersheds\n            starts at the confluence of streams. If False (the default)\n            subwatersheds will start one pixel up from the confluence.\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_25calculate_subwatershed_boundary = {"calculate_subwatershed_boundary", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_25calculate_subwatershed_boundary, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_24calculate_subwatershed_boundary};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_25calculate_subwatershed_boundary(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_d8_flow_dir_raster_path_band = 0;
  PyObject *__pyx_v_strahler_stream_vector_path = 0;
  PyObject *__pyx_v_target_watershed_boundary_vector_path = 0;
  PyObject *__pyx_v_max_steps_per_watershed = 0;
  PyObject *__pyx_v_outlet_at_confluence = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[5] = {0,0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("calculate_subwatershed_boundary (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_d8_flow_dir_raster_path_band,&__pyx_mstate_global->__pyx_n_u_strahler_stream_vector_path,&__pyx_mstate_global->__pyx_n_u_target_watershed_boundary_vector,&__pyx_mstate_global->__pyx_n_u_max_steps_per_watershed,&__pyx_mstate_global->__pyx_n_u_outlet_at_confluence,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 3729, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "calculate_subwatershed_boundary", 0) < (0)) __PYX_ERR(0, 3729, __pyx_L3_error)
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)((PyObject*)__pyx_mstate_global->__pyx_int_1000000)));

      /* "pygeoprocessing/routing/routing.pyx":3734
 *         strahler_stream_vector_path, target_watershed_boundary_vector_path,
 *         max_steps_per_watershed=1000000,
 *         outlet_at_confluence=False):             # <<<<<<<<<<<<<<
 *     """Calculate a linestring boundary around all subwatersheds.
 * 
*/
      if (!values[4]) values[4] = __Pyx_NewRef(((PyObject *)((PyObject*)Py_False)));
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("calculate_subwatershed_boundary", 0, 3, 5, i); __PYX_ERR(0, 3729, __pyx_L3_error) }
      }
    } else {
      switch (__pyx_nargs) {
        case  5:
        values[4] = __Pyx_ArgRef_FASTCALL(__pyx_args, 4);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[4])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 3729, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 3729, __pyx_L3_error)
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 3729, __pyx_L3_error)
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 3729, __pyx_L3_error)
        break;
        default: goto __pyx_L5_argtuple_error;
      }
      if (!values[3]) values[3] = __Pyx_NewRef(((PyObject *)((PyObject*)__pyx_mstate_global->__pyx_int_1000000)));
      if (!values[4]) values[4] = __Pyx_NewRef(((PyObject *)((PyObject*)Py_False)));
    }
    __pyx_v_d8_flow_dir_raster_path_band = values[0];
    __pyx_v_strahler_stream_vector_path = values[1];
    __pyx_v_target_watershed_boundary_vector_path = values[2];
    __pyx_v_max_steps_per_watershed = values[3];
    __pyx_v_outlet_at_confluence = values[4];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("calculate_subwatershed_boundary", 0, 3, 5, __pyx_nargs); __PYX_ERR(0, 3729, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.calculate_subwatershed_boundary", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_24calculate_subwatershed_boundary(__pyx_self, __pyx_v_d8_flow_dir_raster_path_band, __pyx_v_strahler_stream_vector_path, __pyx_v_target_watershed_boundary_vector_path, __pyx_v_max_steps_per_watershed, __pyx_v_outlet_at_confluence);

  /* "pygeoprocessing/routing/routing.pyx":3729
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def calculate_subwatershed_boundary(
 *         d8_flow_dir_raster_path_band,
*/

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_24calculate_subwatershed_boundary(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_d8_flow_dir_raster_path_band, PyObject *__pyx_v_strahler_stream_vector_path, PyObject *__pyx_v_target_watershed_boundary_vector_path, PyObject *__pyx_v_max_steps_per_watershed, PyObject *__pyx_v_outlet_at_confluence) {
  PyObject *__pyx_v_workspace_dir = NULL;
  PyObject *__pyx_v_discovery_time_raster_path = NULL;
  PyObject *__pyx_v_finish_time_raster_path = NULL;
  ManagedRaster __pyx_v_discovery_managed_raster;
  ManagedRaster __pyx_v_finish_managed_raster;
  ManagedRaster __pyx_v_d8_flow_dir_managed_raster;
  PyObject *__pyx_v_discovery_info = NULL;
  long __pyx_v_discovery_nodata;
  unsigned int __pyx_v_n_cols;
  unsigned int __pyx_v_n_rows;
  PyObject *__pyx_v_geotransform = NULL;
  double __pyx_v_g0;
  double __pyx_v_g1;
  double __pyx_v_g2;
  double __pyx_v_g3;
  double __pyx_v_g4;
  double __pyx_v_g5;
  PyObject *__pyx_v_discovery_srs = NULL;
  PyObject *__pyx_v_gpkg_driver = NULL;
  PyObject *__pyx_v_watershed_vector = NULL;
  PyObject *__pyx_v_watershed_basename = NULL;
  PyObject *__pyx_v_watershed_layer = NULL;
  unsigned int __pyx_v_x_l;
  unsigned int __pyx_v_y_l;
  int __pyx_v_outflow_dir;
  double __pyx_v_x_f;
  double __pyx_v_y_f;
  double __pyx_v_x_p;
  double __pyx_v_y_p;
  long __pyx_v_discovery;
  long __pyx_v_finish;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_stream_vector = NULL;
  PyObject *__pyx_v_stream_layer = NULL;
  PyObject *__pyx_v_upstream_fid_map = NULL;
  PyObject *__pyx_v_stream_feature = NULL;
  PyObject *__pyx_v_ds_x = NULL;
  PyObject *__pyx_v_ds_y = NULL;
  PyObject *__pyx_v_visit_order_stack = NULL;
  CYTHON_UNUSED PyObject *__pyx_v__ = NULL;
  PyObject *__pyx_v_outlet_fid = NULL;
  PyObject *__pyx_v_working_stack = NULL;
  PyObject *__pyx_v_processed_nodes = NULL;
  PyObject *__pyx_v_working_fid = NULL;
  PyObject *__pyx_v_working_feature = NULL;
  PyObject *__pyx_v_us_x = NULL;
  PyObject *__pyx_v_us_y = NULL;
  PyObject *__pyx_v_ds_x_1 = NULL;
  PyObject *__pyx_v_ds_y_1 = NULL;
  PyObject *__pyx_v_upstream_coord = NULL;
  PyObject *__pyx_v_upstream_fids = NULL;
  int __pyx_v_edge_side;
  int __pyx_v_edge_dir;
  int __pyx_v_cell_to_test;
  int __pyx_v_out_dir_increase;
  int __pyx_v_left;
  int __pyx_v_right;
  int __pyx_v_n_steps;
  int __pyx_v_terminated_early;
  int __pyx_v_delta_x;
  int __pyx_v_delta_y;
  int __pyx_v__int_max_steps_per_watershed;
  PyObject *__pyx_v_index = NULL;
  PyObject *__pyx_v_stream_fid = NULL;
  PyObject *__pyx_v_boundary_list = NULL;
  unsigned int __pyx_v_outlet_x;
  unsigned int __pyx_v_outlet_y;
  PyObject *__pyx_v_watershed_boundary = NULL;
  int __pyx_v_left_in;
  int __pyx_v_right_in;
  int __pyx_v_out_dir;
  PyObject *__pyx_v_watershed_feature = NULL;
  PyObject *__pyx_v_watershed_polygon = NULL;
  PyObject *__pyx_v_boundary_x = NULL;
  PyObject *__pyx_v_boundary_y = NULL;
  PyObject *__pyx_8genexpr2__pyx_v_x = NULL;
  PyObject *__pyx_8genexpr3__pyx_v_fid = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  PyObject *__pyx_t_4 = NULL;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  PyObject *__pyx_t_10 = NULL;
  size_t __pyx_t_11;
  char *__pyx_t_12;
  ManagedRaster __pyx_t_13;
  int __pyx_t_14;
  long __pyx_t_15;
  PyObject *(*__pyx_t_16)(PyObject *);
  unsigned int __pyx_t_17;
  unsigned int __pyx_t_18;
  double __pyx_t_19;
  double __pyx_t_20;
  double __pyx_t_21;
  double __pyx_t_22;
  double __pyx_t_23;
  double __pyx_t_24;
  int __pyx_t_25;
  Py_ssize_t __pyx_t_26;
  PyObject *(*__pyx_t_27)(PyObject *);
  int __pyx_t_28;
  Py_ssize_t __pyx_t_29;
  PyObject *(*__pyx_t_30)(PyObject *);
  int __pyx_t_31;
  int __pyx_t_32;
  PyObject *__pyx_t_33[3];
  int __pyx_t_34;
  PyObject *__pyx_t_35[8];
  long __pyx_t_36;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("calculate_subwatershed_boundary", 0);

  /* "pygeoprocessing/routing/routing.pyx":3777
 *         None.
 *     """
 *     workspace_dir = tempfile.mkdtemp(             # <<<<<<<<<<<<<<
 *         prefix='calculate_subwatershed_boundary_workspace_',
 *         dir=os.path.join(
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_tempfile); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3777, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_mkdtemp); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3777, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3779
 *     workspace_dir = tempfile.mkdtemp(
 *         prefix='calculate_subwatershed_boundary_workspace_',
 *         dir=os.path.join(             # <<<<<<<<<<<<<<
 *             os.path.dirname(target_watershed_boundary_vector_path)))
 *     discovery_time_raster_path = os.path.join(workspace_dir, 'discovery.tif')
*/
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3779, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3779, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_5 = __pyx_t_7;
  __Pyx_INCREF(__pyx_t_5);

  /* "pygeoprocessing/routing/routing.pyx":3780
 *         prefix='calculate_subwatershed_boundary_workspace_',
 *         dir=os.path.join(
 *             os.path.dirname(target_watershed_boundary_vector_path)))             # <<<<<<<<<<<<<<
 *     discovery_time_raster_path = os.path.join(workspace_dir, 'discovery.tif')
 *     finish_time_raster_path = os.path.join(workspace_dir, 'finish.tif')
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 3780, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 3780, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_8 = __pyx_t_10;
  __Pyx_INCREF(__pyx_t_8);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_v_target_watershed_boundary_vector_path};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_dirname, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
    __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3780, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3779, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
  }
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_2, NULL};
    __pyx_t_7 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3777, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_prefix, __pyx_mstate_global->__pyx_n_u_calculate_subwatershed_boundary, __pyx_t_7, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 3777, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dir, __pyx_t_3, __pyx_t_7, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 3777, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_7);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3777, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_workspace_dir = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3781
 *         dir=os.path.join(
 *             os.path.dirname(target_watershed_boundary_vector_path)))
 *     discovery_time_raster_path = os.path.join(workspace_dir, 'discovery.tif')             # <<<<<<<<<<<<<<
 *     finish_time_raster_path = os.path.join(workspace_dir, 'finish.tif')
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3781, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3781, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_4 = __pyx_t_3;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_v_workspace_dir, __pyx_mstate_global->__pyx_kp_u_discovery_tif};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3781, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_discovery_time_raster_path = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3782
 *             os.path.dirname(target_watershed_boundary_vector_path)))
 *     discovery_time_raster_path = os.path.join(workspace_dir, 'discovery.tif')
 *     finish_time_raster_path = os.path.join(workspace_dir, 'finish.tif')             # <<<<<<<<<<<<<<
 * 
 *     # construct the discovery/finish time rasters for fast individual cell
*/
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3782, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3782, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_3 = __pyx_t_7;
  __Pyx_INCREF(__pyx_t_3);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_v_workspace_dir, __pyx_mstate_global->__pyx_kp_u_finish_tif};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_join, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3782, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_finish_time_raster_path = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3786
 *     # construct the discovery/finish time rasters for fast individual cell
 *     # watershed detection
 *     _build_discovery_finish_rasters(             # <<<<<<<<<<<<<<
 *         d8_flow_dir_raster_path_band, discovery_time_raster_path,
 *         finish_time_raster_path)
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_build_discovery_finish_rasters); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3786, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);

  /* "pygeoprocessing/routing/routing.pyx":3788
 *     _build_discovery_finish_rasters(
 *         d8_flow_dir_raster_path_band, discovery_time_raster_path,
 *         finish_time_raster_path)             # <<<<<<<<<<<<<<
 * 
 *     shutil.copyfile(
*/
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[4] = {__pyx_t_7, __pyx_v_d8_flow_dir_raster_path_band, __pyx_v_discovery_time_raster_path, __pyx_v_finish_time_raster_path};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_11, (4-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3786, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3790
 *         finish_time_raster_path)
 * 
 *     shutil.copyfile(             # <<<<<<<<<<<<<<
 *         discovery_time_raster_path, f'{discovery_time_raster_path}_bak.tif')
 * 
*/
  __pyx_t_3 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3790, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_copyfile); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3790, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3791
 * 
 *     shutil.copyfile(
 *         discovery_time_raster_path, f'{discovery_time_raster_path}_bak.tif')             # <<<<<<<<<<<<<<
 * 
 *     # the discovery raster is filled with nodata around the edges of
*/
  __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_v_discovery_time_raster_path, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3791, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_2 = __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(__pyx_t_7, __pyx_mstate_global->__pyx_kp_u_bak_tif); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3791, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_3);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_3, __pyx_v_discovery_time_raster_path, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3790, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3796
 *     # discovered watersheds, so it is opened for writing
 *     discovery_managed_raster = ManagedRaster(
 *         discovery_time_raster_path.encode('utf-8'), 1, True)             # <<<<<<<<<<<<<<
 *     finish_managed_raster = ManagedRaster(
 *         finish_time_raster_path.encode('utf-8'), 1, False)
*/
  __pyx_t_4 = __pyx_v_discovery_time_raster_path;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3796, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 3796, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3795
 *     # the discovery raster is filled with nodata around the edges of
 *     # discovered watersheds, so it is opened for writing
 *     discovery_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         discovery_time_raster_path.encode('utf-8'), 1, True)
 *     finish_managed_raster = ManagedRaster(
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, 1, Py_True);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3795, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_discovery_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":3798
 *         discovery_time_raster_path.encode('utf-8'), 1, True)
 *     finish_managed_raster = ManagedRaster(
 *         finish_time_raster_path.encode('utf-8'), 1, False)             # <<<<<<<<<<<<<<
 *     d8_flow_dir_managed_raster = ManagedRaster(
 *         d8_flow_dir_raster_path_band[0].encode('utf-8'),
*/
  __pyx_t_4 = __pyx_v_finish_time_raster_path;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3798, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 3798, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3797
 *     discovery_managed_raster = ManagedRaster(
 *         discovery_time_raster_path.encode('utf-8'), 1, True)
 *     finish_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         finish_time_raster_path.encode('utf-8'), 1, False)
 *     d8_flow_dir_managed_raster = ManagedRaster(
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, 1, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3797, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_finish_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":3800
 *         finish_time_raster_path.encode('utf-8'), 1, False)
 *     d8_flow_dir_managed_raster = ManagedRaster(
 *         d8_flow_dir_raster_path_band[0].encode('utf-8'),             # <<<<<<<<<<<<<<
 *         d8_flow_dir_raster_path_band[1], False)
 * 
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_d8_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3800, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = __pyx_t_2;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3800, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_12 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_12) && PyErr_Occurred())) __PYX_ERR(0, 3800, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":3801
 *     d8_flow_dir_managed_raster = ManagedRaster(
 *         d8_flow_dir_raster_path_band[0].encode('utf-8'),
 *         d8_flow_dir_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     discovery_info = pygeoprocessing.get_raster_info(
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_d8_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3801, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_t_2); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3801, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3799
 *     finish_managed_raster = ManagedRaster(
 *         finish_time_raster_path.encode('utf-8'), 1, False)
 *     d8_flow_dir_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         d8_flow_dir_raster_path_band[0].encode('utf-8'),
 *         d8_flow_dir_raster_path_band[1], False)
*/
  try {
    __pyx_t_13 = ManagedRaster(__pyx_t_12, __pyx_t_14, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 3799, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_d8_flow_dir_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":3803
 *         d8_flow_dir_raster_path_band[1], False)
 * 
 *     discovery_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         discovery_time_raster_path)
 *     cdef long discovery_nodata = discovery_info['nodata'][0]
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3803, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3803, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3804
 * 
 *     discovery_info = pygeoprocessing.get_raster_info(
 *         discovery_time_raster_path)             # <<<<<<<<<<<<<<
 *     cdef long discovery_nodata = discovery_info['nodata'][0]
 * 
*/
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_discovery_time_raster_path};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3803, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_discovery_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3805
 *     discovery_info = pygeoprocessing.get_raster_info(
 *         discovery_time_raster_path)
 *     cdef long discovery_nodata = discovery_info['nodata'][0]             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned int n_cols, n_rows
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_discovery_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3805, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3805, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_15 = __Pyx_PyLong_As_long(__pyx_t_3); if (unlikely((__pyx_t_15 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 3805, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_discovery_nodata = __pyx_t_15;

  /* "pygeoprocessing/routing/routing.pyx":3808
 * 
 *     cdef unsigned int n_cols, n_rows
 *     n_cols, n_rows = discovery_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     geotransform = discovery_info['geotransform']
*/
  __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_discovery_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3808, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
    PyObject* sequence = __pyx_t_3;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 3808, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_1);
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_2);
    } else {
      __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3808, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3808, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
    }
    #else
    __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3808, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3808, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    #endif
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3808, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_4);
    index = 0; __pyx_t_1 = __pyx_t_16(__pyx_t_4); if (unlikely(!__pyx_t_1)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_1);
    index = 1; __pyx_t_2 = __pyx_t_16(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_4), 2) < (0)) __PYX_ERR(0, 3808, __pyx_L1_error)
    __pyx_t_16 = NULL;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    goto __pyx_L4_unpacking_done;
    __pyx_L3_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_16 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 3808, __pyx_L1_error)
    __pyx_L4_unpacking_done:;
  }
  __pyx_t_17 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_17 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3808, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_18 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_18 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3808, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_cols = __pyx_t_17;
  __pyx_v_n_rows = __pyx_t_18;

  /* "pygeoprocessing/routing/routing.pyx":3810
 *     n_cols, n_rows = discovery_info['raster_size']
 * 
 *     geotransform = discovery_info['geotransform']             # <<<<<<<<<<<<<<
 *     cdef double g0, g1, g2, g3, g4, g5
 *     g0, g1, g2, g3, g4, g5 = geotransform
*/
  __pyx_t_3 = __Pyx_PyObject_Dict_GetItem(__pyx_v_discovery_info, __pyx_mstate_global->__pyx_n_u_geotransform); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3810, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_v_geotransform = __pyx_t_3;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3812
 *     geotransform = discovery_info['geotransform']
 *     cdef double g0, g1, g2, g3, g4, g5
 *     g0, g1, g2, g3, g4, g5 = geotransform             # <<<<<<<<<<<<<<
 * 
 *     if discovery_info['projection_wkt']:
*/
  if ((likely(PyTuple_CheckExact(__pyx_v_geotransform))) || (PyList_CheckExact(__pyx_v_geotransform))) {
    PyObject* sequence = __pyx_v_geotransform;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 6)) {
      if (size > 6) __Pyx_RaiseTooManyValuesError(6);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 3812, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_3);
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2);
      __Pyx_INCREF(__pyx_t_1);
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 3);
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4);
      __Pyx_INCREF(__pyx_t_7);
      __pyx_t_6 = PyTuple_GET_ITEM(sequence, 5);
      __Pyx_INCREF(__pyx_t_6);
    } else {
      __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_3);
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_1);
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 3, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
      __pyx_t_7 = __Pyx_PyList_GetItemRefFast(sequence, 4, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_7);
      __pyx_t_6 = __Pyx_PyList_GetItemRefFast(sequence, 5, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3812, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_6);
    }
    #else
    {
      Py_ssize_t i;
      PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_2,&__pyx_t_1,&__pyx_t_4,&__pyx_t_7,&__pyx_t_6};
      for (i=0; i < 6; i++) {
        PyObject* item = __Pyx_PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 3812, __pyx_L1_error)
        __Pyx_GOTREF(item);
        *(temps[i]) = item;
      }
    }
    #endif
  } else {
    Py_ssize_t index = -1;
    PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_2,&__pyx_t_1,&__pyx_t_4,&__pyx_t_7,&__pyx_t_6};
    __pyx_t_5 = PyObject_GetIter(__pyx_v_geotransform); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3812, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_5);
    for (index=0; index < 6; index++) {
      PyObject* item = __pyx_t_16(__pyx_t_5); if (unlikely(!item)) goto __pyx_L5_unpacking_failed;
      __Pyx_GOTREF(item);
      *(temps[index]) = item;
    }
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_5), 6) < (0)) __PYX_ERR(0, 3812, __pyx_L1_error)
    __pyx_t_16 = NULL;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    goto __pyx_L6_unpacking_done;
    __pyx_L5_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_16 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 3812, __pyx_L1_error)
    __pyx_L6_unpacking_done:;
  }
  __pyx_t_19 = __Pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_19 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_20 = __Pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_20 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_21 = __Pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_21 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_22 = __Pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_22 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_23 = __Pyx_PyFloat_AsDouble(__pyx_t_7); if (unlikely((__pyx_t_23 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_24 = __Pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_24 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3812, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_v_g0 = __pyx_t_19;
  __pyx_v_g1 = __pyx_t_20;
  __pyx_v_g2 = __pyx_t_21;
  __pyx_v_g3 = __pyx_t_22;
  __pyx_v_g4 = __pyx_t_23;
  __pyx_v_g5 = __pyx_t_24;

  /* "pygeoprocessing/routing/routing.pyx":3814
 *     g0, g1, g2, g3, g4, g5 = geotransform
 * 
 *     if discovery_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         discovery_srs = osr.SpatialReference()
 *         discovery_srs.ImportFromWkt(discovery_info['projection_wkt'])
*/
  __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_discovery_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3814, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3814, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  if (__pyx_t_25) {

    /* "pygeoprocessing/routing/routing.pyx":3815
 * 
 *     if discovery_info['projection_wkt']:
 *         discovery_srs = osr.SpatialReference()             # <<<<<<<<<<<<<<
 *         discovery_srs.ImportFromWkt(discovery_info['projection_wkt'])
 *     else:
*/
    __pyx_t_7 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_osr); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3815, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_SpatialReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3815, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_7);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_7, NULL};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3815, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __pyx_v_discovery_srs = __pyx_t_6;
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3816
 *     if discovery_info['projection_wkt']:
 *         discovery_srs = osr.SpatialReference()
 *         discovery_srs.ImportFromWkt(discovery_info['projection_wkt'])             # <<<<<<<<<<<<<<
 *     else:
 *         discovery_srs = None
*/
    __pyx_t_1 = __pyx_v_discovery_srs;
    __Pyx_INCREF(__pyx_t_1);
    __pyx_t_7 = __Pyx_PyObject_Dict_GetItem(__pyx_v_discovery_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3816, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_7};
      __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_ImportFromWkt, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3816, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3814
 *     g0, g1, g2, g3, g4, g5 = geotransform
 * 
 *     if discovery_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         discovery_srs = osr.SpatialReference()
 *         discovery_srs.ImportFromWkt(discovery_info['projection_wkt'])
*/
    goto __pyx_L7;
  }

  /* "pygeoprocessing/routing/routing.pyx":3818
 *         discovery_srs.ImportFromWkt(discovery_info['projection_wkt'])
 *     else:
 *         discovery_srs = None             # <<<<<<<<<<<<<<
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
*/
  /*else*/ {
    __Pyx_INCREF(Py_None);
    __pyx_v_discovery_srs = Py_None;
  }
  __pyx_L7:;

  /* "pygeoprocessing/routing/routing.pyx":3819
 *     else:
 *         discovery_srs = None
 *     gpkg_driver = gdal.GetDriverByName('GPKG')             # <<<<<<<<<<<<<<
 * 
 *     if os.path.exists(target_watershed_boundary_vector_path):
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3819, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_GetDriverByName); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3819, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_GPKG};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3819, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_gpkg_driver = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3821
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
 *     if os.path.exists(target_watershed_boundary_vector_path):             # <<<<<<<<<<<<<<
 *         LOGGER.warning(
 *             f'{target_watershed_boundary_vector_path} exists, removing '
*/
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3821, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3821, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_4 = __pyx_t_1;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_target_watershed_boundary_vector_path};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_exists, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3821, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3821, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  if (__pyx_t_25) {

    /* "pygeoprocessing/routing/routing.pyx":3822
 * 
 *     if os.path.exists(target_watershed_boundary_vector_path):
 *         LOGGER.warning(             # <<<<<<<<<<<<<<
 *             f'{target_watershed_boundary_vector_path} exists, removing '
 *             'before creating a new one.')
*/
    __pyx_t_1 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3822, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_warning); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3822, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3823
 *     if os.path.exists(target_watershed_boundary_vector_path):
 *         LOGGER.warning(
 *             f'{target_watershed_boundary_vector_path} exists, removing '             # <<<<<<<<<<<<<<
 *             'before creating a new one.')
 *         os.remove(target_watershed_boundary_vector_path)
*/
    __pyx_t_4 = __Pyx_PyObject_FormatSimple(__pyx_v_target_watershed_boundary_vector_path, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3823, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_2 = __Pyx_PyUnicode_Concat__Pyx_ReferenceSharing_OwnStrongReferenceInPlace(__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_exists_removing_before_creating); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3823, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_7))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
      assert(__pyx_t_1);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_2};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3822, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3825
 *             f'{target_watershed_boundary_vector_path} exists, removing '
 *             'before creating a new one.')
 *         os.remove(target_watershed_boundary_vector_path)             # <<<<<<<<<<<<<<
 *     watershed_vector = gpkg_driver.Create(
 *         target_watershed_boundary_vector_path, 0, 0, 0, gdal.GDT_Unknown)
*/
    __pyx_t_7 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3825, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_remove); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3825, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1);
      assert(__pyx_t_7);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_7);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_v_target_watershed_boundary_vector_path};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3825, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3821
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
 *     if os.path.exists(target_watershed_boundary_vector_path):             # <<<<<<<<<<<<<<
 *         LOGGER.warning(
 *             f'{target_watershed_boundary_vector_path} exists, removing '
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":3826
 *             'before creating a new one.')
 *         os.remove(target_watershed_boundary_vector_path)
 *     watershed_vector = gpkg_driver.Create(             # <<<<<<<<<<<<<<
 *         target_watershed_boundary_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     watershed_basename = os.path.basename(os.path.splitext(
*/
  __pyx_t_1 = __pyx_v_gpkg_driver;
  __Pyx_INCREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":3827
 *         os.remove(target_watershed_boundary_vector_path)
 *     watershed_vector = gpkg_driver.Create(
 *         target_watershed_boundary_vector_path, 0, 0, 0, gdal.GDT_Unknown)             # <<<<<<<<<<<<<<
 *     watershed_basename = os.path.basename(os.path.splitext(
 *         target_watershed_boundary_vector_path)[0])
*/
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_GDT_Unknown); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3827, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[6] = {__pyx_t_1, __pyx_v_target_watershed_boundary_vector_path, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_t_2};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_Create, __pyx_callargs+__pyx_t_11, (6-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3826, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_watershed_vector = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3828
 *     watershed_vector = gpkg_driver.Create(
 *         target_watershed_boundary_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     watershed_basename = os.path.basename(os.path.splitext(             # <<<<<<<<<<<<<<
 *         target_watershed_boundary_vector_path)[0])
 *     watershed_layer = watershed_vector.CreateLayer(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3828, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3828, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_2 = __pyx_t_7;
  __Pyx_INCREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3828, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3828, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_4 = __pyx_t_5;
  __Pyx_INCREF(__pyx_t_4);

  /* "pygeoprocessing/routing/routing.pyx":3829
 *         target_watershed_boundary_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     watershed_basename = os.path.basename(os.path.splitext(
 *         target_watershed_boundary_vector_path)[0])             # <<<<<<<<<<<<<<
 *     watershed_layer = watershed_vector.CreateLayer(
 *         watershed_basename, discovery_srs, ogr.wkbPolygon)
*/
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_target_watershed_boundary_vector_path};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_splitext, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3828, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3829, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_5};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_basename, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3828, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_watershed_basename = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3830
 *     watershed_basename = os.path.basename(os.path.splitext(
 *         target_watershed_boundary_vector_path)[0])
 *     watershed_layer = watershed_vector.CreateLayer(             # <<<<<<<<<<<<<<
 *         watershed_basename, discovery_srs, ogr.wkbPolygon)
 *     watershed_layer.CreateField(ogr.FieldDefn('stream_fid', ogr.OFTInteger))
*/
  __pyx_t_7 = __pyx_v_watershed_vector;
  __Pyx_INCREF(__pyx_t_7);

  /* "pygeoprocessing/routing/routing.pyx":3831
 *         target_watershed_boundary_vector_path)[0])
 *     watershed_layer = watershed_vector.CreateLayer(
 *         watershed_basename, discovery_srs, ogr.wkbPolygon)             # <<<<<<<<<<<<<<
 *     watershed_layer.CreateField(ogr.FieldDefn('stream_fid', ogr.OFTInteger))
 *     watershed_layer.CreateField(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3831, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_wkbPolygon); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3831, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[4] = {__pyx_t_7, __pyx_v_watershed_basename, __pyx_v_discovery_srs, __pyx_t_2};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateLayer, __pyx_callargs+__pyx_t_11, (4-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3830, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_watershed_layer = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3832
 *     watershed_layer = watershed_vector.CreateLayer(
 *         watershed_basename, discovery_srs, ogr.wkbPolygon)
 *     watershed_layer.CreateField(ogr.FieldDefn('stream_fid', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     watershed_layer.CreateField(
 *         ogr.FieldDefn('terminated_early', ogr.OFTInteger))
*/
  __pyx_t_2 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3832, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3832, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3832, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3832, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_stream_fid, __pyx_t_3};
    __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3832, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
  }
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3832, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3833
 *         watershed_basename, discovery_srs, ogr.wkbPolygon)
 *     watershed_layer.CreateField(ogr.FieldDefn('stream_fid', ogr.OFTInteger))
 *     watershed_layer.CreateField(             # <<<<<<<<<<<<<<
 *         ogr.FieldDefn('terminated_early', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_x', ogr.OFTInteger))
*/
  __pyx_t_7 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_7);

  /* "pygeoprocessing/routing/routing.pyx":3834
 *     watershed_layer.CreateField(ogr.FieldDefn('stream_fid', ogr.OFTInteger))
 *     watershed_layer.CreateField(
 *         ogr.FieldDefn('terminated_early', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_x', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_y', ogr.OFTInteger))
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3834, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3834, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3834, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3834, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_terminated_early, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3834, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_2};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3833, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3835
 *     watershed_layer.CreateField(
 *         ogr.FieldDefn('terminated_early', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_x', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_y', ogr.OFTInteger))
 *     watershed_layer.StartTransaction()
*/
  __pyx_t_2 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3835, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3835, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3835, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3835, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_outlet_x, __pyx_t_3};
    __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3835, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
  }
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3835, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3836
 *         ogr.FieldDefn('terminated_early', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_x', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_y', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     watershed_layer.StartTransaction()
 * 
*/
  __pyx_t_7 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3836, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3836, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3836, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3836, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_outlet_y, __pyx_t_1};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3836, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_2};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3836, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3837
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_x', ogr.OFTInteger))
 *     watershed_layer.CreateField(ogr.FieldDefn('outlet_y', ogr.OFTInteger))
 *     watershed_layer.StartTransaction()             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned int x_l, y_l
*/
  __pyx_t_2 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3837, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3845
 *     cdef long discovery, finish
 * 
 *     cdef time_t last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     stream_vector = gdal.OpenEx(strahler_stream_vector_path, gdal.OF_VECTOR)
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":3847
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     stream_vector = gdal.OpenEx(strahler_stream_vector_path, gdal.OF_VECTOR)             # <<<<<<<<<<<<<<
 *     stream_layer = stream_vector.GetLayer()
 * 
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3847, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3847, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3847, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_OF_VECTOR); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3847, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_v_strahler_stream_vector_path, __pyx_t_1};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3847, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_stream_vector = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3848
 * 
 *     stream_vector = gdal.OpenEx(strahler_stream_vector_path, gdal.OF_VECTOR)
 *     stream_layer = stream_vector.GetLayer()             # <<<<<<<<<<<<<<
 * 
 *     # construct linkage data structure for upstream streams
*/
  __pyx_t_5 = __pyx_v_stream_vector;
  __Pyx_INCREF(__pyx_t_5);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, NULL};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetLayer, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3848, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_stream_layer = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3851
 * 
 *     # construct linkage data structure for upstream streams
 *     upstream_fid_map = collections.defaultdict(list)             # <<<<<<<<<<<<<<
 *     for stream_feature in stream_layer:
 *         ds_x = int(stream_feature.GetField('ds_x'))
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_collections); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3851, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_defaultdict); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3851, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, ((PyObject *)(&PyList_Type))};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3851, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_upstream_fid_map = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3852
 *     # construct linkage data structure for upstream streams
 *     upstream_fid_map = collections.defaultdict(list)
 *     for stream_feature in stream_layer:             # <<<<<<<<<<<<<<
 *         ds_x = int(stream_feature.GetField('ds_x'))
 *         ds_y = int(stream_feature.GetField('ds_y'))
*/
  if (likely(PyList_CheckExact(__pyx_v_stream_layer)) || PyTuple_CheckExact(__pyx_v_stream_layer)) {
    __pyx_t_6 = __pyx_v_stream_layer; __Pyx_INCREF(__pyx_t_6);
    __pyx_t_26 = 0;
    __pyx_t_27 = NULL;
  } else {
    __pyx_t_26 = -1; __pyx_t_6 = PyObject_GetIter(__pyx_v_stream_layer); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3852, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_27 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6); if (unlikely(!__pyx_t_27)) __PYX_ERR(0, 3852, __pyx_L1_error)
  }
  for (;;) {
    if (likely(!__pyx_t_27)) {
      if (likely(PyList_CheckExact(__pyx_t_6))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3852, __pyx_L1_error)
          #endif
          if (__pyx_t_26 >= __pyx_temp) break;
        }
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_6, __pyx_t_26, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_26;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_6);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3852, __pyx_L1_error)
          #endif
          if (__pyx_t_26 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_6, __pyx_t_26));
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_6, __pyx_t_26);
        #endif
        ++__pyx_t_26;
      }
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3852, __pyx_L1_error)
    } else {
      __pyx_t_2 = __pyx_t_27(__pyx_t_6);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3852, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_XDECREF_SET(__pyx_v_stream_feature, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3853
 *     upstream_fid_map = collections.defaultdict(list)
 *     for stream_feature in stream_layer:
 *         ds_x = int(stream_feature.GetField('ds_x'))             # <<<<<<<<<<<<<<
 *         ds_y = int(stream_feature.GetField('ds_y'))
 *         upstream_fid_map[(ds_x, ds_y)].append(
*/
    __pyx_t_5 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_5);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_ds_x};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3853, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __pyx_t_5 = __Pyx_PyNumber_Int(__pyx_t_2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3853, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ds_x, ((PyObject*)__pyx_t_5));
    __pyx_t_5 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3854
 *     for stream_feature in stream_layer:
 *         ds_x = int(stream_feature.GetField('ds_x'))
 *         ds_y = int(stream_feature.GetField('ds_y'))             # <<<<<<<<<<<<<<
 *         upstream_fid_map[(ds_x, ds_y)].append(
 *             stream_feature.GetFID())
*/
    __pyx_t_2 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ds_y};
      __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3854, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
    }
    __pyx_t_2 = __Pyx_PyNumber_Int(__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3854, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_XDECREF_SET(__pyx_v_ds_y, ((PyObject*)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3855
 *         ds_x = int(stream_feature.GetField('ds_x'))
 *         ds_y = int(stream_feature.GetField('ds_y'))
 *         upstream_fid_map[(ds_x, ds_y)].append(             # <<<<<<<<<<<<<<
 *             stream_feature.GetFID())
 * 
*/
    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3855, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_INCREF(__pyx_v_ds_x);
    __Pyx_GIVEREF(__pyx_v_ds_x);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_ds_x) != (0)) __PYX_ERR(0, 3855, __pyx_L1_error);
    __Pyx_INCREF(__pyx_v_ds_y);
    __Pyx_GIVEREF(__pyx_v_ds_y);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_v_ds_y) != (0)) __PYX_ERR(0, 3855, __pyx_L1_error);
    __pyx_t_5 = __Pyx_PyObject_GetItem(__pyx_v_upstream_fid_map, __pyx_t_2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3855, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3856
 *         ds_y = int(stream_feature.GetField('ds_y'))
 *         upstream_fid_map[(ds_x, ds_y)].append(
 *             stream_feature.GetFID())             # <<<<<<<<<<<<<<
 * 
 *     stream_layer.ResetReading()
*/
    __pyx_t_1 = __pyx_v_stream_feature;
    __Pyx_INCREF(__pyx_t_1);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_1, NULL};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3856, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }

    /* "pygeoprocessing/routing/routing.pyx":3855
 *         ds_x = int(stream_feature.GetField('ds_x'))
 *         ds_y = int(stream_feature.GetField('ds_y'))
 *         upstream_fid_map[(ds_x, ds_y)].append(             # <<<<<<<<<<<<<<
 *             stream_feature.GetFID())
 * 
*/
    __pyx_t_28 = __Pyx_PyObject_Append(__pyx_t_5, __pyx_t_2); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3855, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3852
 *     # construct linkage data structure for upstream streams
 *     upstream_fid_map = collections.defaultdict(list)
 *     for stream_feature in stream_layer:             # <<<<<<<<<<<<<<
 *         ds_x = int(stream_feature.GetField('ds_x'))
 *         ds_y = int(stream_feature.GetField('ds_y'))
*/
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3858
 *             stream_feature.GetFID())
 * 
 *     stream_layer.ResetReading()             # <<<<<<<<<<<<<<
 *     # construct visit order, this list will have a tuple of (fid, 0/1)
 *     # this stack will be used to build watersheds from upstream to downstream
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_ResetReading, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3858, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3861
 *     # construct visit order, this list will have a tuple of (fid, 0/1)
 *     # this stack will be used to build watersheds from upstream to downstream
 *     visit_order_stack = []             # <<<<<<<<<<<<<<
 *     # visit the highest order to lowest order in case there's a branching
 *     # junction of a order 1 and order 5 stream... visit order 5 upstream
*/
  __pyx_t_6 = PyList_New(0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3861, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_v_visit_order_stack = ((PyObject*)__pyx_t_6);
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3865
 *     # junction of a order 1 and order 5 stream... visit order 5 upstream
 *     # first
 *     stream_layer.SetAttributeFilter(f'"outlet"=1')             # <<<<<<<<<<<<<<
 *     # these are done last
 *     for _, outlet_fid in sorted([
*/
  __pyx_t_2 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_kp_u_outlet_1};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetAttributeFilter, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3865, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3867
 *     stream_layer.SetAttributeFilter(f'"outlet"=1')
 *     # these are done last
 *     for _, outlet_fid in sorted([             # <<<<<<<<<<<<<<
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],
 *             reverse=True):
*/
  __pyx_t_2 = NULL;
  { /* enter inner scope */
    __pyx_t_5 = PyList_New(0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3867, __pyx_L16_error)
    __Pyx_GOTREF(__pyx_t_5);

    /* "pygeoprocessing/routing/routing.pyx":3868
 *     # these are done last
 *     for _, outlet_fid in sorted([
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],             # <<<<<<<<<<<<<<
 *             reverse=True):
 *         working_stack = [outlet_fid]
*/
    if (likely(PyList_CheckExact(__pyx_v_stream_layer)) || PyTuple_CheckExact(__pyx_v_stream_layer)) {
      __pyx_t_1 = __pyx_v_stream_layer; __Pyx_INCREF(__pyx_t_1);
      __pyx_t_26 = 0;
      __pyx_t_27 = NULL;
    } else {
      __pyx_t_26 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_stream_layer); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3868, __pyx_L16_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_27 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_27)) __PYX_ERR(0, 3868, __pyx_L16_error)
    }
    for (;;) {
      if (likely(!__pyx_t_27)) {
        if (likely(PyList_CheckExact(__pyx_t_1))) {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3868, __pyx_L16_error)
            #endif
            if (__pyx_t_26 >= __pyx_temp) break;
          }
          __pyx_t_7 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_26, __Pyx_ReferenceSharing_OwnStrongReference);
          ++__pyx_t_26;
        } else {
          {
            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
            #if !CYTHON_ASSUME_SAFE_SIZE
            if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3868, __pyx_L16_error)
            #endif
            if (__pyx_t_26 >= __pyx_temp) break;
          }
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_7 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_26));
          #else
          __pyx_t_7 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_26);
          #endif
          ++__pyx_t_26;
        }
        if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3868, __pyx_L16_error)
      } else {
        __pyx_t_7 = __pyx_t_27(__pyx_t_1);
        if (unlikely(!__pyx_t_7)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3868, __pyx_L16_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_XDECREF_SET(__pyx_8genexpr2__pyx_v_x, __pyx_t_7);
      __pyx_t_7 = 0;
      __pyx_t_4 = __pyx_8genexpr2__pyx_v_x;
      __Pyx_INCREF(__pyx_t_4);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_order};
        __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3868, __pyx_L16_error)
        __Pyx_GOTREF(__pyx_t_7);
      }
      __pyx_t_3 = __pyx_8genexpr2__pyx_v_x;
      __Pyx_INCREF(__pyx_t_3);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_3, NULL};
        __pyx_t_4 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3868, __pyx_L16_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3868, __pyx_L16_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_GIVEREF(__pyx_t_7);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7) != (0)) __PYX_ERR(0, 3868, __pyx_L16_error);
      __Pyx_GIVEREF(__pyx_t_4);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_4) != (0)) __PYX_ERR(0, 3868, __pyx_L16_error);
      __pyx_t_7 = 0;
      __pyx_t_4 = 0;
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_5, (PyObject*)__pyx_t_3))) __PYX_ERR(0, 3867, __pyx_L16_error)
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    }
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_x); __pyx_8genexpr2__pyx_v_x = 0;
    goto __pyx_L20_exit_scope;
    __pyx_L16_error:;
    __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_x); __pyx_8genexpr2__pyx_v_x = 0;
    goto __pyx_L1_error;
    __pyx_L20_exit_scope:;
  } /* exit inner scope */

  /* "pygeoprocessing/routing/routing.pyx":3869
 *     for _, outlet_fid in sorted([
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],
 *             reverse=True):             # <<<<<<<<<<<<<<
 *         working_stack = [outlet_fid]
 *         processed_nodes = set()
*/
  __pyx_t_11 = 1;
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_2, __pyx_t_5};
    __pyx_t_1 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3867, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_reverse, Py_True, __pyx_t_1, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 3867, __pyx_L1_error)
    __pyx_t_6 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_builtin_sorted, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_1);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3867, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }

  /* "pygeoprocessing/routing/routing.pyx":3867
 *     stream_layer.SetAttributeFilter(f'"outlet"=1')
 *     # these are done last
 *     for _, outlet_fid in sorted([             # <<<<<<<<<<<<<<
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],
 *             reverse=True):
*/
  if (likely(PyList_CheckExact(__pyx_t_6)) || PyTuple_CheckExact(__pyx_t_6)) {
    __pyx_t_1 = __pyx_t_6; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_26 = 0;
    __pyx_t_27 = NULL;
  } else {
    __pyx_t_26 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3867, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_27 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_27)) __PYX_ERR(0, 3867, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  for (;;) {
    if (likely(!__pyx_t_27)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3867, __pyx_L1_error)
          #endif
          if (__pyx_t_26 >= __pyx_temp) break;
        }
        __pyx_t_6 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_26, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_26;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3867, __pyx_L1_error)
          #endif
          if (__pyx_t_26 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_6 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_26));
        #else
        __pyx_t_6 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_26);
        #endif
        ++__pyx_t_26;
      }
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3867, __pyx_L1_error)
    } else {
      __pyx_t_6 = __pyx_t_27(__pyx_t_1);
      if (unlikely(!__pyx_t_6)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3867, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_6);
    if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) {
      PyObject* sequence = __pyx_t_6;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 3867, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_5);
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_2);
      } else {
        __pyx_t_5 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3867, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_5);
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3867, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
      }
      #else
      __pyx_t_5 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3867, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3867, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      #endif
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_3 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3867, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3);
      index = 0; __pyx_t_5 = __pyx_t_16(__pyx_t_3); if (unlikely(!__pyx_t_5)) goto __pyx_L21_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_5);
      index = 1; __pyx_t_2 = __pyx_t_16(__pyx_t_3); if (unlikely(!__pyx_t_2)) goto __pyx_L21_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_3), 2) < (0)) __PYX_ERR(0, 3867, __pyx_L1_error)
      __pyx_t_16 = NULL;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      goto __pyx_L22_unpacking_done;
      __pyx_L21_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_16 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 3867, __pyx_L1_error)
      __pyx_L22_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v__, __pyx_t_5);
    __pyx_t_5 = 0;
    __Pyx_XDECREF_SET(__pyx_v_outlet_fid, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3870
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],
 *             reverse=True):
 *         working_stack = [outlet_fid]             # <<<<<<<<<<<<<<
 *         processed_nodes = set()
 *         while working_stack:
*/
    __pyx_t_6 = PyList_New(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3870, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_INCREF(__pyx_v_outlet_fid);
    __Pyx_GIVEREF(__pyx_v_outlet_fid);
    if (__Pyx_PyList_SET_ITEM(__pyx_t_6, 0, __pyx_v_outlet_fid) != (0)) __PYX_ERR(0, 3870, __pyx_L1_error);
    __Pyx_XDECREF_SET(__pyx_v_working_stack, ((PyObject*)__pyx_t_6));
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3871
 *             reverse=True):
 *         working_stack = [outlet_fid]
 *         processed_nodes = set()             # <<<<<<<<<<<<<<
 *         while working_stack:
 *             working_fid = working_stack[-1]
*/
    __pyx_t_6 = PySet_New(0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3871, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_XDECREF_SET(__pyx_v_processed_nodes, ((PyObject*)__pyx_t_6));
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3872
 *         working_stack = [outlet_fid]
 *         processed_nodes = set()
 *         while working_stack:             # <<<<<<<<<<<<<<
 *             working_fid = working_stack[-1]
 *             processed_nodes.add(working_fid)
*/
    while (1) {
      {
        Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_working_stack);
        if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3872, __pyx_L1_error)
        __pyx_t_25 = (__pyx_temp != 0);
      }

      if (!__pyx_t_25) break;

      /* "pygeoprocessing/routing/routing.pyx":3873
 *         processed_nodes = set()
 *         while working_stack:
 *             working_fid = working_stack[-1]             # <<<<<<<<<<<<<<
 *             processed_nodes.add(working_fid)
 *             working_feature = stream_layer.GetFeature(working_fid)
*/
      __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_working_stack, -1L, long, 1, __Pyx_PyLong_From_long, 1, 1, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3873, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_XDECREF_SET(__pyx_v_working_fid, __pyx_t_6);
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3874
 *         while working_stack:
 *             working_fid = working_stack[-1]
 *             processed_nodes.add(working_fid)             # <<<<<<<<<<<<<<
 *             working_feature = stream_layer.GetFeature(working_fid)
 * 
*/
      __pyx_t_28 = PySet_Add(__pyx_v_processed_nodes, __pyx_v_working_fid); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3874, __pyx_L1_error)

      /* "pygeoprocessing/routing/routing.pyx":3875
 *             working_fid = working_stack[-1]
 *             processed_nodes.add(working_fid)
 *             working_feature = stream_layer.GetFeature(working_fid)             # <<<<<<<<<<<<<<
 * 
 *             us_x = int(working_feature.GetField('us_x'))
*/
      __pyx_t_2 = __pyx_v_stream_layer;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_working_fid};
        __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFeature, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3875, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
      }
      __Pyx_XDECREF_SET(__pyx_v_working_feature, __pyx_t_6);
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3877
 *             working_feature = stream_layer.GetFeature(working_fid)
 * 
 *             us_x = int(working_feature.GetField('us_x'))             # <<<<<<<<<<<<<<
 *             us_y = int(working_feature.GetField('us_y'))
 *             ds_x_1 = int(working_feature.GetField('ds_x_1'))
*/
      __pyx_t_2 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_us_x};
        __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3877, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
      }
      __pyx_t_2 = __Pyx_PyNumber_Int(__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3877, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_XDECREF_SET(__pyx_v_us_x, ((PyObject*)__pyx_t_2));
      __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3878
 * 
 *             us_x = int(working_feature.GetField('us_x'))
 *             us_y = int(working_feature.GetField('us_y'))             # <<<<<<<<<<<<<<
 *             ds_x_1 = int(working_feature.GetField('ds_x_1'))
 *             ds_y_1 = int(working_feature.GetField('ds_y_1'))
*/
      __pyx_t_6 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_6);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_n_u_us_y};
        __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3878, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __pyx_t_6 = __Pyx_PyNumber_Int(__pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3878, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_XDECREF_SET(__pyx_v_us_y, ((PyObject*)__pyx_t_6));
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3879
 *             us_x = int(working_feature.GetField('us_x'))
 *             us_y = int(working_feature.GetField('us_y'))
 *             ds_x_1 = int(working_feature.GetField('ds_x_1'))             # <<<<<<<<<<<<<<
 *             ds_y_1 = int(working_feature.GetField('ds_y_1'))
 * 
*/
      __pyx_t_2 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ds_x_1};
        __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3879, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
      }
      __pyx_t_2 = __Pyx_PyNumber_Int(__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3879, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_XDECREF_SET(__pyx_v_ds_x_1, ((PyObject*)__pyx_t_2));
      __pyx_t_2 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3880
 *             us_y = int(working_feature.GetField('us_y'))
 *             ds_x_1 = int(working_feature.GetField('ds_x_1'))
 *             ds_y_1 = int(working_feature.GetField('ds_y_1'))             # <<<<<<<<<<<<<<
 * 
 *             upstream_coord = (us_x, us_y)
*/
      __pyx_t_6 = __pyx_v_working_feature;
      __Pyx_INCREF(__pyx_t_6);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ds_y_1};
        __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3880, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
      }
      __pyx_t_6 = __Pyx_PyNumber_Int(__pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3880, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_XDECREF_SET(__pyx_v_ds_y_1, ((PyObject*)__pyx_t_6));
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3882
 *             ds_y_1 = int(working_feature.GetField('ds_y_1'))
 * 
 *             upstream_coord = (us_x, us_y)             # <<<<<<<<<<<<<<
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]
*/
      __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3882, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __Pyx_INCREF(__pyx_v_us_x);
      __Pyx_GIVEREF(__pyx_v_us_x);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_v_us_x) != (0)) __PYX_ERR(0, 3882, __pyx_L1_error);
      __Pyx_INCREF(__pyx_v_us_y);
      __Pyx_GIVEREF(__pyx_v_us_y);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_v_us_y) != (0)) __PYX_ERR(0, 3882, __pyx_L1_error);
      __Pyx_XDECREF_SET(__pyx_v_upstream_coord, ((PyObject*)__pyx_t_6));
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3883
 * 
 *             upstream_coord = (us_x, us_y)
 *             upstream_fids = [             # <<<<<<<<<<<<<<
 *                 fid for fid in upstream_fid_map[upstream_coord]
 *                 if fid not in processed_nodes]
*/
      { /* enter inner scope */
        __pyx_t_6 = PyList_New(0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3883, __pyx_L27_error)
        __Pyx_GOTREF(__pyx_t_6);

        /* "pygeoprocessing/routing/routing.pyx":3884
 *             upstream_coord = (us_x, us_y)
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]             # <<<<<<<<<<<<<<
 *                 if fid not in processed_nodes]
 *             if upstream_fids:
*/
        __pyx_t_2 = __Pyx_PyObject_GetItem(__pyx_v_upstream_fid_map, __pyx_v_upstream_coord); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3884, __pyx_L27_error)
        __Pyx_GOTREF(__pyx_t_2);
        if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
          __pyx_t_5 = __pyx_t_2; __Pyx_INCREF(__pyx_t_5);
          __pyx_t_29 = 0;
          __pyx_t_30 = NULL;
        } else {
          __pyx_t_29 = -1; __pyx_t_5 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3884, __pyx_L27_error)
          __Pyx_GOTREF(__pyx_t_5);
          __pyx_t_30 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_5); if (unlikely(!__pyx_t_30)) __PYX_ERR(0, 3884, __pyx_L27_error)
        }
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        for (;;) {
          if (likely(!__pyx_t_30)) {
            if (likely(PyList_CheckExact(__pyx_t_5))) {
              {
                Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_5);
                #if !CYTHON_ASSUME_SAFE_SIZE
                if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3884, __pyx_L27_error)
                #endif
                if (__pyx_t_29 >= __pyx_temp) break;
              }
              __pyx_t_2 = __Pyx_PyList_GetItemRefFast(__pyx_t_5, __pyx_t_29, __Pyx_ReferenceSharing_OwnStrongReference);
              ++__pyx_t_29;
            } else {
              {
                Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_5);
                #if !CYTHON_ASSUME_SAFE_SIZE
                if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3884, __pyx_L27_error)
                #endif
                if (__pyx_t_29 >= __pyx_temp) break;
              }
              #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
              __pyx_t_2 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_5, __pyx_t_29));
              #else
              __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_5, __pyx_t_29);
              #endif
              ++__pyx_t_29;
            }
            if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3884, __pyx_L27_error)
          } else {
            __pyx_t_2 = __pyx_t_30(__pyx_t_5);
            if (unlikely(!__pyx_t_2)) {
              PyObject* exc_type = PyErr_Occurred();
              if (exc_type) {
                if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 3884, __pyx_L27_error)
                PyErr_Clear();
              }
              break;
            }
          }
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_XDECREF_SET(__pyx_8genexpr3__pyx_v_fid, __pyx_t_2);
          __pyx_t_2 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3885
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]
 *                 if fid not in processed_nodes]             # <<<<<<<<<<<<<<
 *             if upstream_fids:
 *                 working_stack.extend(upstream_fids)
*/
          __pyx_t_25 = (__Pyx_PySet_ContainsTF(__pyx_8genexpr3__pyx_v_fid, __pyx_v_processed_nodes, Py_NE)); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3885, __pyx_L27_error)
          if (__pyx_t_25) {

            /* "pygeoprocessing/routing/routing.pyx":3884
 *             upstream_coord = (us_x, us_y)
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]             # <<<<<<<<<<<<<<
 *                 if fid not in processed_nodes]
 *             if upstream_fids:
*/
            if (unlikely(__Pyx_ListComp_Append(__pyx_t_6, (PyObject*)__pyx_8genexpr3__pyx_v_fid))) __PYX_ERR(0, 3883, __pyx_L27_error)

            /* "pygeoprocessing/routing/routing.pyx":3885
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]
 *                 if fid not in processed_nodes]             # <<<<<<<<<<<<<<
 *             if upstream_fids:
 *                 working_stack.extend(upstream_fids)
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":3884
 *             upstream_coord = (us_x, us_y)
 *             upstream_fids = [
 *                 fid for fid in upstream_fid_map[upstream_coord]             # <<<<<<<<<<<<<<
 *                 if fid not in processed_nodes]
 *             if upstream_fids:
*/
        }
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        __Pyx_XDECREF(__pyx_8genexpr3__pyx_v_fid); __pyx_8genexpr3__pyx_v_fid = 0;
        goto __pyx_L32_exit_scope;
        __pyx_L27_error:;
        __Pyx_XDECREF(__pyx_8genexpr3__pyx_v_fid); __pyx_8genexpr3__pyx_v_fid = 0;
        goto __pyx_L1_error;
        __pyx_L32_exit_scope:;
      } /* exit inner scope */
      __Pyx_XDECREF_SET(__pyx_v_upstream_fids, ((PyObject*)__pyx_t_6));
      __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3886
 *                 fid for fid in upstream_fid_map[upstream_coord]
 *                 if fid not in processed_nodes]
 *             if upstream_fids:             # <<<<<<<<<<<<<<
 *                 working_stack.extend(upstream_fids)
 *             else:
*/
      {
        Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_v_upstream_fids);
        if (unlikely(((!CYTHON_ASSUME_SAFE_SIZE) && __pyx_temp < 0))) __PYX_ERR(0, 3886, __pyx_L1_error)
        __pyx_t_25 = (__pyx_temp != 0);
      }

      if (__pyx_t_25) {

        /* "pygeoprocessing/routing/routing.pyx":3887
 *                 if fid not in processed_nodes]
 *             if upstream_fids:
 *                 working_stack.extend(upstream_fids)             # <<<<<<<<<<<<<<
 *             else:
 *                 working_stack.pop()
*/
        __pyx_t_28 = __Pyx_PyList_Extend(__pyx_v_working_stack, __pyx_v_upstream_fids); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3887, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":3886
 *                 fid for fid in upstream_fid_map[upstream_coord]
 *                 if fid not in processed_nodes]
 *             if upstream_fids:             # <<<<<<<<<<<<<<
 *                 working_stack.extend(upstream_fids)
 *             else:
*/
        goto __pyx_L33;
      }

      /* "pygeoprocessing/routing/routing.pyx":3889
 *                 working_stack.extend(upstream_fids)
 *             else:
 *                 working_stack.pop()             # <<<<<<<<<<<<<<
 *                 # the `not outlet_at_confluence` bit allows us to seed
 *                 # even if the order is 1, otherwise confluences fill
*/
      /*else*/ {
        __pyx_t_6 = __Pyx_PyList_Pop(__pyx_v_working_stack); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3889, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3893
 *                 # even if the order is 1, otherwise confluences fill
 *                 # the order 1 streams
 *                 if (working_feature.GetField('order') > 1 or             # <<<<<<<<<<<<<<
 *                         not outlet_at_confluence):
 *                     if outlet_at_confluence:
*/
        __pyx_t_5 = __pyx_v_working_feature;
        __Pyx_INCREF(__pyx_t_5);
        __pyx_t_11 = 0;
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_order};
          __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
          if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3893, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_6);
        }
        __pyx_t_5 = PyObject_RichCompare(__pyx_t_6, __pyx_mstate_global->__pyx_int_1, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3893, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __pyx_t_31 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely((__pyx_t_31 < 0))) __PYX_ERR(0, 3893, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        if (!__pyx_t_31) {
        } else {
          __pyx_t_25 = __pyx_t_31;
          goto __pyx_L35_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":3894
 *                 # the order 1 streams
 *                 if (working_feature.GetField('order') > 1 or
 *                         not outlet_at_confluence):             # <<<<<<<<<<<<<<
 *                     if outlet_at_confluence:
 *                         # seed the upstream point
*/
        __pyx_t_31 = __Pyx_PyObject_IsTrue(__pyx_v_outlet_at_confluence); if (unlikely((__pyx_t_31 < 0))) __PYX_ERR(0, 3894, __pyx_L1_error)
        __pyx_t_32 = (!__pyx_t_31);
        __pyx_t_25 = __pyx_t_32;
        __pyx_L35_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":3893
 *                 # even if the order is 1, otherwise confluences fill
 *                 # the order 1 streams
 *                 if (working_feature.GetField('order') > 1 or             # <<<<<<<<<<<<<<
 *                         not outlet_at_confluence):
 *                     if outlet_at_confluence:
*/
        if (__pyx_t_25) {

          /* "pygeoprocessing/routing/routing.pyx":3895
 *                 if (working_feature.GetField('order') > 1 or
 *                         not outlet_at_confluence):
 *                     if outlet_at_confluence:             # <<<<<<<<<<<<<<
 *                         # seed the upstream point
 *                         visit_order_stack.append((working_fid, us_x, us_y))
*/
          __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_v_outlet_at_confluence); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3895, __pyx_L1_error)
          if (__pyx_t_25) {

            /* "pygeoprocessing/routing/routing.pyx":3897
 *                     if outlet_at_confluence:
 *                         # seed the upstream point
 *                         visit_order_stack.append((working_fid, us_x, us_y))             # <<<<<<<<<<<<<<
 *                     else:
 *                         # seed the downstream but +1 step point
*/
            __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3897, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_5);
            __Pyx_INCREF(__pyx_v_working_fid);
            __Pyx_GIVEREF(__pyx_v_working_fid);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_working_fid) != (0)) __PYX_ERR(0, 3897, __pyx_L1_error);
            __Pyx_INCREF(__pyx_v_us_x);
            __Pyx_GIVEREF(__pyx_v_us_x);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_v_us_x) != (0)) __PYX_ERR(0, 3897, __pyx_L1_error);
            __Pyx_INCREF(__pyx_v_us_y);
            __Pyx_GIVEREF(__pyx_v_us_y);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_us_y) != (0)) __PYX_ERR(0, 3897, __pyx_L1_error);
            __pyx_t_28 = __Pyx_PyList_Append(__pyx_v_visit_order_stack, __pyx_t_5); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3897, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3895
 *                 if (working_feature.GetField('order') > 1 or
 *                         not outlet_at_confluence):
 *                     if outlet_at_confluence:             # <<<<<<<<<<<<<<
 *                         # seed the upstream point
 *                         visit_order_stack.append((working_fid, us_x, us_y))
*/
            goto __pyx_L37;
          }

          /* "pygeoprocessing/routing/routing.pyx":3900
 *                     else:
 *                         # seed the downstream but +1 step point
 *                         visit_order_stack.append(             # <<<<<<<<<<<<<<
 *                             (working_fid, ds_x_1, ds_y_1))
 *                 if working_feature.GetField('outlet') == 1:
*/
          /*else*/ {

            /* "pygeoprocessing/routing/routing.pyx":3901
 *                         # seed the downstream but +1 step point
 *                         visit_order_stack.append(
 *                             (working_fid, ds_x_1, ds_y_1))             # <<<<<<<<<<<<<<
 *                 if working_feature.GetField('outlet') == 1:
 *                     # an outlet is a special case where the outlet itself
*/
            __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3901, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_5);
            __Pyx_INCREF(__pyx_v_working_fid);
            __Pyx_GIVEREF(__pyx_v_working_fid);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_working_fid) != (0)) __PYX_ERR(0, 3901, __pyx_L1_error);
            __Pyx_INCREF(__pyx_v_ds_x_1);
            __Pyx_GIVEREF(__pyx_v_ds_x_1);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_v_ds_x_1) != (0)) __PYX_ERR(0, 3901, __pyx_L1_error);
            __Pyx_INCREF(__pyx_v_ds_y_1);
            __Pyx_GIVEREF(__pyx_v_ds_y_1);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_ds_y_1) != (0)) __PYX_ERR(0, 3901, __pyx_L1_error);

            /* "pygeoprocessing/routing/routing.pyx":3900
 *                     else:
 *                         # seed the downstream but +1 step point
 *                         visit_order_stack.append(             # <<<<<<<<<<<<<<
 *                             (working_fid, ds_x_1, ds_y_1))
 *                 if working_feature.GetField('outlet') == 1:
*/
            __pyx_t_28 = __Pyx_PyList_Append(__pyx_v_visit_order_stack, __pyx_t_5); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3900, __pyx_L1_error)
            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          }
          __pyx_L37:;

          /* "pygeoprocessing/routing/routing.pyx":3893
 *                 # even if the order is 1, otherwise confluences fill
 *                 # the order 1 streams
 *                 if (working_feature.GetField('order') > 1 or             # <<<<<<<<<<<<<<
 *                         not outlet_at_confluence):
 *                     if outlet_at_confluence:
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":3902
 *                         visit_order_stack.append(
 *                             (working_fid, ds_x_1, ds_y_1))
 *                 if working_feature.GetField('outlet') == 1:             # <<<<<<<<<<<<<<
 *                     # an outlet is a special case where the outlet itself
 *                     # should be a subwatershed done last.
*/
        __pyx_t_6 = __pyx_v_working_feature;
        __Pyx_INCREF(__pyx_t_6);
        __pyx_t_11 = 0;
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_n_u_outlet};
          __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3902, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
        }
        __pyx_t_25 = (__Pyx_PyLong_BoolEqObjC(__pyx_t_5, __pyx_mstate_global->__pyx_int_1, 1, 0)); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3902, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        if (__pyx_t_25) {

          /* "pygeoprocessing/routing/routing.pyx":3905
 *                     # an outlet is a special case where the outlet itself
 *                     # should be a subwatershed done last.
 *                     ds_x = int(working_feature.GetField('ds_x'))             # <<<<<<<<<<<<<<
 *                     ds_y = int(working_feature.GetField('ds_y'))
 *                     if not outlet_at_confluence:
*/
          __pyx_t_6 = __pyx_v_working_feature;
          __Pyx_INCREF(__pyx_t_6);
          __pyx_t_11 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ds_x};
            __pyx_t_5 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
            if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3905, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_5);
          }
          __pyx_t_6 = __Pyx_PyNumber_Int(__pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3905, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_6);
          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          __Pyx_XDECREF_SET(__pyx_v_ds_x, ((PyObject*)__pyx_t_6));
          __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3906
 *                     # should be a subwatershed done last.
 *                     ds_x = int(working_feature.GetField('ds_x'))
 *                     ds_y = int(working_feature.GetField('ds_y'))             # <<<<<<<<<<<<<<
 *                     if not outlet_at_confluence:
 *                         # undo the previous visit because it will be at
*/
          __pyx_t_5 = __pyx_v_working_feature;
          __Pyx_INCREF(__pyx_t_5);
          __pyx_t_11 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_mstate_global->__pyx_n_u_ds_y};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetField, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3906, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __pyx_t_5 = __Pyx_PyNumber_Int(__pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3906, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_XDECREF_SET(__pyx_v_ds_y, ((PyObject*)__pyx_t_5));
          __pyx_t_5 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3907
 *                     ds_x = int(working_feature.GetField('ds_x'))
 *                     ds_y = int(working_feature.GetField('ds_y'))
 *                     if not outlet_at_confluence:             # <<<<<<<<<<<<<<
 *                         # undo the previous visit because it will be at
 *                         # one pixel up and we want the pixel right at
*/
          __pyx_t_25 = __Pyx_PyObject_IsTrue(__pyx_v_outlet_at_confluence); if (unlikely((__pyx_t_25 < 0))) __PYX_ERR(0, 3907, __pyx_L1_error)
          __pyx_t_32 = (!__pyx_t_25);
          if (__pyx_t_32) {

            /* "pygeoprocessing/routing/routing.pyx":3911
 *                         # one pixel up and we want the pixel right at
 *                         # the outlet
 *                         visit_order_stack.pop()             # <<<<<<<<<<<<<<
 *                     visit_order_stack.append((working_fid, ds_x, ds_y))
 * 
*/
            __pyx_t_5 = __Pyx_PyList_Pop(__pyx_v_visit_order_stack); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3911, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_5);
            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

            /* "pygeoprocessing/routing/routing.pyx":3907
 *                     ds_x = int(working_feature.GetField('ds_x'))
 *                     ds_y = int(working_feature.GetField('ds_y'))
 *                     if not outlet_at_confluence:             # <<<<<<<<<<<<<<
 *                         # undo the previous visit because it will be at
 *                         # one pixel up and we want the pixel right at
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":3912
 *                         # the outlet
 *                         visit_order_stack.pop()
 *                     visit_order_stack.append((working_fid, ds_x, ds_y))             # <<<<<<<<<<<<<<
 * 
 *     cdef int edge_side, edge_dir, cell_to_test, out_dir_increase=-1
*/
          __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3912, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_5);
          __Pyx_INCREF(__pyx_v_working_fid);
          __Pyx_GIVEREF(__pyx_v_working_fid);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_working_fid) != (0)) __PYX_ERR(0, 3912, __pyx_L1_error);
          __Pyx_INCREF(__pyx_v_ds_x);
          __Pyx_GIVEREF(__pyx_v_ds_x);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_v_ds_x) != (0)) __PYX_ERR(0, 3912, __pyx_L1_error);
          __Pyx_INCREF(__pyx_v_ds_y);
          __Pyx_GIVEREF(__pyx_v_ds_y);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_ds_y) != (0)) __PYX_ERR(0, 3912, __pyx_L1_error);
          __pyx_t_28 = __Pyx_PyList_Append(__pyx_v_visit_order_stack, __pyx_t_5); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3912, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

          /* "pygeoprocessing/routing/routing.pyx":3902
 *                         visit_order_stack.append(
 *                             (working_fid, ds_x_1, ds_y_1))
 *                 if working_feature.GetField('outlet') == 1:             # <<<<<<<<<<<<<<
 *                     # an outlet is a special case where the outlet itself
 *                     # should be a subwatershed done last.
*/
        }
      }
      __pyx_L33:;
    }

    /* "pygeoprocessing/routing/routing.pyx":3867
 *     stream_layer.SetAttributeFilter(f'"outlet"=1')
 *     # these are done last
 *     for _, outlet_fid in sorted([             # <<<<<<<<<<<<<<
 *             (x.GetField('order'), x.GetFID()) for x in stream_layer],
 *             reverse=True):
*/
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3914
 *                     visit_order_stack.append((working_fid, ds_x, ds_y))
 * 
 *     cdef int edge_side, edge_dir, cell_to_test, out_dir_increase=-1             # <<<<<<<<<<<<<<
 *     cdef int left, right, n_steps, terminated_early
 *     cdef int delta_x, delta_y
*/
  __pyx_v_out_dir_increase = -1;

  /* "pygeoprocessing/routing/routing.pyx":3917
 *     cdef int left, right, n_steps, terminated_early
 *     cdef int delta_x, delta_y
 *     cdef int _int_max_steps_per_watershed = max_steps_per_watershed             # <<<<<<<<<<<<<<
 * 
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):
*/
  __pyx_t_14 = __Pyx_PyLong_As_int(__pyx_v_max_steps_per_watershed); if (unlikely((__pyx_t_14 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3917, __pyx_L1_error)
  __pyx_v__int_max_steps_per_watershed = __pyx_t_14;

  /* "pygeoprocessing/routing/routing.pyx":3919
 *     cdef int _int_max_steps_per_watershed = max_steps_per_watershed
 * 
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):             # <<<<<<<<<<<<<<
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
*/
  __Pyx_INCREF(__pyx_mstate_global->__pyx_int_0);
  __pyx_t_1 = __pyx_mstate_global->__pyx_int_0;
  __pyx_t_5 = __pyx_v_visit_order_stack; __Pyx_INCREF(__pyx_t_5);
  __pyx_t_26 = 0;
  for (;;) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_5);
      #if !CYTHON_ASSUME_SAFE_SIZE
      if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 3919, __pyx_L1_error)
      #endif
      if (__pyx_t_26 >= __pyx_temp) break;
    }
    __pyx_t_6 = __Pyx_PyList_GetItemRefFast(__pyx_t_5, __pyx_t_26, __Pyx_ReferenceSharing_OwnStrongReference);
    ++__pyx_t_26;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3919, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) {
      PyObject* sequence = __pyx_t_6;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 3)) {
        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 3919, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_2);
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_3);
        __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2);
        __Pyx_INCREF(__pyx_t_4);
      } else {
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3919, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3919, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
        __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 2, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3919, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_4);
      }
      #else
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3919, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3919, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3919, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      #endif
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_7 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3919, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
      index = 0; __pyx_t_2 = __pyx_t_16(__pyx_t_7); if (unlikely(!__pyx_t_2)) goto __pyx_L43_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      index = 1; __pyx_t_3 = __pyx_t_16(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L43_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_3);
      index = 2; __pyx_t_4 = __pyx_t_16(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L43_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_4);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_7), 3) < (0)) __PYX_ERR(0, 3919, __pyx_L1_error)
      __pyx_t_16 = NULL;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      goto __pyx_L44_unpacking_done;
      __pyx_L43_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_16 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 3919, __pyx_L1_error)
      __pyx_L44_unpacking_done:;
    }
    __pyx_t_18 = __Pyx_PyLong_As_unsigned_int(__pyx_t_3); if (unlikely((__pyx_t_18 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3919, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_17 = __Pyx_PyLong_As_unsigned_int(__pyx_t_4); if (unlikely((__pyx_t_17 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3919, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_XDECREF_SET(__pyx_v_stream_fid, __pyx_t_2);
    __pyx_t_2 = 0;
    __pyx_v_x_l = __pyx_t_18;
    __pyx_v_y_l = __pyx_t_17;
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_index, __pyx_t_1);
    __pyx_t_6 = __Pyx_PyLong_AddObjC(__pyx_t_1, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3919, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_DECREF(__pyx_t_1);
    __pyx_t_1 = __pyx_t_6;
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3920
 * 
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 f'(calculate_subwatershed_boundary): watershed building '
*/
    __pyx_t_32 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_32) {

      /* "pygeoprocessing/routing/routing.pyx":3921
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 f'(calculate_subwatershed_boundary): watershed building '
 *                 f'{(index/len(visit_order_stack))*100:.1f}% complete')
*/
      __pyx_t_4 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3921, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3921, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3923
 *             LOGGER.info(
 *                 f'(calculate_subwatershed_boundary): watershed building '
 *                 f'{(index/len(visit_order_stack))*100:.1f}% complete')             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)
*/
      __pyx_t_29 = __Pyx_PyList_GET_SIZE(__pyx_v_visit_order_stack); if (unlikely(__pyx_t_29 == ((Py_ssize_t)-1))) __PYX_ERR(0, 3923, __pyx_L1_error)
      __pyx_t_3 = PyLong_FromSsize_t(__pyx_t_29); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3923, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_7 = __Pyx_PyNumber_Divide(__pyx_v_index, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3923, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_3 = __Pyx_PyLong_MultiplyObjC(__pyx_t_7, __pyx_mstate_global->__pyx_int_100, 0x64, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3923, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_7 = __Pyx_PyObject_Format(__pyx_t_3, __pyx_mstate_global->__pyx_kp_u_1f); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3923, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_33[0] = __pyx_mstate_global->__pyx_kp_u_calculate_subwatershed_boundary_2;
      __pyx_t_33[1] = __pyx_t_7;
      __pyx_t_33[2] = __pyx_mstate_global->__pyx_kp_u_complete;

      /* "pygeoprocessing/routing/routing.pyx":3922
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
 *                 f'(calculate_subwatershed_boundary): watershed building '             # <<<<<<<<<<<<<<
 *                 f'{(index/len(visit_order_stack))*100:.1f}% complete')
 *             last_log_time = ctime(NULL)
*/
      __pyx_t_3 = __Pyx_PyUnicode_Join(__pyx_t_33, 3, 54 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7) + 10, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7));
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3922, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_11 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
        assert(__pyx_t_4);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_4);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
        __pyx_t_11 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
        __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3921, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
      }
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3924
 *                 f'(calculate_subwatershed_boundary): watershed building '
 *                 f'{(index/len(visit_order_stack))*100:.1f}% complete')
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)
 *         if discovery == -1:
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":3920
 * 
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 f'(calculate_subwatershed_boundary): watershed building '
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3925
 *                 f'{(index/len(visit_order_stack))*100:.1f}% complete')
 *             last_log_time = ctime(NULL)
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)             # <<<<<<<<<<<<<<
 *         if discovery == -1:
 *             continue
*/
    __pyx_v_discovery = ((long)__pyx_v_discovery_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

    /* "pygeoprocessing/routing/routing.pyx":3926
 *             last_log_time = ctime(NULL)
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)
 *         if discovery == -1:             # <<<<<<<<<<<<<<
 *             continue
 *         boundary_list = [(x_l, y_l)]
*/
    __pyx_t_32 = (__pyx_v_discovery == -1L);
    if (__pyx_t_32) {

      /* "pygeoprocessing/routing/routing.pyx":3927
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)
 *         if discovery == -1:
 *             continue             # <<<<<<<<<<<<<<
 *         boundary_list = [(x_l, y_l)]
 *         finish = <long>finish_managed_raster.get(x_l, y_l)
*/
      goto __pyx_L41_continue;

      /* "pygeoprocessing/routing/routing.pyx":3926
 *             last_log_time = ctime(NULL)
 *         discovery = <long>discovery_managed_raster.get(x_l, y_l)
 *         if discovery == -1:             # <<<<<<<<<<<<<<
 *             continue
 *         boundary_list = [(x_l, y_l)]
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3928
 *         if discovery == -1:
 *             continue
 *         boundary_list = [(x_l, y_l)]             # <<<<<<<<<<<<<<
 *         finish = <long>finish_managed_raster.get(x_l, y_l)
 *         outlet_x = x_l
*/
    __pyx_t_6 = __Pyx_PyLong_From_unsigned_int(__pyx_v_x_l); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3928, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_2 = __Pyx_PyLong_From_unsigned_int(__pyx_v_y_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3928, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3928, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_GIVEREF(__pyx_t_6);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_6) != (0)) __PYX_ERR(0, 3928, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_2);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 3928, __pyx_L1_error);
    __pyx_t_6 = 0;
    __pyx_t_2 = 0;
    __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3928, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_GIVEREF(__pyx_t_3);
    if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 3928, __pyx_L1_error);
    __pyx_t_3 = 0;
    __Pyx_XDECREF_SET(__pyx_v_boundary_list, ((PyObject*)__pyx_t_2));
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3929
 *             continue
 *         boundary_list = [(x_l, y_l)]
 *         finish = <long>finish_managed_raster.get(x_l, y_l)             # <<<<<<<<<<<<<<
 *         outlet_x = x_l
 *         outlet_y = y_l
*/
    __pyx_v_finish = ((long)__pyx_v_finish_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

    /* "pygeoprocessing/routing/routing.pyx":3930
 *         boundary_list = [(x_l, y_l)]
 *         finish = <long>finish_managed_raster.get(x_l, y_l)
 *         outlet_x = x_l             # <<<<<<<<<<<<<<
 *         outlet_y = y_l
 * 
*/
    __pyx_v_outlet_x = __pyx_v_x_l;

    /* "pygeoprocessing/routing/routing.pyx":3931
 *         finish = <long>finish_managed_raster.get(x_l, y_l)
 *         outlet_x = x_l
 *         outlet_y = y_l             # <<<<<<<<<<<<<<
 * 
 *         watershed_boundary = ogr.Geometry(ogr.wkbLinearRing)
*/
    __pyx_v_outlet_y = __pyx_v_y_l;

    /* "pygeoprocessing/routing/routing.pyx":3933
 *         outlet_y = y_l
 * 
 *         watershed_boundary = ogr.Geometry(ogr.wkbLinearRing)             # <<<<<<<<<<<<<<
 *         outflow_dir = <int>d8_flow_dir_managed_raster.get(x_l, y_l)
 * 
*/
    __pyx_t_3 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3933, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_Geometry); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 3933, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3933, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_wkbLinearRing); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3933, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_4))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_4);
      assert(__pyx_t_3);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_7};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3933, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_watershed_boundary, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3934
 * 
 *         watershed_boundary = ogr.Geometry(ogr.wkbLinearRing)
 *         outflow_dir = <int>d8_flow_dir_managed_raster.get(x_l, y_l)             # <<<<<<<<<<<<<<
 * 
 *         # this is the center point of the pixel that will be offset to
*/
    __pyx_v_outflow_dir = ((int)__pyx_v_d8_flow_dir_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l));

    /* "pygeoprocessing/routing/routing.pyx":3938
 *         # this is the center point of the pixel that will be offset to
 *         # make the edge
 *         x_f = x_l+0.5             # <<<<<<<<<<<<<<
 *         y_f = y_l+0.5
 * 
*/
    __pyx_v_x_f = (__pyx_v_x_l + 0.5);

    /* "pygeoprocessing/routing/routing.pyx":3939
 *         # make the edge
 *         x_f = x_l+0.5
 *         y_f = y_l+0.5             # <<<<<<<<<<<<<<
 * 
 *         x_f += COL_OFFSETS[outflow_dir]*0.5
*/
    __pyx_v_y_f = (__pyx_v_y_l + 0.5);

    /* "pygeoprocessing/routing/routing.pyx":3941
 *         y_f = y_l+0.5
 * 
 *         x_f += COL_OFFSETS[outflow_dir]*0.5             # <<<<<<<<<<<<<<
 *         y_f += ROW_OFFSETS[outflow_dir]*0.5
 *         if outflow_dir % 2 == 0:
*/
    __pyx_v_x_f = (__pyx_v_x_f + ((COL_OFFSETS[__pyx_v_outflow_dir]) * 0.5));

    /* "pygeoprocessing/routing/routing.pyx":3942
 * 
 *         x_f += COL_OFFSETS[outflow_dir]*0.5
 *         y_f += ROW_OFFSETS[outflow_dir]*0.5             # <<<<<<<<<<<<<<
 *         if outflow_dir % 2 == 0:
 *             # need to back up the point a bit
*/
    __pyx_v_y_f = (__pyx_v_y_f + ((ROW_OFFSETS[__pyx_v_outflow_dir]) * 0.5));

    /* "pygeoprocessing/routing/routing.pyx":3943
 *         x_f += COL_OFFSETS[outflow_dir]*0.5
 *         y_f += ROW_OFFSETS[outflow_dir]*0.5
 *         if outflow_dir % 2 == 0:             # <<<<<<<<<<<<<<
 *             # need to back up the point a bit
 *             x_f -= ROW_OFFSETS[outflow_dir]*0.5
*/
    __pyx_t_32 = (__Pyx_mod_long(__pyx_v_outflow_dir, 2, 1) == 0);
    if (__pyx_t_32) {

      /* "pygeoprocessing/routing/routing.pyx":3945
 *         if outflow_dir % 2 == 0:
 *             # need to back up the point a bit
 *             x_f -= ROW_OFFSETS[outflow_dir]*0.5             # <<<<<<<<<<<<<<
 *             y_f += COL_OFFSETS[outflow_dir]*0.5
 * 
*/
      __pyx_v_x_f = (__pyx_v_x_f - ((ROW_OFFSETS[__pyx_v_outflow_dir]) * 0.5));

      /* "pygeoprocessing/routing/routing.pyx":3946
 *             # need to back up the point a bit
 *             x_f -= ROW_OFFSETS[outflow_dir]*0.5
 *             y_f += COL_OFFSETS[outflow_dir]*0.5             # <<<<<<<<<<<<<<
 * 
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_f, y_f)
*/
      __pyx_v_y_f = (__pyx_v_y_f + ((COL_OFFSETS[__pyx_v_outflow_dir]) * 0.5));

      /* "pygeoprocessing/routing/routing.pyx":3943
 *         x_f += COL_OFFSETS[outflow_dir]*0.5
 *         y_f += ROW_OFFSETS[outflow_dir]*0.5
 *         if outflow_dir % 2 == 0:             # <<<<<<<<<<<<<<
 *             # need to back up the point a bit
 *             x_f -= ROW_OFFSETS[outflow_dir]*0.5
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":3948
 *             y_f += COL_OFFSETS[outflow_dir]*0.5
 * 
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_f, y_f)             # <<<<<<<<<<<<<<
 *         watershed_boundary.AddPoint(x_p, y_p)
 * 
*/
    __pyx_t_4 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_ApplyGeoTransform); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_7 = PyFloat_FromDouble(__pyx_v_x_f); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_6 = PyFloat_FromDouble(__pyx_v_y_f); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
      assert(__pyx_t_4);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[4] = {__pyx_t_4, __pyx_v_geotransform, __pyx_t_7, __pyx_t_6};
      __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_11, (4-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3948, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
      PyObject* sequence = __pyx_t_2;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 3948, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_3);
        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_6);
      } else {
        __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3948, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_3);
        __pyx_t_6 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3948, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_6);
      }
      #else
      __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3948, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_6 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3948, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      #endif
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_7 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3948, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
      index = 0; __pyx_t_3 = __pyx_t_16(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L48_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_3);
      index = 1; __pyx_t_6 = __pyx_t_16(__pyx_t_7); if (unlikely(!__pyx_t_6)) goto __pyx_L48_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_6);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_7), 2) < (0)) __PYX_ERR(0, 3948, __pyx_L1_error)
      __pyx_t_16 = NULL;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      goto __pyx_L49_unpacking_done;
      __pyx_L48_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_16 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 3948, __pyx_L1_error)
      __pyx_L49_unpacking_done:;
    }
    __pyx_t_24 = __Pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_24 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_23 = __Pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_23 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 3948, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_x_p = __pyx_t_24;
    __pyx_v_y_p = __pyx_t_23;

    /* "pygeoprocessing/routing/routing.pyx":3949
 * 
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_f, y_f)
 *         watershed_boundary.AddPoint(x_p, y_p)             # <<<<<<<<<<<<<<
 * 
 *         # keep track of how many steps x/y and when we get back to 0 we've
*/
    __pyx_t_6 = __pyx_v_watershed_boundary;
    __Pyx_INCREF(__pyx_t_6);
    __pyx_t_3 = PyFloat_FromDouble(__pyx_v_x_p); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3949, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_7 = PyFloat_FromDouble(__pyx_v_y_p); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3949, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_6, __pyx_t_3, __pyx_t_7};
      __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddPoint, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3949, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3953
 *         # keep track of how many steps x/y and when we get back to 0 we've
 *         # made a loop
 *         delta_x, delta_y = 0, 0             # <<<<<<<<<<<<<<
 * 
 *         # determine the first edge
*/
    __pyx_t_14 = 0;
    __pyx_t_34 = 0;
    __pyx_v_delta_x = __pyx_t_14;
    __pyx_v_delta_y = __pyx_t_34;

    /* "pygeoprocessing/routing/routing.pyx":3956
 * 
 *         # determine the first edge
 *         if outflow_dir % 2 == 0:             # <<<<<<<<<<<<<<
 *             # outflow through a straight side, so trivial edge detection
 *             edge_side = outflow_dir
*/
    __pyx_t_32 = (__Pyx_mod_long(__pyx_v_outflow_dir, 2, 1) == 0);
    if (__pyx_t_32) {

      /* "pygeoprocessing/routing/routing.pyx":3958
 *         if outflow_dir % 2 == 0:
 *             # outflow through a straight side, so trivial edge detection
 *             edge_side = outflow_dir             # <<<<<<<<<<<<<<
 *             edge_dir = (2+edge_side) % 8
 *         else:
*/
      __pyx_v_edge_side = __pyx_v_outflow_dir;

      /* "pygeoprocessing/routing/routing.pyx":3959
 *             # outflow through a straight side, so trivial edge detection
 *             edge_side = outflow_dir
 *             edge_dir = (2+edge_side) % 8             # <<<<<<<<<<<<<<
 *         else:
 *             # diagonal outflow requires testing neighboring cells to
*/
      __pyx_v_edge_dir = __Pyx_mod_long((2 + __pyx_v_edge_side), 8, 1);

      /* "pygeoprocessing/routing/routing.pyx":3956
 * 
 *         # determine the first edge
 *         if outflow_dir % 2 == 0:             # <<<<<<<<<<<<<<
 *             # outflow through a straight side, so trivial edge detection
 *             edge_side = outflow_dir
*/
      goto __pyx_L50;
    }

    /* "pygeoprocessing/routing/routing.pyx":3963
 *             # diagonal outflow requires testing neighboring cells to
 *             # determine first edge
 *             cell_to_test = (outflow_dir+1) % 8             # <<<<<<<<<<<<<<
 *             edge_side = cell_to_test
 *             edge_dir = (cell_to_test+2) % 8
*/
    /*else*/ {
      __pyx_v_cell_to_test = __Pyx_mod_long((__pyx_v_outflow_dir + 1), 8, 1);

      /* "pygeoprocessing/routing/routing.pyx":3964
 *             # determine first edge
 *             cell_to_test = (outflow_dir+1) % 8
 *             edge_side = cell_to_test             # <<<<<<<<<<<<<<
 *             edge_dir = (cell_to_test+2) % 8
 *             if _in_watershed(
*/
      __pyx_v_edge_side = __pyx_v_cell_to_test;

      /* "pygeoprocessing/routing/routing.pyx":3965
 *             cell_to_test = (outflow_dir+1) % 8
 *             edge_side = cell_to_test
 *             edge_dir = (cell_to_test+2) % 8             # <<<<<<<<<<<<<<
 *             if _in_watershed(
 *                     x_l, y_l, cell_to_test, discovery, finish,
*/
      __pyx_v_edge_dir = __Pyx_mod_long((__pyx_v_cell_to_test + 2), 8, 1);

      /* "pygeoprocessing/routing/routing.pyx":3966
 *             edge_side = cell_to_test
 *             edge_dir = (cell_to_test+2) % 8
 *             if _in_watershed(             # <<<<<<<<<<<<<<
 *                     x_l, y_l, cell_to_test, discovery, finish,
 *                     n_cols, n_rows,
*/
      __pyx_t_34 = __pyx_f_15pygeoprocessing_7routing_7routing__in_watershed(__pyx_v_x_l, __pyx_v_y_l, __pyx_v_cell_to_test, __pyx_v_discovery, __pyx_v_finish, __pyx_v_n_cols, __pyx_v_n_rows, __pyx_v_discovery_managed_raster, __pyx_v_discovery_nodata); if (unlikely(__pyx_t_34 == ((int)-1) && PyErr_Occurred())) __PYX_ERR(0, 3966, __pyx_L1_error)
      __pyx_t_32 = (__pyx_t_34 != 0);
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":3970
 *                     n_cols, n_rows,
 *                     discovery_managed_raster, discovery_nodata):
 *                 edge_side = (edge_side-2) % 8             # <<<<<<<<<<<<<<
 *                 edge_dir = (edge_dir-2) % 8
 *                 x_l += COL_OFFSETS[edge_dir]
*/
        __pyx_v_edge_side = __Pyx_mod_long((__pyx_v_edge_side - 2), 8, 1);

        /* "pygeoprocessing/routing/routing.pyx":3971
 *                     discovery_managed_raster, discovery_nodata):
 *                 edge_side = (edge_side-2) % 8
 *                 edge_dir = (edge_dir-2) % 8             # <<<<<<<<<<<<<<
 *                 x_l += COL_OFFSETS[edge_dir]
 *                 y_l += ROW_OFFSETS[edge_dir]
*/
        __pyx_v_edge_dir = __Pyx_mod_long((__pyx_v_edge_dir - 2), 8, 1);

        /* "pygeoprocessing/routing/routing.pyx":3972
 *                 edge_side = (edge_side-2) % 8
 *                 edge_dir = (edge_dir-2) % 8
 *                 x_l += COL_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *                 y_l += ROW_OFFSETS[edge_dir]
 *                 # note the pixel moved
*/
        __pyx_v_x_l = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_edge_dir]));

        /* "pygeoprocessing/routing/routing.pyx":3973
 *                 edge_dir = (edge_dir-2) % 8
 *                 x_l += COL_OFFSETS[edge_dir]
 *                 y_l += ROW_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *                 # note the pixel moved
 *                 boundary_list.append((x_l, y_l))
*/
        __pyx_v_y_l = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_edge_dir]));

        /* "pygeoprocessing/routing/routing.pyx":3975
 *                 y_l += ROW_OFFSETS[edge_dir]
 *                 # note the pixel moved
 *                 boundary_list.append((x_l, y_l))             # <<<<<<<<<<<<<<
 * 
 *         n_steps = 0
*/
        __pyx_t_2 = __Pyx_PyLong_From_unsigned_int(__pyx_v_x_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3975, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_7 = __Pyx_PyLong_From_unsigned_int(__pyx_v_y_l); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3975, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3975, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_GIVEREF(__pyx_t_2);
        if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 3975, __pyx_L1_error);
        __Pyx_GIVEREF(__pyx_t_7);
        if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7) != (0)) __PYX_ERR(0, 3975, __pyx_L1_error);
        __pyx_t_2 = 0;
        __pyx_t_7 = 0;
        __pyx_t_28 = __Pyx_PyList_Append(__pyx_v_boundary_list, __pyx_t_3); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 3975, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3966
 *             edge_side = cell_to_test
 *             edge_dir = (cell_to_test+2) % 8
 *             if _in_watershed(             # <<<<<<<<<<<<<<
 *                     x_l, y_l, cell_to_test, discovery, finish,
 *                     n_cols, n_rows,
*/
      }
    }
    __pyx_L50:;

    /* "pygeoprocessing/routing/routing.pyx":3977
 *                 boundary_list.append((x_l, y_l))
 * 
 *         n_steps = 0             # <<<<<<<<<<<<<<
 *         terminated_early = 0
 *         while True:
*/
    __pyx_v_n_steps = 0;

    /* "pygeoprocessing/routing/routing.pyx":3978
 * 
 *         n_steps = 0
 *         terminated_early = 0             # <<<<<<<<<<<<<<
 *         while True:
 *             # step the edge then determine the projected coordinates
*/
    __pyx_v_terminated_early = 0;

    /* "pygeoprocessing/routing/routing.pyx":3979
 *         n_steps = 0
 *         terminated_early = 0
 *         while True:             # <<<<<<<<<<<<<<
 *             # step the edge then determine the projected coordinates
 *             x_f += COL_OFFSETS[edge_dir]
*/
    while (1) {

      /* "pygeoprocessing/routing/routing.pyx":3981
 *         while True:
 *             # step the edge then determine the projected coordinates
 *             x_f += COL_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *             y_f += ROW_OFFSETS[edge_dir]
 *             delta_x += COL_OFFSETS[edge_dir]
*/
      __pyx_v_x_f = (__pyx_v_x_f + (COL_OFFSETS[__pyx_v_edge_dir]));

      /* "pygeoprocessing/routing/routing.pyx":3982
 *             # step the edge then determine the projected coordinates
 *             x_f += COL_OFFSETS[edge_dir]
 *             y_f += ROW_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *             delta_x += COL_OFFSETS[edge_dir]
 *             delta_y += ROW_OFFSETS[edge_dir]
*/
      __pyx_v_y_f = (__pyx_v_y_f + (ROW_OFFSETS[__pyx_v_edge_dir]));

      /* "pygeoprocessing/routing/routing.pyx":3983
 *             x_f += COL_OFFSETS[edge_dir]
 *             y_f += ROW_OFFSETS[edge_dir]
 *             delta_x += COL_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *             delta_y += ROW_OFFSETS[edge_dir]
 *             # equivalent to gdal.ApplyGeoTransform(geotransform, x_f, y_f)
*/
      __pyx_v_delta_x = (__pyx_v_delta_x + (COL_OFFSETS[__pyx_v_edge_dir]));

      /* "pygeoprocessing/routing/routing.pyx":3984
 *             y_f += ROW_OFFSETS[edge_dir]
 *             delta_x += COL_OFFSETS[edge_dir]
 *             delta_y += ROW_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *             # equivalent to gdal.ApplyGeoTransform(geotransform, x_f, y_f)
 *             # to eliminate python function call overhead
*/
      __pyx_v_delta_y = (__pyx_v_delta_y + (ROW_OFFSETS[__pyx_v_edge_dir]));

      /* "pygeoprocessing/routing/routing.pyx":3987
 *             # equivalent to gdal.ApplyGeoTransform(geotransform, x_f, y_f)
 *             # to eliminate python function call overhead
 *             x_p = g0 + g1*x_f + g2*y_f             # <<<<<<<<<<<<<<
 *             y_p = g3 + g4*x_f + g5*y_f
 *             watershed_boundary.AddPoint(x_p, y_p)
*/
      __pyx_v_x_p = ((__pyx_v_g0 + (__pyx_v_g1 * __pyx_v_x_f)) + (__pyx_v_g2 * __pyx_v_y_f));

      /* "pygeoprocessing/routing/routing.pyx":3988
 *             # to eliminate python function call overhead
 *             x_p = g0 + g1*x_f + g2*y_f
 *             y_p = g3 + g4*x_f + g5*y_f             # <<<<<<<<<<<<<<
 *             watershed_boundary.AddPoint(x_p, y_p)
 *             n_steps += 1
*/
      __pyx_v_y_p = ((__pyx_v_g3 + (__pyx_v_g4 * __pyx_v_x_f)) + (__pyx_v_g5 * __pyx_v_y_f));

      /* "pygeoprocessing/routing/routing.pyx":3989
 *             x_p = g0 + g1*x_f + g2*y_f
 *             y_p = g3 + g4*x_f + g5*y_f
 *             watershed_boundary.AddPoint(x_p, y_p)             # <<<<<<<<<<<<<<
 *             n_steps += 1
 *             if n_steps > _int_max_steps_per_watershed:
*/
      __pyx_t_7 = __pyx_v_watershed_boundary;
      __Pyx_INCREF(__pyx_t_7);
      __pyx_t_2 = PyFloat_FromDouble(__pyx_v_x_p); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3989, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_6 = PyFloat_FromDouble(__pyx_v_y_p); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3989, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      __pyx_t_11 = 0;
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_t_2, __pyx_t_6};
        __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddPoint, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3989, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
      }
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

      /* "pygeoprocessing/routing/routing.pyx":3990
 *             y_p = g3 + g4*x_f + g5*y_f
 *             watershed_boundary.AddPoint(x_p, y_p)
 *             n_steps += 1             # <<<<<<<<<<<<<<
 *             if n_steps > _int_max_steps_per_watershed:
 *                 LOGGER.warning('quitting, too many steps')
*/
      __pyx_v_n_steps = (__pyx_v_n_steps + 1);

      /* "pygeoprocessing/routing/routing.pyx":3991
 *             watershed_boundary.AddPoint(x_p, y_p)
 *             n_steps += 1
 *             if n_steps > _int_max_steps_per_watershed:             # <<<<<<<<<<<<<<
 *                 LOGGER.warning('quitting, too many steps')
 *                 terminated_early = 1
*/
      __pyx_t_32 = (__pyx_v_n_steps > __pyx_v__int_max_steps_per_watershed);
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":3992
 *             n_steps += 1
 *             if n_steps > _int_max_steps_per_watershed:
 *                 LOGGER.warning('quitting, too many steps')             # <<<<<<<<<<<<<<
 *                 terminated_early = 1
 *                 break
*/
        __pyx_t_6 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3992, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_warning); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3992, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __pyx_t_11 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_7))) {
          __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_7);
          assert(__pyx_t_6);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
          __Pyx_INCREF(__pyx_t_6);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
          __pyx_t_11 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_kp_u_quitting_too_many_steps};
          __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
          if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3992, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_3);
        }
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

        /* "pygeoprocessing/routing/routing.pyx":3993
 *             if n_steps > _int_max_steps_per_watershed:
 *                 LOGGER.warning('quitting, too many steps')
 *                 terminated_early = 1             # <<<<<<<<<<<<<<
 *                 break
 *             if x_l < 0 or y_l < 0 or x_l >= n_cols or y_l >= n_rows:
*/
        __pyx_v_terminated_early = 1;

        /* "pygeoprocessing/routing/routing.pyx":3994
 *                 LOGGER.warning('quitting, too many steps')
 *                 terminated_early = 1
 *                 break             # <<<<<<<<<<<<<<
 *             if x_l < 0 or y_l < 0 or x_l >= n_cols or y_l >= n_rows:
 *                 # This is unexpected but worth checking since missing this
*/
        goto __pyx_L53_break;

        /* "pygeoprocessing/routing/routing.pyx":3991
 *             watershed_boundary.AddPoint(x_p, y_p)
 *             n_steps += 1
 *             if n_steps > _int_max_steps_per_watershed:             # <<<<<<<<<<<<<<
 *                 LOGGER.warning('quitting, too many steps')
 *                 terminated_early = 1
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":3995
 *                 terminated_early = 1
 *                 break
 *             if x_l < 0 or y_l < 0 or x_l >= n_cols or y_l >= n_rows:             # <<<<<<<<<<<<<<
 *                 # This is unexpected but worth checking since missing this
 *                 # error would be very difficult to debug.
*/
      __pyx_t_25 = (__pyx_v_x_l < 0);
      if (!__pyx_t_25) {
      } else {
        __pyx_t_32 = __pyx_t_25;
        goto __pyx_L56_bool_binop_done;
      }
      __pyx_t_25 = (__pyx_v_y_l < 0);
      if (!__pyx_t_25) {
      } else {
        __pyx_t_32 = __pyx_t_25;
        goto __pyx_L56_bool_binop_done;
      }
      __pyx_t_25 = (__pyx_v_x_l >= __pyx_v_n_cols);
      if (!__pyx_t_25) {
      } else {
        __pyx_t_32 = __pyx_t_25;
        goto __pyx_L56_bool_binop_done;
      }
      __pyx_t_25 = (__pyx_v_y_l >= __pyx_v_n_rows);
      __pyx_t_32 = __pyx_t_25;
      __pyx_L56_bool_binop_done:;
      if (unlikely(__pyx_t_32)) {

        /* "pygeoprocessing/routing/routing.pyx":3998
 *                 # This is unexpected but worth checking since missing this
 *                 # error would be very difficult to debug.
 *                 raise RuntimeError(             # <<<<<<<<<<<<<<
 *                     f'{x_l}, {y_l} out of bounds for '
 *                     f'{n_cols}x{n_rows} raster.')
*/
        __pyx_t_7 = NULL;

        /* "pygeoprocessing/routing/routing.pyx":3999
 *                 # error would be very difficult to debug.
 *                 raise RuntimeError(
 *                     f'{x_l}, {y_l} out of bounds for '             # <<<<<<<<<<<<<<
 *                     f'{n_cols}x{n_rows} raster.')
 *             if edge_side - ((edge_dir-2) % 8) == 0:
*/
        __pyx_t_6 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_x_l, 0, ' ', 'd'); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3999, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __pyx_t_2 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_y_l, 0, ' ', 'd'); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3999, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);

        /* "pygeoprocessing/routing/routing.pyx":4000
 *                 raise RuntimeError(
 *                     f'{x_l}, {y_l} out of bounds for '
 *                     f'{n_cols}x{n_rows} raster.')             # <<<<<<<<<<<<<<
 *             if edge_side - ((edge_dir-2) % 8) == 0:
 *                 # counterclockwise configuration
*/
        __pyx_t_4 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_n_cols, 0, ' ', 'd'); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4000, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __pyx_t_10 = __Pyx_PyUnicode_From_unsigned_int(__pyx_v_n_rows, 0, ' ', 'd'); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4000, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_10);
        __pyx_t_35[0] = __pyx_t_6;
        __pyx_t_35[1] = __pyx_mstate_global->__pyx_kp_u_;
        __pyx_t_35[2] = __pyx_t_2;
        __pyx_t_35[3] = __pyx_mstate_global->__pyx_kp_u_out_of_bounds_for;
        __pyx_t_35[4] = __pyx_t_4;
        __pyx_t_35[5] = __pyx_mstate_global->__pyx_n_u_x;
        __pyx_t_35[6] = __pyx_t_10;
        __pyx_t_35[7] = __pyx_mstate_global->__pyx_kp_u_raster;

        /* "pygeoprocessing/routing/routing.pyx":3999
 *                 # error would be very difficult to debug.
 *                 raise RuntimeError(
 *                     f'{x_l}, {y_l} out of bounds for '             # <<<<<<<<<<<<<<
 *                     f'{n_cols}x{n_rows} raster.')
 *             if edge_side - ((edge_dir-2) % 8) == 0:
*/
        __pyx_t_8 = __Pyx_PyUnicode_Join(__pyx_t_35, 8, __Pyx_PyUnicode_GET_LENGTH(__pyx_t_6) + 2 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_2) + 19 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_4) + 1 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_10) + 8, 127);
        if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 3999, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
        __pyx_t_11 = 1;
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_8};
          __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_RuntimeError)), __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
          if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 3998, __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;
        __PYX_ERR(0, 3998, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":3995
 *                 terminated_early = 1
 *                 break
 *             if x_l < 0 or y_l < 0 or x_l >= n_cols or y_l >= n_rows:             # <<<<<<<<<<<<<<
 *                 # This is unexpected but worth checking since missing this
 *                 # error would be very difficult to debug.
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":4001
 *                     f'{x_l}, {y_l} out of bounds for '
 *                     f'{n_cols}x{n_rows} raster.')
 *             if edge_side - ((edge_dir-2) % 8) == 0:             # <<<<<<<<<<<<<<
 *                 # counterclockwise configuration
 *                 left = edge_dir
*/
      __pyx_t_32 = ((__pyx_v_edge_side - __Pyx_mod_long((__pyx_v_edge_dir - 2), 8, 1)) == 0);
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":4003
 *             if edge_side - ((edge_dir-2) % 8) == 0:
 *                 # counterclockwise configuration
 *                 left = edge_dir             # <<<<<<<<<<<<<<
 *                 right = (left-1) % 8
 *                 out_dir_increase = 2
*/
        __pyx_v_left = __pyx_v_edge_dir;

        /* "pygeoprocessing/routing/routing.pyx":4004
 *                 # counterclockwise configuration
 *                 left = edge_dir
 *                 right = (left-1) % 8             # <<<<<<<<<<<<<<
 *                 out_dir_increase = 2
 *             else:
*/
        __pyx_v_right = __Pyx_mod_long((__pyx_v_left - 1), 8, 1);

        /* "pygeoprocessing/routing/routing.pyx":4005
 *                 left = edge_dir
 *                 right = (left-1) % 8
 *                 out_dir_increase = 2             # <<<<<<<<<<<<<<
 *             else:
 *                 # clockwise configuration (swapping "left" and "right")
*/
        __pyx_v_out_dir_increase = 2;

        /* "pygeoprocessing/routing/routing.pyx":4001
 *                     f'{x_l}, {y_l} out of bounds for '
 *                     f'{n_cols}x{n_rows} raster.')
 *             if edge_side - ((edge_dir-2) % 8) == 0:             # <<<<<<<<<<<<<<
 *                 # counterclockwise configuration
 *                 left = edge_dir
*/
        goto __pyx_L60;
      }

      /* "pygeoprocessing/routing/routing.pyx":4008
 *             else:
 *                 # clockwise configuration (swapping "left" and "right")
 *                 right = edge_dir             # <<<<<<<<<<<<<<
 *                 left = (edge_side+1)
 *                 out_dir_increase = -2
*/
      /*else*/ {
        __pyx_v_right = __pyx_v_edge_dir;

        /* "pygeoprocessing/routing/routing.pyx":4009
 *                 # clockwise configuration (swapping "left" and "right")
 *                 right = edge_dir
 *                 left = (edge_side+1)             # <<<<<<<<<<<<<<
 *                 out_dir_increase = -2
 *             left_in = _in_watershed(
*/
        __pyx_v_left = (__pyx_v_edge_side + 1);

        /* "pygeoprocessing/routing/routing.pyx":4010
 *                 right = edge_dir
 *                 left = (edge_side+1)
 *                 out_dir_increase = -2             # <<<<<<<<<<<<<<
 *             left_in = _in_watershed(
 *                 x_l, y_l, left, discovery, finish, n_cols, n_rows,
*/
        __pyx_v_out_dir_increase = -2;
      }
      __pyx_L60:;

      /* "pygeoprocessing/routing/routing.pyx":4011
 *                 left = (edge_side+1)
 *                 out_dir_increase = -2
 *             left_in = _in_watershed(             # <<<<<<<<<<<<<<
 *                 x_l, y_l, left, discovery, finish, n_cols, n_rows,
 *                 discovery_managed_raster, discovery_nodata)
*/
      __pyx_t_34 = __pyx_f_15pygeoprocessing_7routing_7routing__in_watershed(__pyx_v_x_l, __pyx_v_y_l, __pyx_v_left, __pyx_v_discovery, __pyx_v_finish, __pyx_v_n_cols, __pyx_v_n_rows, __pyx_v_discovery_managed_raster, __pyx_v_discovery_nodata); if (unlikely(__pyx_t_34 == ((int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4011, __pyx_L1_error)
      __pyx_v_left_in = __pyx_t_34;

      /* "pygeoprocessing/routing/routing.pyx":4014
 *                 x_l, y_l, left, discovery, finish, n_cols, n_rows,
 *                 discovery_managed_raster, discovery_nodata)
 *             right_in = _in_watershed(             # <<<<<<<<<<<<<<
 *                 x_l, y_l, right, discovery, finish, n_cols, n_rows,
 *                 discovery_managed_raster, discovery_nodata)
*/
      __pyx_t_34 = __pyx_f_15pygeoprocessing_7routing_7routing__in_watershed(__pyx_v_x_l, __pyx_v_y_l, __pyx_v_right, __pyx_v_discovery, __pyx_v_finish, __pyx_v_n_cols, __pyx_v_n_rows, __pyx_v_discovery_managed_raster, __pyx_v_discovery_nodata); if (unlikely(__pyx_t_34 == ((int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4014, __pyx_L1_error)
      __pyx_v_right_in = __pyx_t_34;

      /* "pygeoprocessing/routing/routing.pyx":4017
 *                 x_l, y_l, right, discovery, finish, n_cols, n_rows,
 *                 discovery_managed_raster, discovery_nodata)
 *             if right_in:             # <<<<<<<<<<<<<<
 *                 # turn right
 *                 out_dir = edge_side
*/
      __pyx_t_32 = (__pyx_v_right_in != 0);
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":4019
 *             if right_in:
 *                 # turn right
 *                 out_dir = edge_side             # <<<<<<<<<<<<<<
 *                 edge_side = (edge_side-out_dir_increase) % 8
 *                 edge_dir = out_dir
*/
        __pyx_v_out_dir = __pyx_v_edge_side;

        /* "pygeoprocessing/routing/routing.pyx":4020
 *                 # turn right
 *                 out_dir = edge_side
 *                 edge_side = (edge_side-out_dir_increase) % 8             # <<<<<<<<<<<<<<
 *                 edge_dir = out_dir
 *                 # pixel moves to be the right cell
*/
        __pyx_v_edge_side = __Pyx_mod_long((__pyx_v_edge_side - __pyx_v_out_dir_increase), 8, 1);

        /* "pygeoprocessing/routing/routing.pyx":4021
 *                 out_dir = edge_side
 *                 edge_side = (edge_side-out_dir_increase) % 8
 *                 edge_dir = out_dir             # <<<<<<<<<<<<<<
 *                 # pixel moves to be the right cell
 *                 x_l += COL_OFFSETS[right]
*/
        __pyx_v_edge_dir = __pyx_v_out_dir;

        /* "pygeoprocessing/routing/routing.pyx":4023
 *                 edge_dir = out_dir
 *                 # pixel moves to be the right cell
 *                 x_l += COL_OFFSETS[right]             # <<<<<<<<<<<<<<
 *                 y_l += ROW_OFFSETS[right]
 *                 _diagonal_fill_step(
*/
        __pyx_v_x_l = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_right]));

        /* "pygeoprocessing/routing/routing.pyx":4024
 *                 # pixel moves to be the right cell
 *                 x_l += COL_OFFSETS[right]
 *                 y_l += ROW_OFFSETS[right]             # <<<<<<<<<<<<<<
 *                 _diagonal_fill_step(
 *                     x_l, y_l, right,
*/
        __pyx_v_y_l = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_right]));

        /* "pygeoprocessing/routing/routing.pyx":4025
 *                 x_l += COL_OFFSETS[right]
 *                 y_l += ROW_OFFSETS[right]
 *                 _diagonal_fill_step(             # <<<<<<<<<<<<<<
 *                     x_l, y_l, right,
 *                     discovery, finish, discovery_managed_raster,
*/
        __pyx_f_15pygeoprocessing_7routing_7routing__diagonal_fill_step(__pyx_v_x_l, __pyx_v_y_l, __pyx_v_right, __pyx_v_discovery, __pyx_v_finish, __pyx_v_discovery_managed_raster, __pyx_v_discovery_nodata, __pyx_v_boundary_list); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 4025, __pyx_L1_error)

        /* "pygeoprocessing/routing/routing.pyx":4017
 *                 x_l, y_l, right, discovery, finish, n_cols, n_rows,
 *                 discovery_managed_raster, discovery_nodata)
 *             if right_in:             # <<<<<<<<<<<<<<
 *                 # turn right
 *                 out_dir = edge_side
*/
        goto __pyx_L61;
      }

      /* "pygeoprocessing/routing/routing.pyx":4030
 *                     discovery_nodata,
 *                     boundary_list)
 *             elif left_in:             # <<<<<<<<<<<<<<
 *                 # step forward
 *                 x_l += COL_OFFSETS[edge_dir]
*/
      __pyx_t_32 = (__pyx_v_left_in != 0);
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":4032
 *             elif left_in:
 *                 # step forward
 *                 x_l += COL_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *                 y_l += ROW_OFFSETS[edge_dir]
 *                 # the pixel moves forward
*/
        __pyx_v_x_l = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_edge_dir]));

        /* "pygeoprocessing/routing/routing.pyx":4033
 *                 # step forward
 *                 x_l += COL_OFFSETS[edge_dir]
 *                 y_l += ROW_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *                 # the pixel moves forward
 *                 boundary_list.append((x_l, y_l))
*/
        __pyx_v_y_l = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_edge_dir]));

        /* "pygeoprocessing/routing/routing.pyx":4035
 *                 y_l += ROW_OFFSETS[edge_dir]
 *                 # the pixel moves forward
 *                 boundary_list.append((x_l, y_l))             # <<<<<<<<<<<<<<
 *             else:
 *                 # turn left
*/
        __pyx_t_3 = __Pyx_PyLong_From_unsigned_int(__pyx_v_x_l); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4035, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __pyx_t_8 = __Pyx_PyLong_From_unsigned_int(__pyx_v_y_l); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4035, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4035, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_7);
        __Pyx_GIVEREF(__pyx_t_3);
        if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 4035, __pyx_L1_error);
        __Pyx_GIVEREF(__pyx_t_8);
        if (__Pyx_PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8) != (0)) __PYX_ERR(0, 4035, __pyx_L1_error);
        __pyx_t_3 = 0;
        __pyx_t_8 = 0;
        __pyx_t_28 = __Pyx_PyList_Append(__pyx_v_boundary_list, __pyx_t_7); if (unlikely(__pyx_t_28 == ((int)-1))) __PYX_ERR(0, 4035, __pyx_L1_error)
        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4030
 *                     discovery_nodata,
 *                     boundary_list)
 *             elif left_in:             # <<<<<<<<<<<<<<
 *                 # step forward
 *                 x_l += COL_OFFSETS[edge_dir]
*/
        goto __pyx_L61;
      }

      /* "pygeoprocessing/routing/routing.pyx":4038
 *             else:
 *                 # turn left
 *                 edge_side = edge_dir             # <<<<<<<<<<<<<<
 *                 edge_dir = (edge_side + out_dir_increase) % 8
 * 
*/
      /*else*/ {
        __pyx_v_edge_side = __pyx_v_edge_dir;

        /* "pygeoprocessing/routing/routing.pyx":4039
 *                 # turn left
 *                 edge_side = edge_dir
 *                 edge_dir = (edge_side + out_dir_increase) % 8             # <<<<<<<<<<<<<<
 * 
 *             if delta_x == 0 and delta_y == 0:
*/
        __pyx_v_edge_dir = __Pyx_mod_long((__pyx_v_edge_side + __pyx_v_out_dir_increase), 8, 1);
      }
      __pyx_L61:;

      /* "pygeoprocessing/routing/routing.pyx":4041
 *                 edge_dir = (edge_side + out_dir_increase) % 8
 * 
 *             if delta_x == 0 and delta_y == 0:             # <<<<<<<<<<<<<<
 *                 # met the start point so we completed the watershed loop
 *                 break
*/
      __pyx_t_25 = (__pyx_v_delta_x == 0);
      if (__pyx_t_25) {
      } else {
        __pyx_t_32 = __pyx_t_25;
        goto __pyx_L63_bool_binop_done;
      }
      __pyx_t_25 = (__pyx_v_delta_y == 0);
      __pyx_t_32 = __pyx_t_25;
      __pyx_L63_bool_binop_done:;
      if (__pyx_t_32) {

        /* "pygeoprocessing/routing/routing.pyx":4043
 *             if delta_x == 0 and delta_y == 0:
 *                 # met the start point so we completed the watershed loop
 *                 break             # <<<<<<<<<<<<<<
 * 
 *         watershed_feature = ogr.Feature(watershed_layer.GetLayerDefn())
*/
        goto __pyx_L53_break;

        /* "pygeoprocessing/routing/routing.pyx":4041
 *                 edge_dir = (edge_side + out_dir_increase) % 8
 * 
 *             if delta_x == 0 and delta_y == 0:             # <<<<<<<<<<<<<<
 *                 # met the start point so we completed the watershed loop
 *                 break
*/
      }
    }
    __pyx_L53_break:;

    /* "pygeoprocessing/routing/routing.pyx":4045
 *                 break
 * 
 *         watershed_feature = ogr.Feature(watershed_layer.GetLayerDefn())             # <<<<<<<<<<<<<<
 *         watershed_polygon = ogr.Geometry(ogr.wkbPolygon)
 *         watershed_polygon.AddGeometry(watershed_boundary)
*/
    __pyx_t_8 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4045, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_Feature); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4045, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_10);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_4 = __pyx_v_watershed_layer;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, NULL};
      __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetLayerDefn, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4045, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_10))) {
      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_10);
      assert(__pyx_t_8);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_10);
      __Pyx_INCREF(__pyx_t_8);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_10, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_3};
      __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_10, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4045, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_watershed_feature, __pyx_t_7);
    __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4046
 * 
 *         watershed_feature = ogr.Feature(watershed_layer.GetLayerDefn())
 *         watershed_polygon = ogr.Geometry(ogr.wkbPolygon)             # <<<<<<<<<<<<<<
 *         watershed_polygon.AddGeometry(watershed_boundary)
 *         watershed_feature.SetGeometry(watershed_polygon)
*/
    __pyx_t_10 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4046, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_Geometry); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4046, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4046, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_wkbPolygon); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4046, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_11 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_8))) {
      __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_8);
      assert(__pyx_t_10);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_10);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_8, __pyx__function);
      __pyx_t_11 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_4};
      __pyx_t_7 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_8, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4046, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_XDECREF_SET(__pyx_v_watershed_polygon, __pyx_t_7);
    __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4047
 *         watershed_feature = ogr.Feature(watershed_layer.GetLayerDefn())
 *         watershed_polygon = ogr.Geometry(ogr.wkbPolygon)
 *         watershed_polygon.AddGeometry(watershed_boundary)             # <<<<<<<<<<<<<<
 *         watershed_feature.SetGeometry(watershed_polygon)
 *         watershed_feature.SetField('stream_fid', stream_fid)
*/
    __pyx_t_8 = __pyx_v_watershed_polygon;
    __Pyx_INCREF(__pyx_t_8);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_v_watershed_boundary};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddGeometry, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4047, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4048
 *         watershed_polygon = ogr.Geometry(ogr.wkbPolygon)
 *         watershed_polygon.AddGeometry(watershed_boundary)
 *         watershed_feature.SetGeometry(watershed_polygon)             # <<<<<<<<<<<<<<
 *         watershed_feature.SetField('stream_fid', stream_fid)
 *         watershed_feature.SetField('terminated_early', terminated_early)
*/
    __pyx_t_8 = __pyx_v_watershed_feature;
    __Pyx_INCREF(__pyx_t_8);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_v_watershed_polygon};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetGeometry, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4048, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4049
 *         watershed_polygon.AddGeometry(watershed_boundary)
 *         watershed_feature.SetGeometry(watershed_polygon)
 *         watershed_feature.SetField('stream_fid', stream_fid)             # <<<<<<<<<<<<<<
 *         watershed_feature.SetField('terminated_early', terminated_early)
 *         watershed_feature.SetField('outlet_x', outlet_x)
*/
    __pyx_t_8 = __pyx_v_watershed_feature;
    __Pyx_INCREF(__pyx_t_8);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_stream_fid, __pyx_v_stream_fid};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4049, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4050
 *         watershed_feature.SetGeometry(watershed_polygon)
 *         watershed_feature.SetField('stream_fid', stream_fid)
 *         watershed_feature.SetField('terminated_early', terminated_early)             # <<<<<<<<<<<<<<
 *         watershed_feature.SetField('outlet_x', outlet_x)
 *         watershed_feature.SetField('outlet_y', outlet_y)
*/
    __pyx_t_8 = __pyx_v_watershed_feature;
    __Pyx_INCREF(__pyx_t_8);
    __pyx_t_4 = __Pyx_PyLong_From_int(__pyx_v_terminated_early); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4050, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_terminated_early, __pyx_t_4};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4050, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4051
 *         watershed_feature.SetField('stream_fid', stream_fid)
 *         watershed_feature.SetField('terminated_early', terminated_early)
 *         watershed_feature.SetField('outlet_x', outlet_x)             # <<<<<<<<<<<<<<
 *         watershed_feature.SetField('outlet_y', outlet_y)
 *         watershed_layer.CreateFeature(watershed_feature)
*/
    __pyx_t_4 = __pyx_v_watershed_feature;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_8 = __Pyx_PyLong_From_unsigned_int(__pyx_v_outlet_x); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4051, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_8);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_mstate_global->__pyx_n_u_outlet_x, __pyx_t_8};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4051, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4052
 *         watershed_feature.SetField('terminated_early', terminated_early)
 *         watershed_feature.SetField('outlet_x', outlet_x)
 *         watershed_feature.SetField('outlet_y', outlet_y)             # <<<<<<<<<<<<<<
 *         watershed_layer.CreateFeature(watershed_feature)
 * 
*/
    __pyx_t_8 = __pyx_v_watershed_feature;
    __Pyx_INCREF(__pyx_t_8);
    __pyx_t_4 = __Pyx_PyLong_From_unsigned_int(__pyx_v_outlet_y); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4052, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_8, __pyx_mstate_global->__pyx_n_u_outlet_y, __pyx_t_4};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_11, (3-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4052, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4053
 *         watershed_feature.SetField('outlet_x', outlet_x)
 *         watershed_feature.SetField('outlet_y', outlet_y)
 *         watershed_layer.CreateFeature(watershed_feature)             # <<<<<<<<<<<<<<
 * 
 *         # this loop fills in the raster at the boundary, done at end so it
*/
    __pyx_t_4 = __pyx_v_watershed_layer;
    __Pyx_INCREF(__pyx_t_4);
    __pyx_t_11 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_v_watershed_feature};
      __pyx_t_7 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateFeature, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
      if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4053, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4058
 *         # doesn't interfere with the loop return to think the cells are no
 *         # longer in the watershed
 *         for boundary_x, boundary_y in boundary_list:             # <<<<<<<<<<<<<<
 *             discovery_managed_raster.set(boundary_x, boundary_y, -1)
 *     watershed_layer.CommitTransaction()
*/
    __pyx_t_7 = __pyx_v_boundary_list; __Pyx_INCREF(__pyx_t_7);
    __pyx_t_29 = 0;
    for (;;) {
      {
        Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_7);
        #if !CYTHON_ASSUME_SAFE_SIZE
        if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4058, __pyx_L1_error)
        #endif
        if (__pyx_t_29 >= __pyx_temp) break;
      }
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(__pyx_t_7, __pyx_t_29, __Pyx_ReferenceSharing_OwnStrongReference);
      ++__pyx_t_29;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4058, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
        PyObject* sequence = __pyx_t_4;
        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
        if (unlikely(size != 2)) {
          if (size > 2) __Pyx_RaiseTooManyValuesError(2);
          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
          __PYX_ERR(0, 4058, __pyx_L1_error)
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        if (likely(PyTuple_CheckExact(sequence))) {
          __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0);
          __Pyx_INCREF(__pyx_t_8);
          __pyx_t_10 = PyTuple_GET_ITEM(sequence, 1);
          __Pyx_INCREF(__pyx_t_10);
        } else {
          __pyx_t_8 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
          if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4058, __pyx_L1_error)
          __Pyx_XGOTREF(__pyx_t_8);
          __pyx_t_10 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
          if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4058, __pyx_L1_error)
          __Pyx_XGOTREF(__pyx_t_10);
        }
        #else
        __pyx_t_8 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4058, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_8);
        __pyx_t_10 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 4058, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_10);
        #endif
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      } else {
        Py_ssize_t index = -1;
        __pyx_t_3 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4058, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_3);
        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
        __pyx_t_16 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_3);
        index = 0; __pyx_t_8 = __pyx_t_16(__pyx_t_3); if (unlikely(!__pyx_t_8)) goto __pyx_L67_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_8);
        index = 1; __pyx_t_10 = __pyx_t_16(__pyx_t_3); if (unlikely(!__pyx_t_10)) goto __pyx_L67_unpacking_failed;
        __Pyx_GOTREF(__pyx_t_10);
        if (__Pyx_IternextUnpackEndCheck(__pyx_t_16(__pyx_t_3), 2) < (0)) __PYX_ERR(0, 4058, __pyx_L1_error)
        __pyx_t_16 = NULL;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        goto __pyx_L68_unpacking_done;
        __pyx_L67_unpacking_failed:;
        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
        __pyx_t_16 = NULL;
        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
        __PYX_ERR(0, 4058, __pyx_L1_error)
        __pyx_L68_unpacking_done:;
      }
      __Pyx_XDECREF_SET(__pyx_v_boundary_x, __pyx_t_8);
      __pyx_t_8 = 0;
      __Pyx_XDECREF_SET(__pyx_v_boundary_y, __pyx_t_10);
      __pyx_t_10 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4059
 *         # longer in the watershed
 *         for boundary_x, boundary_y in boundary_list:
 *             discovery_managed_raster.set(boundary_x, boundary_y, -1)             # <<<<<<<<<<<<<<
 *     watershed_layer.CommitTransaction()
 *     watershed_layer = None
*/
      __pyx_t_15 = __Pyx_PyLong_As_long(__pyx_v_boundary_x); if (unlikely((__pyx_t_15 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4059, __pyx_L1_error)
      __pyx_t_36 = __Pyx_PyLong_As_long(__pyx_v_boundary_y); if (unlikely((__pyx_t_36 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4059, __pyx_L1_error)
      __pyx_v_discovery_managed_raster.set(__pyx_t_15, __pyx_t_36, -1.0);

      /* "pygeoprocessing/routing/routing.pyx":4058
 *         # doesn't interfere with the loop return to think the cells are no
 *         # longer in the watershed
 *         for boundary_x, boundary_y in boundary_list:             # <<<<<<<<<<<<<<
 *             discovery_managed_raster.set(boundary_x, boundary_y, -1)
 *     watershed_layer.CommitTransaction()
*/
    }
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":3919
 *     cdef int _int_max_steps_per_watershed = max_steps_per_watershed
 * 
 *     for index, (stream_fid, x_l, y_l) in enumerate(visit_order_stack):             # <<<<<<<<<<<<<<
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             LOGGER.info(
*/
    __pyx_L41_continue:;
  }
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4060
 *         for boundary_x, boundary_y in boundary_list:
 *             discovery_managed_raster.set(boundary_x, boundary_y, -1)
 *     watershed_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *     watershed_layer = None
 *     watershed_vector = None
*/
  __pyx_t_5 = __pyx_v_watershed_layer;
  __Pyx_INCREF(__pyx_t_5);
  __pyx_t_11 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_11, (1-__pyx_t_11) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4060, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4061
 *             discovery_managed_raster.set(boundary_x, boundary_y, -1)
 *     watershed_layer.CommitTransaction()
 *     watershed_layer = None             # <<<<<<<<<<<<<<
 *     watershed_vector = None
 *     discovery_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_watershed_layer, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4062
 *     watershed_layer.CommitTransaction()
 *     watershed_layer = None
 *     watershed_vector = None             # <<<<<<<<<<<<<<
 *     discovery_managed_raster.close()
 *     finish_managed_raster.close()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_watershed_vector, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4063
 *     watershed_layer = None
 *     watershed_vector = None
 *     discovery_managed_raster.close()             # <<<<<<<<<<<<<<
 *     finish_managed_raster.close()
 *     d8_flow_dir_managed_raster.close()
*/
  __pyx_v_discovery_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":4064
 *     watershed_vector = None
 *     discovery_managed_raster.close()
 *     finish_managed_raster.close()             # <<<<<<<<<<<<<<
 *     d8_flow_dir_managed_raster.close()
 *     shutil.rmtree(workspace_dir)
*/
  __pyx_v_finish_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":4065
 *     discovery_managed_raster.close()
 *     finish_managed_raster.close()
 *     d8_flow_dir_managed_raster.close()             # <<<<<<<<<<<<<<
 *     shutil.rmtree(workspace_dir)
 *     LOGGER.info(
*/
  __pyx_v_d8_flow_dir_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":4066
 *     finish_managed_raster.close()
 *     d8_flow_dir_managed_raster.close()
 *     shutil.rmtree(workspace_dir)             # <<<<<<<<<<<<<<
 *     LOGGER.info(
 *         '(calculate_subwatershed_boundary): watershed building 100% complete')
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_shutil); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4066, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_rmtree); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4066, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_4);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_4, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_v_workspace_dir};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_4, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4066, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4067
 *     d8_flow_dir_managed_raster.close()
 *     shutil.rmtree(workspace_dir)
 *     LOGGER.info(             # <<<<<<<<<<<<<<
 *         '(calculate_subwatershed_boundary): watershed building 100% complete')
 * 
*/
  __pyx_t_4 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4067, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4067, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_11 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_4);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_4);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_11 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_calculate_subwatershed_boundary_3};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_11, (2-__pyx_t_11) | (__pyx_t_11*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4067, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3729
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def calculate_subwatershed_boundary(
 *         d8_flow_dir_raster_path_band,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.calculate_subwatershed_boundary", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_workspace_dir);
  __Pyx_XDECREF(__pyx_v_discovery_time_raster_path);
  __Pyx_XDECREF(__pyx_v_finish_time_raster_path);
  __Pyx_XDECREF(__pyx_v_discovery_info);
  __Pyx_XDECREF(__pyx_v_geotransform);
  __Pyx_XDECREF(__pyx_v_discovery_srs);
  __Pyx_XDECREF(__pyx_v_gpkg_driver);
  __Pyx_XDECREF(__pyx_v_watershed_vector);
  __Pyx_XDECREF(__pyx_v_watershed_basename);
  __Pyx_XDECREF(__pyx_v_watershed_layer);
  __Pyx_XDECREF(__pyx_v_stream_vector);
  __Pyx_XDECREF(__pyx_v_stream_layer);
  __Pyx_XDECREF(__pyx_v_upstream_fid_map);
  __Pyx_XDECREF(__pyx_v_stream_feature);
  __Pyx_XDECREF(__pyx_v_ds_x);
  __Pyx_XDECREF(__pyx_v_ds_y);
  __Pyx_XDECREF(__pyx_v_visit_order_stack);
  __Pyx_XDECREF(__pyx_v__);
  __Pyx_XDECREF(__pyx_v_outlet_fid);
  __Pyx_XDECREF(__pyx_v_working_stack);
  __Pyx_XDECREF(__pyx_v_processed_nodes);
  __Pyx_XDECREF(__pyx_v_working_fid);
  __Pyx_XDECREF(__pyx_v_working_feature);
  __Pyx_XDECREF(__pyx_v_us_x);
  __Pyx_XDECREF(__pyx_v_us_y);
  __Pyx_XDECREF(__pyx_v_ds_x_1);
  __Pyx_XDECREF(__pyx_v_ds_y_1);
  __Pyx_XDECREF(__pyx_v_upstream_coord);
  __Pyx_XDECREF(__pyx_v_upstream_fids);
  __Pyx_XDECREF(__pyx_v_index);
  __Pyx_XDECREF(__pyx_v_stream_fid);
  __Pyx_XDECREF(__pyx_v_boundary_list);
  __Pyx_XDECREF(__pyx_v_watershed_boundary);
  __Pyx_XDECREF(__pyx_v_watershed_feature);
  __Pyx_XDECREF(__pyx_v_watershed_polygon);
  __Pyx_XDECREF(__pyx_v_boundary_x);
  __Pyx_XDECREF(__pyx_v_boundary_y);
  __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_x);
  __Pyx_XDECREF(__pyx_8genexpr3__pyx_v_fid);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":4071
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_lowest_drain_and_sink(dem_raster_path_band):
 *     """Find the lowest drain and sink pixel in the DEM.
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_27detect_lowest_drain_and_sink(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_26detect_lowest_drain_and_sink, "Find the lowest drain and sink pixel in the DEM.\n\n    This function is used to specify conditions to DEMs that are known to\n    have one real sink/drain, but may have several numerical sink/drains by\n    detecting both the lowest pixel that could drain the raster on an edge\n    and the lowest internal pixel that might sink the whole raster.\n\n    Example:\n        raster A contains the following\n            * pixel at (3, 4) at 10m draining to a nodata  pixel\n            * pixel at (15, 19) at 11m draining to a nodata pixel\n            * pixel at (19, 21) at 10m draining to a nodata pixel\n            * pit pixel at (10, 15) at 5m surrounded by non-draining pixels\n            * pit pixel at (25, 15) at 15m surrounded by non-draining pixels\n            * pit pixel at (2, 125) at 5m surrounded by non-draining pixels\n\n        The result is two pixels indicating the first lowest edge and first\n        lowest sink seen:\n            drain_pixel = (3, 4), 10\n            sink_pixel = (10, 15), 5\n\n    Args:\n        dem_raster_path_band (tuple): a raster/path band tuple to detect\n            sinks in. Paths may use any GDAL-supported scheme, including\n            virtual file system /vsi schemes.\n\n    Return:\n        (drain_pixel, drain_height, sink_pixel, sink_height) -\n            two (x, y) tuples with corresponding heights, first\n            list is for edge drains, the second is for pit sinks. The x/y\n            coordinate is in raster coordinate space and _height is the\n            height of the given pixels in edge and pit respectively.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_27detect_lowest_drain_and_sink = {"detect_lowest_drain_and_sink", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_27detect_lowest_drain_and_sink, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_26detect_lowest_drain_and_sink};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_27detect_lowest_drain_and_sink(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_dem_raster_path_band = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[1] = {0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("detect_lowest_drain_and_sink (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_dem_raster_path_band,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 4071, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4071, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "detect_lowest_drain_and_sink", 0) < (0)) __PYX_ERR(0, 4071, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 1; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("detect_lowest_drain_and_sink", 1, 1, 1, i); __PYX_ERR(0, 4071, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 1)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4071, __pyx_L3_error)
    }
    __pyx_v_dem_raster_path_band = values[0];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("detect_lowest_drain_and_sink", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 4071, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.detect_lowest_drain_and_sink", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_26detect_lowest_drain_and_sink(__pyx_self, __pyx_v_dem_raster_path_band);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_26detect_lowest_drain_and_sink(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_dem_raster_path_band) {
  double __pyx_v_lowest_drain_height;
  double __pyx_v_lowest_sink_height;
  PyObject *__pyx_v_drain_pixel = NULL;
  PyObject *__pyx_v_sink_pixel = NULL;
  PyObject *__pyx_v_dem_raster_info = NULL;
  double __pyx_v_dem_nodata;
  PyObject *__pyx_v_raster_x_size = NULL;
  PyObject *__pyx_v_raster_y_size = NULL;
  ManagedRaster __pyx_v_dem_managed_raster;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_offset_dict = NULL;
  PyObject *__pyx_v_win_xsize = NULL;
  PyObject *__pyx_v_win_ysize = NULL;
  PyObject *__pyx_v_xoff = NULL;
  PyObject *__pyx_v_yoff = NULL;
  PyObject *__pyx_v_current_pixel = NULL;
  PyObject *__pyx_v_yi = NULL;
  PyObject *__pyx_v_yi_root = NULL;
  PyObject *__pyx_v_xi = NULL;
  PyObject *__pyx_v_xi_root = NULL;
  double __pyx_v_center_val;
  long __pyx_v_pixel_drains;
  long __pyx_v_i_n;
  PyObject *__pyx_v_xi_n = NULL;
  PyObject *__pyx_v_yi_n = NULL;
  double __pyx_v_n_height;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  double __pyx_t_3;
  PyObject *__pyx_t_4 = NULL;
  PyObject *__pyx_t_5 = NULL;
  size_t __pyx_t_6;
  int __pyx_t_7;
  PyObject *(*__pyx_t_8)(PyObject *);
  char *__pyx_t_9;
  int __pyx_t_10;
  ManagedRaster __pyx_t_11;
  Py_ssize_t __pyx_t_12;
  PyObject *(*__pyx_t_13)(PyObject *);
  PyObject *__pyx_t_14 = NULL;
  PyObject *__pyx_t_15 = NULL;
  PyObject *__pyx_t_16 = NULL;
  PyObject *__pyx_t_17[5];
  PyObject *(*__pyx_t_18)(PyObject *);
  PyObject *(*__pyx_t_19)(PyObject *);
  long __pyx_t_20;
  long __pyx_t_21;
  int __pyx_t_22;
  long __pyx_t_23;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("detect_lowest_drain_and_sink", 0);

  /* "pygeoprocessing/routing/routing.pyx":4107
 *     """
 *     # this outer loop drives the raster block search
 *     cdef double lowest_drain_height = numpy.inf             # <<<<<<<<<<<<<<
 *     cdef double lowest_sink_height = numpy.inf
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4107, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_inf); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4107, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 4107, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_lowest_drain_height = __pyx_t_3;

  /* "pygeoprocessing/routing/routing.pyx":4108
 *     # this outer loop drives the raster block search
 *     cdef double lowest_drain_height = numpy.inf
 *     cdef double lowest_sink_height = numpy.inf             # <<<<<<<<<<<<<<
 * 
 *     drain_pixel = None
*/
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4108, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_inf); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4108, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 4108, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_lowest_sink_height = __pyx_t_3;

  /* "pygeoprocessing/routing/routing.pyx":4110
 *     cdef double lowest_sink_height = numpy.inf
 * 
 *     drain_pixel = None             # <<<<<<<<<<<<<<
 *     sink_pixel = None
 * 
*/
  __Pyx_INCREF(Py_None);
  __pyx_v_drain_pixel = ((PyObject*)Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4111
 * 
 *     drain_pixel = None
 *     sink_pixel = None             # <<<<<<<<<<<<<<
 * 
 *     dem_raster_info = pygeoprocessing.get_raster_info(
*/
  __Pyx_INCREF(Py_None);
  __pyx_v_sink_pixel = ((PyObject*)Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4113
 *     sink_pixel = None
 * 
 *     dem_raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0])
 *     cdef double dem_nodata
*/
  __pyx_t_2 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4113, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4113, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4114
 * 
 *     dem_raster_info = pygeoprocessing.get_raster_info(
 *         dem_raster_path_band[0])             # <<<<<<<<<<<<<<
 *     cdef double dem_nodata
 *     # guard against undefined nodata by picking a value that's unlikely to
*/
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4114, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_6 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_5);
    assert(__pyx_t_2);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_5);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_5, __pyx__function);
    __pyx_t_6 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_4};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4113, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_dem_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4118
 *     # guard against undefined nodata by picking a value that's unlikely to
 *     # be a dem value
 *     if dem_raster_info['nodata'][0] is not None:             # <<<<<<<<<<<<<<
 *         dem_nodata = dem_raster_info['nodata'][0]
 *     else:
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4118, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4118, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_7 = (__pyx_t_5 != Py_None);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (__pyx_t_7) {

    /* "pygeoprocessing/routing/routing.pyx":4119
 *     # be a dem value
 *     if dem_raster_info['nodata'][0] is not None:
 *         dem_nodata = dem_raster_info['nodata'][0]             # <<<<<<<<<<<<<<
 *     else:
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA
*/
    __pyx_t_5 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4119, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_t_5, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4119, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_3 = __Pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 4119, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_v_dem_nodata = __pyx_t_3;

    /* "pygeoprocessing/routing/routing.pyx":4118
 *     # guard against undefined nodata by picking a value that's unlikely to
 *     # be a dem value
 *     if dem_raster_info['nodata'][0] is not None:             # <<<<<<<<<<<<<<
 *         dem_nodata = dem_raster_info['nodata'][0]
 *     else:
*/
    goto __pyx_L3;
  }

  /* "pygeoprocessing/routing/routing.pyx":4121
 *         dem_nodata = dem_raster_info['nodata'][0]
 *     else:
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA             # <<<<<<<<<<<<<<
 * 
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']
*/
  /*else*/ {
    __pyx_v_dem_nodata = __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA;
  }
  __pyx_L3:;

  /* "pygeoprocessing/routing/routing.pyx":4123
 *         dem_nodata = IMPROBABLE_FLOAT_NODATA
 * 
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     cdef ManagedRaster dem_managed_raster = ManagedRaster(
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_dem_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4123, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 4123, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_5);
      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_4);
    } else {
      __pyx_t_5 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4123, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_5);
      __pyx_t_4 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4123, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_4);
    }
    #else
    __pyx_t_5 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4123, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_4 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4123, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4123, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2);
    index = 0; __pyx_t_5 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_5)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_5);
    index = 1; __pyx_t_4 = __pyx_t_8(__pyx_t_2); if (unlikely(!__pyx_t_4)) goto __pyx_L4_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_2), 2) < (0)) __PYX_ERR(0, 4123, __pyx_L1_error)
    __pyx_t_8 = NULL;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    goto __pyx_L5_unpacking_done;
    __pyx_L4_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_8 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 4123, __pyx_L1_error)
    __pyx_L5_unpacking_done:;
  }
  __pyx_v_raster_x_size = __pyx_t_5;
  __pyx_t_5 = 0;
  __pyx_v_raster_y_size = __pyx_t_4;
  __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4126
 * 
 *     cdef ManagedRaster dem_managed_raster = ManagedRaster(
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)             # <<<<<<<<<<<<<<
 * 
 *     cdef time_t last_log_time = ctime(NULL)
*/
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4126, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_4 = __pyx_t_5;
  __Pyx_INCREF(__pyx_t_4);
  __pyx_t_6 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_mstate_global->__pyx_kp_u_utf_8};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_encode, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4126, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_t_1); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 4126, __pyx_L1_error)
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_dem_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4126, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_10 = __Pyx_PyLong_As_int(__pyx_t_5); if (unlikely((__pyx_t_10 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4126, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4125
 *     raster_x_size, raster_y_size = dem_raster_info['raster_size']
 * 
 *     cdef ManagedRaster dem_managed_raster = ManagedRaster(             # <<<<<<<<<<<<<<
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)
 * 
*/
  try {
    __pyx_t_11 = ManagedRaster(__pyx_t_9, __pyx_t_10, Py_False);
  } catch(...) {
    __Pyx_CppExn2PyErr();
    __PYX_ERR(0, 4125, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_dem_managed_raster = __PYX_STD_MOVE_IF_SUPPORTED(__pyx_t_11);

  /* "pygeoprocessing/routing/routing.pyx":4128
 *         dem_raster_path_band[0].encode('utf-8'), dem_raster_path_band[1], False)
 * 
 *     cdef time_t last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":4130
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4130, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4130, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4131
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             dem_raster_path_band, offset_only=True, largest_block=0):             # <<<<<<<<<<<<<<
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
*/
  __pyx_t_6 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
    assert(__pyx_t_5);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_5);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
    __pyx_t_6 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 2 : 0)] = {__pyx_t_5, __pyx_v_dem_raster_path_band};
    __pyx_t_4 = __Pyx_MakeVectorcallBuilderKwds(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4130, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_4, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 4130, __pyx_L1_error)
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_largest_block, __pyx_mstate_global->__pyx_int_0, __pyx_t_4, __pyx_callargs+2, 1) < (0)) __PYX_ERR(0, 4130, __pyx_L1_error)
    __pyx_t_1 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_4);
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4130, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }

  /* "pygeoprocessing/routing/routing.pyx":4130
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2);
    __pyx_t_12 = 0;
    __pyx_t_13 = NULL;
  } else {
    __pyx_t_12 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4130, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_13 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4130, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  for (;;) {
    if (likely(!__pyx_t_13)) {
      if (likely(PyList_CheckExact(__pyx_t_2))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4130, __pyx_L1_error)
          #endif
          if (__pyx_t_12 >= __pyx_temp) break;
        }
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(__pyx_t_2, __pyx_t_12, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_12;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_2);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4130, __pyx_L1_error)
          #endif
          if (__pyx_t_12 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_1 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_12));
        #else
        __pyx_t_1 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_12);
        #endif
        ++__pyx_t_12;
      }
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4130, __pyx_L1_error)
    } else {
      __pyx_t_1 = __pyx_t_13(__pyx_t_2);
      if (unlikely(!__pyx_t_1)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4130, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_offset_dict, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4132
 *     for offset_dict in pygeoprocessing.iterblocks(
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4132, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_win_xsize, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4133
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']             # <<<<<<<<<<<<<<
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4133, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_win_ysize, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4134
 *         win_xsize = offset_dict['win_xsize']
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']             # <<<<<<<<<<<<<<
 *         yoff = offset_dict['yoff']
 * 
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4134, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_xoff, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4135
 *         win_ysize = offset_dict['win_ysize']
 *         xoff = offset_dict['xoff']
 *         yoff = offset_dict['yoff']             # <<<<<<<<<<<<<<
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
*/
    __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_offset_dict, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4135, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_XDECREF_SET(__pyx_v_yoff, __pyx_t_1);
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4137
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    __pyx_t_7 = ((time(NULL) - __pyx_v_last_log_time) > __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD);
    if (__pyx_t_7) {

      /* "pygeoprocessing/routing/routing.pyx":4138
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
*/
      __pyx_v_last_log_time = time(NULL);

      /* "pygeoprocessing/routing/routing.pyx":4139
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *             LOGGER.info(
 *                 '(infer_sinks): '
*/
      __pyx_t_1 = PyNumber_Multiply(__pyx_v_yoff, __pyx_v_raster_x_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4139, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_4 = PyNumber_Add(__pyx_v_xoff, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4139, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_XDECREF_SET(__pyx_v_current_pixel, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4140
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(             # <<<<<<<<<<<<<<
 *                 '(infer_sinks): '
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '
*/
      __pyx_t_1 = NULL;
      __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4140, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_14 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 4140, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_14);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4142
 *             LOGGER.info(
 *                 '(infer_sinks): '
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '             # <<<<<<<<<<<<<<
 *                 'pixels complete')
 * 
*/
      __pyx_t_5 = __Pyx_PyObject_FormatSimple(__pyx_v_current_pixel, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4142, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_15 = PyNumber_Multiply(__pyx_v_raster_x_size, __pyx_v_raster_y_size); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4142, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      __pyx_t_16 = __Pyx_PyObject_FormatSimple(__pyx_t_15, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_16)) __PYX_ERR(0, 4142, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_16);
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __pyx_t_17[0] = __pyx_mstate_global->__pyx_kp_u_infer_sinks;
      __pyx_t_17[1] = __pyx_t_5;
      __pyx_t_17[2] = __pyx_mstate_global->__pyx_kp_u_of;
      __pyx_t_17[3] = __pyx_t_16;
      __pyx_t_17[4] = __pyx_mstate_global->__pyx_kp_u_pixels_complete;

      /* "pygeoprocessing/routing/routing.pyx":4141
 *             current_pixel = xoff + yoff * raster_x_size
 *             LOGGER.info(
 *                 '(infer_sinks): '             # <<<<<<<<<<<<<<
 *                 f'{current_pixel} of {raster_x_size * raster_y_size} '
 *                 'pixels complete')
*/
      __pyx_t_15 = __Pyx_PyUnicode_Join(__pyx_t_17, 5, 15 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5) + 4 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_16) + 16, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_16));
      if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4141, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
      __pyx_t_6 = 1;
      #if CYTHON_UNPACK_METHODS
      if (unlikely(PyMethod_Check(__pyx_t_14))) {
        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_14);
        assert(__pyx_t_1);
        PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_14);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(__pyx__function);
        __Pyx_DECREF_SET(__pyx_t_14, __pyx__function);
        __pyx_t_6 = 0;
      }
      #endif
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_15};
        __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_14, __pyx_callargs+__pyx_t_6, (2-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
        __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4140, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4137
 *         yoff = offset_dict['yoff']
 * 
 *         if ctime(NULL) - last_log_time > _LOGGING_PERIOD:             # <<<<<<<<<<<<<<
 *             last_log_time = ctime(NULL)
 *             current_pixel = xoff + yoff * raster_x_size
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":4146
 * 
 *         # search block for local sinks
 *         for yi in range(0, win_ysize):             # <<<<<<<<<<<<<<
 *             yi_root = yi+yoff
 *             for xi in range(0, win_xsize):
*/
    __pyx_t_14 = NULL;
    __pyx_t_6 = 1;
    {
      PyObject *__pyx_callargs[3] = {__pyx_t_14, __pyx_mstate_global->__pyx_int_0, __pyx_v_win_ysize};
      __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)(&PyRange_Type), __pyx_callargs+__pyx_t_6, (3-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4146, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
    }
    __pyx_t_14 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 4146, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_14);
    __pyx_t_18 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_14); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 4146, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    for (;;) {
      {
        __pyx_t_4 = __pyx_t_18(__pyx_t_14);
        if (unlikely(!__pyx_t_4)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4146, __pyx_L1_error)
            PyErr_Clear();
          }
          break;
        }
      }
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_XDECREF_SET(__pyx_v_yi, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4147
 *         # search block for local sinks
 *         for yi in range(0, win_ysize):
 *             yi_root = yi+yoff             # <<<<<<<<<<<<<<
 *             for xi in range(0, win_xsize):
 *                 xi_root = xi+xoff
*/
      __pyx_t_4 = PyNumber_Add(__pyx_v_yi, __pyx_v_yoff); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4147, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_4);
      __Pyx_XDECREF_SET(__pyx_v_yi_root, __pyx_t_4);
      __pyx_t_4 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4148
 *         for yi in range(0, win_ysize):
 *             yi_root = yi+yoff
 *             for xi in range(0, win_xsize):             # <<<<<<<<<<<<<<
 *                 xi_root = xi+xoff
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
*/
      __pyx_t_15 = NULL;
      __pyx_t_6 = 1;
      {
        PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_mstate_global->__pyx_int_0, __pyx_v_win_xsize};
        __pyx_t_4 = __Pyx_PyObject_FastCall((PyObject*)(&PyRange_Type), __pyx_callargs+__pyx_t_6, (3-__pyx_t_6) | (__pyx_t_6*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
        if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4148, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
      }
      __pyx_t_15 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4148, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      __pyx_t_19 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_15); if (unlikely(!__pyx_t_19)) __PYX_ERR(0, 4148, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
      for (;;) {
        {
          __pyx_t_4 = __pyx_t_19(__pyx_t_15);
          if (unlikely(!__pyx_t_4)) {
            PyObject* exc_type = PyErr_Occurred();
            if (exc_type) {
              if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4148, __pyx_L1_error)
              PyErr_Clear();
            }
            break;
          }
        }
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_XDECREF_SET(__pyx_v_xi, __pyx_t_4);
        __pyx_t_4 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4149
 *             yi_root = yi+yoff
 *             for xi in range(0, win_xsize):
 *                 xi_root = xi+xoff             # <<<<<<<<<<<<<<
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):
*/
        __pyx_t_4 = PyNumber_Add(__pyx_v_xi, __pyx_v_xoff); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4149, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_4);
        __Pyx_XDECREF_SET(__pyx_v_xi_root, __pyx_t_4);
        __pyx_t_4 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4150
 *             for xi in range(0, win_xsize):
 *                 xi_root = xi+xoff
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                 if is_close(center_val, dem_nodata):
 *                     continue
*/
        __pyx_t_20 = __Pyx_PyLong_As_long(__pyx_v_xi_root); if (unlikely((__pyx_t_20 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4150, __pyx_L1_error)
        __pyx_t_21 = __Pyx_PyLong_As_long(__pyx_v_yi_root); if (unlikely((__pyx_t_21 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4150, __pyx_L1_error)
        __pyx_v_center_val = __pyx_v_dem_managed_raster.get(__pyx_t_20, __pyx_t_21);

        /* "pygeoprocessing/routing/routing.pyx":4151
 *                 xi_root = xi+xoff
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_7 = is_close(__pyx_v_center_val, __pyx_v_dem_nodata);
        if (__pyx_t_7) {

          /* "pygeoprocessing/routing/routing.pyx":4152
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 if (center_val > lowest_drain_height and
*/
          goto __pyx_L11_continue;

          /* "pygeoprocessing/routing/routing.pyx":4151
 *                 xi_root = xi+xoff
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
 *                 if is_close(center_val, dem_nodata):             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":4154
 *                     continue
 * 
 *                 if (center_val > lowest_drain_height and             # <<<<<<<<<<<<<<
 *                         center_val > lowest_sink_height):
 *                     # already found something lower
*/
        __pyx_t_22 = (__pyx_v_center_val > __pyx_v_lowest_drain_height);
        if (__pyx_t_22) {
        } else {
          __pyx_t_7 = __pyx_t_22;
          goto __pyx_L15_bool_binop_done;
        }

        /* "pygeoprocessing/routing/routing.pyx":4155
 * 
 *                 if (center_val > lowest_drain_height and
 *                         center_val > lowest_sink_height):             # <<<<<<<<<<<<<<
 *                     # already found something lower
 *                     continue
*/
        __pyx_t_22 = (__pyx_v_center_val > __pyx_v_lowest_sink_height);
        __pyx_t_7 = __pyx_t_22;
        __pyx_L15_bool_binop_done:;

        /* "pygeoprocessing/routing/routing.pyx":4154
 *                     continue
 * 
 *                 if (center_val > lowest_drain_height and             # <<<<<<<<<<<<<<
 *                         center_val > lowest_sink_height):
 *                     # already found something lower
*/
        if (__pyx_t_7) {

          /* "pygeoprocessing/routing/routing.pyx":4157
 *                         center_val > lowest_sink_height):
 *                     # already found something lower
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 # search neighbors for downhill or nodata
*/
          goto __pyx_L11_continue;

          /* "pygeoprocessing/routing/routing.pyx":4154
 *                     continue
 * 
 *                 if (center_val > lowest_drain_height and             # <<<<<<<<<<<<<<
 *                         center_val > lowest_sink_height):
 *                     # already found something lower
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":4160
 * 
 *                 # search neighbors for downhill or nodata
 *                 pixel_drains = 0             # <<<<<<<<<<<<<<
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
*/
        __pyx_v_pixel_drains = 0;

        /* "pygeoprocessing/routing/routing.pyx":4161
 *                 # search neighbors for downhill or nodata
 *                 pixel_drains = 0
 *                 for i_n in range(8):             # <<<<<<<<<<<<<<
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
*/
        for (__pyx_t_21 = 0; __pyx_t_21 < 8; __pyx_t_21+=1) {
          __pyx_v_i_n = __pyx_t_21;

          /* "pygeoprocessing/routing/routing.pyx":4162
 *                 pixel_drains = 0
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
*/
          __pyx_t_4 = __Pyx_PyLong_From_int((COL_OFFSETS[__pyx_v_i_n])); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4162, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __pyx_t_1 = PyNumber_Add(__pyx_v_xi_root, __pyx_t_4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4162, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __Pyx_XDECREF_SET(__pyx_v_xi_n, __pyx_t_1);
          __pyx_t_1 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4163
 *                 for i_n in range(8):
 *                     xi_n = xi_root+COL_OFFSETS[i_n]
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]             # <<<<<<<<<<<<<<
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
*/
          __pyx_t_1 = __Pyx_PyLong_From_int((ROW_OFFSETS[__pyx_v_i_n])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4163, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_t_4 = PyNumber_Add(__pyx_v_yi_root, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4163, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          __Pyx_XDECREF_SET(__pyx_v_yi_n, __pyx_t_4);
          __pyx_t_4 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4165
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          __pyx_t_4 = PyObject_RichCompare(__pyx_v_xi_n, __pyx_mstate_global->__pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4165, __pyx_L1_error)
          __pyx_t_22 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_22 < 0))) __PYX_ERR(0, 4165, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (!__pyx_t_22) {
          } else {
            __pyx_t_7 = __pyx_t_22;
            goto __pyx_L20_bool_binop_done;
          }
          __pyx_t_4 = PyObject_RichCompare(__pyx_v_xi_n, __pyx_v_raster_x_size, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4165, __pyx_L1_error)
          __pyx_t_22 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_22 < 0))) __PYX_ERR(0, 4165, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (!__pyx_t_22) {
          } else {
            __pyx_t_7 = __pyx_t_22;
            goto __pyx_L20_bool_binop_done;
          }

          /* "pygeoprocessing/routing/routing.pyx":4166
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or
 *                             yi_n < 0 or yi_n >= raster_y_size):             # <<<<<<<<<<<<<<
 *                         # it'll drain off the edge of the raster
 *                         if center_val < lowest_drain_height:
*/
          __pyx_t_4 = PyObject_RichCompare(__pyx_v_yi_n, __pyx_mstate_global->__pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4166, __pyx_L1_error)
          __pyx_t_22 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_22 < 0))) __PYX_ERR(0, 4166, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          if (!__pyx_t_22) {
          } else {
            __pyx_t_7 = __pyx_t_22;
            goto __pyx_L20_bool_binop_done;
          }
          __pyx_t_4 = PyObject_RichCompare(__pyx_v_yi_n, __pyx_v_raster_y_size, Py_GE); __Pyx_XGOTREF(__pyx_t_4); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4166, __pyx_L1_error)
          __pyx_t_22 = __Pyx_PyObject_IsTrue(__pyx_t_4); if (unlikely((__pyx_t_22 < 0))) __PYX_ERR(0, 4166, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
          __pyx_t_7 = __pyx_t_22;
          __pyx_L20_bool_binop_done:;

          /* "pygeoprocessing/routing/routing.pyx":4165
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          if (__pyx_t_7) {

            /* "pygeoprocessing/routing/routing.pyx":4168
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
 *                         if center_val < lowest_drain_height:             # <<<<<<<<<<<<<<
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
*/
            __pyx_t_7 = (__pyx_v_center_val < __pyx_v_lowest_drain_height);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":4170
 *                         if center_val < lowest_drain_height:
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val             # <<<<<<<<<<<<<<
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1
*/
              __pyx_v_lowest_drain_height = __pyx_v_center_val;

              /* "pygeoprocessing/routing/routing.pyx":4171
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
 *                             drain_pixel = (xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                         pixel_drains = 1
 *                         break
*/
              __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4171, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_4);
              __Pyx_INCREF(__pyx_v_xi_root);
              __Pyx_GIVEREF(__pyx_v_xi_root);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_xi_root) != (0)) __PYX_ERR(0, 4171, __pyx_L1_error);
              __Pyx_INCREF(__pyx_v_yi_root);
              __Pyx_GIVEREF(__pyx_v_yi_root);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_yi_root) != (0)) __PYX_ERR(0, 4171, __pyx_L1_error);
              __Pyx_DECREF_SET(__pyx_v_drain_pixel, ((PyObject*)__pyx_t_4));
              __pyx_t_4 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4168
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
 *                         if center_val < lowest_drain_height:             # <<<<<<<<<<<<<<
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":4172
 *                             lowest_drain_height = center_val
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1             # <<<<<<<<<<<<<<
 *                         break
 *                     n_height = dem_managed_raster.get(xi_n, yi_n)
*/
            __pyx_v_pixel_drains = 1;

            /* "pygeoprocessing/routing/routing.pyx":4173
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1
 *                         break             # <<<<<<<<<<<<<<
 *                     n_height = dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):
*/
            goto __pyx_L18_break;

            /* "pygeoprocessing/routing/routing.pyx":4165
 *                     yi_n = yi_root+ROW_OFFSETS[i_n]
 * 
 *                     if (xi_n < 0 or xi_n >= raster_x_size or             # <<<<<<<<<<<<<<
 *                             yi_n < 0 or yi_n >= raster_y_size):
 *                         # it'll drain off the edge of the raster
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":4174
 *                         pixel_drains = 1
 *                         break
 *                     n_height = dem_managed_raster.get(xi_n, yi_n)             # <<<<<<<<<<<<<<
 *                     if is_close(n_height, dem_nodata):
 *                         # it'll drain to nodata
*/
          __pyx_t_20 = __Pyx_PyLong_As_long(__pyx_v_xi_n); if (unlikely((__pyx_t_20 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4174, __pyx_L1_error)
          __pyx_t_23 = __Pyx_PyLong_As_long(__pyx_v_yi_n); if (unlikely((__pyx_t_23 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4174, __pyx_L1_error)
          __pyx_v_n_height = __pyx_v_dem_managed_raster.get(__pyx_t_20, __pyx_t_23);

          /* "pygeoprocessing/routing/routing.pyx":4175
 *                         break
 *                     n_height = dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         # it'll drain to nodata
 *                         if center_val < lowest_drain_height:
*/
          __pyx_t_7 = is_close(__pyx_v_n_height, __pyx_v_dem_nodata);
          if (__pyx_t_7) {

            /* "pygeoprocessing/routing/routing.pyx":4177
 *                     if is_close(n_height, dem_nodata):
 *                         # it'll drain to nodata
 *                         if center_val < lowest_drain_height:             # <<<<<<<<<<<<<<
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
*/
            __pyx_t_7 = (__pyx_v_center_val < __pyx_v_lowest_drain_height);
            if (__pyx_t_7) {

              /* "pygeoprocessing/routing/routing.pyx":4179
 *                         if center_val < lowest_drain_height:
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val             # <<<<<<<<<<<<<<
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1
*/
              __pyx_v_lowest_drain_height = __pyx_v_center_val;

              /* "pygeoprocessing/routing/routing.pyx":4180
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
 *                             drain_pixel = (xi_root, yi_root)             # <<<<<<<<<<<<<<
 *                         pixel_drains = 1
 *                         break
*/
              __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4180, __pyx_L1_error)
              __Pyx_GOTREF(__pyx_t_4);
              __Pyx_INCREF(__pyx_v_xi_root);
              __Pyx_GIVEREF(__pyx_v_xi_root);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_xi_root) != (0)) __PYX_ERR(0, 4180, __pyx_L1_error);
              __Pyx_INCREF(__pyx_v_yi_root);
              __Pyx_GIVEREF(__pyx_v_yi_root);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_yi_root) != (0)) __PYX_ERR(0, 4180, __pyx_L1_error);
              __Pyx_DECREF_SET(__pyx_v_drain_pixel, ((PyObject*)__pyx_t_4));
              __pyx_t_4 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4177
 *                     if is_close(n_height, dem_nodata):
 *                         # it'll drain to nodata
 *                         if center_val < lowest_drain_height:             # <<<<<<<<<<<<<<
 *                             # found a new lower edge height
 *                             lowest_drain_height = center_val
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":4181
 *                             lowest_drain_height = center_val
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1             # <<<<<<<<<<<<<<
 *                         break
 *                     if n_height < center_val:
*/
            __pyx_v_pixel_drains = 1;

            /* "pygeoprocessing/routing/routing.pyx":4182
 *                             drain_pixel = (xi_root, yi_root)
 *                         pixel_drains = 1
 *                         break             # <<<<<<<<<<<<<<
 *                     if n_height < center_val:
 *                         # it'll drain downhill
*/
            goto __pyx_L18_break;

            /* "pygeoprocessing/routing/routing.pyx":4175
 *                         break
 *                     n_height = dem_managed_raster.get(xi_n, yi_n)
 *                     if is_close(n_height, dem_nodata):             # <<<<<<<<<<<<<<
 *                         # it'll drain to nodata
 *                         if center_val < lowest_drain_height:
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":4183
 *                         pixel_drains = 1
 *                         break
 *                     if n_height < center_val:             # <<<<<<<<<<<<<<
 *                         # it'll drain downhill
 *                         pixel_drains = 1
*/
          __pyx_t_7 = (__pyx_v_n_height < __pyx_v_center_val);
          if (__pyx_t_7) {

            /* "pygeoprocessing/routing/routing.pyx":4185
 *                     if n_height < center_val:
 *                         # it'll drain downhill
 *                         pixel_drains = 1             # <<<<<<<<<<<<<<
 *                         break
 *                 if not pixel_drains and center_val < lowest_sink_height:
*/
            __pyx_v_pixel_drains = 1;

            /* "pygeoprocessing/routing/routing.pyx":4186
 *                         # it'll drain downhill
 *                         pixel_drains = 1
 *                         break             # <<<<<<<<<<<<<<
 *                 if not pixel_drains and center_val < lowest_sink_height:
 *                     lowest_sink_height = center_val
*/
            goto __pyx_L18_break;

            /* "pygeoprocessing/routing/routing.pyx":4183
 *                         pixel_drains = 1
 *                         break
 *                     if n_height < center_val:             # <<<<<<<<<<<<<<
 *                         # it'll drain downhill
 *                         pixel_drains = 1
*/
          }
        }
        __pyx_L18_break:;

        /* "pygeoprocessing/routing/routing.pyx":4187
 *                         pixel_drains = 1
 *                         break
 *                 if not pixel_drains and center_val < lowest_sink_height:             # <<<<<<<<<<<<<<
 *                     lowest_sink_height = center_val
 *                     sink_pixel = (xi_root, yi_root)
*/
        __pyx_t_22 = (!(__pyx_v_pixel_drains != 0));
        if (__pyx_t_22) {
        } else {
          __pyx_t_7 = __pyx_t_22;
          goto __pyx_L29_bool_binop_done;
        }
        __pyx_t_22 = (__pyx_v_center_val < __pyx_v_lowest_sink_height);
        __pyx_t_7 = __pyx_t_22;
        __pyx_L29_bool_binop_done:;
        if (__pyx_t_7) {

          /* "pygeoprocessing/routing/routing.pyx":4188
 *                         break
 *                 if not pixel_drains and center_val < lowest_sink_height:
 *                     lowest_sink_height = center_val             # <<<<<<<<<<<<<<
 *                     sink_pixel = (xi_root, yi_root)
 *     dem_managed_raster.close()
*/
          __pyx_v_lowest_sink_height = __pyx_v_center_val;

          /* "pygeoprocessing/routing/routing.pyx":4189
 *                 if not pixel_drains and center_val < lowest_sink_height:
 *                     lowest_sink_height = center_val
 *                     sink_pixel = (xi_root, yi_root)             # <<<<<<<<<<<<<<
 *     dem_managed_raster.close()
 *     return (
*/
          __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 4189, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_4);
          __Pyx_INCREF(__pyx_v_xi_root);
          __Pyx_GIVEREF(__pyx_v_xi_root);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_xi_root) != (0)) __PYX_ERR(0, 4189, __pyx_L1_error);
          __Pyx_INCREF(__pyx_v_yi_root);
          __Pyx_GIVEREF(__pyx_v_yi_root);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_yi_root) != (0)) __PYX_ERR(0, 4189, __pyx_L1_error);
          __Pyx_DECREF_SET(__pyx_v_sink_pixel, ((PyObject*)__pyx_t_4));
          __pyx_t_4 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4187
 *                         pixel_drains = 1
 *                         break
 *                 if not pixel_drains and center_val < lowest_sink_height:             # <<<<<<<<<<<<<<
 *                     lowest_sink_height = center_val
 *                     sink_pixel = (xi_root, yi_root)
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":4148
 *         for yi in range(0, win_ysize):
 *             yi_root = yi+yoff
 *             for xi in range(0, win_xsize):             # <<<<<<<<<<<<<<
 *                 xi_root = xi+xoff
 *                 center_val = dem_managed_raster.get(xi_root, yi_root)
*/
        __pyx_L11_continue:;
      }
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4146
 * 
 *         # search block for local sinks
 *         for yi in range(0, win_ysize):             # <<<<<<<<<<<<<<
 *             yi_root = yi+yoff
 *             for xi in range(0, win_xsize):
*/
    }
    __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4130
 *     cdef time_t last_log_time = ctime(NULL)
 * 
 *     for offset_dict in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             dem_raster_path_band, offset_only=True, largest_block=0):
 *         win_xsize = offset_dict['win_xsize']
*/
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4190
 *                     lowest_sink_height = center_val
 *                     sink_pixel = (xi_root, yi_root)
 *     dem_managed_raster.close()             # <<<<<<<<<<<<<<
 *     return (
 *         drain_pixel, lowest_drain_height,
*/
  __pyx_v_dem_managed_raster.close();

  /* "pygeoprocessing/routing/routing.pyx":4191
 *                     sink_pixel = (xi_root, yi_root)
 *     dem_managed_raster.close()
 *     return (             # <<<<<<<<<<<<<<
 *         drain_pixel, lowest_drain_height,
 *         sink_pixel, lowest_sink_height)
*/
  __Pyx_XDECREF(__pyx_r);

  /* "pygeoprocessing/routing/routing.pyx":4192
 *     dem_managed_raster.close()
 *     return (
 *         drain_pixel, lowest_drain_height,             # <<<<<<<<<<<<<<
 *         sink_pixel, lowest_sink_height)
 * 
*/
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_lowest_drain_height); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4192, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":4193
 *     return (
 *         drain_pixel, lowest_drain_height,
 *         sink_pixel, lowest_sink_height)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_14 = PyFloat_FromDouble(__pyx_v_lowest_sink_height); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 4193, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_14);

  /* "pygeoprocessing/routing/routing.pyx":4192
 *     dem_managed_raster.close()
 *     return (
 *         drain_pixel, lowest_drain_height,             # <<<<<<<<<<<<<<
 *         sink_pixel, lowest_sink_height)
 * 
*/
  __pyx_t_15 = PyTuple_New(4); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4192, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_INCREF(__pyx_v_drain_pixel);
  __Pyx_GIVEREF(__pyx_v_drain_pixel);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_v_drain_pixel) != (0)) __PYX_ERR(0, 4192, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 4192, __pyx_L1_error);
  __Pyx_INCREF(__pyx_v_sink_pixel);
  __Pyx_GIVEREF(__pyx_v_sink_pixel);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 2, __pyx_v_sink_pixel) != (0)) __PYX_ERR(0, 4192, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_14);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 3, __pyx_t_14) != (0)) __PYX_ERR(0, 4192, __pyx_L1_error);
  __pyx_t_2 = 0;
  __pyx_t_14 = 0;
  __pyx_r = __pyx_t_15;
  __pyx_t_15 = 0;
  goto __pyx_L0;

  /* "pygeoprocessing/routing/routing.pyx":4071
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_lowest_drain_and_sink(dem_raster_path_band):
 *     """Find the lowest drain and sink pixel in the DEM.
*/

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_14);
  __Pyx_XDECREF(__pyx_t_15);
  __Pyx_XDECREF(__pyx_t_16);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.detect_lowest_drain_and_sink", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_drain_pixel);
  __Pyx_XDECREF(__pyx_v_sink_pixel);
  __Pyx_XDECREF(__pyx_v_dem_raster_info);
  __Pyx_XDECREF(__pyx_v_raster_x_size);
  __Pyx_XDECREF(__pyx_v_raster_y_size);
  __Pyx_XDECREF(__pyx_v_offset_dict);
  __Pyx_XDECREF(__pyx_v_win_xsize);
  __Pyx_XDECREF(__pyx_v_win_ysize);
  __Pyx_XDECREF(__pyx_v_xoff);
  __Pyx_XDECREF(__pyx_v_yoff);
  __Pyx_XDECREF(__pyx_v_current_pixel);
  __Pyx_XDECREF(__pyx_v_yi);
  __Pyx_XDECREF(__pyx_v_yi_root);
  __Pyx_XDECREF(__pyx_v_xi);
  __Pyx_XDECREF(__pyx_v_xi_root);
  __Pyx_XDECREF(__pyx_v_xi_n);
  __Pyx_XDECREF(__pyx_v_yi_n);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":4196
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_outlets(
 *         flow_dir_raster_path_band, flow_dir_type, target_outlet_vector_path):
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_29detect_outlets(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_28detect_outlets, "Create point vector indicating flow raster outlets.\n\n    If either D8 or MFD rasters have a flow direction to the edge of the\n    raster or to a nodata flow direction pixel the originating pixel is\n    considered an outlet.\n\n    Args:\n        flow_dir_raster_path_band (tuple): raster path/band tuple\n            indicating D8 or MFD flow direction created by\n            `routing.flow_dir_d8` or `routing.flow_dir_mfd`. Paths may use\n            any GDAL-supported scheme, including virtual file system /vsi schemes.\n        flow_dir_type (str): one of 'd8' or 'mfd' to indicate the\n            ``flow_dir_raster_path_band`` is either a D8 or MFD flow\n            direction raster.\n        target_outlet_vector_path (str): path to a vector that is created\n            by this call that will be in the same projection units as the\n            raster and have a point feature in the center of each pixel that\n            is a raster outlet. Additional fields include:\n\n                * \"i\" - the column raster coordinate where the outlet exists\n                * \"j\" - the row raster coordinate where the outlet exists\n                * \"ID\" - unique identification for the outlet.\n\n    Return:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_29detect_outlets = {"detect_outlets", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_29detect_outlets, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_28detect_outlets};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_29detect_outlets(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_flow_dir_raster_path_band = 0;
  PyObject *__pyx_v_flow_dir_type = 0;
  PyObject *__pyx_v_target_outlet_vector_path = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[3] = {0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("detect_outlets (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_flow_dir_raster_path_band,&__pyx_mstate_global->__pyx_n_u_flow_dir_type,&__pyx_mstate_global->__pyx_n_u_target_outlet_vector_path,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 4196, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 4196, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 4196, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4196, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "detect_outlets", 0) < (0)) __PYX_ERR(0, 4196, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 3; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("detect_outlets", 1, 3, 3, i); __PYX_ERR(0, 4196, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 3)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4196, __pyx_L3_error)
      values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 4196, __pyx_L3_error)
      values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 4196, __pyx_L3_error)
    }
    __pyx_v_flow_dir_raster_path_band = values[0];
    __pyx_v_flow_dir_type = values[1];
    __pyx_v_target_outlet_vector_path = values[2];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("detect_outlets", 1, 3, 3, __pyx_nargs); __PYX_ERR(0, 4196, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.detect_outlets", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_28detect_outlets(__pyx_self, __pyx_v_flow_dir_raster_path_band, __pyx_v_flow_dir_type, __pyx_v_target_outlet_vector_path);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_28detect_outlets(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_flow_dir_raster_path_band, PyObject *__pyx_v_flow_dir_type, PyObject *__pyx_v_target_outlet_vector_path) {
  int __pyx_v_d8_flow_dir_mode;
  unsigned int __pyx_v_xoff;
  unsigned int __pyx_v_yoff;
  unsigned int __pyx_v_win_xsize;
  unsigned int __pyx_v_win_ysize;
  unsigned int __pyx_v_xi;
  unsigned int __pyx_v_yi;
  unsigned int __pyx_v_xi_root;
  unsigned int __pyx_v_yi_root;
  unsigned int __pyx_v_raster_x_size;
  unsigned int __pyx_v_raster_y_size;
  int __pyx_v_flow_dir;
  int __pyx_v_flow_dir_n;
  int __pyx_v_next_id;
  int __pyx_v_n_dir;
  int __pyx_v_is_outlet;
  char __pyx_v_x_off_border;
  char __pyx_v_y_off_border;
  char __pyx_v_win_xsize_border;
  char __pyx_v_win_ysize_border;
  PyArrayObject *__pyx_v_flow_dir_block = 0;
  PyObject *__pyx_v_raster_info = NULL;
  int __pyx_v_flow_dir_nodata;
  PyObject *__pyx_v_flow_dir_raster = NULL;
  PyObject *__pyx_v_flow_dir_band = NULL;
  PyObject *__pyx_v_raster_srs = NULL;
  PyObject *__pyx_v_gpkg_driver = NULL;
  PyObject *__pyx_v_outlet_vector = NULL;
  PyObject *__pyx_v_outet_basename = NULL;
  PyObject *__pyx_v_outlet_layer = NULL;
  time_t __pyx_v_last_log_time;
  PyObject *__pyx_v_block_offsets = NULL;
  PyObject *__pyx_v_current_pixel = NULL;
  PyObject *__pyx_v_outlet_point = NULL;
  PyObject *__pyx_v_proj_x = NULL;
  PyObject *__pyx_v_proj_y = NULL;
  PyObject *__pyx_v_outlet_feature = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_flow_dir_block;
  __Pyx_Buffer __pyx_pybuffer_flow_dir_block;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  size_t __pyx_t_3;
  int __pyx_t_4;
  int __pyx_t_5;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  int __pyx_t_8;
  PyObject *(*__pyx_t_9)(PyObject *);
  unsigned int __pyx_t_10;
  unsigned int __pyx_t_11;
  PyObject *__pyx_t_12 = NULL;
  PyObject *__pyx_t_13 = NULL;
  PyObject *__pyx_t_14[3];
  PyObject *__pyx_t_15 = NULL;
  Py_ssize_t __pyx_t_16;
  PyObject *(*__pyx_t_17)(PyObject *);
  PyObject *__pyx_t_18 = NULL;
  PyObject *__pyx_t_19 = NULL;
  PyObject *__pyx_t_20 = NULL;
  PyObject *__pyx_t_21 = NULL;
  PyObject *__pyx_t_22 = NULL;
  PyObject *__pyx_t_23 = NULL;
  long __pyx_t_24;
  long __pyx_t_25;
  long __pyx_t_26;
  long __pyx_t_27;
  size_t __pyx_t_28;
  int __pyx_t_29;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("detect_outlets", 0);
  __Pyx_INCREF(__pyx_v_flow_dir_type);
  __pyx_pybuffer_flow_dir_block.pybuffer.buf = NULL;
  __pyx_pybuffer_flow_dir_block.refcount = 0;
  __pyx_pybuffernd_flow_dir_block.data = NULL;
  __pyx_pybuffernd_flow_dir_block.rcbuffer = &__pyx_pybuffer_flow_dir_block;

  /* "pygeoprocessing/routing/routing.pyx":4225
 *         None.
 *     """
 *     flow_dir_type = flow_dir_type.lower()             # <<<<<<<<<<<<<<
 *     if flow_dir_type not in ['d8', 'mfd']:
 *         raise ValueError(
*/
  __pyx_t_2 = __pyx_v_flow_dir_type;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_lower, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4225, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF_SET(__pyx_v_flow_dir_type, __pyx_t_1);
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4226
 *     """
 *     flow_dir_type = flow_dir_type.lower()
 *     if flow_dir_type not in ['d8', 'mfd']:             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             f'expected flow dir type of either d8 or mfd but got '
*/
  __Pyx_INCREF(__pyx_v_flow_dir_type);
  __pyx_t_1 = __pyx_v_flow_dir_type;
  __pyx_t_5 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_d8, Py_NE)); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 4226, __pyx_L1_error)
  if (__pyx_t_5) {
  } else {
    __pyx_t_4 = __pyx_t_5;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_5 = (__Pyx_PyUnicode_Equals(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_mfd, Py_NE)); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 4226, __pyx_L1_error)
  __pyx_t_4 = __pyx_t_5;
  __pyx_L4_bool_binop_done:;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_5 = __pyx_t_4;
  if (unlikely(__pyx_t_5)) {

    /* "pygeoprocessing/routing/routing.pyx":4227
 *     flow_dir_type = flow_dir_type.lower()
 *     if flow_dir_type not in ['d8', 'mfd']:
 *         raise ValueError(             # <<<<<<<<<<<<<<
 *             f'expected flow dir type of either d8 or mfd but got '
 *             f'{flow_dir_type}')
*/
    __pyx_t_2 = NULL;

    /* "pygeoprocessing/routing/routing.pyx":4229
 *         raise ValueError(
 *             f'expected flow dir type of either d8 or mfd but got '
 *             f'{flow_dir_type}')             # <<<<<<<<<<<<<<
 *     cdef int d8_flow_dir_mode = (flow_dir_type == 'd8')
 * 
*/
    __pyx_t_6 = __Pyx_PyObject_FormatSimple(__pyx_v_flow_dir_type, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4229, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);

    /* "pygeoprocessing/routing/routing.pyx":4228
 *     if flow_dir_type not in ['d8', 'mfd']:
 *         raise ValueError(
 *             f'expected flow dir type of either d8 or mfd but got '             # <<<<<<<<<<<<<<
 *             f'{flow_dir_type}')
 *     cdef int d8_flow_dir_mode = (flow_dir_type == 'd8')
*/
    __pyx_t_7 = __Pyx_PyUnicode_Concat(__pyx_mstate_global->__pyx_kp_u_expected_flow_dir_type_of_either, __pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4228, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_3 = 1;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_7};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)(((PyTypeObject*)PyExc_ValueError)), __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4227, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __PYX_ERR(0, 4227, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":4226
 *     """
 *     flow_dir_type = flow_dir_type.lower()
 *     if flow_dir_type not in ['d8', 'mfd']:             # <<<<<<<<<<<<<<
 *         raise ValueError(
 *             f'expected flow dir type of either d8 or mfd but got '
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":4230
 *             f'expected flow dir type of either d8 or mfd but got '
 *             f'{flow_dir_type}')
 *     cdef int d8_flow_dir_mode = (flow_dir_type == 'd8')             # <<<<<<<<<<<<<<
 * 
 *     cdef unsigned int xoff, yoff, win_xsize, win_ysize, xi, yi
*/
  __pyx_t_1 = PyObject_RichCompare(__pyx_v_flow_dir_type, __pyx_mstate_global->__pyx_n_u_d8, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4230, __pyx_L1_error)
  __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_1); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4230, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_d8_flow_dir_mode = __pyx_t_8;

  /* "pygeoprocessing/routing/routing.pyx":4235
 *     cdef unsigned int xi_root, yi_root, raster_x_size, raster_y_size
 *     cdef int flow_dir, flow_dir_n
 *     cdef int next_id=0, n_dir, is_outlet             # <<<<<<<<<<<<<<
 *     cdef char x_off_border, y_off_border, win_xsize_border, win_ysize_border
 * 
*/
  __pyx_v_next_id = 0;

  /* "pygeoprocessing/routing/routing.pyx":4240
 *     cdef numpy.ndarray[numpy.npy_int32, ndim=2] flow_dir_block
 * 
 *     raster_info = pygeoprocessing.get_raster_info(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0])
 * 
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_get_raster_info); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4240, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4241
 * 
 *     raster_info = pygeoprocessing.get_raster_info(
 *         flow_dir_raster_path_band[0])             # <<<<<<<<<<<<<<
 * 
 *     cdef int flow_dir_nodata = raster_info['nodata'][
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4241, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_6))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4240, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_raster_info = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4243
 *         flow_dir_raster_path_band[0])
 * 
 *     cdef int flow_dir_nodata = raster_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1]-1]
 * 
*/
  __pyx_t_1 = __Pyx_PyObject_Dict_GetItem(__pyx_v_raster_info, __pyx_mstate_global->__pyx_n_u_nodata); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4243, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":4244
 * 
 *     cdef int flow_dir_nodata = raster_info['nodata'][
 *         flow_dir_raster_path_band[1]-1]             # <<<<<<<<<<<<<<
 * 
 *     raster_x_size, raster_y_size = raster_info['raster_size']
*/
  __pyx_t_6 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4244, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_2 = __Pyx_PyLong_SubtractObjC(__pyx_t_6, __pyx_mstate_global->__pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4244, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4243
 *         flow_dir_raster_path_band[0])
 * 
 *     cdef int flow_dir_nodata = raster_info['nodata'][             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1]-1]
 * 
*/
  __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4243, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_8 = __Pyx_PyLong_As_int(__pyx_t_6); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4243, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_v_flow_dir_nodata = __pyx_t_8;

  /* "pygeoprocessing/routing/routing.pyx":4246
 *         flow_dir_raster_path_band[1]-1]
 * 
 *     raster_x_size, raster_y_size = raster_info['raster_size']             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster = gdal.OpenEx(
*/
  __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_raster_info, __pyx_mstate_global->__pyx_n_u_raster_size); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4246, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) {
    PyObject* sequence = __pyx_t_6;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 2)) {
      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 4246, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    if (likely(PyTuple_CheckExact(sequence))) {
      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0);
      __Pyx_INCREF(__pyx_t_2);
      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1);
      __Pyx_INCREF(__pyx_t_1);
    } else {
      __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4246, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4246, __pyx_L1_error)
      __Pyx_XGOTREF(__pyx_t_1);
    }
    #else
    __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4246, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4246, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    #endif
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  } else {
    Py_ssize_t index = -1;
    __pyx_t_7 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4246, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_t_9 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
    index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_2)) goto __pyx_L6_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_2);
    index = 1; __pyx_t_1 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_1)) goto __pyx_L6_unpacking_failed;
    __Pyx_GOTREF(__pyx_t_1);
    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < (0)) __PYX_ERR(0, 4246, __pyx_L1_error)
    __pyx_t_9 = NULL;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    goto __pyx_L7_unpacking_done;
    __pyx_L6_unpacking_failed:;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_9 = NULL;
    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
    __PYX_ERR(0, 4246, __pyx_L1_error)
    __pyx_L7_unpacking_done:;
  }
  __pyx_t_10 = __Pyx_PyLong_As_unsigned_int(__pyx_t_2); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4246, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_1); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4246, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_raster_x_size = __pyx_t_10;
  __pyx_v_raster_y_size = __pyx_t_11;

  /* "pygeoprocessing/routing/routing.pyx":4248
 *     raster_x_size, raster_y_size = raster_info['raster_size']
 * 
 *     flow_dir_raster = gdal.OpenEx(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
*/
  __pyx_t_1 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4248, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_OpenEx); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4248, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4249
 * 
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)             # <<<<<<<<<<<<<<
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_raster_path_band[1])
*/
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4249, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4249, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_OF_RASTER); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4249, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_1);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_1);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_t_2, __pyx_t_13};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_3, (3-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4248, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_flow_dir_raster = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4250
 *     flow_dir_raster = gdal.OpenEx(
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(             # <<<<<<<<<<<<<<
 *         flow_dir_raster_path_band[1])
 * 
*/
  __pyx_t_7 = __pyx_v_flow_dir_raster;
  __Pyx_INCREF(__pyx_t_7);

  /* "pygeoprocessing/routing/routing.pyx":4251
 *         flow_dir_raster_path_band[0], gdal.OF_RASTER)
 *     flow_dir_band = flow_dir_raster.GetRasterBand(
 *         flow_dir_raster_path_band[1])             # <<<<<<<<<<<<<<
 * 
 *     if raster_info['projection_wkt']:
*/
  __pyx_t_13 = __Pyx_GetItemInt(__pyx_v_flow_dir_raster_path_band, 1, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_FunctionArgument); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4251, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_13};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetRasterBand, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4250, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_flow_dir_band = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4253
 *         flow_dir_raster_path_band[1])
 * 
 *     if raster_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         raster_srs = osr.SpatialReference()
 *         raster_srs.ImportFromWkt(raster_info['projection_wkt'])
*/
  __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_raster_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4253, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 4253, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  if (__pyx_t_5) {

    /* "pygeoprocessing/routing/routing.pyx":4254
 * 
 *     if raster_info['projection_wkt']:
 *         raster_srs = osr.SpatialReference()             # <<<<<<<<<<<<<<
 *         raster_srs.ImportFromWkt(raster_info['projection_wkt'])
 *     else:
*/
    __pyx_t_13 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_osr); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4254, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_SpatialReference); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4254, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_3 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_13);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_13);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_3 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_13, NULL};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4254, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __pyx_v_raster_srs = __pyx_t_6;
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4255
 *     if raster_info['projection_wkt']:
 *         raster_srs = osr.SpatialReference()
 *         raster_srs.ImportFromWkt(raster_info['projection_wkt'])             # <<<<<<<<<<<<<<
 *     else:
 *         raster_srs = None
*/
    __pyx_t_2 = __pyx_v_raster_srs;
    __Pyx_INCREF(__pyx_t_2);
    __pyx_t_13 = __Pyx_PyObject_Dict_GetItem(__pyx_v_raster_info, __pyx_mstate_global->__pyx_n_u_projection_wkt); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4255, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
    __pyx_t_3 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_13};
      __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_ImportFromWkt, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4255, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4253
 *         flow_dir_raster_path_band[1])
 * 
 *     if raster_info['projection_wkt']:             # <<<<<<<<<<<<<<
 *         raster_srs = osr.SpatialReference()
 *         raster_srs.ImportFromWkt(raster_info['projection_wkt'])
*/
    goto __pyx_L8;
  }

  /* "pygeoprocessing/routing/routing.pyx":4257
 *         raster_srs.ImportFromWkt(raster_info['projection_wkt'])
 *     else:
 *         raster_srs = None             # <<<<<<<<<<<<<<
 * 
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
*/
  /*else*/ {
    __Pyx_INCREF(Py_None);
    __pyx_v_raster_srs = Py_None;
  }
  __pyx_L8:;

  /* "pygeoprocessing/routing/routing.pyx":4259
 *         raster_srs = None
 * 
 *     gpkg_driver = gdal.GetDriverByName('GPKG')             # <<<<<<<<<<<<<<
 * 
 *     if os.path.exists(target_outlet_vector_path):
*/
  __pyx_t_13 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4259, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_GetDriverByName); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4259, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_13);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_13);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_13, __pyx_mstate_global->__pyx_n_u_GPKG};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4259, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_gpkg_driver = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4261
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
 *     if os.path.exists(target_outlet_vector_path):             # <<<<<<<<<<<<<<
 *         LOGGER.warning(
 *             f'outlet detection: {target_outlet_vector_path} exists, '
*/
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4261, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4261, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __pyx_t_7 = __pyx_t_2;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_v_target_outlet_vector_path};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_exists, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4261, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_6); if (unlikely((__pyx_t_5 < 0))) __PYX_ERR(0, 4261, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  if (__pyx_t_5) {

    /* "pygeoprocessing/routing/routing.pyx":4262
 * 
 *     if os.path.exists(target_outlet_vector_path):
 *         LOGGER.warning(             # <<<<<<<<<<<<<<
 *             f'outlet detection: {target_outlet_vector_path} exists, '
 *             'removing before creating a new one.')
*/
    __pyx_t_2 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4262, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_warning); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4262, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4263
 *     if os.path.exists(target_outlet_vector_path):
 *         LOGGER.warning(
 *             f'outlet detection: {target_outlet_vector_path} exists, '             # <<<<<<<<<<<<<<
 *             'removing before creating a new one.')
 *         os.remove(target_outlet_vector_path)
*/
    __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_v_target_outlet_vector_path, __pyx_mstate_global->__pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4263, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_14[0] = __pyx_mstate_global->__pyx_kp_u_outlet_detection;
    __pyx_t_14[1] = __pyx_t_7;
    __pyx_t_14[2] = __pyx_mstate_global->__pyx_kp_u_exists_removing_before_creating;
    __pyx_t_1 = __Pyx_PyUnicode_Join(__pyx_t_14, 3, 18 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7) + 44, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7));
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4263, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __pyx_t_3 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_13))) {
      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_13);
      assert(__pyx_t_2);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_13);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_13, __pyx__function);
      __pyx_t_3 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_t_1};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_13, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4262, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4265
 *             f'outlet detection: {target_outlet_vector_path} exists, '
 *             'removing before creating a new one.')
 *         os.remove(target_outlet_vector_path)             # <<<<<<<<<<<<<<
 *     outlet_vector = gpkg_driver.Create(
 *         target_outlet_vector_path, 0, 0, 0, gdal.GDT_Unknown)
*/
    __pyx_t_13 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4265, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_remove); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4265, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_3 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_2);
      assert(__pyx_t_13);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_13);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
      __pyx_t_3 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_13, __pyx_v_target_outlet_vector_path};
      __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4265, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4261
 *     gpkg_driver = gdal.GetDriverByName('GPKG')
 * 
 *     if os.path.exists(target_outlet_vector_path):             # <<<<<<<<<<<<<<
 *         LOGGER.warning(
 *             f'outlet detection: {target_outlet_vector_path} exists, '
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":4266
 *             'removing before creating a new one.')
 *         os.remove(target_outlet_vector_path)
 *     outlet_vector = gpkg_driver.Create(             # <<<<<<<<<<<<<<
 *         target_outlet_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     outet_basename = os.path.basename(
*/
  __pyx_t_2 = __pyx_v_gpkg_driver;
  __Pyx_INCREF(__pyx_t_2);

  /* "pygeoprocessing/routing/routing.pyx":4267
 *         os.remove(target_outlet_vector_path)
 *     outlet_vector = gpkg_driver.Create(
 *         target_outlet_vector_path, 0, 0, 0, gdal.GDT_Unknown)             # <<<<<<<<<<<<<<
 *     outet_basename = os.path.basename(
 *         os.path.splitext(target_outlet_vector_path)[0])
*/
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4267, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_GDT_Unknown); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4267, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[6] = {__pyx_t_2, __pyx_v_target_outlet_vector_path, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_int_0, __pyx_t_1};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_Create, __pyx_callargs+__pyx_t_3, (6-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4266, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_outlet_vector = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4268
 *     outlet_vector = gpkg_driver.Create(
 *         target_outlet_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     outet_basename = os.path.basename(             # <<<<<<<<<<<<<<
 *         os.path.splitext(target_outlet_vector_path)[0])
 *     outlet_layer = outlet_vector.CreateLayer(
*/
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4268, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4268, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_1 = __pyx_t_13;
  __Pyx_INCREF(__pyx_t_1);

  /* "pygeoprocessing/routing/routing.pyx":4269
 *         target_outlet_vector_path, 0, 0, 0, gdal.GDT_Unknown)
 *     outet_basename = os.path.basename(
 *         os.path.splitext(target_outlet_vector_path)[0])             # <<<<<<<<<<<<<<
 *     outlet_layer = outlet_vector.CreateLayer(
 *         outet_basename, raster_srs, ogr.wkbPoint)
*/
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_os); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4269, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_path); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4269, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_7 = __pyx_t_15;
  __Pyx_INCREF(__pyx_t_7);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_v_target_outlet_vector_path};
    __pyx_t_2 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_splitext, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4269, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  __pyx_t_15 = __Pyx_GetItemInt(__pyx_t_2, 0, long, 1, __Pyx_PyLong_From_long, 0, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4269, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_15};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_basename, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4268, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_outet_basename = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4270
 *     outet_basename = os.path.basename(
 *         os.path.splitext(target_outlet_vector_path)[0])
 *     outlet_layer = outlet_vector.CreateLayer(             # <<<<<<<<<<<<<<
 *         outet_basename, raster_srs, ogr.wkbPoint)
 *     # i and j indicate the coordinates of the point in raster space whereas
*/
  __pyx_t_13 = __pyx_v_outlet_vector;
  __Pyx_INCREF(__pyx_t_13);

  /* "pygeoprocessing/routing/routing.pyx":4271
 *         os.path.splitext(target_outlet_vector_path)[0])
 *     outlet_layer = outlet_vector.CreateLayer(
 *         outet_basename, raster_srs, ogr.wkbPoint)             # <<<<<<<<<<<<<<
 *     # i and j indicate the coordinates of the point in raster space whereas
 *     # the geometry is in projected space
*/
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4271, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_wkbPoint); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4271, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[4] = {__pyx_t_13, __pyx_v_outet_basename, __pyx_v_raster_srs, __pyx_t_1};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateLayer, __pyx_callargs+__pyx_t_3, (4-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4270, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __pyx_v_outlet_layer = __pyx_t_6;
  __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4274
 *     # i and j indicate the coordinates of the point in raster space whereas
 *     # the geometry is in projected space
 *     outlet_layer.CreateField(ogr.FieldDefn('i', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     outlet_layer.CreateField(ogr.FieldDefn('j', ogr.OFTInteger))
 *     outlet_layer.CreateField(ogr.FieldDefn('ID', ogr.OFTInteger))
*/
  __pyx_t_1 = __pyx_v_outlet_layer;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_15 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4274, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4274, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4274, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4274, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_15);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_15);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_mstate_global->__pyx_n_u_i, __pyx_t_12};
    __pyx_t_13 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_3, (3-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
  }
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_13};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4274, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4275
 *     # the geometry is in projected space
 *     outlet_layer.CreateField(ogr.FieldDefn('i', ogr.OFTInteger))
 *     outlet_layer.CreateField(ogr.FieldDefn('j', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     outlet_layer.CreateField(ogr.FieldDefn('ID', ogr.OFTInteger))
 *     outlet_layer.StartTransaction()
*/
  __pyx_t_13 = __pyx_v_outlet_layer;
  __Pyx_INCREF(__pyx_t_13);
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4275, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4275, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_15);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4275, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4275, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_15))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_15);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_7, __pyx_mstate_global->__pyx_n_u_j, __pyx_t_2};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_3, (3-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4275, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_13, __pyx_t_1};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4275, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4276
 *     outlet_layer.CreateField(ogr.FieldDefn('i', ogr.OFTInteger))
 *     outlet_layer.CreateField(ogr.FieldDefn('j', ogr.OFTInteger))
 *     outlet_layer.CreateField(ogr.FieldDefn('ID', ogr.OFTInteger))             # <<<<<<<<<<<<<<
 *     outlet_layer.StartTransaction()
 * 
*/
  __pyx_t_1 = __pyx_v_outlet_layer;
  __Pyx_INCREF(__pyx_t_1);
  __pyx_t_15 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4276, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_FieldDefn); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4276, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4276, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_mstate_global->__pyx_n_u_OFTInteger); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4276, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_15);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_15);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[3] = {__pyx_t_15, __pyx_mstate_global->__pyx_n_u_ID, __pyx_t_12};
    __pyx_t_13 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_3, (3-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4276, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
  }
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_13};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateField, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4276, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4277
 *     outlet_layer.CreateField(ogr.FieldDefn('j', ogr.OFTInteger))
 *     outlet_layer.CreateField(ogr.FieldDefn('ID', ogr.OFTInteger))
 *     outlet_layer.StartTransaction()             # <<<<<<<<<<<<<<
 * 
 *     cdef time_t last_log_time = ctime(NULL)
*/
  __pyx_t_13 = __pyx_v_outlet_layer;
  __Pyx_INCREF(__pyx_t_13);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_13, NULL};
    __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_StartTransaction, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4277, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4279
 *     outlet_layer.StartTransaction()
 * 
 *     cdef time_t last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *     # iterate by iterblocks so ReadAsArray can efficiently cache reads
 *     # and writes
*/
  __pyx_v_last_log_time = time(NULL);

  /* "pygeoprocessing/routing/routing.pyx":4282
 *     # iterate by iterblocks so ReadAsArray can efficiently cache reads
 *     # and writes
 *     LOGGER.info('outlet detection: 0% complete')             # <<<<<<<<<<<<<<
 *     for block_offsets in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True):
*/
  __pyx_t_13 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4282, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4282, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_7))) {
    __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_7);
    assert(__pyx_t_13);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_13);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_7, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_13, __pyx_mstate_global->__pyx_kp_u_outlet_detection_0_complete};
    __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4282, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4283
 *     # and writes
 *     LOGGER.info('outlet detection: 0% complete')
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_pygeoprocessing); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4283, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_mstate_global->__pyx_n_u_iterblocks); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4283, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4284
 *     LOGGER.info('outlet detection: 0% complete')
 *     for block_offsets in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True):             # <<<<<<<<<<<<<<
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']
*/
  __pyx_t_3 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1);
    assert(__pyx_t_7);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_1);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_1, __pyx__function);
    __pyx_t_3 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_7, __pyx_v_flow_dir_raster_path_band};
    __pyx_t_13 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4283, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);
    if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_offset_only, Py_True, __pyx_t_13, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 4283, __pyx_L1_error)
    __pyx_t_6 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_1, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_13);
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4283, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
  }

  /* "pygeoprocessing/routing/routing.pyx":4283
 *     # and writes
 *     LOGGER.info('outlet detection: 0% complete')
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  if (likely(PyList_CheckExact(__pyx_t_6)) || PyTuple_CheckExact(__pyx_t_6)) {
    __pyx_t_1 = __pyx_t_6; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_16 = 0;
    __pyx_t_17 = NULL;
  } else {
    __pyx_t_16 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4283, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_17 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 4283, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  for (;;) {
    if (likely(!__pyx_t_17)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4283, __pyx_L1_error)
          #endif
          if (__pyx_t_16 >= __pyx_temp) break;
        }
        __pyx_t_6 = __Pyx_PyList_GetItemRefFast(__pyx_t_1, __pyx_t_16, __Pyx_ReferenceSharing_OwnStrongReference);
        ++__pyx_t_16;
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4283, __pyx_L1_error)
          #endif
          if (__pyx_t_16 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_6 = __Pyx_NewRef(PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_16));
        #else
        __pyx_t_6 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_16);
        #endif
        ++__pyx_t_16;
      }
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4283, __pyx_L1_error)
    } else {
      __pyx_t_6 = __pyx_t_17(__pyx_t_1);
      if (unlikely(!__pyx_t_6)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) __PYX_ERR(0, 4283, __pyx_L1_error)
          PyErr_Clear();
        }
        break;
      }
    }
    __Pyx_GOTREF(__pyx_t_6);
    __Pyx_XDECREF_SET(__pyx_v_block_offsets, __pyx_t_6);
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4285
 *     for block_offsets in pygeoprocessing.iterblocks(
 *             flow_dir_raster_path_band, offset_only=True):
 *         xoff = block_offsets['xoff']             # <<<<<<<<<<<<<<
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']
*/
    __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_xoff); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4285, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4285, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_xoff = __pyx_t_11;

    /* "pygeoprocessing/routing/routing.pyx":4286
 *             flow_dir_raster_path_band, offset_only=True):
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']             # <<<<<<<<<<<<<<
 *         win_xsize = block_offsets['win_xsize']
 *         win_ysize = block_offsets['win_ysize']
*/
    __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_yoff); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4286, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4286, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_yoff = __pyx_t_11;

    /* "pygeoprocessing/routing/routing.pyx":4287
 *         xoff = block_offsets['xoff']
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']             # <<<<<<<<<<<<<<
 *         win_ysize = block_offsets['win_ysize']
 * 
*/
    __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_win_xsize); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4287, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4287, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_win_xsize = __pyx_t_11;

    /* "pygeoprocessing/routing/routing.pyx":4288
 *         yoff = block_offsets['yoff']
 *         win_xsize = block_offsets['win_xsize']
 *         win_ysize = block_offsets['win_ysize']             # <<<<<<<<<<<<<<
 * 
 *         # Make an array with a 1 pixel border around the iterblocks window
*/
    __pyx_t_6 = __Pyx_PyObject_Dict_GetItem(__pyx_v_block_offsets, __pyx_mstate_global->__pyx_n_u_win_ysize); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4288, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_11 = __Pyx_PyLong_As_unsigned_int(__pyx_t_6); if (unlikely((__pyx_t_11 == (unsigned int)-1) && PyErr_Occurred())) __PYX_ERR(0, 4288, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __pyx_v_win_ysize = __pyx_t_11;

    /* "pygeoprocessing/routing/routing.pyx":4293
 *         # That border will be filled in with nodata or data from the raster
 *         # if the window does not align with a top/bottom/left/right edge
 *         flow_dir_block = numpy.empty(             # <<<<<<<<<<<<<<
 *             (win_ysize+2, win_xsize+2), dtype=numpy.int32)
 * 
*/
    __pyx_t_13 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4293, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_empty); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4293, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4294
 *         # if the window does not align with a top/bottom/left/right edge
 *         flow_dir_block = numpy.empty(
 *             (win_ysize+2, win_xsize+2), dtype=numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         # Test for left border and if so stripe nodata on the left margin
*/
    __pyx_t_7 = __Pyx_PyLong_From_long((__pyx_v_win_ysize + 2)); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4294, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __pyx_t_15 = __Pyx_PyLong_From_long((__pyx_v_win_xsize + 2)); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4294, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4294, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_GIVEREF(__pyx_t_7);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_7) != (0)) __PYX_ERR(0, 4294, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_15);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_15) != (0)) __PYX_ERR(0, 4294, __pyx_L1_error);
    __pyx_t_7 = 0;
    __pyx_t_15 = 0;
    __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4294, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4294, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_7);
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __pyx_t_3 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_12))) {
      __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_12);
      assert(__pyx_t_13);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
      __Pyx_INCREF(__pyx_t_13);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
      __pyx_t_3 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 1 : 0)] = {__pyx_t_13, __pyx_t_2};
      __pyx_t_15 = __Pyx_MakeVectorcallBuilderKwds(1); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4293, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_dtype, __pyx_t_7, __pyx_t_15, __pyx_callargs+2, 0) < (0)) __PYX_ERR(0, 4293, __pyx_L1_error)
      __pyx_t_6 = __Pyx_Object_Vectorcall_CallFromBuilder((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_15);
      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4293, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }

    /* "pygeoprocessing/routing/routing.pyx":4293
 *         # That border will be filled in with nodata or data from the raster
 *         # if the window does not align with a top/bottom/left/right edge
 *         flow_dir_block = numpy.empty(             # <<<<<<<<<<<<<<
 *             (win_ysize+2, win_xsize+2), dtype=numpy.int32)
 * 
*/
    if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_mstate_global->__pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 4293, __pyx_L1_error)
    {
      __Pyx_BufFmt_StackElem __pyx_stack[1];
      __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer);
      __pyx_t_8 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer, (PyObject*)((PyArrayObject *)__pyx_t_6), &__Pyx_TypeInfo_nn_npy_int32, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack);
      if (unlikely(__pyx_t_8 < 0)) {
        PyErr_Fetch(&__pyx_t_18, &__pyx_t_19, &__pyx_t_20);
        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer, (PyObject*)__pyx_v_flow_dir_block, &__Pyx_TypeInfo_nn_npy_int32, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {
          Py_XDECREF(__pyx_t_18); Py_XDECREF(__pyx_t_19); Py_XDECREF(__pyx_t_20);
          __Pyx_RaiseBufferFallbackError();
        } else {
          PyErr_Restore(__pyx_t_18, __pyx_t_19, __pyx_t_20);
        }
        __pyx_t_18 = __pyx_t_19 = __pyx_t_20 = 0;
      }
      __pyx_pybuffernd_flow_dir_block.diminfo[0].strides = __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_flow_dir_block.diminfo[0].shape = __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_flow_dir_block.diminfo[1].strides = __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_flow_dir_block.diminfo[1].shape = __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.shape[1];
      if (unlikely((__pyx_t_8 < 0))) __PYX_ERR(0, 4293, __pyx_L1_error)
    }
    __Pyx_XDECREF_SET(__pyx_v_flow_dir_block, ((PyArrayObject *)__pyx_t_6));
    __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4297
 * 
 *         # Test for left border and if so stripe nodata on the left margin
 *         x_off_border = 0             # <<<<<<<<<<<<<<
 *         if xoff > 0:
 *             x_off_border = 1
*/
    __pyx_v_x_off_border = 0;

    /* "pygeoprocessing/routing/routing.pyx":4298
 *         # Test for left border and if so stripe nodata on the left margin
 *         x_off_border = 0
 *         if xoff > 0:             # <<<<<<<<<<<<<<
 *             x_off_border = 1
 *         else:
*/
    __pyx_t_5 = (__pyx_v_xoff > 0);
    if (__pyx_t_5) {

      /* "pygeoprocessing/routing/routing.pyx":4299
 *         x_off_border = 0
 *         if xoff > 0:
 *             x_off_border = 1             # <<<<<<<<<<<<<<
 *         else:
 *             flow_dir_block[:, 0] = flow_dir_nodata
*/
      __pyx_v_x_off_border = 1;

      /* "pygeoprocessing/routing/routing.pyx":4298
 *         # Test for left border and if so stripe nodata on the left margin
 *         x_off_border = 0
 *         if xoff > 0:             # <<<<<<<<<<<<<<
 *             x_off_border = 1
 *         else:
*/
      goto __pyx_L12;
    }

    /* "pygeoprocessing/routing/routing.pyx":4301
 *             x_off_border = 1
 *         else:
 *             flow_dir_block[:, 0] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for top border and if so stripe nodata on the top margin
*/
    /*else*/ {
      __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4301, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_block), __pyx_mstate_global->__pyx_tuple[8], __pyx_t_6) < 0))) __PYX_ERR(0, 4301, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    }
    __pyx_L12:;

    /* "pygeoprocessing/routing/routing.pyx":4304
 * 
 *         # Test for top border and if so stripe nodata on the top margin
 *         y_off_border = 0             # <<<<<<<<<<<<<<
 *         if yoff > 0:
 *             y_off_border = 1
*/
    __pyx_v_y_off_border = 0;

    /* "pygeoprocessing/routing/routing.pyx":4305
 *         # Test for top border and if so stripe nodata on the top margin
 *         y_off_border = 0
 *         if yoff > 0:             # <<<<<<<<<<<<<<
 *             y_off_border = 1
 *         else:
*/
    __pyx_t_5 = (__pyx_v_yoff > 0);
    if (__pyx_t_5) {

      /* "pygeoprocessing/routing/routing.pyx":4306
 *         y_off_border = 0
 *         if yoff > 0:
 *             y_off_border = 1             # <<<<<<<<<<<<<<
 *         else:
 *             flow_dir_block[0, :] = flow_dir_nodata
*/
      __pyx_v_y_off_border = 1;

      /* "pygeoprocessing/routing/routing.pyx":4305
 *         # Test for top border and if so stripe nodata on the top margin
 *         y_off_border = 0
 *         if yoff > 0:             # <<<<<<<<<<<<<<
 *             y_off_border = 1
 *         else:
*/
      goto __pyx_L13;
    }

    /* "pygeoprocessing/routing/routing.pyx":4308
 *             y_off_border = 1
 *         else:
 *             flow_dir_block[0, :] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for right border and if so stripe nodata on the right margin
*/
    /*else*/ {
      __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4308, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_block), __pyx_mstate_global->__pyx_tuple[9], __pyx_t_6) < 0))) __PYX_ERR(0, 4308, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    }
    __pyx_L13:;

    /* "pygeoprocessing/routing/routing.pyx":4311
 * 
 *         # Test for right border and if so stripe nodata on the right margin
 *         win_xsize_border = 0             # <<<<<<<<<<<<<<
 *         if xoff+win_xsize < raster_x_size-1:
 *             win_xsize_border += 1
*/
    __pyx_v_win_xsize_border = 0;

    /* "pygeoprocessing/routing/routing.pyx":4312
 *         # Test for right border and if so stripe nodata on the right margin
 *         win_xsize_border = 0
 *         if xoff+win_xsize < raster_x_size-1:             # <<<<<<<<<<<<<<
 *             win_xsize_border += 1
 *         else:
*/
    __pyx_t_5 = ((__pyx_v_xoff + __pyx_v_win_xsize) < (__pyx_v_raster_x_size - 1));
    if (__pyx_t_5) {

      /* "pygeoprocessing/routing/routing.pyx":4313
 *         win_xsize_border = 0
 *         if xoff+win_xsize < raster_x_size-1:
 *             win_xsize_border += 1             # <<<<<<<<<<<<<<
 *         else:
 *             flow_dir_block[:, -1] = flow_dir_nodata
*/
      __pyx_v_win_xsize_border = (__pyx_v_win_xsize_border + 1);

      /* "pygeoprocessing/routing/routing.pyx":4312
 *         # Test for right border and if so stripe nodata on the right margin
 *         win_xsize_border = 0
 *         if xoff+win_xsize < raster_x_size-1:             # <<<<<<<<<<<<<<
 *             win_xsize_border += 1
 *         else:
*/
      goto __pyx_L14;
    }

    /* "pygeoprocessing/routing/routing.pyx":4315
 *             win_xsize_border += 1
 *         else:
 *             flow_dir_block[:, -1] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for bottom border and if so stripe nodata on the bottom margin
*/
    /*else*/ {
      __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4315, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_block), __pyx_mstate_global->__pyx_tuple[10], __pyx_t_6) < 0))) __PYX_ERR(0, 4315, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    }
    __pyx_L14:;

    /* "pygeoprocessing/routing/routing.pyx":4318
 * 
 *         # Test for bottom border and if so stripe nodata on the bottom margin
 *         win_ysize_border = 0             # <<<<<<<<<<<<<<
 *         if yoff+win_ysize < raster_y_size-1:
 *             win_ysize_border += 1
*/
    __pyx_v_win_ysize_border = 0;

    /* "pygeoprocessing/routing/routing.pyx":4319
 *         # Test for bottom border and if so stripe nodata on the bottom margin
 *         win_ysize_border = 0
 *         if yoff+win_ysize < raster_y_size-1:             # <<<<<<<<<<<<<<
 *             win_ysize_border += 1
 *         else:
*/
    __pyx_t_5 = ((__pyx_v_yoff + __pyx_v_win_ysize) < (__pyx_v_raster_y_size - 1));
    if (__pyx_t_5) {

      /* "pygeoprocessing/routing/routing.pyx":4320
 *         win_ysize_border = 0
 *         if yoff+win_ysize < raster_y_size-1:
 *             win_ysize_border += 1             # <<<<<<<<<<<<<<
 *         else:
 *             flow_dir_block[-1, :] = flow_dir_nodata
*/
      __pyx_v_win_ysize_border = (__pyx_v_win_ysize_border + 1);

      /* "pygeoprocessing/routing/routing.pyx":4319
 *         # Test for bottom border and if so stripe nodata on the bottom margin
 *         win_ysize_border = 0
 *         if yoff+win_ysize < raster_y_size-1:             # <<<<<<<<<<<<<<
 *             win_ysize_border += 1
 *         else:
*/
      goto __pyx_L15;
    }

    /* "pygeoprocessing/routing/routing.pyx":4322
 *             win_ysize_border += 1
 *         else:
 *             flow_dir_block[-1, :] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Read iterblock plus a possible margin on top/bottom/left/right side
*/
    /*else*/ {
      __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_flow_dir_nodata); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4322, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
      if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_block), __pyx_mstate_global->__pyx_tuple[11], __pyx_t_6) < 0))) __PYX_ERR(0, 4322, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    }
    __pyx_L15:;

    /* "pygeoprocessing/routing/routing.pyx":4329
 *             1-y_off_border:win_ysize+1+win_ysize_border,
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \
 *             flow_dir_band.ReadAsArray(             # <<<<<<<<<<<<<<
 *                 xoff=xoff-x_off_border,
 *                 yoff=yoff-y_off_border,
*/
    __pyx_t_7 = __pyx_v_flow_dir_band;
    __Pyx_INCREF(__pyx_t_7);

    /* "pygeoprocessing/routing/routing.pyx":4330
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \
 *             flow_dir_band.ReadAsArray(
 *                 xoff=xoff-x_off_border,             # <<<<<<<<<<<<<<
 *                 yoff=yoff-y_off_border,
 *                 win_xsize=win_xsize+win_xsize_border+x_off_border,
*/
    __pyx_t_2 = __Pyx_PyLong_From_unsigned_int((__pyx_v_xoff - __pyx_v_x_off_border)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4330, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);

    /* "pygeoprocessing/routing/routing.pyx":4331
 *             flow_dir_band.ReadAsArray(
 *                 xoff=xoff-x_off_border,
 *                 yoff=yoff-y_off_border,             # <<<<<<<<<<<<<<
 *                 win_xsize=win_xsize+win_xsize_border+x_off_border,
 *                 win_ysize=win_ysize+win_ysize_border+y_off_border).astype(
*/
    __pyx_t_13 = __Pyx_PyLong_From_unsigned_int((__pyx_v_yoff - __pyx_v_y_off_border)); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 4331, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_13);

    /* "pygeoprocessing/routing/routing.pyx":4332
 *                 xoff=xoff-x_off_border,
 *                 yoff=yoff-y_off_border,
 *                 win_xsize=win_xsize+win_xsize_border+x_off_border,             # <<<<<<<<<<<<<<
 *                 win_ysize=win_ysize+win_ysize_border+y_off_border).astype(
 *                     numpy.int32)
*/
    __pyx_t_21 = __Pyx_PyLong_From_unsigned_int(((__pyx_v_win_xsize + __pyx_v_win_xsize_border) + __pyx_v_x_off_border)); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4332, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_21);

    /* "pygeoprocessing/routing/routing.pyx":4333
 *                 yoff=yoff-y_off_border,
 *                 win_xsize=win_xsize+win_xsize_border+x_off_border,
 *                 win_ysize=win_ysize+win_ysize_border+y_off_border).astype(             # <<<<<<<<<<<<<<
 *                     numpy.int32)
 * 
*/
    __pyx_t_22 = __Pyx_PyLong_From_unsigned_int(((__pyx_v_win_ysize + __pyx_v_win_ysize_border) + __pyx_v_y_off_border)); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4333, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_22);
    __pyx_t_3 = 0;
    {
      PyObject *__pyx_callargs[2 + ((CYTHON_VECTORCALL) ? 4 : 0)] = {__pyx_t_7, NULL};
      __pyx_t_23 = __Pyx_MakeVectorcallBuilderKwds(4); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4329, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_23);
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_xoff, __pyx_t_2, __pyx_t_23, __pyx_callargs+1, 0) < (0)) __PYX_ERR(0, 4329, __pyx_L1_error)
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_yoff, __pyx_t_13, __pyx_t_23, __pyx_callargs+1, 1) < (0)) __PYX_ERR(0, 4329, __pyx_L1_error)
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_win_xsize, __pyx_t_21, __pyx_t_23, __pyx_callargs+1, 2) < (0)) __PYX_ERR(0, 4329, __pyx_L1_error)
      if (__Pyx_VectorcallBuilder_AddArg(__pyx_mstate_global->__pyx_n_u_win_ysize, __pyx_t_22, __pyx_t_23, __pyx_callargs+1, 3) < (0)) __PYX_ERR(0, 4329, __pyx_L1_error)
      __pyx_t_15 = __Pyx_Object_VectorcallMethod_CallFromBuilder((PyObject*)__pyx_mstate_global->__pyx_n_u_ReadAsArray, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET), __pyx_t_23);
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
      __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
      __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
      __Pyx_DECREF(__pyx_t_23); __pyx_t_23 = 0;
      if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4329, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_15);
    }
    __pyx_t_12 = __pyx_t_15;
    __Pyx_INCREF(__pyx_t_12);

    /* "pygeoprocessing/routing/routing.pyx":4334
 *                 win_xsize=win_xsize+win_xsize_border+x_off_border,
 *                 win_ysize=win_ysize+win_ysize_border+y_off_border).astype(
 *                     numpy.int32)             # <<<<<<<<<<<<<<
 * 
 *         for yi in range(1, win_ysize+1):
*/
    __Pyx_GetModuleGlobalName(__pyx_t_23, __pyx_mstate_global->__pyx_n_u_numpy); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4334, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_23);
    __pyx_t_22 = __Pyx_PyObject_GetAttrStr(__pyx_t_23, __pyx_mstate_global->__pyx_n_u_int32); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4334, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_22);
    __Pyx_DECREF(__pyx_t_23); __pyx_t_23 = 0;
    __pyx_t_3 = 0;
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_t_22};
      __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_astype, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
      __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
      if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4333, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_6);
    }

    /* "pygeoprocessing/routing/routing.pyx":4327
 *         # and read as type int32 to handle both d8 or mfd formats
 *         flow_dir_block[
 *             1-y_off_border:win_ysize+1+win_ysize_border,             # <<<<<<<<<<<<<<
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \
 *             flow_dir_band.ReadAsArray(
*/
    __pyx_t_15 = __Pyx_PyLong_From_long((1 - __pyx_v_y_off_border)); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4327, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __pyx_t_22 = __Pyx_PyLong_From_long(((__pyx_v_win_ysize + 1) + __pyx_v_win_ysize_border)); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4327, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_22);

    /* "pygeoprocessing/routing/routing.pyx":4326
 *         # Read iterblock plus a possible margin on top/bottom/left/right side
 *         # and read as type int32 to handle both d8 or mfd formats
 *         flow_dir_block[             # <<<<<<<<<<<<<<
 *             1-y_off_border:win_ysize+1+win_ysize_border,
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \
*/
    __pyx_t_12 = PySlice_New(__pyx_t_15, __pyx_t_22, Py_None); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4326, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_12);
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4328
 *         flow_dir_block[
 *             1-y_off_border:win_ysize+1+win_ysize_border,
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \             # <<<<<<<<<<<<<<
 *             flow_dir_band.ReadAsArray(
 *                 xoff=xoff-x_off_border,
*/
    __pyx_t_22 = __Pyx_PyLong_From_long((1 - __pyx_v_x_off_border)); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4328, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_22);
    __pyx_t_15 = __Pyx_PyLong_From_long(((__pyx_v_win_xsize + 1) + __pyx_v_win_xsize_border)); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4328, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);

    /* "pygeoprocessing/routing/routing.pyx":4326
 *         # Read iterblock plus a possible margin on top/bottom/left/right side
 *         # and read as type int32 to handle both d8 or mfd formats
 *         flow_dir_block[             # <<<<<<<<<<<<<<
 *             1-y_off_border:win_ysize+1+win_ysize_border,
 *             1-x_off_border:win_xsize+1+win_xsize_border] = \
*/
    __pyx_t_23 = PySlice_New(__pyx_t_22, __pyx_t_15, Py_None); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4326, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_23);
    __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __pyx_t_15 = PyTuple_New(2); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4326, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_15);
    __Pyx_GIVEREF(__pyx_t_12);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 0, __pyx_t_12) != (0)) __PYX_ERR(0, 4326, __pyx_L1_error);
    __Pyx_GIVEREF(__pyx_t_23);
    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_15, 1, __pyx_t_23) != (0)) __PYX_ERR(0, 4326, __pyx_L1_error);
    __pyx_t_12 = 0;
    __pyx_t_23 = 0;
    if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_flow_dir_block), __pyx_t_15, __pyx_t_6) < 0))) __PYX_ERR(0, 4326, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4336
 *                     numpy.int32)
 * 
 *         for yi in range(1, win_ysize+1):             # <<<<<<<<<<<<<<
 *             if ctime(NULL) - last_log_time > 5.0:
 *                 last_log_time = ctime(NULL)
*/
    __pyx_t_24 = (__pyx_v_win_ysize + 1);
    __pyx_t_25 = __pyx_t_24;
    for (__pyx_t_11 = 1; __pyx_t_11 < __pyx_t_25; __pyx_t_11+=1) {
      __pyx_v_yi = __pyx_t_11;

      /* "pygeoprocessing/routing/routing.pyx":4337
 * 
 *         for yi in range(1, win_ysize+1):
 *             if ctime(NULL) - last_log_time > 5.0:             # <<<<<<<<<<<<<<
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
*/
      __pyx_t_5 = ((time(NULL) - __pyx_v_last_log_time) > 5.0);
      if (__pyx_t_5) {

        /* "pygeoprocessing/routing/routing.pyx":4338
 *         for yi in range(1, win_ysize+1):
 *             if ctime(NULL) - last_log_time > 5.0:
 *                 last_log_time = ctime(NULL)             # <<<<<<<<<<<<<<
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info(
*/
        __pyx_v_last_log_time = time(NULL);

        /* "pygeoprocessing/routing/routing.pyx":4339
 *             if ctime(NULL) - last_log_time > 5.0:
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size             # <<<<<<<<<<<<<<
 *                 LOGGER.info(
 *                     f'''outlet detection: {
*/
        __pyx_t_6 = __Pyx_PyLong_From_unsigned_int((__pyx_v_xoff + (__pyx_v_yoff * __pyx_v_raster_x_size))); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4339, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __Pyx_XDECREF_SET(__pyx_v_current_pixel, __pyx_t_6);
        __pyx_t_6 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4340
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info(             # <<<<<<<<<<<<<<
 *                     f'''outlet detection: {
 *                         100.0 * current_pixel / <float>(
*/
        __pyx_t_15 = NULL;
        __Pyx_GetModuleGlobalName(__pyx_t_23, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4340, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_23);
        __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_23, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4340, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_12);
        __Pyx_DECREF(__pyx_t_23); __pyx_t_23 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4342
 *                 LOGGER.info(
 *                     f'''outlet detection: {
 *                         100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                             raster_x_size * raster_y_size):.1f} complete''')
 *             for xi in range(1, win_xsize+1):
*/
        __pyx_t_23 = PyNumber_Multiply(__pyx_mstate_global->__pyx_float_100_0, __pyx_v_current_pixel); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4342, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_23);

        /* "pygeoprocessing/routing/routing.pyx":4343
 *                     f'''outlet detection: {
 *                         100.0 * current_pixel / <float>(
 *                             raster_x_size * raster_y_size):.1f} complete''')             # <<<<<<<<<<<<<<
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_block[yi, xi]
*/
        __pyx_t_22 = PyFloat_FromDouble(((float)(__pyx_v_raster_x_size * __pyx_v_raster_y_size))); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4342, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_22);

        /* "pygeoprocessing/routing/routing.pyx":4342
 *                 LOGGER.info(
 *                     f'''outlet detection: {
 *                         100.0 * current_pixel / <float>(             # <<<<<<<<<<<<<<
 *                             raster_x_size * raster_y_size):.1f} complete''')
 *             for xi in range(1, win_xsize+1):
*/
        __pyx_t_21 = __Pyx_PyNumber_Divide(__pyx_t_23, __pyx_t_22); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4342, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_21);
        __Pyx_DECREF(__pyx_t_23); __pyx_t_23 = 0;
        __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4341
 *                 current_pixel = xoff + yoff * raster_x_size
 *                 LOGGER.info(
 *                     f'''outlet detection: {             # <<<<<<<<<<<<<<
 *                         100.0 * current_pixel / <float>(
 *                             raster_x_size * raster_y_size):.1f} complete''')
*/
        __pyx_t_22 = __Pyx_PyObject_Format(__pyx_t_21, __pyx_mstate_global->__pyx_kp_u_1f); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4341, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_22);
        __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
        __pyx_t_14[0] = __pyx_mstate_global->__pyx_kp_u_outlet_detection;
        __pyx_t_14[1] = __pyx_t_22;
        __pyx_t_14[2] = __pyx_mstate_global->__pyx_kp_u_complete_2;
        __pyx_t_21 = __Pyx_PyUnicode_Join(__pyx_t_14, 3, 18 + __Pyx_PyUnicode_GET_LENGTH(__pyx_t_22) + 9, 127 | __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_22));
        if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4341, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_21);
        __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
        __pyx_t_3 = 1;
        #if CYTHON_UNPACK_METHODS
        if (unlikely(PyMethod_Check(__pyx_t_12))) {
          __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_12);
          assert(__pyx_t_15);
          PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
          __Pyx_INCREF(__pyx_t_15);
          __Pyx_INCREF(__pyx__function);
          __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
          __pyx_t_3 = 0;
        }
        #endif
        {
          PyObject *__pyx_callargs[2] = {__pyx_t_15, __pyx_t_21};
          __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (__pyx_t_3*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
          __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
          __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
          if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4340, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_6);
        }
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

        /* "pygeoprocessing/routing/routing.pyx":4337
 * 
 *         for yi in range(1, win_ysize+1):
 *             if ctime(NULL) - last_log_time > 5.0:             # <<<<<<<<<<<<<<
 *                 last_log_time = ctime(NULL)
 *                 current_pixel = xoff + yoff * raster_x_size
*/
      }

      /* "pygeoprocessing/routing/routing.pyx":4344
 *                         100.0 * current_pixel / <float>(
 *                             raster_x_size * raster_y_size):.1f} complete''')
 *             for xi in range(1, win_xsize+1):             # <<<<<<<<<<<<<<
 *                 flow_dir = flow_dir_block[yi, xi]
 *                 if flow_dir == flow_dir_nodata:
*/
      __pyx_t_26 = (__pyx_v_win_xsize + 1);
      __pyx_t_27 = __pyx_t_26;
      for (__pyx_t_10 = 1; __pyx_t_10 < __pyx_t_27; __pyx_t_10+=1) {
        __pyx_v_xi = __pyx_t_10;

        /* "pygeoprocessing/routing/routing.pyx":4345
 *                             raster_x_size * raster_y_size):.1f} complete''')
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_block[yi, xi]             # <<<<<<<<<<<<<<
 *                 if flow_dir == flow_dir_nodata:
 *                     continue
*/
        __pyx_t_3 = __pyx_v_yi;
        __pyx_t_28 = __pyx_v_xi;
        __pyx_t_8 = -1;
        if (unlikely(__pyx_t_3 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[0].shape)) __pyx_t_8 = 0;
        if (unlikely(__pyx_t_28 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[1].shape)) __pyx_t_8 = 1;
        if (unlikely(__pyx_t_8 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_8);
          __PYX_ERR(0, 4345, __pyx_L1_error)
        }
        __pyx_v_flow_dir = (*__Pyx_BufPtrStrided2d(npy_int32 *, __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.buf, __pyx_t_3, __pyx_pybuffernd_flow_dir_block.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_flow_dir_block.diminfo[1].strides));

        /* "pygeoprocessing/routing/routing.pyx":4346
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_block[yi, xi]
 *                 if flow_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        __pyx_t_5 = (__pyx_v_flow_dir == __pyx_v_flow_dir_nodata);
        if (__pyx_t_5) {

          /* "pygeoprocessing/routing/routing.pyx":4347
 *                 flow_dir = flow_dir_block[yi, xi]
 *                 if flow_dir == flow_dir_nodata:
 *                     continue             # <<<<<<<<<<<<<<
 * 
 *                 is_outlet = 1
*/
          goto __pyx_L19_continue;

          /* "pygeoprocessing/routing/routing.pyx":4346
 *             for xi in range(1, win_xsize+1):
 *                 flow_dir = flow_dir_block[yi, xi]
 *                 if flow_dir == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                     continue
 * 
*/
        }

        /* "pygeoprocessing/routing/routing.pyx":4349
 *                     continue
 * 
 *                 is_outlet = 1             # <<<<<<<<<<<<<<
 *                 if d8_flow_dir_mode:
 *                     # inspect the outflow pixel neighbor
*/
        __pyx_v_is_outlet = 1;

        /* "pygeoprocessing/routing/routing.pyx":4350
 * 
 *                 is_outlet = 1
 *                 if d8_flow_dir_mode:             # <<<<<<<<<<<<<<
 *                     # inspect the outflow pixel neighbor
 *                     flow_dir_n = flow_dir_block[
*/
        __pyx_t_5 = (__pyx_v_d8_flow_dir_mode != 0);
        if (__pyx_t_5) {

          /* "pygeoprocessing/routing/routing.pyx":4352
 *                 if d8_flow_dir_mode:
 *                     # inspect the outflow pixel neighbor
 *                     flow_dir_n = flow_dir_block[             # <<<<<<<<<<<<<<
 *                         yi+ROW_OFFSETS[flow_dir],
 *                         xi+COL_OFFSETS[flow_dir]]
*/
          __pyx_t_28 = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_flow_dir]));
          __pyx_t_3 = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_flow_dir]));
          __pyx_t_8 = -1;
          if (unlikely(__pyx_t_28 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[0].shape)) __pyx_t_8 = 0;
          if (unlikely(__pyx_t_3 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[1].shape)) __pyx_t_8 = 1;
          if (unlikely(__pyx_t_8 != -1)) {
            __Pyx_RaiseBufferIndexError(__pyx_t_8);
            __PYX_ERR(0, 4352, __pyx_L1_error)
          }
          __pyx_v_flow_dir_n = (*__Pyx_BufPtrStrided2d(npy_int32 *, __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.buf, __pyx_t_28, __pyx_pybuffernd_flow_dir_block.diminfo[0].strides, __pyx_t_3, __pyx_pybuffernd_flow_dir_block.diminfo[1].strides));

          /* "pygeoprocessing/routing/routing.pyx":4358
 *                     # if the outflow pixel is outside the raster boundaries or
 *                     # is a nodata pixel it must mean xi,yi is an outlet
 *                     if flow_dir_n != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                         is_outlet = 0
 *                 else:
*/
          __pyx_t_5 = (__pyx_v_flow_dir_n != __pyx_v_flow_dir_nodata);
          if (__pyx_t_5) {

            /* "pygeoprocessing/routing/routing.pyx":4359
 *                     # is a nodata pixel it must mean xi,yi is an outlet
 *                     if flow_dir_n != flow_dir_nodata:
 *                         is_outlet = 0             # <<<<<<<<<<<<<<
 *                 else:
 *                     # inspect all the outflow pixel neighbors in MFD mode
*/
            __pyx_v_is_outlet = 0;

            /* "pygeoprocessing/routing/routing.pyx":4358
 *                     # if the outflow pixel is outside the raster boundaries or
 *                     # is a nodata pixel it must mean xi,yi is an outlet
 *                     if flow_dir_n != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                         is_outlet = 0
 *                 else:
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":4350
 * 
 *                 is_outlet = 1
 *                 if d8_flow_dir_mode:             # <<<<<<<<<<<<<<
 *                     # inspect the outflow pixel neighbor
 *                     flow_dir_n = flow_dir_block[
*/
          goto __pyx_L22;
        }

        /* "pygeoprocessing/routing/routing.pyx":4362
 *                 else:
 *                     # inspect all the outflow pixel neighbors in MFD mode
 *                     for n_dir in range(8):             # <<<<<<<<<<<<<<
 *                         # shift the 0xF mask to the outflow direction and
 *                         # test if there's any outflow or not. 0 means nothing
*/
        /*else*/ {
          for (__pyx_t_8 = 0; __pyx_t_8 < 8; __pyx_t_8+=1) {
            __pyx_v_n_dir = __pyx_t_8;

            /* "pygeoprocessing/routing/routing.pyx":4374
 *                         # if it equals 0 it means there was no proportional
 *                         # flow in the `n_dir` direction.
 *                         if flow_dir&(0xF<<(n_dir*4)) == 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         flow_dir_n = flow_dir_block[
*/
            __pyx_t_5 = ((__pyx_v_flow_dir & (0xF << (__pyx_v_n_dir * 4))) == 0);
            if (__pyx_t_5) {

              /* "pygeoprocessing/routing/routing.pyx":4375
 *                         # flow in the `n_dir` direction.
 *                         if flow_dir&(0xF<<(n_dir*4)) == 0:
 *                             continue             # <<<<<<<<<<<<<<
 *                         flow_dir_n = flow_dir_block[
 *                             yi+ROW_OFFSETS[n_dir],
*/
              goto __pyx_L24_continue;

              /* "pygeoprocessing/routing/routing.pyx":4374
 *                         # if it equals 0 it means there was no proportional
 *                         # flow in the `n_dir` direction.
 *                         if flow_dir&(0xF<<(n_dir*4)) == 0:             # <<<<<<<<<<<<<<
 *                             continue
 *                         flow_dir_n = flow_dir_block[
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":4376
 *                         if flow_dir&(0xF<<(n_dir*4)) == 0:
 *                             continue
 *                         flow_dir_n = flow_dir_block[             # <<<<<<<<<<<<<<
 *                             yi+ROW_OFFSETS[n_dir],
 *                             xi+COL_OFFSETS[n_dir]]
*/
            __pyx_t_3 = (__pyx_v_yi + (ROW_OFFSETS[__pyx_v_n_dir]));
            __pyx_t_28 = (__pyx_v_xi + (COL_OFFSETS[__pyx_v_n_dir]));
            __pyx_t_29 = -1;
            if (unlikely(__pyx_t_3 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[0].shape)) __pyx_t_29 = 0;
            if (unlikely(__pyx_t_28 >= (size_t)__pyx_pybuffernd_flow_dir_block.diminfo[1].shape)) __pyx_t_29 = 1;
            if (unlikely(__pyx_t_29 != -1)) {
              __Pyx_RaiseBufferIndexError(__pyx_t_29);
              __PYX_ERR(0, 4376, __pyx_L1_error)
            }
            __pyx_v_flow_dir_n = (*__Pyx_BufPtrStrided2d(npy_int32 *, __pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer.buf, __pyx_t_3, __pyx_pybuffernd_flow_dir_block.diminfo[0].strides, __pyx_t_28, __pyx_pybuffernd_flow_dir_block.diminfo[1].strides));

            /* "pygeoprocessing/routing/routing.pyx":4379
 *                             yi+ROW_OFFSETS[n_dir],
 *                             xi+COL_OFFSETS[n_dir]]
 *                         if flow_dir_n != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             is_outlet = 0
 *                             break
*/
            __pyx_t_5 = (__pyx_v_flow_dir_n != __pyx_v_flow_dir_nodata);
            if (__pyx_t_5) {

              /* "pygeoprocessing/routing/routing.pyx":4380
 *                             xi+COL_OFFSETS[n_dir]]
 *                         if flow_dir_n != flow_dir_nodata:
 *                             is_outlet = 0             # <<<<<<<<<<<<<<
 *                             break
 * 
*/
              __pyx_v_is_outlet = 0;

              /* "pygeoprocessing/routing/routing.pyx":4381
 *                         if flow_dir_n != flow_dir_nodata:
 *                             is_outlet = 0
 *                             break             # <<<<<<<<<<<<<<
 * 
 *                 # if the outflow pixel is outside the raster boundaries or
*/
              goto __pyx_L25_break;

              /* "pygeoprocessing/routing/routing.pyx":4379
 *                             yi+ROW_OFFSETS[n_dir],
 *                             xi+COL_OFFSETS[n_dir]]
 *                         if flow_dir_n != flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                             is_outlet = 0
 *                             break
*/
            }
            __pyx_L24_continue:;
          }
          __pyx_L25_break:;
        }
        __pyx_L22:;

        /* "pygeoprocessing/routing/routing.pyx":4385
 *                 # if the outflow pixel is outside the raster boundaries or
 *                 # is a nodata pixel it must mean xi,yi is an outlet
 *                 if is_outlet:             # <<<<<<<<<<<<<<
 *                     outlet_point = ogr.Geometry(ogr.wkbPoint)
 *                     # calculate global x/y raster coordinate, the -1 is for
*/
        __pyx_t_5 = (__pyx_v_is_outlet != 0);
        if (__pyx_t_5) {

          /* "pygeoprocessing/routing/routing.pyx":4386
 *                 # is a nodata pixel it must mean xi,yi is an outlet
 *                 if is_outlet:
 *                     outlet_point = ogr.Geometry(ogr.wkbPoint)             # <<<<<<<<<<<<<<
 *                     # calculate global x/y raster coordinate, the -1 is for
 *                     # the left/top border of the test array window
*/
          __pyx_t_12 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_21, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4386, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_21);
          __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_21, __pyx_mstate_global->__pyx_n_u_Geometry); if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4386, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_15);
          __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
          __Pyx_GetModuleGlobalName(__pyx_t_21, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4386, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_21);
          __pyx_t_22 = __Pyx_PyObject_GetAttrStr(__pyx_t_21, __pyx_mstate_global->__pyx_n_u_wkbPoint); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4386, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_22);
          __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
          __pyx_t_28 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_15))) {
            __pyx_t_12 = PyMethod_GET_SELF(__pyx_t_15);
            assert(__pyx_t_12);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_15);
            __Pyx_INCREF(__pyx_t_12);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_15, __pyx__function);
            __pyx_t_28 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_t_22};
            __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_15, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (__pyx_t_28*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
            __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
            __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4386, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_XDECREF_SET(__pyx_v_outlet_point, __pyx_t_6);
          __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4389
 *                     # calculate global x/y raster coordinate, the -1 is for
 *                     # the left/top border of the test array window
 *                     xi_root = xi+xoff-1             # <<<<<<<<<<<<<<
 *                     yi_root = yi+yoff-1
 *                     # created a projected point in the center of the pixel
*/
          __pyx_v_xi_root = ((__pyx_v_xi + __pyx_v_xoff) - 1);

          /* "pygeoprocessing/routing/routing.pyx":4390
 *                     # the left/top border of the test array window
 *                     xi_root = xi+xoff-1
 *                     yi_root = yi+yoff-1             # <<<<<<<<<<<<<<
 *                     # created a projected point in the center of the pixel
 *                     # thus the + 0.5 to x and y
*/
          __pyx_v_yi_root = ((__pyx_v_yi + __pyx_v_yoff) - 1);

          /* "pygeoprocessing/routing/routing.pyx":4393
 *                     # created a projected point in the center of the pixel
 *                     # thus the + 0.5 to x and y
 *                     proj_x, proj_y = gdal.ApplyGeoTransform(             # <<<<<<<<<<<<<<
 *                         raster_info['geotransform'],
 *                         xi_root+0.5, yi_root+0.5)
*/
          __pyx_t_15 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_22, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4393, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_22);
          __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_22, __pyx_mstate_global->__pyx_n_u_ApplyGeoTransform); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4393, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_12);
          __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4394
 *                     # thus the + 0.5 to x and y
 *                     proj_x, proj_y = gdal.ApplyGeoTransform(
 *                         raster_info['geotransform'],             # <<<<<<<<<<<<<<
 *                         xi_root+0.5, yi_root+0.5)
 *                     outlet_point.AddPoint(proj_x, proj_y)
*/
          __pyx_t_22 = __Pyx_PyObject_Dict_GetItem(__pyx_v_raster_info, __pyx_mstate_global->__pyx_n_u_geotransform); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 4394, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_22);

          /* "pygeoprocessing/routing/routing.pyx":4395
 *                     proj_x, proj_y = gdal.ApplyGeoTransform(
 *                         raster_info['geotransform'],
 *                         xi_root+0.5, yi_root+0.5)             # <<<<<<<<<<<<<<
 *                     outlet_point.AddPoint(proj_x, proj_y)
 *                     outlet_feature = ogr.Feature(outlet_layer.GetLayerDefn())
*/
          __pyx_t_21 = PyFloat_FromDouble((__pyx_v_xi_root + 0.5)); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4395, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_21);
          __pyx_t_23 = PyFloat_FromDouble((__pyx_v_yi_root + 0.5)); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4395, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_23);
          __pyx_t_28 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_12))) {
            __pyx_t_15 = PyMethod_GET_SELF(__pyx_t_12);
            assert(__pyx_t_15);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
            __Pyx_INCREF(__pyx_t_15);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
            __pyx_t_28 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[4] = {__pyx_t_15, __pyx_t_22, __pyx_t_21, __pyx_t_23};
            __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_28, (4-__pyx_t_28) | (__pyx_t_28*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
            __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
            __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
            __Pyx_DECREF(__pyx_t_23); __pyx_t_23 = 0;
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4393, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) {
            PyObject* sequence = __pyx_t_6;
            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
            if (unlikely(size != 2)) {
              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
              __PYX_ERR(0, 4393, __pyx_L1_error)
            }
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            if (likely(PyTuple_CheckExact(sequence))) {
              __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0);
              __Pyx_INCREF(__pyx_t_12);
              __pyx_t_23 = PyTuple_GET_ITEM(sequence, 1);
              __Pyx_INCREF(__pyx_t_23);
            } else {
              __pyx_t_12 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
              if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4393, __pyx_L1_error)
              __Pyx_XGOTREF(__pyx_t_12);
              __pyx_t_23 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
              if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4393, __pyx_L1_error)
              __Pyx_XGOTREF(__pyx_t_23);
            }
            #else
            __pyx_t_12 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4393, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_12);
            __pyx_t_23 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_23)) __PYX_ERR(0, 4393, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_23);
            #endif
            __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
          } else {
            Py_ssize_t index = -1;
            __pyx_t_21 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4393, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_21);
            __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
            __pyx_t_9 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_21);
            index = 0; __pyx_t_12 = __pyx_t_9(__pyx_t_21); if (unlikely(!__pyx_t_12)) goto __pyx_L29_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_12);
            index = 1; __pyx_t_23 = __pyx_t_9(__pyx_t_21); if (unlikely(!__pyx_t_23)) goto __pyx_L29_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_23);
            if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_21), 2) < (0)) __PYX_ERR(0, 4393, __pyx_L1_error)
            __pyx_t_9 = NULL;
            __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
            goto __pyx_L30_unpacking_done;
            __pyx_L29_unpacking_failed:;
            __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
            __pyx_t_9 = NULL;
            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
            __PYX_ERR(0, 4393, __pyx_L1_error)
            __pyx_L30_unpacking_done:;
          }

          /* "pygeoprocessing/routing/routing.pyx":4393
 *                     # created a projected point in the center of the pixel
 *                     # thus the + 0.5 to x and y
 *                     proj_x, proj_y = gdal.ApplyGeoTransform(             # <<<<<<<<<<<<<<
 *                         raster_info['geotransform'],
 *                         xi_root+0.5, yi_root+0.5)
*/
          __Pyx_XDECREF_SET(__pyx_v_proj_x, __pyx_t_12);
          __pyx_t_12 = 0;
          __Pyx_XDECREF_SET(__pyx_v_proj_y, __pyx_t_23);
          __pyx_t_23 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4396
 *                         raster_info['geotransform'],
 *                         xi_root+0.5, yi_root+0.5)
 *                     outlet_point.AddPoint(proj_x, proj_y)             # <<<<<<<<<<<<<<
 *                     outlet_feature = ogr.Feature(outlet_layer.GetLayerDefn())
 *                     outlet_feature.SetGeometry(outlet_point)
*/
          __pyx_t_23 = __pyx_v_outlet_point;
          __Pyx_INCREF(__pyx_t_23);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_23, __pyx_v_proj_x, __pyx_v_proj_y};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddPoint, __pyx_callargs+__pyx_t_28, (3-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_23); __pyx_t_23 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4396, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4397
 *                         xi_root+0.5, yi_root+0.5)
 *                     outlet_point.AddPoint(proj_x, proj_y)
 *                     outlet_feature = ogr.Feature(outlet_layer.GetLayerDefn())             # <<<<<<<<<<<<<<
 *                     outlet_feature.SetGeometry(outlet_point)
 *                     # save the raster coordinates of the outlet pixel as i,j
*/
          __pyx_t_23 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4397, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_12);
          __pyx_t_21 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_Feature); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4397, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_21);
          __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
          __pyx_t_22 = __pyx_v_outlet_layer;
          __Pyx_INCREF(__pyx_t_22);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_22, NULL};
            __pyx_t_12 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetLayerDefn, __pyx_callargs+__pyx_t_28, (1-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_22); __pyx_t_22 = 0;
            if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4397, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_12);
          }
          __pyx_t_28 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_21))) {
            __pyx_t_23 = PyMethod_GET_SELF(__pyx_t_21);
            assert(__pyx_t_23);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_21);
            __Pyx_INCREF(__pyx_t_23);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_21, __pyx__function);
            __pyx_t_28 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_23, __pyx_t_12};
            __pyx_t_6 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_21, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (__pyx_t_28*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_23); __pyx_t_23 = 0;
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
            __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4397, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_XDECREF_SET(__pyx_v_outlet_feature, __pyx_t_6);
          __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4398
 *                     outlet_point.AddPoint(proj_x, proj_y)
 *                     outlet_feature = ogr.Feature(outlet_layer.GetLayerDefn())
 *                     outlet_feature.SetGeometry(outlet_point)             # <<<<<<<<<<<<<<
 *                     # save the raster coordinates of the outlet pixel as i,j
 *                     outlet_feature.SetField('i', xi_root)
*/
          __pyx_t_21 = __pyx_v_outlet_feature;
          __Pyx_INCREF(__pyx_t_21);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_21, __pyx_v_outlet_point};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetGeometry, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4398, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4400
 *                     outlet_feature.SetGeometry(outlet_point)
 *                     # save the raster coordinates of the outlet pixel as i,j
 *                     outlet_feature.SetField('i', xi_root)             # <<<<<<<<<<<<<<
 *                     outlet_feature.SetField('j', yi_root)
 *                     outlet_feature.SetField('ID', next_id)
*/
          __pyx_t_21 = __pyx_v_outlet_feature;
          __Pyx_INCREF(__pyx_t_21);
          __pyx_t_12 = __Pyx_PyLong_From_unsigned_int(__pyx_v_xi_root); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4400, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_12);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_21, __pyx_mstate_global->__pyx_n_u_i, __pyx_t_12};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_28, (3-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0;
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4400, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4401
 *                     # save the raster coordinates of the outlet pixel as i,j
 *                     outlet_feature.SetField('i', xi_root)
 *                     outlet_feature.SetField('j', yi_root)             # <<<<<<<<<<<<<<
 *                     outlet_feature.SetField('ID', next_id)
 *                     next_id += 1
*/
          __pyx_t_12 = __pyx_v_outlet_feature;
          __Pyx_INCREF(__pyx_t_12);
          __pyx_t_21 = __Pyx_PyLong_From_unsigned_int(__pyx_v_yi_root); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4401, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_21);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_12, __pyx_mstate_global->__pyx_n_u_j, __pyx_t_21};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_28, (3-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
            __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4401, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4402
 *                     outlet_feature.SetField('i', xi_root)
 *                     outlet_feature.SetField('j', yi_root)
 *                     outlet_feature.SetField('ID', next_id)             # <<<<<<<<<<<<<<
 *                     next_id += 1
 *                     outlet_layer.CreateFeature(outlet_feature)
*/
          __pyx_t_21 = __pyx_v_outlet_feature;
          __Pyx_INCREF(__pyx_t_21);
          __pyx_t_12 = __Pyx_PyLong_From_int(__pyx_v_next_id); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4402, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_12);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_21, __pyx_mstate_global->__pyx_n_u_ID, __pyx_t_12};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_SetField, __pyx_callargs+__pyx_t_28, (3-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0;
            __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4402, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4403
 *                     outlet_feature.SetField('j', yi_root)
 *                     outlet_feature.SetField('ID', next_id)
 *                     next_id += 1             # <<<<<<<<<<<<<<
 *                     outlet_layer.CreateFeature(outlet_feature)
 *                     outlet_feature = None
*/
          __pyx_v_next_id = (__pyx_v_next_id + 1);

          /* "pygeoprocessing/routing/routing.pyx":4404
 *                     outlet_feature.SetField('ID', next_id)
 *                     next_id += 1
 *                     outlet_layer.CreateFeature(outlet_feature)             # <<<<<<<<<<<<<<
 *                     outlet_feature = None
 *                     outlet_point = None
*/
          __pyx_t_12 = __pyx_v_outlet_layer;
          __Pyx_INCREF(__pyx_t_12);
          __pyx_t_28 = 0;
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_12, __pyx_v_outlet_feature};
            __pyx_t_6 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CreateFeature, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_12); __pyx_t_12 = 0;
            if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4404, __pyx_L1_error)
            __Pyx_GOTREF(__pyx_t_6);
          }
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4405
 *                     next_id += 1
 *                     outlet_layer.CreateFeature(outlet_feature)
 *                     outlet_feature = None             # <<<<<<<<<<<<<<
 *                     outlet_point = None
 * 
*/
          __Pyx_INCREF(Py_None);
          __Pyx_DECREF_SET(__pyx_v_outlet_feature, Py_None);

          /* "pygeoprocessing/routing/routing.pyx":4406
 *                     outlet_layer.CreateFeature(outlet_feature)
 *                     outlet_feature = None
 *                     outlet_point = None             # <<<<<<<<<<<<<<
 * 
 *     flow_dir_raster = None
*/
          __Pyx_INCREF(Py_None);
          __Pyx_DECREF_SET(__pyx_v_outlet_point, Py_None);

          /* "pygeoprocessing/routing/routing.pyx":4385
 *                 # if the outflow pixel is outside the raster boundaries or
 *                 # is a nodata pixel it must mean xi,yi is an outlet
 *                 if is_outlet:             # <<<<<<<<<<<<<<
 *                     outlet_point = ogr.Geometry(ogr.wkbPoint)
 *                     # calculate global x/y raster coordinate, the -1 is for
*/
        }
        __pyx_L19_continue:;
      }
    }

    /* "pygeoprocessing/routing/routing.pyx":4283
 *     # and writes
 *     LOGGER.info('outlet detection: 0% complete')
 *     for block_offsets in pygeoprocessing.iterblocks(             # <<<<<<<<<<<<<<
 *             flow_dir_raster_path_band, offset_only=True):
 *         xoff = block_offsets['xoff']
*/
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4408
 *                     outlet_point = None
 * 
 *     flow_dir_raster = None             # <<<<<<<<<<<<<<
 *     flow_dir_band = None
 *     LOGGER.info('outlet detection: 100% complete -- committing transaction')
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_flow_dir_raster, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4409
 * 
 *     flow_dir_raster = None
 *     flow_dir_band = None             # <<<<<<<<<<<<<<
 *     LOGGER.info('outlet detection: 100% complete -- committing transaction')
 *     outlet_layer.CommitTransaction()
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_flow_dir_band, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4410
 *     flow_dir_raster = None
 *     flow_dir_band = None
 *     LOGGER.info('outlet detection: 100% complete -- committing transaction')             # <<<<<<<<<<<<<<
 *     outlet_layer.CommitTransaction()
 *     outlet_layer = None
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4410, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_21 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_21)) __PYX_ERR(0, 4410, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_21);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_28 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_21))) {
    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_21);
    assert(__pyx_t_6);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_21);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_21, __pyx__function);
    __pyx_t_28 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_mstate_global->__pyx_kp_u_outlet_detection_100_complete_co};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_21, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (__pyx_t_28*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4410, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4411
 *     flow_dir_band = None
 *     LOGGER.info('outlet detection: 100% complete -- committing transaction')
 *     outlet_layer.CommitTransaction()             # <<<<<<<<<<<<<<
 *     outlet_layer = None
 *     outlet_vector = None
*/
  __pyx_t_21 = __pyx_v_outlet_layer;
  __Pyx_INCREF(__pyx_t_21);
  __pyx_t_28 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_21, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_CommitTransaction, __pyx_callargs+__pyx_t_28, (1-__pyx_t_28) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4411, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4412
 *     LOGGER.info('outlet detection: 100% complete -- committing transaction')
 *     outlet_layer.CommitTransaction()
 *     outlet_layer = None             # <<<<<<<<<<<<<<
 *     outlet_vector = None
 *     LOGGER.info('outlet detection: done')
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_outlet_layer, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4413
 *     outlet_layer.CommitTransaction()
 *     outlet_layer = None
 *     outlet_vector = None             # <<<<<<<<<<<<<<
 *     LOGGER.info('outlet detection: done')
 * 
*/
  __Pyx_INCREF(Py_None);
  __Pyx_DECREF_SET(__pyx_v_outlet_vector, Py_None);

  /* "pygeoprocessing/routing/routing.pyx":4414
 *     outlet_layer = None
 *     outlet_vector = None
 *     LOGGER.info('outlet detection: done')             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_21 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_LOGGER); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4414, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_info); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 4414, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_28 = 1;
  #if CYTHON_UNPACK_METHODS
  if (unlikely(PyMethod_Check(__pyx_t_12))) {
    __pyx_t_21 = PyMethod_GET_SELF(__pyx_t_12);
    assert(__pyx_t_21);
    PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_12);
    __Pyx_INCREF(__pyx_t_21);
    __Pyx_INCREF(__pyx__function);
    __Pyx_DECREF_SET(__pyx_t_12, __pyx__function);
    __pyx_t_28 = 0;
  }
  #endif
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_21, __pyx_mstate_global->__pyx_kp_u_outlet_detection_done};
    __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_12, __pyx_callargs+__pyx_t_28, (2-__pyx_t_28) | (__pyx_t_28*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_21); __pyx_t_21 = 0;
    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4414, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4196
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_outlets(
 *         flow_dir_raster_path_band, flow_dir_type, target_outlet_vector_path):
*/

  /* function exit code */
  __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_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_XDECREF(__pyx_t_13);
  __Pyx_XDECREF(__pyx_t_15);
  __Pyx_XDECREF(__pyx_t_21);
  __Pyx_XDECREF(__pyx_t_22);
  __Pyx_XDECREF(__pyx_t_23);
  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("pygeoprocessing.routing.routing.detect_outlets", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_flow_dir_block.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_flow_dir_block);
  __Pyx_XDECREF(__pyx_v_raster_info);
  __Pyx_XDECREF(__pyx_v_flow_dir_raster);
  __Pyx_XDECREF(__pyx_v_flow_dir_band);
  __Pyx_XDECREF(__pyx_v_raster_srs);
  __Pyx_XDECREF(__pyx_v_gpkg_driver);
  __Pyx_XDECREF(__pyx_v_outlet_vector);
  __Pyx_XDECREF(__pyx_v_outet_basename);
  __Pyx_XDECREF(__pyx_v_outlet_layer);
  __Pyx_XDECREF(__pyx_v_block_offsets);
  __Pyx_XDECREF(__pyx_v_current_pixel);
  __Pyx_XDECREF(__pyx_v_outlet_point);
  __Pyx_XDECREF(__pyx_v_proj_x);
  __Pyx_XDECREF(__pyx_v_proj_y);
  __Pyx_XDECREF(__pyx_v_outlet_feature);
  __Pyx_XDECREF(__pyx_v_flow_dir_type);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":4417
 * 
 * 
 * cdef void _diagonal_fill_step(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int edge_dir,
 *         long discovery, long finish,
*/

static void __pyx_f_15pygeoprocessing_7routing_7routing__diagonal_fill_step(int __pyx_v_x_l, int __pyx_v_y_l, int __pyx_v_edge_dir, long __pyx_v_discovery, long __pyx_v_finish, ManagedRaster __pyx_v_discovery_managed_raster, long __pyx_v_discovery_nodata, PyObject *__pyx_v_boundary_list) {
  int __pyx_v_xdelta;
  int __pyx_v_ydelta;
  PyObject *__pyx_v_test_list = NULL;
  PyObject *__pyx_v_x_t = NULL;
  PyObject *__pyx_v_y_t = NULL;
  long __pyx_v_point_discovery;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  Py_ssize_t __pyx_t_6;
  PyObject *__pyx_t_7 = NULL;
  PyObject *(*__pyx_t_8)(PyObject *);
  long __pyx_t_9;
  long __pyx_t_10;
  int __pyx_t_11;
  int __pyx_t_12;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_diagonal_fill_step", 0);

  /* "pygeoprocessing/routing/routing.pyx":4455
 *     """
 *     # always add the current pixel
 *     boundary_list.append((x_l, y_l))             # <<<<<<<<<<<<<<
 * 
 *     # this section determines which back diagonal was in the watershed and
*/
  __pyx_t_1 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4455, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4455, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4455, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 4455, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 4455, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_2 = 0;
  __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_boundary_list, __pyx_t_3); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 4455, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4459
 *     # this section determines which back diagonal was in the watershed and
 *     # fills it. if none are we pick one so there's no degenerate case
 *     cdef int xdelta = COL_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *     cdef int ydelta = ROW_OFFSETS[edge_dir]
 *     test_list = [
*/
  __pyx_v_xdelta = (COL_OFFSETS[__pyx_v_edge_dir]);

  /* "pygeoprocessing/routing/routing.pyx":4460
 *     # fills it. if none are we pick one so there's no degenerate case
 *     cdef int xdelta = COL_OFFSETS[edge_dir]
 *     cdef int ydelta = ROW_OFFSETS[edge_dir]             # <<<<<<<<<<<<<<
 *     test_list = [
 *         (x_l - xdelta, y_l),
*/
  __pyx_v_ydelta = (ROW_OFFSETS[__pyx_v_edge_dir]);

  /* "pygeoprocessing/routing/routing.pyx":4462
 *     cdef int ydelta = ROW_OFFSETS[edge_dir]
 *     test_list = [
 *         (x_l - xdelta, y_l),             # <<<<<<<<<<<<<<
 *         (x_l, y_l - ydelta)]
 *     for x_t, y_t in test_list:
*/
  __pyx_t_3 = __Pyx_PyLong_From_int((__pyx_v_x_l - __pyx_v_xdelta)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4462, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_3);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 4462, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 4462, __pyx_L1_error);
  __pyx_t_3 = 0;
  __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4463
 *     test_list = [
 *         (x_l - xdelta, y_l),
 *         (x_l, y_l - ydelta)]             # <<<<<<<<<<<<<<
 *     for x_t, y_t in test_list:
 *         point_discovery = <long>discovery_managed_raster.get(
*/
  __pyx_t_2 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4463, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyLong_From_int((__pyx_v_y_l - __pyx_v_ydelta)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4463, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4463, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GIVEREF(__pyx_t_2);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2) != (0)) __PYX_ERR(0, 4463, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_3);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_3) != (0)) __PYX_ERR(0, 4463, __pyx_L1_error);
  __pyx_t_2 = 0;
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4461
 *     cdef int xdelta = COL_OFFSETS[edge_dir]
 *     cdef int ydelta = ROW_OFFSETS[edge_dir]
 *     test_list = [             # <<<<<<<<<<<<<<
 *         (x_l - xdelta, y_l),
 *         (x_l, y_l - ydelta)]
*/
  __pyx_t_3 = PyList_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4461, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_1);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 4461, __pyx_L1_error);
  __Pyx_GIVEREF(__pyx_t_5);
  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 1, __pyx_t_5) != (0)) __PYX_ERR(0, 4461, __pyx_L1_error);
  __pyx_t_1 = 0;
  __pyx_t_5 = 0;
  __pyx_v_test_list = ((PyObject*)__pyx_t_3);
  __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4464
 *         (x_l - xdelta, y_l),
 *         (x_l, y_l - ydelta)]
 *     for x_t, y_t in test_list:             # <<<<<<<<<<<<<<
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)
*/
  __pyx_t_3 = __pyx_v_test_list; __Pyx_INCREF(__pyx_t_3);
  __pyx_t_6 = 0;
  for (;;) {
    {
      Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_3);
      #if !CYTHON_ASSUME_SAFE_SIZE
      if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 4464, __pyx_L1_error)
      #endif
      if (__pyx_t_6 >= __pyx_temp) break;
    }
    __pyx_t_5 = __Pyx_PyList_GetItemRefFast(__pyx_t_3, __pyx_t_6, __Pyx_ReferenceSharing_OwnStrongReference);
    ++__pyx_t_6;
    if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4464, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    if ((likely(PyTuple_CheckExact(__pyx_t_5))) || (PyList_CheckExact(__pyx_t_5))) {
      PyObject* sequence = __pyx_t_5;
      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
      if (unlikely(size != 2)) {
        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
        __PYX_ERR(0, 4464, __pyx_L1_error)
      }
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      if (likely(PyTuple_CheckExact(sequence))) {
        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0);
        __Pyx_INCREF(__pyx_t_1);
        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
        __Pyx_INCREF(__pyx_t_2);
      } else {
        __pyx_t_1 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4464, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_1);
        __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
        if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4464, __pyx_L1_error)
        __Pyx_XGOTREF(__pyx_t_2);
      }
      #else
      __pyx_t_1 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4464, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4464, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      #endif
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    } else {
      Py_ssize_t index = -1;
      __pyx_t_7 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4464, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_7);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __pyx_t_8 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_7);
      index = 0; __pyx_t_1 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_1)) goto __pyx_L5_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_1);
      index = 1; __pyx_t_2 = __pyx_t_8(__pyx_t_7); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed;
      __Pyx_GOTREF(__pyx_t_2);
      if (__Pyx_IternextUnpackEndCheck(__pyx_t_8(__pyx_t_7), 2) < (0)) __PYX_ERR(0, 4464, __pyx_L1_error)
      __pyx_t_8 = NULL;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      goto __pyx_L6_unpacking_done;
      __pyx_L5_unpacking_failed:;
      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
      __pyx_t_8 = NULL;
      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
      __PYX_ERR(0, 4464, __pyx_L1_error)
      __pyx_L6_unpacking_done:;
    }
    __Pyx_XDECREF_SET(__pyx_v_x_t, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_XDECREF_SET(__pyx_v_y_t, __pyx_t_2);
    __pyx_t_2 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4466
 *     for x_t, y_t in test_list:
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)             # <<<<<<<<<<<<<<
 *         if (point_discovery != discovery_nodata and
 *                 point_discovery >= discovery and
*/
    __pyx_t_9 = __Pyx_PyLong_As_long(__pyx_v_x_t); if (unlikely((__pyx_t_9 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4466, __pyx_L1_error)
    __pyx_t_10 = __Pyx_PyLong_As_long(__pyx_v_y_t); if (unlikely((__pyx_t_10 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 4466, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":4465
 *         (x_l, y_l - ydelta)]
 *     for x_t, y_t in test_list:
 *         point_discovery = <long>discovery_managed_raster.get(             # <<<<<<<<<<<<<<
 *             x_t, y_t)
 *         if (point_discovery != discovery_nodata and
*/
    __pyx_v_point_discovery = ((long)__pyx_v_discovery_managed_raster.get(__pyx_t_9, __pyx_t_10));

    /* "pygeoprocessing/routing/routing.pyx":4467
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)
 *         if (point_discovery != discovery_nodata and             # <<<<<<<<<<<<<<
 *                 point_discovery >= discovery and
 *                 point_discovery <= finish):
*/
    __pyx_t_12 = (__pyx_v_point_discovery != __pyx_v_discovery_nodata);
    if (__pyx_t_12) {
    } else {
      __pyx_t_11 = __pyx_t_12;
      goto __pyx_L8_bool_binop_done;
    }

    /* "pygeoprocessing/routing/routing.pyx":4468
 *             x_t, y_t)
 *         if (point_discovery != discovery_nodata and
 *                 point_discovery >= discovery and             # <<<<<<<<<<<<<<
 *                 point_discovery <= finish):
 *             boundary_list.append((int(x_t), int(y_t)))
*/
    __pyx_t_12 = (__pyx_v_point_discovery >= __pyx_v_discovery);
    if (__pyx_t_12) {
    } else {
      __pyx_t_11 = __pyx_t_12;
      goto __pyx_L8_bool_binop_done;
    }

    /* "pygeoprocessing/routing/routing.pyx":4469
 *         if (point_discovery != discovery_nodata and
 *                 point_discovery >= discovery and
 *                 point_discovery <= finish):             # <<<<<<<<<<<<<<
 *             boundary_list.append((int(x_t), int(y_t)))
 *             # there's only one diagonal to fill in so it's done here
*/
    __pyx_t_12 = (__pyx_v_point_discovery <= __pyx_v_finish);
    __pyx_t_11 = __pyx_t_12;
    __pyx_L8_bool_binop_done:;

    /* "pygeoprocessing/routing/routing.pyx":4467
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)
 *         if (point_discovery != discovery_nodata and             # <<<<<<<<<<<<<<
 *                 point_discovery >= discovery and
 *                 point_discovery <= finish):
*/
    if (__pyx_t_11) {

      /* "pygeoprocessing/routing/routing.pyx":4470
 *                 point_discovery >= discovery and
 *                 point_discovery <= finish):
 *             boundary_list.append((int(x_t), int(y_t)))             # <<<<<<<<<<<<<<
 *             # there's only one diagonal to fill in so it's done here
 *             return
*/
      __pyx_t_5 = __Pyx_PyNumber_Int(__pyx_v_x_t); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4470, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_2 = __Pyx_PyNumber_Int(__pyx_v_y_t); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4470, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4470, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_GIVEREF(__pyx_t_5);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5) != (0)) __PYX_ERR(0, 4470, __pyx_L1_error);
      __Pyx_GIVEREF(__pyx_t_2);
      if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 4470, __pyx_L1_error);
      __pyx_t_5 = 0;
      __pyx_t_2 = 0;
      __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_boundary_list, __pyx_t_1); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 4470, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4472
 *             boundary_list.append((int(x_t), int(y_t)))
 *             # there's only one diagonal to fill in so it's done here
 *             return             # <<<<<<<<<<<<<<
 * 
 *     # if there's a degenerate case then just add the xdelta,
*/
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      goto __pyx_L0;

      /* "pygeoprocessing/routing/routing.pyx":4467
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)
 *         if (point_discovery != discovery_nodata and             # <<<<<<<<<<<<<<
 *                 point_discovery >= discovery and
 *                 point_discovery <= finish):
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":4464
 *         (x_l - xdelta, y_l),
 *         (x_l, y_l - ydelta)]
 *     for x_t, y_t in test_list:             # <<<<<<<<<<<<<<
 *         point_discovery = <long>discovery_managed_raster.get(
 *             x_t, y_t)
*/
  }
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4476
 *     # if there's a degenerate case then just add the xdelta,
 *     # it doesn't matter
 *     boundary_list.append(test_list[0])             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_test_list, 0, long, 1, __Pyx_PyLong_From_long, 1, 0, 1, 1, __Pyx_ReferenceSharing_OwnStrongReference); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4476, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_Append(__pyx_v_boundary_list, __pyx_t_3); if (unlikely(__pyx_t_4 == ((int)-1))) __PYX_ERR(0, 4476, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4417
 * 
 * 
 * cdef void _diagonal_fill_step(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int edge_dir,
 *         long discovery, long finish,
*/

  /* function exit code */
  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_5);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._diagonal_fill_step", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_test_list);
  __Pyx_XDECREF(__pyx_v_x_t);
  __Pyx_XDECREF(__pyx_v_y_t);
  __Pyx_RefNannyFinishContext();
}

/* "pygeoprocessing/routing/routing.pyx":4479
 * 
 * 
 * cdef int _in_watershed(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int direction_to_test, int discovery, int finish,
 *         int n_cols, int n_rows,
*/

static int __pyx_f_15pygeoprocessing_7routing_7routing__in_watershed(int __pyx_v_x_l, int __pyx_v_y_l, int __pyx_v_direction_to_test, int __pyx_v_discovery, int __pyx_v_finish, int __pyx_v_n_cols, int __pyx_v_n_rows, ManagedRaster __pyx_v_discovery_managed_raster, long __pyx_v_discovery_nodata) {
  int __pyx_v_x_n;
  int __pyx_v_y_n;
  long __pyx_v_point_discovery;
  int __pyx_r;
  int __pyx_t_1;
  int __pyx_t_2;
  int __pyx_t_3;

  /* "pygeoprocessing/routing/routing.pyx":4502
 *         1 if in, 0 if out.
 *     """
 *     cdef int x_n = x_l + COL_OFFSETS[direction_to_test]             # <<<<<<<<<<<<<<
 *     cdef int y_n = y_l + ROW_OFFSETS[direction_to_test]
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
*/
  __pyx_v_x_n = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_direction_to_test]));

  /* "pygeoprocessing/routing/routing.pyx":4503
 *     """
 *     cdef int x_n = x_l + COL_OFFSETS[direction_to_test]
 *     cdef int y_n = y_l + ROW_OFFSETS[direction_to_test]             # <<<<<<<<<<<<<<
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *         return 0
*/
  __pyx_v_y_n = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_direction_to_test]));

  /* "pygeoprocessing/routing/routing.pyx":4504
 *     cdef int x_n = x_l + COL_OFFSETS[direction_to_test]
 *     cdef int y_n = y_l + ROW_OFFSETS[direction_to_test]
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *         return 0
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)
*/
  __pyx_t_2 = (__pyx_v_x_n < 0);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = (__pyx_v_y_n < 0);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = (__pyx_v_x_n >= __pyx_v_n_cols);
  if (!__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = (__pyx_v_y_n >= __pyx_v_n_rows);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (__pyx_t_1) {

    /* "pygeoprocessing/routing/routing.pyx":4505
 *     cdef int y_n = y_l + ROW_OFFSETS[direction_to_test]
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *         return 0             # <<<<<<<<<<<<<<
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)
 *     return (point_discovery != discovery_nodata and
*/
    __pyx_r = 0;
    goto __pyx_L0;

    /* "pygeoprocessing/routing/routing.pyx":4504
 *     cdef int x_n = x_l + COL_OFFSETS[direction_to_test]
 *     cdef int y_n = y_l + ROW_OFFSETS[direction_to_test]
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *         return 0
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":4506
 *     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *         return 0
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)             # <<<<<<<<<<<<<<
 *     return (point_discovery != discovery_nodata and
 *             point_discovery >= discovery and
*/
  __pyx_v_point_discovery = ((long)__pyx_v_discovery_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n));

  /* "pygeoprocessing/routing/routing.pyx":4507
 *         return 0
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)
 *     return (point_discovery != discovery_nodata and             # <<<<<<<<<<<<<<
 *             point_discovery >= discovery and
 *             point_discovery <= finish)
*/
  __pyx_t_1 = (__pyx_v_point_discovery != __pyx_v_discovery_nodata);
  if (__pyx_t_1) {
  } else {
    __pyx_t_3 = __pyx_t_1;
    goto __pyx_L8_bool_binop_done;
  }

  /* "pygeoprocessing/routing/routing.pyx":4508
 *     cdef long point_discovery = <long>discovery_managed_raster.get(x_n, y_n)
 *     return (point_discovery != discovery_nodata and
 *             point_discovery >= discovery and             # <<<<<<<<<<<<<<
 *             point_discovery <= finish)
 * 
*/
  __pyx_t_1 = (__pyx_v_point_discovery >= __pyx_v_discovery);
  if (__pyx_t_1) {
  } else {
    __pyx_t_3 = __pyx_t_1;
    goto __pyx_L8_bool_binop_done;
  }

  /* "pygeoprocessing/routing/routing.pyx":4509
 *     return (point_discovery != discovery_nodata and
 *             point_discovery >= discovery and
 *             point_discovery <= finish)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_t_1 = (__pyx_v_point_discovery <= __pyx_v_finish);
  __pyx_t_3 = __pyx_t_1;
  __pyx_L8_bool_binop_done:;
  __pyx_r = __pyx_t_3;
  goto __pyx_L0;

  /* "pygeoprocessing/routing/routing.pyx":4479
 * 
 * 
 * cdef int _in_watershed(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int direction_to_test, int discovery, int finish,
 *         int n_cols, int n_rows,
*/

  /* function exit code */
  __pyx_L0:;
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":4512
 * 
 * 
 * cdef _calculate_stream_geometry(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int upstream_d8_dir, geotransform, int n_cols,
 *         int n_rows, ManagedRaster flow_accum_managed_raster,
*/

static PyObject *__pyx_f_15pygeoprocessing_7routing_7routing__calculate_stream_geometry(int __pyx_v_x_l, int __pyx_v_y_l, int __pyx_v_upstream_d8_dir, PyObject *__pyx_v_geotransform, int __pyx_v_n_cols, int __pyx_v_n_rows, ManagedRaster __pyx_v_flow_accum_managed_raster, ManagedRaster __pyx_v_flow_dir_managed_raster, int __pyx_v_flow_dir_nodata, int __pyx_v_flow_accum_threshold, PyObject *__pyx_v_coord_to_stream_ids) {
  int __pyx_v_x_1;
  int __pyx_v_y_1;
  int __pyx_v_x_n;
  int __pyx_v_y_n;
  int __pyx_v_d;
  int __pyx_v_d_n;
  int __pyx_v_stream_end;
  int __pyx_v_pixel_length;
  int __pyx_v_next_dir;
  int __pyx_v_last_dir;
  PyObject *__pyx_v_upstream_id_list = NULL;
  PyObject *__pyx_v_stream_line = NULL;
  PyObject *__pyx_v_x_p = NULL;
  PyObject *__pyx_v_y_p = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  PyObject *__pyx_t_3 = NULL;
  size_t __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  PyObject *__pyx_t_8 = NULL;
  PyObject *__pyx_t_9 = NULL;
  int __pyx_t_10;
  PyObject *__pyx_t_11 = NULL;
  PyObject *(*__pyx_t_12)(PyObject *);
  int __pyx_t_13;
  int __pyx_t_14;
  PyObject *__pyx_t_15 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_calculate_stream_geometry", 0);

  /* "pygeoprocessing/routing/routing.pyx":4554
 * 
 *     """
 *     cdef int x_1, y_1, x_n, y_n, d, d_n, stream_end=0, pixel_length             # <<<<<<<<<<<<<<
 *     cdef int next_dir
 *     cdef int last_dir
*/
  __pyx_v_stream_end = 0;

  /* "pygeoprocessing/routing/routing.pyx":4558
 *     cdef int last_dir
 * 
 *     with GDALUseExceptions():             # <<<<<<<<<<<<<<
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:
*/
  /*with:*/ {
    __pyx_t_2 = NULL;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_mstate_global->__pyx_n_u_GDALUseExceptions); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4558, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
      assert(__pyx_t_2);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
      __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (1-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4558, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
    }
    __pyx_t_5 = __Pyx_PyObject_LookupSpecial(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_exit); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4558, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_2 = NULL;
    __pyx_t_6 = __Pyx_PyObject_LookupSpecial(__pyx_t_1, __pyx_mstate_global->__pyx_n_u_enter); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4558, __pyx_L3_error)
    __Pyx_GOTREF(__pyx_t_6);
    __pyx_t_4 = 1;
    #if CYTHON_UNPACK_METHODS
    if (likely(PyMethod_Check(__pyx_t_6))) {
      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_6);
      assert(__pyx_t_2);
      PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_6);
      __Pyx_INCREF(__pyx_t_2);
      __Pyx_INCREF(__pyx__function);
      __Pyx_DECREF_SET(__pyx_t_6, __pyx__function);
      __pyx_t_4 = 0;
    }
    #endif
    {
      PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
      __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_4, (1-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4558, __pyx_L3_error)
      __Pyx_GOTREF(__pyx_t_3);
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    /*try:*/ {
      {
        __Pyx_PyThreadState_declare
        __Pyx_PyThreadState_assign
        __Pyx_ExceptionSave(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9);
        __Pyx_XGOTREF(__pyx_t_7);
        __Pyx_XGOTREF(__pyx_t_8);
        __Pyx_XGOTREF(__pyx_t_9);
        /*try:*/ {

          /* "pygeoprocessing/routing/routing.pyx":4560
 *     with GDALUseExceptions():
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:             # <<<<<<<<<<<<<<
 *             return None
 *         upstream_id_list = []
*/
          __pyx_t_10 = (__pyx_v_flow_accum_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l) < __pyx_v_flow_accum_threshold);
          if (__pyx_t_10) {

            /* "pygeoprocessing/routing/routing.pyx":4561
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:
 *             return None             # <<<<<<<<<<<<<<
 *         upstream_id_list = []
 *         # anchor the line at the downstream end
*/
            __Pyx_XDECREF(__pyx_r);
            __pyx_r = Py_None; __Pyx_INCREF(Py_None);
            goto __pyx_L11_try_return;

            /* "pygeoprocessing/routing/routing.pyx":4560
 *     with GDALUseExceptions():
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:             # <<<<<<<<<<<<<<
 *             return None
 *         upstream_id_list = []
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":4562
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:
 *             return None
 *         upstream_id_list = []             # <<<<<<<<<<<<<<
 *         # anchor the line at the downstream end
 *         stream_line = ogr.Geometry(ogr.wkbLineString)
*/
          __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4562, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __pyx_v_upstream_id_list = __pyx_t_1;
          __pyx_t_1 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4564
 *         upstream_id_list = []
 *         # anchor the line at the downstream end
 *         stream_line = ogr.Geometry(ogr.wkbLineString)             # <<<<<<<<<<<<<<
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_l+0.5, y_l+0.5)
 *         stream_line.AddPoint(x_p, y_p)
*/
          __pyx_t_3 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4564, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_6);
          __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_Geometry); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4564, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ogr); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4564, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_6);
          __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_wkbLineString); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4564, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_11);
          __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
          __pyx_t_4 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_2))) {
            __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
            assert(__pyx_t_3);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_2);
            __Pyx_INCREF(__pyx_t_3);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_2, __pyx__function);
            __pyx_t_4 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_t_11};
            __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_2, __pyx_callargs+__pyx_t_4, (2-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
            __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
            __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
            if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4564, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_1);
          }
          __pyx_v_stream_line = __pyx_t_1;
          __pyx_t_1 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4565
 *         # anchor the line at the downstream end
 *         stream_line = ogr.Geometry(ogr.wkbLineString)
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_l+0.5, y_l+0.5)             # <<<<<<<<<<<<<<
 *         stream_line.AddPoint(x_p, y_p)
 * 
*/
          __pyx_t_2 = NULL;
          __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4565, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_11);
          __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_mstate_global->__pyx_n_u_ApplyGeoTransform); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4565, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_3);
          __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
          __pyx_t_11 = PyFloat_FromDouble((__pyx_v_x_l + 0.5)); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4565, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_11);
          __pyx_t_6 = PyFloat_FromDouble((__pyx_v_y_l + 0.5)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4565, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_6);
          __pyx_t_4 = 1;
          #if CYTHON_UNPACK_METHODS
          if (unlikely(PyMethod_Check(__pyx_t_3))) {
            __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
            assert(__pyx_t_2);
            PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_3);
            __Pyx_INCREF(__pyx_t_2);
            __Pyx_INCREF(__pyx__function);
            __Pyx_DECREF_SET(__pyx_t_3, __pyx__function);
            __pyx_t_4 = 0;
          }
          #endif
          {
            PyObject *__pyx_callargs[4] = {__pyx_t_2, __pyx_v_geotransform, __pyx_t_11, __pyx_t_6};
            __pyx_t_1 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_3, __pyx_callargs+__pyx_t_4, (4-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
            __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
            __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4565, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_1);
          }
          if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
            PyObject* sequence = __pyx_t_1;
            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
            if (unlikely(size != 2)) {
              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
              __PYX_ERR(0, 4565, __pyx_L7_error)
            }
            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
            if (likely(PyTuple_CheckExact(sequence))) {
              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0);
              __Pyx_INCREF(__pyx_t_3);
              __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1);
              __Pyx_INCREF(__pyx_t_6);
            } else {
              __pyx_t_3 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
              if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4565, __pyx_L7_error)
              __Pyx_XGOTREF(__pyx_t_3);
              __pyx_t_6 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
              if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4565, __pyx_L7_error)
              __Pyx_XGOTREF(__pyx_t_6);
            }
            #else
            __pyx_t_3 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4565, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_3);
            __pyx_t_6 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4565, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_6);
            #endif
            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          } else {
            Py_ssize_t index = -1;
            __pyx_t_11 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4565, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_11);
            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
            __pyx_t_12 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_11);
            index = 0; __pyx_t_3 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_3)) goto __pyx_L14_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_3);
            index = 1; __pyx_t_6 = __pyx_t_12(__pyx_t_11); if (unlikely(!__pyx_t_6)) goto __pyx_L14_unpacking_failed;
            __Pyx_GOTREF(__pyx_t_6);
            if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_11), 2) < (0)) __PYX_ERR(0, 4565, __pyx_L7_error)
            __pyx_t_12 = NULL;
            __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
            goto __pyx_L15_unpacking_done;
            __pyx_L14_unpacking_failed:;
            __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
            __pyx_t_12 = NULL;
            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
            __PYX_ERR(0, 4565, __pyx_L7_error)
            __pyx_L15_unpacking_done:;
          }
          __pyx_v_x_p = __pyx_t_3;
          __pyx_t_3 = 0;
          __pyx_v_y_p = __pyx_t_6;
          __pyx_t_6 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4566
 *         stream_line = ogr.Geometry(ogr.wkbLineString)
 *         x_p, y_p = gdal.ApplyGeoTransform(geotransform, x_l+0.5, y_l+0.5)
 *         stream_line.AddPoint(x_p, y_p)             # <<<<<<<<<<<<<<
 * 
 *         # initialize next_dir and last_dir so we only drop new points when
*/
          __pyx_t_6 = __pyx_v_stream_line;
          __Pyx_INCREF(__pyx_t_6);
          __pyx_t_4 = 0;
          {
            PyObject *__pyx_callargs[3] = {__pyx_t_6, __pyx_v_x_p, __pyx_v_y_p};
            __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddPoint, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
            __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
            if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4566, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_1);
          }
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

          /* "pygeoprocessing/routing/routing.pyx":4570
 *         # initialize next_dir and last_dir so we only drop new points when
 *         # the line changes direction
 *         next_dir = upstream_d8_dir             # <<<<<<<<<<<<<<
 *         last_dir = next_dir
 * 
*/
          __pyx_v_next_dir = __pyx_v_upstream_d8_dir;

          /* "pygeoprocessing/routing/routing.pyx":4571
 *         # the line changes direction
 *         next_dir = upstream_d8_dir
 *         last_dir = next_dir             # <<<<<<<<<<<<<<
 * 
 *         stream_end = 0
*/
          __pyx_v_last_dir = __pyx_v_next_dir;

          /* "pygeoprocessing/routing/routing.pyx":4573
 *         last_dir = next_dir
 * 
 *         stream_end = 0             # <<<<<<<<<<<<<<
 *         pixel_length = 0
 *         # initialize these for the compiler warniing
*/
          __pyx_v_stream_end = 0;

          /* "pygeoprocessing/routing/routing.pyx":4574
 * 
 *         stream_end = 0
 *         pixel_length = 0             # <<<<<<<<<<<<<<
 *         # initialize these for the compiler warniing
 *         x_1 = -1
*/
          __pyx_v_pixel_length = 0;

          /* "pygeoprocessing/routing/routing.pyx":4576
 *         pixel_length = 0
 *         # initialize these for the compiler warniing
 *         x_1 = -1             # <<<<<<<<<<<<<<
 *         y_1 = -1
 *         while not stream_end:
*/
          __pyx_v_x_1 = -1;

          /* "pygeoprocessing/routing/routing.pyx":4577
 *         # initialize these for the compiler warniing
 *         x_1 = -1
 *         y_1 = -1             # <<<<<<<<<<<<<<
 *         while not stream_end:
 *             # walk upstream
*/
          __pyx_v_y_1 = -1;

          /* "pygeoprocessing/routing/routing.pyx":4578
 *         x_1 = -1
 *         y_1 = -1
 *         while not stream_end:             # <<<<<<<<<<<<<<
 *             # walk upstream
 *             x_l += COL_OFFSETS[next_dir]
*/
          while (1) {
            __pyx_t_10 = (!(__pyx_v_stream_end != 0));
            if (!__pyx_t_10) break;

            /* "pygeoprocessing/routing/routing.pyx":4580
 *         while not stream_end:
 *             # walk upstream
 *             x_l += COL_OFFSETS[next_dir]             # <<<<<<<<<<<<<<
 *             y_l += ROW_OFFSETS[next_dir]
 * 
*/
            __pyx_v_x_l = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_next_dir]));

            /* "pygeoprocessing/routing/routing.pyx":4581
 *             # walk upstream
 *             x_l += COL_OFFSETS[next_dir]
 *             y_l += ROW_OFFSETS[next_dir]             # <<<<<<<<<<<<<<
 * 
 *             stream_end = 1
*/
            __pyx_v_y_l = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_next_dir]));

            /* "pygeoprocessing/routing/routing.pyx":4583
 *             y_l += ROW_OFFSETS[next_dir]
 * 
 *             stream_end = 1             # <<<<<<<<<<<<<<
 *             pixel_length += 1
 *             # do <= 1 in case there's a degenerate single point stream
*/
            __pyx_v_stream_end = 1;

            /* "pygeoprocessing/routing/routing.pyx":4584
 * 
 *             stream_end = 1
 *             pixel_length += 1             # <<<<<<<<<<<<<<
 *             # do <= 1 in case there's a degenerate single point stream
 *             if pixel_length <= 1:
*/
            __pyx_v_pixel_length = (__pyx_v_pixel_length + 1);

            /* "pygeoprocessing/routing/routing.pyx":4586
 *             pixel_length += 1
 *             # do <= 1 in case there's a degenerate single point stream
 *             if pixel_length <= 1:             # <<<<<<<<<<<<<<
 *                 x_1 = x_l
 *                 y_1 = y_l
*/
            __pyx_t_10 = (__pyx_v_pixel_length <= 1);
            if (__pyx_t_10) {

              /* "pygeoprocessing/routing/routing.pyx":4587
 *             # do <= 1 in case there's a degenerate single point stream
 *             if pixel_length <= 1:
 *                 x_1 = x_l             # <<<<<<<<<<<<<<
 *                 y_1 = y_l
 * 
*/
              __pyx_v_x_1 = __pyx_v_x_l;

              /* "pygeoprocessing/routing/routing.pyx":4588
 *             if pixel_length <= 1:
 *                 x_1 = x_l
 *                 y_1 = y_l             # <<<<<<<<<<<<<<
 * 
 *             # check if we reached an upstream junction
*/
              __pyx_v_y_1 = __pyx_v_y_l;

              /* "pygeoprocessing/routing/routing.pyx":4586
 *             pixel_length += 1
 *             # do <= 1 in case there's a degenerate single point stream
 *             if pixel_length <= 1:             # <<<<<<<<<<<<<<
 *                 x_1 = x_l
 *                 y_1 = y_l
*/
            }

            /* "pygeoprocessing/routing/routing.pyx":4591
 * 
 *             # check if we reached an upstream junction
 *             if (x_l, y_l) in coord_to_stream_ids:             # <<<<<<<<<<<<<<
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]
 *                 del coord_to_stream_ids[(x_l, y_l)]
*/
            __pyx_t_1 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4591, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_1);
            __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4591, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_6);
            __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4591, __pyx_L7_error)
            __Pyx_GOTREF(__pyx_t_3);
            __Pyx_GIVEREF(__pyx_t_1);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_1) != (0)) __PYX_ERR(0, 4591, __pyx_L7_error);
            __Pyx_GIVEREF(__pyx_t_6);
            if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_6) != (0)) __PYX_ERR(0, 4591, __pyx_L7_error);
            __pyx_t_1 = 0;
            __pyx_t_6 = 0;
            __pyx_t_10 = (__Pyx_PySequence_ContainsTF(__pyx_t_3, __pyx_v_coord_to_stream_ids, Py_EQ)); if (unlikely((__pyx_t_10 < 0))) __PYX_ERR(0, 4591, __pyx_L7_error)
            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
            if (__pyx_t_10) {

              /* "pygeoprocessing/routing/routing.pyx":4592
 *             # check if we reached an upstream junction
 *             if (x_l, y_l) in coord_to_stream_ids:
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]             # <<<<<<<<<<<<<<
 *                 del coord_to_stream_ids[(x_l, y_l)]
 *             elif <int>flow_accum_managed_raster.get(x_l, y_l) >= \
*/
              __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4592, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_3);
              __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4592, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_6);
              __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4592, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_1);
              __Pyx_GIVEREF(__pyx_t_3);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 4592, __pyx_L7_error);
              __Pyx_GIVEREF(__pyx_t_6);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_6) != (0)) __PYX_ERR(0, 4592, __pyx_L7_error);
              __pyx_t_3 = 0;
              __pyx_t_6 = 0;
              __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_coord_to_stream_ids, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4592, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_6);
              __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
              __Pyx_DECREF_SET(__pyx_v_upstream_id_list, __pyx_t_6);
              __pyx_t_6 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4593
 *             if (x_l, y_l) in coord_to_stream_ids:
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]
 *                 del coord_to_stream_ids[(x_l, y_l)]             # <<<<<<<<<<<<<<
 *             elif <int>flow_accum_managed_raster.get(x_l, y_l) >= \
 *                     flow_accum_threshold:
*/
              __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4593, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_6);
              __pyx_t_1 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4593, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_1);
              __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4593, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_3);
              __Pyx_GIVEREF(__pyx_t_6);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_6) != (0)) __PYX_ERR(0, 4593, __pyx_L7_error);
              __Pyx_GIVEREF(__pyx_t_1);
              if (__Pyx_PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1) != (0)) __PYX_ERR(0, 4593, __pyx_L7_error);
              __pyx_t_6 = 0;
              __pyx_t_1 = 0;
              if (unlikely((PyObject_DelItem(__pyx_v_coord_to_stream_ids, __pyx_t_3) < 0))) __PYX_ERR(0, 4593, __pyx_L7_error)
              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4591
 * 
 *             # check if we reached an upstream junction
 *             if (x_l, y_l) in coord_to_stream_ids:             # <<<<<<<<<<<<<<
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]
 *                 del coord_to_stream_ids[(x_l, y_l)]
*/
              goto __pyx_L19;
            }

            /* "pygeoprocessing/routing/routing.pyx":4594
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]
 *                 del coord_to_stream_ids[(x_l, y_l)]
 *             elif <int>flow_accum_managed_raster.get(x_l, y_l) >= \             # <<<<<<<<<<<<<<
 *                     flow_accum_threshold:
 *                 # check to see if we can take a step upstream
*/
            __pyx_t_10 = (((int)__pyx_v_flow_accum_managed_raster.get(__pyx_v_x_l, __pyx_v_y_l)) >= __pyx_v_flow_accum_threshold);
            if (__pyx_t_10) {

              /* "pygeoprocessing/routing/routing.pyx":4597
 *                     flow_accum_threshold:
 *                 # check to see if we can take a step upstream
 *                 for d in range(8):             # <<<<<<<<<<<<<<
 *                     x_n = x_l + COL_OFFSETS[d]
 *                     y_n = y_l + ROW_OFFSETS[d]
*/
              for (__pyx_t_13 = 0; __pyx_t_13 < 8; __pyx_t_13+=1) {
                __pyx_v_d = __pyx_t_13;

                /* "pygeoprocessing/routing/routing.pyx":4598
 *                 # check to see if we can take a step upstream
 *                 for d in range(8):
 *                     x_n = x_l + COL_OFFSETS[d]             # <<<<<<<<<<<<<<
 *                     y_n = y_l + ROW_OFFSETS[d]
 * 
*/
                __pyx_v_x_n = (__pyx_v_x_l + (COL_OFFSETS[__pyx_v_d]));

                /* "pygeoprocessing/routing/routing.pyx":4599
 *                 for d in range(8):
 *                     x_n = x_l + COL_OFFSETS[d]
 *                     y_n = y_l + ROW_OFFSETS[d]             # <<<<<<<<<<<<<<
 * 
 *                     # check out of bounds
*/
                __pyx_v_y_n = (__pyx_v_y_l + (ROW_OFFSETS[__pyx_v_d]));

                /* "pygeoprocessing/routing/routing.pyx":4602
 * 
 *                     # check out of bounds
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
                __pyx_t_14 = (__pyx_v_x_n < 0);
                if (!__pyx_t_14) {
                } else {
                  __pyx_t_10 = __pyx_t_14;
                  goto __pyx_L23_bool_binop_done;
                }
                __pyx_t_14 = (__pyx_v_y_n < 0);
                if (!__pyx_t_14) {
                } else {
                  __pyx_t_10 = __pyx_t_14;
                  goto __pyx_L23_bool_binop_done;
                }
                __pyx_t_14 = (__pyx_v_x_n >= __pyx_v_n_cols);
                if (!__pyx_t_14) {
                } else {
                  __pyx_t_10 = __pyx_t_14;
                  goto __pyx_L23_bool_binop_done;
                }
                __pyx_t_14 = (__pyx_v_y_n >= __pyx_v_n_rows);
                __pyx_t_10 = __pyx_t_14;
                __pyx_L23_bool_binop_done:;
                if (__pyx_t_10) {

                  /* "pygeoprocessing/routing/routing.pyx":4603
 *                     # check out of bounds
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:
 *                         continue             # <<<<<<<<<<<<<<
 * 
 *                     # check for nodata
*/
                  goto __pyx_L20_continue;

                  /* "pygeoprocessing/routing/routing.pyx":4602
 * 
 *                     # check out of bounds
 *                     if x_n < 0 or y_n < 0 or x_n >= n_cols or y_n >= n_rows:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
                }

                /* "pygeoprocessing/routing/routing.pyx":4606
 * 
 *                     # check for nodata
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)             # <<<<<<<<<<<<<<
 *                     if d_n == flow_dir_nodata:
 *                         continue
*/
                __pyx_v_d_n = ((int)__pyx_v_flow_dir_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n));

                /* "pygeoprocessing/routing/routing.pyx":4607
 *                     # check for nodata
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
                __pyx_t_10 = (__pyx_v_d_n == __pyx_v_flow_dir_nodata);
                if (__pyx_t_10) {

                  /* "pygeoprocessing/routing/routing.pyx":4608
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_dir_nodata:
 *                         continue             # <<<<<<<<<<<<<<
 * 
 *                     # check if there's an upstream inflow pixel with flow accum
*/
                  goto __pyx_L20_continue;

                  /* "pygeoprocessing/routing/routing.pyx":4607
 *                     # check for nodata
 *                     d_n = <int>flow_dir_managed_raster.get(x_n, y_n)
 *                     if d_n == flow_dir_nodata:             # <<<<<<<<<<<<<<
 *                         continue
 * 
*/
                }

                /* "pygeoprocessing/routing/routing.pyx":4612
 *                     # check if there's an upstream inflow pixel with flow accum
 *                     # greater than the threshold
 *                     if INFLOW_OFFSETS[d] == d_n and (             # <<<<<<<<<<<<<<
 *                             <int>flow_accum_managed_raster.get(
 *                              x_n, y_n) > flow_accum_threshold):
*/
                __pyx_t_14 = ((INFLOW_OFFSETS[__pyx_v_d]) == __pyx_v_d_n);
                if (__pyx_t_14) {
                } else {
                  __pyx_t_10 = __pyx_t_14;
                  goto __pyx_L29_bool_binop_done;
                }

                /* "pygeoprocessing/routing/routing.pyx":4614
 *                     if INFLOW_OFFSETS[d] == d_n and (
 *                             <int>flow_accum_managed_raster.get(
 *                              x_n, y_n) > flow_accum_threshold):             # <<<<<<<<<<<<<<
 *                         stream_end = 0
 *                         next_dir = d
*/
                __pyx_t_14 = (((int)__pyx_v_flow_accum_managed_raster.get(__pyx_v_x_n, __pyx_v_y_n)) > __pyx_v_flow_accum_threshold);
                __pyx_t_10 = __pyx_t_14;
                __pyx_L29_bool_binop_done:;

                /* "pygeoprocessing/routing/routing.pyx":4612
 *                     # check if there's an upstream inflow pixel with flow accum
 *                     # greater than the threshold
 *                     if INFLOW_OFFSETS[d] == d_n and (             # <<<<<<<<<<<<<<
 *                             <int>flow_accum_managed_raster.get(
 *                              x_n, y_n) > flow_accum_threshold):
*/
                if (__pyx_t_10) {

                  /* "pygeoprocessing/routing/routing.pyx":4615
 *                             <int>flow_accum_managed_raster.get(
 *                              x_n, y_n) > flow_accum_threshold):
 *                         stream_end = 0             # <<<<<<<<<<<<<<
 *                         next_dir = d
 *                         break
*/
                  __pyx_v_stream_end = 0;

                  /* "pygeoprocessing/routing/routing.pyx":4616
 *                              x_n, y_n) > flow_accum_threshold):
 *                         stream_end = 0
 *                         next_dir = d             # <<<<<<<<<<<<<<
 *                         break
 *             else:
*/
                  __pyx_v_next_dir = __pyx_v_d;

                  /* "pygeoprocessing/routing/routing.pyx":4617
 *                         stream_end = 0
 *                         next_dir = d
 *                         break             # <<<<<<<<<<<<<<
 *             else:
 *                 # terminated because of flow accumulation too small, so back up
*/
                  goto __pyx_L21_break;

                  /* "pygeoprocessing/routing/routing.pyx":4612
 *                     # check if there's an upstream inflow pixel with flow accum
 *                     # greater than the threshold
 *                     if INFLOW_OFFSETS[d] == d_n and (             # <<<<<<<<<<<<<<
 *                             <int>flow_accum_managed_raster.get(
 *                              x_n, y_n) > flow_accum_threshold):
*/
                }
                __pyx_L20_continue:;
              }
              __pyx_L21_break:;

              /* "pygeoprocessing/routing/routing.pyx":4594
 *                 upstream_id_list = coord_to_stream_ids[(x_l, y_l)]
 *                 del coord_to_stream_ids[(x_l, y_l)]
 *             elif <int>flow_accum_managed_raster.get(x_l, y_l) >= \             # <<<<<<<<<<<<<<
 *                     flow_accum_threshold:
 *                 # check to see if we can take a step upstream
*/
              goto __pyx_L19;
            }

            /* "pygeoprocessing/routing/routing.pyx":4621
 *                 # terminated because of flow accumulation too small, so back up
 *                 # one pixel
 *                 pixel_length -= 1             # <<<<<<<<<<<<<<
 * 
 *             # drop a point on the line if direction changed or last point
*/
            /*else*/ {
              __pyx_v_pixel_length = (__pyx_v_pixel_length - 1);
            }
            __pyx_L19:;

            /* "pygeoprocessing/routing/routing.pyx":4624
 * 
 *             # drop a point on the line if direction changed or last point
 *             if last_dir != next_dir or stream_end:             # <<<<<<<<<<<<<<
 *                 x_p, y_p = gdal.ApplyGeoTransform(
 *                     geotransform, x_l+0.5, y_l+0.5)
*/
            __pyx_t_14 = (__pyx_v_last_dir != __pyx_v_next_dir);
            if (!__pyx_t_14) {
            } else {
              __pyx_t_10 = __pyx_t_14;
              goto __pyx_L32_bool_binop_done;
            }
            __pyx_t_14 = (__pyx_v_stream_end != 0);
            __pyx_t_10 = __pyx_t_14;
            __pyx_L32_bool_binop_done:;
            if (__pyx_t_10) {

              /* "pygeoprocessing/routing/routing.pyx":4625
 *             # drop a point on the line if direction changed or last point
 *             if last_dir != next_dir or stream_end:
 *                 x_p, y_p = gdal.ApplyGeoTransform(             # <<<<<<<<<<<<<<
 *                     geotransform, x_l+0.5, y_l+0.5)
 *                 stream_line.AddPoint(x_p, y_p)
*/
              __pyx_t_1 = NULL;
              __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4625, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_6);
              __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_ApplyGeoTransform); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4625, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_11);
              __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4626
 *             if last_dir != next_dir or stream_end:
 *                 x_p, y_p = gdal.ApplyGeoTransform(
 *                     geotransform, x_l+0.5, y_l+0.5)             # <<<<<<<<<<<<<<
 *                 stream_line.AddPoint(x_p, y_p)
 *                 last_dir = next_dir
*/
              __pyx_t_6 = PyFloat_FromDouble((__pyx_v_x_l + 0.5)); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4626, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_6);
              __pyx_t_2 = PyFloat_FromDouble((__pyx_v_y_l + 0.5)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4626, __pyx_L7_error)
              __Pyx_GOTREF(__pyx_t_2);
              __pyx_t_4 = 1;
              #if CYTHON_UNPACK_METHODS
              if (unlikely(PyMethod_Check(__pyx_t_11))) {
                __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_11);
                assert(__pyx_t_1);
                PyObject* __pyx__function = PyMethod_GET_FUNCTION(__pyx_t_11);
                __Pyx_INCREF(__pyx_t_1);
                __Pyx_INCREF(__pyx__function);
                __Pyx_DECREF_SET(__pyx_t_11, __pyx__function);
                __pyx_t_4 = 0;
              }
              #endif
              {
                PyObject *__pyx_callargs[4] = {__pyx_t_1, __pyx_v_geotransform, __pyx_t_6, __pyx_t_2};
                __pyx_t_3 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_11, __pyx_callargs+__pyx_t_4, (4-__pyx_t_4) | (__pyx_t_4*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
                __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
                __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
                __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
                if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4625, __pyx_L7_error)
                __Pyx_GOTREF(__pyx_t_3);
              }
              if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
                PyObject* sequence = __pyx_t_3;
                Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
                if (unlikely(size != 2)) {
                  if (size > 2) __Pyx_RaiseTooManyValuesError(2);
                  else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
                  __PYX_ERR(0, 4625, __pyx_L7_error)
                }
                #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
                if (likely(PyTuple_CheckExact(sequence))) {
                  __pyx_t_11 = PyTuple_GET_ITEM(sequence, 0);
                  __Pyx_INCREF(__pyx_t_11);
                  __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1);
                  __Pyx_INCREF(__pyx_t_2);
                } else {
                  __pyx_t_11 = __Pyx_PyList_GetItemRefFast(sequence, 0, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4625, __pyx_L7_error)
                  __Pyx_XGOTREF(__pyx_t_11);
                  __pyx_t_2 = __Pyx_PyList_GetItemRefFast(sequence, 1, __Pyx_ReferenceSharing_SharedReference);
                  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4625, __pyx_L7_error)
                  __Pyx_XGOTREF(__pyx_t_2);
                }
                #else
                __pyx_t_11 = __Pyx_PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4625, __pyx_L7_error)
                __Pyx_GOTREF(__pyx_t_11);
                __pyx_t_2 = __Pyx_PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4625, __pyx_L7_error)
                __Pyx_GOTREF(__pyx_t_2);
                #endif
                __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
              } else {
                Py_ssize_t index = -1;
                __pyx_t_6 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4625, __pyx_L7_error)
                __Pyx_GOTREF(__pyx_t_6);
                __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
                __pyx_t_12 = (CYTHON_COMPILING_IN_LIMITED_API) ? PyIter_Next : __Pyx_PyObject_GetIterNextFunc(__pyx_t_6);
                index = 0; __pyx_t_11 = __pyx_t_12(__pyx_t_6); if (unlikely(!__pyx_t_11)) goto __pyx_L34_unpacking_failed;
                __Pyx_GOTREF(__pyx_t_11);
                index = 1; __pyx_t_2 = __pyx_t_12(__pyx_t_6); if (unlikely(!__pyx_t_2)) goto __pyx_L34_unpacking_failed;
                __Pyx_GOTREF(__pyx_t_2);
                if (__Pyx_IternextUnpackEndCheck(__pyx_t_12(__pyx_t_6), 2) < (0)) __PYX_ERR(0, 4625, __pyx_L7_error)
                __pyx_t_12 = NULL;
                __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
                goto __pyx_L35_unpacking_done;
                __pyx_L34_unpacking_failed:;
                __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
                __pyx_t_12 = NULL;
                if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
                __PYX_ERR(0, 4625, __pyx_L7_error)
                __pyx_L35_unpacking_done:;
              }

              /* "pygeoprocessing/routing/routing.pyx":4625
 *             # drop a point on the line if direction changed or last point
 *             if last_dir != next_dir or stream_end:
 *                 x_p, y_p = gdal.ApplyGeoTransform(             # <<<<<<<<<<<<<<
 *                     geotransform, x_l+0.5, y_l+0.5)
 *                 stream_line.AddPoint(x_p, y_p)
*/
              __Pyx_DECREF_SET(__pyx_v_x_p, __pyx_t_11);
              __pyx_t_11 = 0;
              __Pyx_DECREF_SET(__pyx_v_y_p, __pyx_t_2);
              __pyx_t_2 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4627
 *                 x_p, y_p = gdal.ApplyGeoTransform(
 *                     geotransform, x_l+0.5, y_l+0.5)
 *                 stream_line.AddPoint(x_p, y_p)             # <<<<<<<<<<<<<<
 *                 last_dir = next_dir
 * 
*/
              __pyx_t_2 = __pyx_v_stream_line;
              __Pyx_INCREF(__pyx_t_2);
              __pyx_t_4 = 0;
              {
                PyObject *__pyx_callargs[3] = {__pyx_t_2, __pyx_v_x_p, __pyx_v_y_p};
                __pyx_t_3 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_AddPoint, __pyx_callargs+__pyx_t_4, (3-__pyx_t_4) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
                __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
                if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4627, __pyx_L7_error)
                __Pyx_GOTREF(__pyx_t_3);
              }
              __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;

              /* "pygeoprocessing/routing/routing.pyx":4628
 *                     geotransform, x_l+0.5, y_l+0.5)
 *                 stream_line.AddPoint(x_p, y_p)
 *                 last_dir = next_dir             # <<<<<<<<<<<<<<
 * 
 *         if pixel_length == 0:
*/
              __pyx_v_last_dir = __pyx_v_next_dir;

              /* "pygeoprocessing/routing/routing.pyx":4624
 * 
 *             # drop a point on the line if direction changed or last point
 *             if last_dir != next_dir or stream_end:             # <<<<<<<<<<<<<<
 *                 x_p, y_p = gdal.ApplyGeoTransform(
 *                     geotransform, x_l+0.5, y_l+0.5)
*/
            }
          }

          /* "pygeoprocessing/routing/routing.pyx":4630
 *                 last_dir = next_dir
 * 
 *         if pixel_length == 0:             # <<<<<<<<<<<<<<
 *             return None
 *         return x_l, y_l, x_1, y_1, upstream_id_list, stream_line
*/
          __pyx_t_10 = (__pyx_v_pixel_length == 0);
          if (__pyx_t_10) {

            /* "pygeoprocessing/routing/routing.pyx":4631
 * 
 *         if pixel_length == 0:
 *             return None             # <<<<<<<<<<<<<<
 *         return x_l, y_l, x_1, y_1, upstream_id_list, stream_line
 * 
*/
            __Pyx_XDECREF(__pyx_r);
            __pyx_r = Py_None; __Pyx_INCREF(Py_None);
            goto __pyx_L11_try_return;

            /* "pygeoprocessing/routing/routing.pyx":4630
 *                 last_dir = next_dir
 * 
 *         if pixel_length == 0:             # <<<<<<<<<<<<<<
 *             return None
 *         return x_l, y_l, x_1, y_1, upstream_id_list, stream_line
*/
          }

          /* "pygeoprocessing/routing/routing.pyx":4632
 *         if pixel_length == 0:
 *             return None
 *         return x_l, y_l, x_1, y_1, upstream_id_list, stream_line             # <<<<<<<<<<<<<<
 * 
 * 
*/
          __Pyx_XDECREF(__pyx_r);
          __pyx_t_3 = __Pyx_PyLong_From_int(__pyx_v_x_l); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 4632, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_3);
          __pyx_t_2 = __Pyx_PyLong_From_int(__pyx_v_y_l); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4632, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_2);
          __pyx_t_11 = __Pyx_PyLong_From_int(__pyx_v_x_1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 4632, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_11);
          __pyx_t_6 = __Pyx_PyLong_From_int(__pyx_v_y_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4632, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_6);
          __pyx_t_1 = PyTuple_New(6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4632, __pyx_L7_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_GIVEREF(__pyx_t_3);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __Pyx_GIVEREF(__pyx_t_2);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_2) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __Pyx_GIVEREF(__pyx_t_11);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_11) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __Pyx_GIVEREF(__pyx_t_6);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_t_6) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __Pyx_INCREF(__pyx_v_upstream_id_list);
          __Pyx_GIVEREF(__pyx_v_upstream_id_list);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_upstream_id_list) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __Pyx_INCREF(__pyx_v_stream_line);
          __Pyx_GIVEREF(__pyx_v_stream_line);
          if (__Pyx_PyTuple_SET_ITEM(__pyx_t_1, 5, __pyx_v_stream_line) != (0)) __PYX_ERR(0, 4632, __pyx_L7_error);
          __pyx_t_3 = 0;
          __pyx_t_2 = 0;
          __pyx_t_11 = 0;
          __pyx_t_6 = 0;
          __pyx_r = __pyx_t_1;
          __pyx_t_1 = 0;
          goto __pyx_L11_try_return;

          /* "pygeoprocessing/routing/routing.pyx":4558
 *     cdef int last_dir
 * 
 *     with GDALUseExceptions():             # <<<<<<<<<<<<<<
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:
*/
        }
        __pyx_L7_error:;
        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
        __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
        __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
        /*except:*/ {
          __Pyx_AddTraceback("pygeoprocessing.routing.routing._calculate_stream_geometry", __pyx_clineno, __pyx_lineno, __pyx_filename);
          if (__Pyx_GetException(&__pyx_t_1, &__pyx_t_6, &__pyx_t_11) < 0) __PYX_ERR(0, 4558, __pyx_L9_except_error)
          __Pyx_XGOTREF(__pyx_t_1);
          __Pyx_XGOTREF(__pyx_t_6);
          __Pyx_XGOTREF(__pyx_t_11);
          __pyx_t_2 = PyTuple_Pack(3, __pyx_t_1, __pyx_t_6, __pyx_t_11); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4558, __pyx_L9_except_error)
          __Pyx_GOTREF(__pyx_t_2);
          __pyx_t_15 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_2, NULL);
          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          if (unlikely(!__pyx_t_15)) __PYX_ERR(0, 4558, __pyx_L9_except_error)
          __Pyx_GOTREF(__pyx_t_15);
          __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_15);
          __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
          if (__pyx_t_10 < (0)) __PYX_ERR(0, 4558, __pyx_L9_except_error)
          __pyx_t_14 = (!__pyx_t_10);
          if (unlikely(__pyx_t_14)) {
            __Pyx_GIVEREF(__pyx_t_1);
            __Pyx_GIVEREF(__pyx_t_6);
            __Pyx_XGIVEREF(__pyx_t_11);
            __Pyx_ErrRestoreWithState(__pyx_t_1, __pyx_t_6, __pyx_t_11);
            __pyx_t_1 = 0;  __pyx_t_6 = 0;  __pyx_t_11 = 0; 
            __PYX_ERR(0, 4558, __pyx_L9_except_error)
          }
          __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
          __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
          __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
          goto __pyx_L8_exception_handled;
        }
        __pyx_L9_except_error:;
        __Pyx_XGIVEREF(__pyx_t_7);
        __Pyx_XGIVEREF(__pyx_t_8);
        __Pyx_XGIVEREF(__pyx_t_9);
        __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
        goto __pyx_L1_error;
        __pyx_L11_try_return:;
        __Pyx_XGIVEREF(__pyx_t_7);
        __Pyx_XGIVEREF(__pyx_t_8);
        __Pyx_XGIVEREF(__pyx_t_9);
        __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
        goto __pyx_L4_return;
        __pyx_L8_exception_handled:;
        __Pyx_XGIVEREF(__pyx_t_7);
        __Pyx_XGIVEREF(__pyx_t_8);
        __Pyx_XGIVEREF(__pyx_t_9);
        __Pyx_ExceptionReset(__pyx_t_7, __pyx_t_8, __pyx_t_9);
      }
    }
    /*finally:*/ {
      /*normal exit:*/{
        if (__pyx_t_5) {
          __pyx_t_9 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_mstate_global->__pyx_tuple[12], NULL);
          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 4558, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_9);
          __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
        }
        goto __pyx_L6;
      }
      __pyx_L4_return: {
        __pyx_t_9 = __pyx_r;
        __pyx_r = 0;
        if (__pyx_t_5) {
          __pyx_t_8 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_mstate_global->__pyx_tuple[12], NULL);
          __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
          if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 4558, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_8);
          __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
        }
        __pyx_r = __pyx_t_9;
        __pyx_t_9 = 0;
        goto __pyx_L0;
      }
      __pyx_L6:;
    }
    goto __pyx_L40;
    __pyx_L3_error:;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    goto __pyx_L1_error;
    __pyx_L40:;
  }

  /* "pygeoprocessing/routing/routing.pyx":4512
 * 
 * 
 * cdef _calculate_stream_geometry(             # <<<<<<<<<<<<<<
 *         int x_l, int y_l, int upstream_d8_dir, geotransform, int n_cols,
 *         int n_rows, ManagedRaster flow_accum_managed_raster,
*/

  /* function exit code */
  __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_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._calculate_stream_geometry", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_upstream_id_list);
  __Pyx_XDECREF(__pyx_v_stream_line);
  __Pyx_XDECREF(__pyx_v_x_p);
  __Pyx_XDECREF(__pyx_v_y_p);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* "pygeoprocessing/routing/routing.pyx":4635
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _delete_feature(
 *         stream_feature, stream_layer, upstream_to_downstream_id,
*/

/* Python wrapper */
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_31_delete_feature(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
); /*proto*/
PyDoc_STRVAR(__pyx_doc_15pygeoprocessing_7routing_7routing_30_delete_feature, "Helper for Strahler extraction to delete all references to a stream.\n\n    Args:\n        stream_feature (ogr.Feature): feature to delete\n        stream_layer (ogr.Layer): layer to delete the feature\n        upstream_to_downstream_id (dict): can be referenced by FID and should\n            remove all instances of stream from this dict\n        downstream_to_upstream_ids (dict): stream feature contained in\n            the values of this dict and should remove all instances of stream\n            from this dict\n\n    Returns:\n        None.\n    ");
static PyMethodDef __pyx_mdef_15pygeoprocessing_7routing_7routing_31_delete_feature = {"_delete_feature", (PyCFunction)(void(*)(void))(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_15pygeoprocessing_7routing_7routing_31_delete_feature, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_15pygeoprocessing_7routing_7routing_30_delete_feature};
static PyObject *__pyx_pw_15pygeoprocessing_7routing_7routing_31_delete_feature(PyObject *__pyx_self, 
#if CYTHON_METH_FASTCALL
PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
#else
PyObject *__pyx_args, PyObject *__pyx_kwds
#endif
) {
  PyObject *__pyx_v_stream_feature = 0;
  PyObject *__pyx_v_stream_layer = 0;
  PyObject *__pyx_v_upstream_to_downstream_id = 0;
  PyObject *__pyx_v_downstream_to_upstream_ids = 0;
  #if !CYTHON_METH_FASTCALL
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  #endif
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  PyObject* values[4] = {0,0,0,0};
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_delete_feature (wrapper)", 0);
  #if !CYTHON_METH_FASTCALL
  #if CYTHON_ASSUME_SAFE_SIZE
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
  #endif
  #endif
  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
  {
    PyObject ** const __pyx_pyargnames[] = {&__pyx_mstate_global->__pyx_n_u_stream_feature,&__pyx_mstate_global->__pyx_n_u_stream_layer,&__pyx_mstate_global->__pyx_n_u_upstream_to_downstream_id,&__pyx_mstate_global->__pyx_n_u_downstream_to_upstream_ids,0};
    const Py_ssize_t __pyx_kwds_len = (__pyx_kwds) ? __Pyx_NumKwargs_FASTCALL(__pyx_kwds) : 0;
    if (unlikely(__pyx_kwds_len) < 0) __PYX_ERR(0, 4635, __pyx_L3_error)
    if (__pyx_kwds_len > 0) {
      switch (__pyx_nargs) {
        case  4:
        values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 4635, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  3:
        values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 4635, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  2:
        values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 4635, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  1:
        values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
        if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4635, __pyx_L3_error)
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      const Py_ssize_t kwd_pos_args = __pyx_nargs;
      if (__Pyx_ParseKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values, kwd_pos_args, __pyx_kwds_len, "_delete_feature", 0) < (0)) __PYX_ERR(0, 4635, __pyx_L3_error)
      for (Py_ssize_t i = __pyx_nargs; i < 4; i++) {
        if (unlikely(!values[i])) { __Pyx_RaiseArgtupleInvalid("_delete_feature", 1, 4, 4, i); __PYX_ERR(0, 4635, __pyx_L3_error) }
      }
    } else if (unlikely(__pyx_nargs != 4)) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = __Pyx_ArgRef_FASTCALL(__pyx_args, 0);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[0])) __PYX_ERR(0, 4635, __pyx_L3_error)
      values[1] = __Pyx_ArgRef_FASTCALL(__pyx_args, 1);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[1])) __PYX_ERR(0, 4635, __pyx_L3_error)
      values[2] = __Pyx_ArgRef_FASTCALL(__pyx_args, 2);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[2])) __PYX_ERR(0, 4635, __pyx_L3_error)
      values[3] = __Pyx_ArgRef_FASTCALL(__pyx_args, 3);
      if (!CYTHON_ASSUME_SAFE_MACROS && unlikely(!values[3])) __PYX_ERR(0, 4635, __pyx_L3_error)
    }
    __pyx_v_stream_feature = values[0];
    __pyx_v_stream_layer = values[1];
    __pyx_v_upstream_to_downstream_id = values[2];
    __pyx_v_downstream_to_upstream_ids = values[3];
  }
  goto __pyx_L6_skip;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("_delete_feature", 1, 4, 4, __pyx_nargs); __PYX_ERR(0, 4635, __pyx_L3_error)
  __pyx_L6_skip:;
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_AddTraceback("pygeoprocessing.routing.routing._delete_feature", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_15pygeoprocessing_7routing_7routing_30_delete_feature(__pyx_self, __pyx_v_stream_feature, __pyx_v_stream_layer, __pyx_v_upstream_to_downstream_id, __pyx_v_downstream_to_upstream_ids);

  /* function exit code */
  for (Py_ssize_t __pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
    Py_XDECREF(values[__pyx_temp]);
  }
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_15pygeoprocessing_7routing_7routing_30_delete_feature(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_stream_feature, PyObject *__pyx_v_stream_layer, PyObject *__pyx_v_upstream_to_downstream_id, PyObject *__pyx_v_downstream_to_upstream_ids) {
  PyObject *__pyx_v_stream_fid = NULL;
  PyObject *__pyx_v_downstream_fid = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  size_t __pyx_t_3;
  int __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("_delete_feature", 0);

  /* "pygeoprocessing/routing/routing.pyx":4653
 *         None.
 *     """
 *     stream_fid = stream_feature.GetFID()             # <<<<<<<<<<<<<<
 *     if stream_fid in upstream_to_downstream_id:
 *         downstream_fid = upstream_to_downstream_id[
*/
  __pyx_t_2 = __pyx_v_stream_feature;
  __Pyx_INCREF(__pyx_t_2);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_2, NULL};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_GetFID, __pyx_callargs+__pyx_t_3, (1-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4653, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __pyx_v_stream_fid = __pyx_t_1;
  __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4654
 *     """
 *     stream_fid = stream_feature.GetFID()
 *     if stream_fid in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *         downstream_fid = upstream_to_downstream_id[
 *             stream_fid]
*/
  __pyx_t_4 = (__Pyx_PySequence_ContainsTF(__pyx_v_stream_fid, __pyx_v_upstream_to_downstream_id, Py_EQ)); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 4654, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":4655
 *     stream_fid = stream_feature.GetFID()
 *     if stream_fid in upstream_to_downstream_id:
 *         downstream_fid = upstream_to_downstream_id[             # <<<<<<<<<<<<<<
 *             stream_fid]
 *         del upstream_to_downstream_id[stream_fid]
*/
    __pyx_t_1 = __Pyx_PyObject_GetItem(__pyx_v_upstream_to_downstream_id, __pyx_v_stream_fid); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4655, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_v_downstream_fid = __pyx_t_1;
    __pyx_t_1 = 0;

    /* "pygeoprocessing/routing/routing.pyx":4657
 *         downstream_fid = upstream_to_downstream_id[
 *             stream_fid]
 *         del upstream_to_downstream_id[stream_fid]             # <<<<<<<<<<<<<<
 *         if downstream_fid in downstream_to_upstream_ids:
 *             downstream_to_upstream_ids[
*/
    if (unlikely((PyObject_DelItem(__pyx_v_upstream_to_downstream_id, __pyx_v_stream_fid) < 0))) __PYX_ERR(0, 4657, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":4658
 *             stream_fid]
 *         del upstream_to_downstream_id[stream_fid]
 *         if downstream_fid in downstream_to_upstream_ids:             # <<<<<<<<<<<<<<
 *             downstream_to_upstream_ids[
 *                 downstream_fid].remove(stream_fid)
*/
    __pyx_t_4 = (__Pyx_PySequence_ContainsTF(__pyx_v_downstream_fid, __pyx_v_downstream_to_upstream_ids, Py_EQ)); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 4658, __pyx_L1_error)
    if (__pyx_t_4) {

      /* "pygeoprocessing/routing/routing.pyx":4659
 *         del upstream_to_downstream_id[stream_fid]
 *         if downstream_fid in downstream_to_upstream_ids:
 *             downstream_to_upstream_ids[             # <<<<<<<<<<<<<<
 *                 downstream_fid].remove(stream_fid)
 *     if stream_fid in downstream_to_upstream_ids:
*/
      __pyx_t_5 = __Pyx_PyObject_GetItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_downstream_fid); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4659, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __pyx_t_2 = __pyx_t_5;
      __Pyx_INCREF(__pyx_t_2);

      /* "pygeoprocessing/routing/routing.pyx":4660
 *         if downstream_fid in downstream_to_upstream_ids:
 *             downstream_to_upstream_ids[
 *                 downstream_fid].remove(stream_fid)             # <<<<<<<<<<<<<<
 *     if stream_fid in downstream_to_upstream_ids:
 *         del downstream_to_upstream_ids[
*/
      __pyx_t_3 = 0;
      {
        PyObject *__pyx_callargs[2] = {__pyx_t_2, __pyx_v_stream_fid};
        __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_remove, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
        __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4660, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_1);
      }
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

      /* "pygeoprocessing/routing/routing.pyx":4658
 *             stream_fid]
 *         del upstream_to_downstream_id[stream_fid]
 *         if downstream_fid in downstream_to_upstream_ids:             # <<<<<<<<<<<<<<
 *             downstream_to_upstream_ids[
 *                 downstream_fid].remove(stream_fid)
*/
    }

    /* "pygeoprocessing/routing/routing.pyx":4654
 *     """
 *     stream_fid = stream_feature.GetFID()
 *     if stream_fid in upstream_to_downstream_id:             # <<<<<<<<<<<<<<
 *         downstream_fid = upstream_to_downstream_id[
 *             stream_fid]
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":4661
 *             downstream_to_upstream_ids[
 *                 downstream_fid].remove(stream_fid)
 *     if stream_fid in downstream_to_upstream_ids:             # <<<<<<<<<<<<<<
 *         del downstream_to_upstream_ids[
 *             stream_fid]
*/
  __pyx_t_4 = (__Pyx_PySequence_ContainsTF(__pyx_v_stream_fid, __pyx_v_downstream_to_upstream_ids, Py_EQ)); if (unlikely((__pyx_t_4 < 0))) __PYX_ERR(0, 4661, __pyx_L1_error)
  if (__pyx_t_4) {

    /* "pygeoprocessing/routing/routing.pyx":4663
 *     if stream_fid in downstream_to_upstream_ids:
 *         del downstream_to_upstream_ids[
 *             stream_fid]             # <<<<<<<<<<<<<<
 *     stream_layer.DeleteFeature(stream_fid)
*/
    if (unlikely((PyObject_DelItem(__pyx_v_downstream_to_upstream_ids, __pyx_v_stream_fid) < 0))) __PYX_ERR(0, 4662, __pyx_L1_error)

    /* "pygeoprocessing/routing/routing.pyx":4661
 *             downstream_to_upstream_ids[
 *                 downstream_fid].remove(stream_fid)
 *     if stream_fid in downstream_to_upstream_ids:             # <<<<<<<<<<<<<<
 *         del downstream_to_upstream_ids[
 *             stream_fid]
*/
  }

  /* "pygeoprocessing/routing/routing.pyx":4664
 *         del downstream_to_upstream_ids[
 *             stream_fid]
 *     stream_layer.DeleteFeature(stream_fid)             # <<<<<<<<<<<<<<
*/
  __pyx_t_5 = __pyx_v_stream_layer;
  __Pyx_INCREF(__pyx_t_5);
  __pyx_t_3 = 0;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_v_stream_fid};
    __pyx_t_1 = __Pyx_PyObject_FastCallMethod((PyObject*)__pyx_mstate_global->__pyx_n_u_DeleteFeature, __pyx_callargs+__pyx_t_3, (2-__pyx_t_3) | (1*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4664, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4635
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _delete_feature(
 *         stream_feature, stream_layer, upstream_to_downstream_id,
*/

  /* function exit code */
  __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("pygeoprocessing.routing.routing._delete_feature", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_stream_fid);
  __Pyx_XDECREF(__pyx_v_downstream_fid);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* #### Code section: module_exttypes ### */

static PyObject *__pyx_tp_new_15pygeoprocessing_7routing_7routing___pyx_defaults(PyTypeObject *t, CYTHON_UNUSED PyObject *a, CYTHON_UNUSED PyObject *k) {
  PyObject *o;
  o = __Pyx_AllocateExtensionType(t, 1);
  if (unlikely(!o)) return 0;
  return o;
}

static void __pyx_tp_dealloc_15pygeoprocessing_7routing_7routing___pyx_defaults(PyObject *o) {
  struct __pyx_defaults *p = (struct __pyx_defaults *)o;
  #if CYTHON_USE_TP_FINALIZE
  if (unlikely(__Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && !__Pyx_PyObject_GC_IsFinalized(o)) {
    if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == __pyx_tp_dealloc_15pygeoprocessing_7routing_7routing___pyx_defaults) {
      if (PyObject_CallFinalizerFromDealloc(o)) return;
    }
  }
  #endif
  PyObject_GC_UnTrack(o);
  Py_CLEAR(p->arg0);
  PyTypeObject *tp = Py_TYPE(o);
  #if CYTHON_USE_TYPE_SLOTS
  (*tp->tp_free)(o);
  #else
  {
    freefunc tp_free = (freefunc)PyType_GetSlot(tp, Py_tp_free);
    if (tp_free) tp_free(o);
  }
  #endif
  #if CYTHON_USE_TYPE_SPECS
  Py_DECREF(tp);
  #endif
}

static int __pyx_tp_traverse_15pygeoprocessing_7routing_7routing___pyx_defaults(PyObject *o, visitproc v, void *a) {
  int e;
  struct __pyx_defaults *p = (struct __pyx_defaults *)o;
  {
    e = __Pyx_call_type_traverse(o, 1, v, a);
    if (e) return e;
  }
  if (p->arg0) {
    e = (*v)(p->arg0, a); if (e) return e;
  }
  return 0;
}

static int __pyx_tp_clear_15pygeoprocessing_7routing_7routing___pyx_defaults(PyObject *o) {
  PyObject* tmp;
  struct __pyx_defaults *p = (struct __pyx_defaults *)o;
  tmp = ((PyObject*)p->arg0);
  p->arg0 = Py_None; Py_INCREF(Py_None);
  Py_XDECREF(tmp);
  return 0;
}
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults_slots[] = {
  {Py_tp_dealloc, (void *)__pyx_tp_dealloc_15pygeoprocessing_7routing_7routing___pyx_defaults},
  {Py_tp_traverse, (void *)__pyx_tp_traverse_15pygeoprocessing_7routing_7routing___pyx_defaults},
  {Py_tp_clear, (void *)__pyx_tp_clear_15pygeoprocessing_7routing_7routing___pyx_defaults},
  {Py_tp_new, (void *)__pyx_tp_new_15pygeoprocessing_7routing_7routing___pyx_defaults},
  {0, 0},
};
static PyType_Spec __pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults_spec = {
  "pygeoprocessing.routing.routing.__pyx_defaults",
  sizeof(struct __pyx_defaults),
  0,
  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_HAVE_GC,
  __pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults_slots,
};
#else

static PyTypeObject __pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults = {
  PyVarObject_HEAD_INIT(0, 0)
  "pygeoprocessing.routing.routing.""__pyx_defaults", /*tp_name*/
  sizeof(struct __pyx_defaults), /*tp_basicsize*/
  0, /*tp_itemsize*/
  __pyx_tp_dealloc_15pygeoprocessing_7routing_7routing___pyx_defaults, /*tp_dealloc*/
  0, /*tp_vectorcall_offset*/
  0, /*tp_getattr*/
  0, /*tp_setattr*/
  0, /*tp_as_async*/
  0, /*tp_repr*/
  0, /*tp_as_number*/
  0, /*tp_as_sequence*/
  0, /*tp_as_mapping*/
  0, /*tp_hash*/
  0, /*tp_call*/
  0, /*tp_str*/
  0, /*tp_getattro*/
  0, /*tp_setattro*/
  0, /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_VERSION_TAG|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER|Py_TPFLAGS_HAVE_GC, /*tp_flags*/
  0, /*tp_doc*/
  __pyx_tp_traverse_15pygeoprocessing_7routing_7routing___pyx_defaults, /*tp_traverse*/
  __pyx_tp_clear_15pygeoprocessing_7routing_7routing___pyx_defaults, /*tp_clear*/
  0, /*tp_richcompare*/
  0, /*tp_weaklistoffset*/
  0, /*tp_iter*/
  0, /*tp_iternext*/
  0, /*tp_methods*/
  0, /*tp_members*/
  0, /*tp_getset*/
  0, /*tp_base*/
  0, /*tp_dict*/
  0, /*tp_descr_get*/
  0, /*tp_descr_set*/
  #if !CYTHON_USE_TYPE_SPECS
  0, /*tp_dictoffset*/
  #endif
  0, /*tp_init*/
  0, /*tp_alloc*/
  __pyx_tp_new_15pygeoprocessing_7routing_7routing___pyx_defaults, /*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*/
  0, /*tp_version_tag*/
  #if CYTHON_USE_TP_FINALIZE
  0, /*tp_finalize*/
  #else
  NULL, /*tp_finalize*/
  #endif
  #if !CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800
  0, /*tp_vectorcall*/
  #endif
  #if __PYX_NEED_TP_PRINT_SLOT == 1
  0, /*tp_print*/
  #endif
  #if PY_VERSION_HEX >= 0x030C0000
  0, /*tp_watched*/
  #endif
  #if PY_VERSION_HEX >= 0x030d00A4
  0, /*tp_versions_used*/
  #endif
  #if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000
  0, /*tp_pypy_flags*/
  #endif
};
#endif

static PyMethodDef __pyx_methods[] = {
  {0, 0, 0, 0}
};
/* #### Code section: initfunc_declarations ### */
static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate); /*proto*/
static CYTHON_SMALL_CODE int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate); /*proto*/
/* #### Code section: init_module ### */

static int __Pyx_modinit_global_init_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0);
  /*--- Global init code ---*/
  __Pyx_RefNannyFinishContext();
  return 0;
}

static int __Pyx_modinit_variable_export_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0);
  /*--- Variable export code ---*/
  __Pyx_RefNannyFinishContext();
  return 0;
}

static int __Pyx_modinit_function_export_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0);
  /*--- Function export code ---*/
  __Pyx_RefNannyFinishContext();
  return 0;
}

static int __Pyx_modinit_type_init_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0);
  /*--- Type init code ---*/
  #if CYTHON_USE_TYPE_SPECS
  __pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults = (PyTypeObject *) __Pyx_PyType_FromModuleAndSpec(__pyx_m, &__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults_spec, NULL); if (unlikely(!__pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 227, __pyx_L1_error)
  if (__Pyx_fix_up_extension_type_from_spec(&__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults_spec, __pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults) < (0)) __PYX_ERR(0, 227, __pyx_L1_error)
  #else
  __pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults = &__pyx_type_15pygeoprocessing_7routing_7routing___pyx_defaults;
  #endif
  #if !CYTHON_COMPILING_IN_LIMITED_API
  #endif
  #if !CYTHON_USE_TYPE_SPECS
  if (__Pyx_PyType_Ready(__pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults) < (0)) __PYX_ERR(0, 227, __pyx_L1_error)
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount((PyObject*)__pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults);
  #endif
  #if !CYTHON_COMPILING_IN_LIMITED_API
  if ((CYTHON_USE_TYPE_SLOTS && CYTHON_USE_PYTYPE_LOOKUP) && likely(!__pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults->tp_dictoffset && __pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults->tp_getattro == PyObject_GenericGetAttr)) {
    __pyx_mstate->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults->tp_getattro = PyObject_GenericGetAttr;
  }
  #endif
  __Pyx_RefNannyFinishContext();
  return 0;
  __pyx_L1_error:;
  __Pyx_RefNannyFinishContext();
  return -1;
}

static int __Pyx_modinit_type_import_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  PyObject *__pyx_t_1 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0);
  /*--- Type import code ---*/
  __pyx_t_1 = PyImport_ImportModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_t_1)) __PYX_ERR(2, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_mstate->__pyx_ptype_7cpython_4type_type = __Pyx_ImportType_3_2_4(__pyx_t_1, __Pyx_BUILTIN_MODULE_NAME, "type",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyTypeObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  0, 0,
  #else
  sizeof(PyHeapTypeObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyHeapTypeObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_7cpython_4type_type) __PYX_ERR(2, 9, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = PyImport_ImportModule("numpy"); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 229, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_mstate->__pyx_ptype_5numpy_dtype = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "dtype",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArray_Descr),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArray_Descr),
  #else
  sizeof(PyArray_Descr), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArray_Descr),
  #endif
  __Pyx_ImportType_CheckSize_Ignore_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_dtype) __PYX_ERR(1, 229, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_flatiter = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "flatiter",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayIterObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayIterObject),
  #else
  sizeof(PyArrayIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayIterObject),
  #endif
  __Pyx_ImportType_CheckSize_Ignore_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_flatiter) __PYX_ERR(1, 274, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_broadcast = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "broadcast",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayMultiIterObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayMultiIterObject),
  #else
  sizeof(PyArrayMultiIterObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayMultiIterObject),
  #endif
  __Pyx_ImportType_CheckSize_Ignore_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_broadcast) __PYX_ERR(1, 278, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_ndarray = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "ndarray",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayObject),
  #else
  sizeof(PyArrayObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyArrayObject),
  #endif
  __Pyx_ImportType_CheckSize_Ignore_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_ndarray) __PYX_ERR(1, 317, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_generic = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "generic",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_generic) __PYX_ERR(1, 826, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_number = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "number",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_number) __PYX_ERR(1, 828, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_integer = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "integer",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_integer) __PYX_ERR(1, 830, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_signedinteger = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "signedinteger",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_signedinteger) __PYX_ERR(1, 832, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_unsignedinteger = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "unsignedinteger",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_unsignedinteger) __PYX_ERR(1, 834, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_inexact = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "inexact",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_inexact) __PYX_ERR(1, 836, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_floating = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "floating",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_floating) __PYX_ERR(1, 838, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_complexfloating = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "complexfloating",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_complexfloating) __PYX_ERR(1, 840, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_flexible = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "flexible",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_flexible) __PYX_ERR(1, 842, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_character = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "character",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #else
  sizeof(PyObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyObject),
  #endif
  __Pyx_ImportType_CheckSize_Warn_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_character) __PYX_ERR(1, 844, __pyx_L1_error)
  __pyx_mstate->__pyx_ptype_5numpy_ufunc = __Pyx_ImportType_3_2_4(__pyx_t_1, "numpy", "ufunc",
  #if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x050B0000
  sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyUFuncObject),
  #elif CYTHON_COMPILING_IN_LIMITED_API
  sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyUFuncObject),
  #else
  sizeof(PyUFuncObject), __PYX_GET_STRUCT_ALIGNMENT_3_2_4(PyUFuncObject),
  #endif
  __Pyx_ImportType_CheckSize_Ignore_3_2_4); if (!__pyx_mstate->__pyx_ptype_5numpy_ufunc) __PYX_ERR(1, 908, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_RefNannyFinishContext();
  return 0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_RefNannyFinishContext();
  return -1;
}

static int __Pyx_modinit_variable_import_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0);
  /*--- Variable import code ---*/
  __Pyx_RefNannyFinishContext();
  return 0;
}

static int __Pyx_modinit_function_import_code(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0);
  /*--- Function import code ---*/
  __Pyx_RefNannyFinishContext();
  return 0;
}

#if CYTHON_PEP489_MULTI_PHASE_INIT
static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/
static int __pyx_pymod_exec_routing(PyObject* module); /*proto*/
static PyModuleDef_Slot __pyx_moduledef_slots[] = {
  {Py_mod_create, (void*)__pyx_pymod_create},
  {Py_mod_exec, (void*)__pyx_pymod_exec_routing},
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
  {Py_mod_gil, __Pyx_FREETHREADING_COMPATIBLE},
  #endif
  #if PY_VERSION_HEX >= 0x030C0000 && CYTHON_USE_MODULE_STATE
  {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
  #endif
  {0, NULL}
};
#endif

#ifdef __cplusplus
namespace {
  struct PyModuleDef __pyx_moduledef =
  #else
  static struct PyModuleDef __pyx_moduledef =
  #endif
  {
      PyModuleDef_HEAD_INIT,
      "routing",
      __pyx_k_Provides_PyGeprocessing_Routing, /* m_doc */
    #if CYTHON_USE_MODULE_STATE
      sizeof(__pyx_mstatetype), /* m_size */
    #else
      (CYTHON_PEP489_MULTI_PHASE_INIT) ? 0 : -1, /* m_size */
    #endif
      __pyx_methods /* m_methods */,
    #if CYTHON_PEP489_MULTI_PHASE_INIT
      __pyx_moduledef_slots, /* m_slots */
    #else
      NULL, /* m_reload */
    #endif
    #if CYTHON_USE_MODULE_STATE
      __pyx_m_traverse, /* m_traverse */
      __pyx_m_clear, /* m_clear */
      NULL /* m_free */
    #else
      NULL, /* m_traverse */
      NULL, /* m_clear */
      NULL /* m_free */
    #endif
  };
  #ifdef __cplusplus
} /* anonymous namespace */
#endif

/* PyModInitFuncType */
#ifndef CYTHON_NO_PYINIT_EXPORT
  #define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC
#else
  #ifdef __cplusplus
  #define __Pyx_PyMODINIT_FUNC extern "C" PyObject *
  #else
  #define __Pyx_PyMODINIT_FUNC PyObject *
  #endif
#endif

__Pyx_PyMODINIT_FUNC PyInit_routing(void) CYTHON_SMALL_CODE; /*proto*/
__Pyx_PyMODINIT_FUNC PyInit_routing(void)
#if CYTHON_PEP489_MULTI_PHASE_INIT
{
  return PyModuleDef_Init(&__pyx_moduledef);
}
/* ModuleCreationPEP489 */
#if CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\
      || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000))
static PY_INT64_T __Pyx_GetCurrentInterpreterId(void) {
    {
        PyObject *module = PyImport_ImportModule("_interpreters"); // 3.13+ I think
        if (!module) {
            PyErr_Clear(); // just try the 3.8-3.12 version
            module = PyImport_ImportModule("_xxsubinterpreters");
            if (!module) goto bad;
        }
        PyObject *current = PyObject_CallMethod(module, "get_current", NULL);
        Py_DECREF(module);
        if (!current) goto bad;
        if (PyTuple_Check(current)) {
            PyObject *new_current = PySequence_GetItem(current, 0);
            Py_DECREF(current);
            current = new_current;
            if (!new_current) goto bad;
        }
        long long as_c_int = PyLong_AsLongLong(current);
        Py_DECREF(current);
        return as_c_int;
    }
  bad:
    PySys_WriteStderr("__Pyx_GetCurrentInterpreterId failed. Try setting the C define CYTHON_PEP489_MULTI_PHASE_INIT=0\n");
    return -1;
}
#endif
#if !CYTHON_USE_MODULE_STATE
static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) {
    static PY_INT64_T main_interpreter_id = -1;
#if CYTHON_COMPILING_IN_GRAAL && defined(GRAALPY_VERSION_NUM) && GRAALPY_VERSION_NUM > 0x19000000
    PY_INT64_T current_id = GraalPyInterpreterState_GetIDFromThreadState(PyThreadState_Get());
#elif CYTHON_COMPILING_IN_GRAAL
    PY_INT64_T current_id = PyInterpreterState_GetIDFromThreadState(PyThreadState_Get());
#elif CYTHON_COMPILING_IN_LIMITED_API && (__PYX_LIMITED_VERSION_HEX < 0x03090000\
      || ((defined(_WIN32) || defined(WIN32) || defined(MS_WINDOWS)) && __PYX_LIMITED_VERSION_HEX < 0x030A0000))
    PY_INT64_T current_id = __Pyx_GetCurrentInterpreterId();
#elif CYTHON_COMPILING_IN_LIMITED_API
    PY_INT64_T current_id = PyInterpreterState_GetID(PyInterpreterState_Get());
#else
    PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp);
#endif
    if (unlikely(current_id == -1)) {
        return -1;
    }
    if (main_interpreter_id == -1) {
        main_interpreter_id = current_id;
        return 0;
    } else if (unlikely(main_interpreter_id != current_id)) {
        PyErr_SetString(
            PyExc_ImportError,
            "Interpreter change detected - this module can only be loaded into one interpreter per process.");
        return -1;
    }
    return 0;
}
#endif
static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none)
{
    PyObject *value = PyObject_GetAttrString(spec, from_name);
    int result = 0;
    if (likely(value)) {
        if (allow_none || value != Py_None) {
            result = PyDict_SetItemString(moddict, to_name, value);
        }
        Py_DECREF(value);
    } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
        PyErr_Clear();
    } else {
        result = -1;
    }
    return result;
}
static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def) {
    PyObject *module = NULL, *moddict, *modname;
    CYTHON_UNUSED_VAR(def);
    #if !CYTHON_USE_MODULE_STATE
    if (__Pyx_check_single_interpreter())
        return NULL;
    #endif
    if (__pyx_m)
        return __Pyx_NewRef(__pyx_m);
    modname = PyObject_GetAttrString(spec, "name");
    if (unlikely(!modname)) goto bad;
    module = PyModule_NewObject(modname);
    Py_DECREF(modname);
    if (unlikely(!module)) goto bad;
    moddict = PyModule_GetDict(module);
    if (unlikely(!moddict)) goto bad;
    if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad;
    if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad;
    if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad;
    if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad;
    return module;
bad:
    Py_XDECREF(module);
    return NULL;
}


static CYTHON_SMALL_CODE int __pyx_pymod_exec_routing(PyObject *__pyx_pyinit_module)
#endif
{
  int stringtab_initialized = 0;
  #if CYTHON_USE_MODULE_STATE
  int pystate_addmodule_run = 0;
  #endif
  __pyx_mstatetype *__pyx_mstate = NULL;
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  int __pyx_t_3;
  Py_ssize_t __pyx_t_4;
  PyObject *__pyx_t_5 = NULL;
  PyObject *__pyx_t_6 = NULL;
  PyObject *__pyx_t_7 = NULL;
  size_t __pyx_t_8;
  PyObject *__pyx_t_9 = NULL;
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;
  __Pyx_RefNannyDeclarations
  #if CYTHON_PEP489_MULTI_PHASE_INIT
  if (__pyx_m) {
    if (__pyx_m == __pyx_pyinit_module) return 0;
    PyErr_SetString(PyExc_RuntimeError, "Module 'routing' has already been imported. Re-initialisation is not supported.");
    return -1;
  }
  #else
  if (__pyx_m) return __Pyx_NewRef(__pyx_m);
  #endif
  /*--- Module creation code ---*/
  #if CYTHON_PEP489_MULTI_PHASE_INIT
  __pyx_t_1 = __pyx_pyinit_module;
  Py_INCREF(__pyx_t_1);
  #else
  __pyx_t_1 = PyModule_Create(&__pyx_moduledef); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  #endif
  #if CYTHON_USE_MODULE_STATE
  {
    int add_module_result = __Pyx_State_AddModule(__pyx_t_1, &__pyx_moduledef);
    __pyx_t_1 = 0; /* transfer ownership from __pyx_t_1 to "routing" pseudovariable */
    if (unlikely((add_module_result < 0))) __PYX_ERR(0, 1, __pyx_L1_error)
    pystate_addmodule_run = 1;
  }
  #else
  __pyx_m = __pyx_t_1;
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
  PyUnstable_Module_SetGIL(__pyx_m, Py_MOD_GIL_USED);
  #endif
  __pyx_mstate = __pyx_mstate_global;
  CYTHON_UNUSED_VAR(__pyx_t_1);
  __pyx_mstate->__pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_mstate->__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error)
  Py_INCREF(__pyx_mstate->__pyx_d);
  __pyx_mstate->__pyx_b = __Pyx_PyImport_AddModuleRef(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_mstate->__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error)
  __pyx_mstate->__pyx_cython_runtime = __Pyx_PyImport_AddModuleRef("cython_runtime"); if (unlikely(!__pyx_mstate->__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error)
  if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_mstate->__pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  /* ImportRefnannyAPI */
  #if CYTHON_REFNANNY
  __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
  if (!__Pyx_RefNanny) {
    PyErr_Clear();
    __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny");
    if (!__Pyx_RefNanny)
        Py_FatalError("failed to import 'refnanny' module");
  }
  #endif
  
__Pyx_RefNannySetupContext("PyInit_routing", 0);
  __Pyx_init_runtime_version();
  if (__Pyx_check_binary_version(__PYX_LIMITED_VERSION_HEX, __Pyx_get_runtime_version(), CYTHON_COMPILING_IN_LIMITED_API) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  __pyx_mstate->__pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_mstate->__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error)
  __pyx_mstate->__pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error)
  __pyx_mstate->__pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_mstate->__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error)
  /*--- Library function declarations ---*/
  /*--- Initialize various global constants etc. ---*/
  if (__Pyx_InitConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  stringtab_initialized = 1;
  if (__Pyx_InitGlobals() < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  if (__pyx_module_is_main_pygeoprocessing__routing__routing) {
    if (PyObject_SetAttr(__pyx_m, __pyx_mstate_global->__pyx_n_u_name, __pyx_mstate_global->__pyx_n_u_main) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  }
  {
    PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error)
    if (!PyDict_GetItemString(modules, "pygeoprocessing.routing.routing")) {
      if (unlikely((PyDict_SetItemString(modules, "pygeoprocessing.routing.routing", __pyx_m) < 0))) __PYX_ERR(0, 1, __pyx_L1_error)
    }
  }
  /*--- Builtin init code ---*/
  if (__Pyx_InitCachedBuiltins(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  /*--- Constants init code ---*/
  if (__Pyx_InitCachedConstants(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  if (__Pyx_CreateCodeObjects(__pyx_mstate) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  /*--- Global type/function init code ---*/
  (void)__Pyx_modinit_global_init_code(__pyx_mstate);
  (void)__Pyx_modinit_variable_export_code(__pyx_mstate);
  (void)__Pyx_modinit_function_export_code(__pyx_mstate);
  if (unlikely((__Pyx_modinit_type_init_code(__pyx_mstate) < 0))) __PYX_ERR(0, 1, __pyx_L1_error)
  if (unlikely((__Pyx_modinit_type_import_code(__pyx_mstate) < 0))) __PYX_ERR(0, 1, __pyx_L1_error)
  (void)__Pyx_modinit_variable_import_code(__pyx_mstate);
  (void)__Pyx_modinit_function_import_code(__pyx_mstate);
  /*--- Execution code ---*/

  /* "pygeoprocessing/routing/routing.pyx":32
 *         'pygeoprocessing_d8_flow_dir.tif')
 * """
 * import collections             # <<<<<<<<<<<<<<
 * import logging
 * import os
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_collections, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 32, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_collections, __pyx_t_2) < (0)) __PYX_ERR(0, 32, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":33
 * """
 * import collections
 * import logging             # <<<<<<<<<<<<<<
 * import os
 * import shutil
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_logging, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 33, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_logging, __pyx_t_2) < (0)) __PYX_ERR(0, 33, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":34
 * import collections
 * import logging
 * import os             # <<<<<<<<<<<<<<
 * import shutil
 * import tempfile
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_os, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 34, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_os, __pyx_t_2) < (0)) __PYX_ERR(0, 34, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":35
 * import logging
 * import os
 * import shutil             # <<<<<<<<<<<<<<
 * import tempfile
 * import time
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_shutil, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_shutil, __pyx_t_2) < (0)) __PYX_ERR(0, 35, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":36
 * import os
 * import shutil
 * import tempfile             # <<<<<<<<<<<<<<
 * import time
 * 
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_tempfile, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 36, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_tempfile, __pyx_t_2) < (0)) __PYX_ERR(0, 36, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":37
 * import shutil
 * import tempfile
 * import time             # <<<<<<<<<<<<<<
 * 
 * cimport cython
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_time, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_time, __pyx_t_2) < (0)) __PYX_ERR(0, 37, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":41
 * cimport cython
 * cimport numpy
 * numpy.import_array()             # <<<<<<<<<<<<<<
 * from cpython.mem cimport PyMem_Malloc, PyMem_Free
 * from cython.operator cimport dereference as deref
*/
  __pyx_t_3 = __pyx_f_5numpy_import_array(); if (unlikely(__pyx_t_3 == ((int)-1))) __PYX_ERR(0, 41, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":55
 * from libcpp.stack cimport stack
 * from libcpp.vector cimport vector
 * from osgeo import gdal             # <<<<<<<<<<<<<<
 * from osgeo import ogr
 * from osgeo import osr
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_gdal};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_osgeo, __pyx_imported_names, 1, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 55, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_gdal};
    __pyx_t_4 = 0; {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 55, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 55, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":56
 * from libcpp.vector cimport vector
 * from osgeo import gdal
 * from osgeo import ogr             # <<<<<<<<<<<<<<
 * from osgeo import osr
 * import numpy
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_ogr};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_osgeo, __pyx_imported_names, 1, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 56, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_ogr};
    __pyx_t_4 = 0; {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 56, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 56, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":57
 * from osgeo import gdal
 * from osgeo import ogr
 * from osgeo import osr             # <<<<<<<<<<<<<<
 * import numpy
 * import shapely.wkb
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_osr};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_osgeo, __pyx_imported_names, 1, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_osr};
    __pyx_t_4 = 0; {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 57, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 57, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":58
 * from osgeo import ogr
 * from osgeo import osr
 * import numpy             # <<<<<<<<<<<<<<
 * import shapely.wkb
 * import shapely.ops
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_numpy, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 58, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_numpy, __pyx_t_2) < (0)) __PYX_ERR(0, 58, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":59
 * from osgeo import osr
 * import numpy
 * import shapely.wkb             # <<<<<<<<<<<<<<
 * import shapely.ops
 * import scipy.stats
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_shapely_wkb, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 59, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_shapely, __pyx_t_2) < (0)) __PYX_ERR(0, 59, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":60
 * import numpy
 * import shapely.wkb
 * import shapely.ops             # <<<<<<<<<<<<<<
 * import scipy.stats
 * 
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_shapely_ops, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 60, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_shapely, __pyx_t_2) < (0)) __PYX_ERR(0, 60, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":61
 * import shapely.wkb
 * import shapely.ops
 * import scipy.stats             # <<<<<<<<<<<<<<
 * 
 * from ..geoprocessing_core import DEFAULT_OSR_AXIS_MAPPING_STRATEGY
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_scipy_stats, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 61, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_scipy, __pyx_t_2) < (0)) __PYX_ERR(0, 61, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":63
 * import scipy.stats
 * 
 * from ..geoprocessing_core import DEFAULT_OSR_AXIS_MAPPING_STRATEGY             # <<<<<<<<<<<<<<
 * from ..geoprocessing_core import DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS
 * from ..geoprocessing_core import SPARSE_CREATION_OPTIONS, BLOCK_BITS
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_DEFAULT_OSR_AXIS_MAPPING_STRATEG};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_geoprocessing_core, __pyx_imported_names, 1, __pyx_mstate_global->__pyx_kp_u_pygeoprocessing_geoprocessing_co, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 63, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_DEFAULT_OSR_AXIS_MAPPING_STRATEG};
    __pyx_t_4 = 0; {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 63, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 63, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":64
 * 
 * from ..geoprocessing_core import DEFAULT_OSR_AXIS_MAPPING_STRATEGY
 * from ..geoprocessing_core import DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS             # <<<<<<<<<<<<<<
 * from ..geoprocessing_core import SPARSE_CREATION_OPTIONS, BLOCK_BITS
 * from ..extensions cimport ManagedRaster, is_close
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_geoprocessing_core, __pyx_imported_names, 1, __pyx_mstate_global->__pyx_kp_u_pygeoprocessing_geoprocessing_co, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 64, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT};
    __pyx_t_4 = 0; {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 64, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 64, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":65
 * from ..geoprocessing_core import DEFAULT_OSR_AXIS_MAPPING_STRATEGY
 * from ..geoprocessing_core import DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS
 * from ..geoprocessing_core import SPARSE_CREATION_OPTIONS, BLOCK_BITS             # <<<<<<<<<<<<<<
 * from ..extensions cimport ManagedRaster, is_close
 * from ..extensions cimport COL_OFFSETS, ROW_OFFSETS, INFLOW_OFFSETS
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_SPARSE_CREATION_OPTIONS,__pyx_mstate_global->__pyx_n_u_BLOCK_BITS};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_geoprocessing_core, __pyx_imported_names, 2, __pyx_mstate_global->__pyx_kp_u_pygeoprocessing_geoprocessing_co, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 65, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_SPARSE_CREATION_OPTIONS,__pyx_mstate_global->__pyx_n_u_BLOCK_BITS};
    for (__pyx_t_4=0; __pyx_t_4 < 2; __pyx_t_4++) {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 65, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 65, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":68
 * from ..extensions cimport ManagedRaster, is_close
 * from ..extensions cimport COL_OFFSETS, ROW_OFFSETS, INFLOW_OFFSETS
 * from ..utils import gdal_use_exceptions, GDALUseExceptions             # <<<<<<<<<<<<<<
 * import pygeoprocessing
 * 
*/
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_gdal_use_exceptions,__pyx_mstate_global->__pyx_n_u_GDALUseExceptions};
    __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_utils, __pyx_imported_names, 2, __pyx_mstate_global->__pyx_kp_u_pygeoprocessing_utils, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 68, __pyx_L1_error)
  }
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  {
    PyObject* const __pyx_imported_names[] = {__pyx_mstate_global->__pyx_n_u_gdal_use_exceptions,__pyx_mstate_global->__pyx_n_u_GDALUseExceptions};
    for (__pyx_t_4=0; __pyx_t_4 < 2; __pyx_t_4++) {
      __pyx_t_5 = __Pyx_ImportFrom(__pyx_t_2, __pyx_imported_names[__pyx_t_4]); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 68, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_imported_names[__pyx_t_4], __pyx_t_5) < (0)) __PYX_ERR(0, 68, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":69
 * from ..extensions cimport COL_OFFSETS, ROW_OFFSETS, INFLOW_OFFSETS
 * from ..utils import gdal_use_exceptions, GDALUseExceptions
 * import pygeoprocessing             # <<<<<<<<<<<<<<
 * 
 * LOGGER = logging.getLogger(__name__)
*/
  __pyx_t_1 = __Pyx_Import(__pyx_mstate_global->__pyx_n_u_pygeoprocessing, 0, 0, NULL, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 69, __pyx_L1_error)
  __pyx_t_2 = __pyx_t_1;
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_pygeoprocessing, __pyx_t_2) < (0)) __PYX_ERR(0, 69, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":71
 * import pygeoprocessing
 * 
 * LOGGER = logging.getLogger(__name__)             # <<<<<<<<<<<<<<
 * 
 * cdef float _LOGGING_PERIOD = 10.0
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_logging); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 71, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_getLogger); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 71, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_name); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 71, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 71, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_LOGGER, __pyx_t_2) < (0)) __PYX_ERR(0, 71, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":73
 * LOGGER = logging.getLogger(__name__)
 * 
 * cdef float _LOGGING_PERIOD = 10.0             # <<<<<<<<<<<<<<
 * 
 * # if nodata is not defined for a float, it's a difficult choice. this number
*/
  __pyx_v_15pygeoprocessing_7routing_7routing__LOGGING_PERIOD = 10.0;

  /* "pygeoprocessing/routing/routing.pyx":77
 * # if nodata is not defined for a float, it's a difficult choice. this number
 * # probably won't collide with anything ever created by humans
 * cdef double IMPROBABLE_FLOAT_NODATA = -1.23789789e29             # <<<<<<<<<<<<<<
 * 
 * # a pre-computed square root of 2 constant
*/
  __pyx_v_15pygeoprocessing_7routing_7routing_IMPROBABLE_FLOAT_NODATA = -1.23789789e29;

  /* "pygeoprocessing/routing/routing.pyx":80
 * 
 * # a pre-computed square root of 2 constant
 * cdef double SQRT2 = 1.4142135623730951             # <<<<<<<<<<<<<<
 * cdef double SQRT2_INV = 1.0 / 1.4142135623730951
 * 
*/
  __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2 = 1.4142135623730951;

  /* "pygeoprocessing/routing/routing.pyx":81
 * # a pre-computed square root of 2 constant
 * cdef double SQRT2 = 1.4142135623730951
 * cdef double SQRT2_INV = 1.0 / 1.4142135623730951             # <<<<<<<<<<<<<<
 * 
 * # exposing stl::priority_queue so we can have all 3 template arguments so
*/
  __pyx_v_15pygeoprocessing_7routing_7routing_SQRT2_INV = (1.0 / 1.4142135623730951);

  /* "pygeoprocessing/routing/routing.pyx":183
 * 
 * 
 * def _generate_read_bounds(offset_dict, raster_x_size, raster_y_size):             # <<<<<<<<<<<<<<
 *     """Helper function to expand GDAL memory block read bound by 1 pixel.
 * 
*/
  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_1_generate_read_bounds, 0, __pyx_mstate_global->__pyx_n_u_generate_read_bounds, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[0])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 183, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2);
  #endif
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_generate_read_bounds, __pyx_t_2) < (0)) __PYX_ERR(0, 183, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":227
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def fill_pits(
 *         dem_raster_path_band, target_filled_dem_raster_path,
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_3fill_pits, 0, __pyx_mstate_global->__pyx_n_u_fill_pits_2, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[1])); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_5);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_5, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 227, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":233
 *         long long max_pixel_fill_count=-1,
 *         single_outlet_tuple=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Fill the pits in a DEM.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 233, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_5)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_5, __pyx_pf_15pygeoprocessing_7routing_7routing_32__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 227, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_fill_pits_2, __pyx_t_2) < (0)) __PYX_ERR(0, 227, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":674
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_d8(
 *         dem_raster_path_band, target_flow_dir_path,
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 674, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_5flow_dir_d8, 0, __pyx_mstate_global->__pyx_n_u_flow_dir_d8_2, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[2])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 674, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_7);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_7, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 674, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":678
 *         dem_raster_path_band, target_flow_dir_path,
 *         working_dir=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """D8 flow direction.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 678, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_7)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_7, __pyx_pf_15pygeoprocessing_7routing_7routing_34__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_7};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 674, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_flow_dir_d8_2, __pyx_t_2) < (0)) __PYX_ERR(0, 674, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1044
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_d8(
 *         flow_dir_raster_path_band, target_flow_accum_raster_path,
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1044, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_6 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_7flow_accumulation_d8, 0, __pyx_mstate_global->__pyx_n_u_flow_accumulation_d8, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[3])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1044, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_6);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_6, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 1044, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1049
 *         weight_raster_path_band=None, custom_decay_factor=None,
 *         double min_decay_proportion=0.001,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """D8 flow accumulation.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1049, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_6)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_6, __pyx_pf_15pygeoprocessing_7routing_7routing_36__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1044, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_flow_accumulation_d8, __pyx_t_2) < (0)) __PYX_ERR(0, 1044, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1362
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 1362, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_9flow_dir_mfd, 0, __pyx_mstate_global->__pyx_n_u_flow_dir_mfd, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[4])); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1362, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_5);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_5, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 1362, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1365
 * def flow_dir_mfd(
 *         dem_raster_path_band, target_flow_dir_path, working_dir=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Multiple flow direction.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1365, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_5)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_5, __pyx_pf_15pygeoprocessing_7routing_7routing_38__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1362, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_flow_dir_mfd, __pyx_t_2) < (0)) __PYX_ERR(0, 1362, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1860
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def flow_accumulation_mfd(
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 1860, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_11flow_accumulation_mfd, 0, __pyx_mstate_global->__pyx_n_u_flow_accumulation_mfd, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[5])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1860, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_7);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_7, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 1860, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":1864
 *         flow_dir_mfd_raster_path_band, target_flow_accum_raster_path,
 *         weight_raster_path_band=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Multiple flow direction accumulation.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 1864, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_7)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_7, __pyx_pf_15pygeoprocessing_7routing_7routing_40__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_7};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1860, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_flow_accumulation_mfd, __pyx_t_2) < (0)) __PYX_ERR(0, 1860, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2146
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_d8(
 *         flow_dir_d8_raster_path_band, channel_raster_path_band,
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2146, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_6 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_13distance_to_channel_d8, 0, __pyx_mstate_global->__pyx_n_u_distance_to_channel_d8, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[6])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2146, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_6);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_6, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 2146, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2151
 *         target_distance_to_channel_raster_path,
 *         weight_raster_path_band=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Calculate distance to channel with D8 flow.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2151, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_6)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_6, __pyx_pf_15pygeoprocessing_7routing_7routing_42__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2146, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_distance_to_channel_d8, __pyx_t_2) < (0)) __PYX_ERR(0, 2146, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2346
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def distance_to_channel_mfd(
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2346, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_15distance_to_channel_mfd, 0, __pyx_mstate_global->__pyx_n_u_distance_to_channel_mfd, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[7])); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2346, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_5);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_5, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 2346, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2350
 *         flow_dir_mfd_raster_path_band, channel_raster_path_band,
 *         target_distance_to_channel_raster_path, weight_raster_path_band=None,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Calculate distance to channel with multiple flow direction.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2350, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_5)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_5, __pyx_pf_15pygeoprocessing_7routing_7routing_44__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2346, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_distance_to_channel_mfd, __pyx_t_2) < (0)) __PYX_ERR(0, 2346, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2679
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_streams_mfd(
 *         flow_accum_raster_path_band, flow_dir_mfd_path_band,
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2679, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_17extract_streams_mfd, 0, __pyx_mstate_global->__pyx_n_u_extract_streams_mfd, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[8])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2679, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_7);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_7, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 2679, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2684
 *         double flow_threshold, target_stream_raster_path,
 *         double trace_threshold_proportion=1.0,
 *         raster_driver_creation_tuple=DEFAULT_GTIFF_CREATION_TUPLE_OPTIONS):             # <<<<<<<<<<<<<<
 *     """Classify a stream raster from MFD flow accumulation.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_GTIFF_CREATION_TUPLE_OPT); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2684, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_7)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_7, __pyx_pf_15pygeoprocessing_7routing_7routing_46__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_7};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2679, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_extract_streams_mfd, __pyx_t_2) < (0)) __PYX_ERR(0, 2679, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2887
 * 
 * 
 * def _is_raster_path_band_formatted(raster_path_band):             # <<<<<<<<<<<<<<
 *     """Return true if raster path band is a (str, int) tuple/list."""
 *     if not isinstance(raster_path_band, (list, tuple)):
*/
  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_19_is_raster_path_band_formatted, 0, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[9])); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2887, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_2);
  #endif
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_is_raster_path_band_formatted, __pyx_t_2) < (0)) __PYX_ERR(0, 2887, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":2901
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def extract_strahler_streams_d8(
 *         flow_dir_d8_raster_path_band, flow_accum_raster_path_band,
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 2901, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_6 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_21extract_strahler_streams_d8, 0, __pyx_mstate_global->__pyx_n_u_extract_strahler_streams_d8, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[10])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 2901, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_6);
  #endif
  if (!__Pyx_CyFunction_InitDefaults(__pyx_t_6, __pyx_mstate_global->__pyx_ptype_15pygeoprocessing_7routing_7routing___pyx_defaults)) __PYX_ERR(0, 2901, __pyx_L1_error)

  /* "pygeoprocessing/routing/routing.pyx":2910
 *         float min_p_val=0.05,
 *         autotune_flow_accumulation=False,
 *         osr_axis_mapping_strategy=DEFAULT_OSR_AXIS_MAPPING_STRATEGY):             # <<<<<<<<<<<<<<
 *     """Extract Strahler order stream geometry from flow accumulation.
 * 
*/
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_mstate_global->__pyx_n_u_DEFAULT_OSR_AXIS_MAPPING_STRATEG); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 2910, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_CyFunction_Defaults(struct __pyx_defaults, __pyx_t_6)->arg0 = __pyx_t_9;
  __Pyx_GIVEREF(__pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_CyFunction_SetDefaultsGetter(__pyx_t_6, __pyx_pf_15pygeoprocessing_7routing_7routing_48__defaults__);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 2901, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_extract_strahler_streams_d8, __pyx_t_2) < (0)) __PYX_ERR(0, 2901, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3590
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _build_discovery_finish_rasters(
 *         flow_dir_d8_raster_path_band, target_discovery_raster_path,
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 3590, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_23_build_discovery_finish_rasters, 0, __pyx_mstate_global->__pyx_n_u_build_discovery_finish_rasters, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[11])); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3590, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_5);
  #endif
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3590, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_build_discovery_finish_rasters, __pyx_t_2) < (0)) __PYX_ERR(0, 3590, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":3729
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def calculate_subwatershed_boundary(
 *         d8_flow_dir_raster_path_band,
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 3729, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_25calculate_subwatershed_boundary, 0, __pyx_mstate_global->__pyx_n_u_calculate_subwatershed_boundary_4, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[12])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 3729, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_7);
  #endif
  __Pyx_CyFunction_SetDefaultsTuple(__pyx_t_7, __pyx_mstate_global->__pyx_tuple[13]);
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_7};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 3729, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_calculate_subwatershed_boundary_4, __pyx_t_2) < (0)) __PYX_ERR(0, 3729, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4071
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_lowest_drain_and_sink(dem_raster_path_band):
 *     """Find the lowest drain and sink pixel in the DEM.
*/
  __pyx_t_5 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4071, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __pyx_t_6 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_27detect_lowest_drain_and_sink, 0, __pyx_mstate_global->__pyx_n_u_detect_lowest_drain_and_sink, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[13])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4071, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_6);
  #endif
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_5, __pyx_t_6};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_7, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4071, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_detect_lowest_drain_and_sink, __pyx_t_2) < (0)) __PYX_ERR(0, 4071, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4196
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def detect_outlets(
 *         flow_dir_raster_path_band, flow_dir_type, target_outlet_vector_path):
*/
  __pyx_t_7 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 4196, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_5 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_29detect_outlets, 0, __pyx_mstate_global->__pyx_n_u_detect_outlets, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[14])); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4196, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_5);
  #endif
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_5};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_6, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4196, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_detect_outlets, __pyx_t_2) < (0)) __PYX_ERR(0, 4196, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":4635
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def _delete_feature(
 *         stream_feature, stream_layer, upstream_to_downstream_id,
*/
  __pyx_t_6 = NULL;
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_mstate_global->__pyx_n_u_gdal_use_exceptions); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 4635, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_7 = __Pyx_CyFunction_New(&__pyx_mdef_15pygeoprocessing_7routing_7routing_31_delete_feature, 0, __pyx_mstate_global->__pyx_n_u_delete_feature, NULL, __pyx_mstate_global->__pyx_n_u_pygeoprocessing_routing_routing, __pyx_mstate_global->__pyx_d, ((PyObject *)__pyx_mstate_global->__pyx_codeobj_tab[15])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 4635, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030E0000
  PyUnstable_Object_EnableDeferredRefcount(__pyx_t_7);
  #endif
  __pyx_t_8 = 1;
  {
    PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_7};
    __pyx_t_2 = __Pyx_PyObject_FastCall((PyObject*)__pyx_t_5, __pyx_callargs+__pyx_t_8, (2-__pyx_t_8) | (__pyx_t_8*__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET));
    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 4635, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
  }
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_delete_feature, __pyx_t_2) < (0)) __PYX_ERR(0, 4635, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "pygeoprocessing/routing/routing.pyx":1
 * # coding=UTF-8             # <<<<<<<<<<<<<<
 * # distutils: language=c++
 * # cython: language_level=3
*/
  __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_test, __pyx_t_2) < (0)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /*--- Wrapped vars code ---*/

  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_9);
  if (__pyx_m) {
    if (__pyx_mstate->__pyx_d && stringtab_initialized) {
      __Pyx_AddTraceback("init pygeoprocessing.routing.routing", __pyx_clineno, __pyx_lineno, __pyx_filename);
    }
    #if !CYTHON_USE_MODULE_STATE
    Py_CLEAR(__pyx_m);
    #else
    Py_DECREF(__pyx_m);
    if (pystate_addmodule_run) {
      PyObject *tp, *value, *tb;
      PyErr_Fetch(&tp, &value, &tb);
      PyState_RemoveModule(&__pyx_moduledef);
      PyErr_Restore(tp, value, tb);
    }
    #endif
  } else if (!PyErr_Occurred()) {
    PyErr_SetString(PyExc_ImportError, "init pygeoprocessing.routing.routing");
  }
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  #if CYTHON_PEP489_MULTI_PHASE_INIT
  return (__pyx_m != NULL) ? 0 : -1;
  #else
  return __pyx_m;
  #endif
}
/* #### Code section: pystring_table ### */
/* #### Code section: cached_builtins ### */

static int __Pyx_InitCachedBuiltins(__pyx_mstatetype *__pyx_mstate) {
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __pyx_builtin_enumerate = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_enumerate); if (!__pyx_builtin_enumerate) __PYX_ERR(0, 3285, __pyx_L1_error)
  __pyx_builtin_min = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_min); if (!__pyx_builtin_min) __PYX_ERR(0, 3341, __pyx_L1_error)
  __pyx_builtin_max = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_max); if (!__pyx_builtin_max) __PYX_ERR(0, 3342, __pyx_L1_error)
  __pyx_builtin_sorted = __Pyx_GetBuiltinName(__pyx_mstate->__pyx_n_u_sorted); if (!__pyx_builtin_sorted) __PYX_ERR(0, 3867, __pyx_L1_error)

  /* Cached unbound methods */
  __pyx_mstate->__pyx_umethod_PyDict_Type_items.type = (PyObject*)&PyDict_Type;
  __pyx_mstate->__pyx_umethod_PyDict_Type_items.method_name = &__pyx_mstate->__pyx_n_u_items;
  __pyx_mstate->__pyx_umethod_PyDict_Type_pop.type = (PyObject*)&PyDict_Type;
  __pyx_mstate->__pyx_umethod_PyDict_Type_pop.method_name = &__pyx_mstate->__pyx_n_u_pop;
  __pyx_mstate->__pyx_umethod_PyDict_Type_values.type = (PyObject*)&PyDict_Type;
  __pyx_mstate->__pyx_umethod_PyDict_Type_values.method_name = &__pyx_mstate->__pyx_n_u_values;
  __pyx_mstate->__pyx_umethod_PyList_Type_pop.type = (PyObject*)&PyList_Type;
  __pyx_mstate->__pyx_umethod_PyList_Type_pop.method_name = &__pyx_mstate->__pyx_n_u_pop;
  return 0;
  __pyx_L1_error:;
  return -1;
}
/* #### Code section: cached_constants ### */

static int __Pyx_InitCachedConstants(__pyx_mstatetype *__pyx_mstate) {
  __Pyx_RefNannyDeclarations
  CYTHON_UNUSED_VAR(__pyx_mstate);
  __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0);

  /* "pygeoprocessing/routing/routing.pyx":865
 *             (offset_dict['win_ysize']+2, offset_dict['win_xsize']+2),
 *             dtype=numpy.float64)
 *         dem_buffer_array[:] = dem_nodata             # <<<<<<<<<<<<<<
 * 
 *         # attempt to expand read block by a pixel boundary
*/
  __pyx_mstate_global->__pyx_slice[0] = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_mstate_global->__pyx_slice[0])) __PYX_ERR(0, 865, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_slice[0]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_slice[0]);

  /* "pygeoprocessing/routing/routing.pyx":1359
 *     if weight_raster_path_band:
 *         weight_raster.close()
 *     LOGGER.info('Flow accumulation D8 %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_mstate_global->__pyx_tuple[0] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_kp_u_Flow_accumulation_D8_1f_complete, __pyx_mstate_global->__pyx_float_100_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[0])) __PYX_ERR(0, 1359, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[0]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[0]);

  /* "pygeoprocessing/routing/routing.pyx":1857
 *     plateau_distance_managed_raster.close()
 *     shutil.rmtree(working_dir_path)
 *     LOGGER.info('Flow dir MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_mstate_global->__pyx_tuple[1] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_kp_u_Flow_dir_MFD_1f_complete, __pyx_mstate_global->__pyx_float_100_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[1])) __PYX_ERR(0, 1857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[1]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[1]);

  /* "pygeoprocessing/routing/routing.pyx":2143
 *     except OSError:
 *         LOGGER.exception("couldn't remove temp dir")
 *     LOGGER.info('Flow accum MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_mstate_global->__pyx_tuple[2] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_kp_u_Flow_accum_MFD_1f_complete, __pyx_mstate_global->__pyx_float_100_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[2])) __PYX_ERR(0, 2143, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[2]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[2]);

  /* "pygeoprocessing/routing/routing.pyx":2676
 *     visited_managed_raster.close()
 *     shutil.rmtree(tmp_work_dir)
 *     LOGGER.info('Dist to channel MFD %.1f%% complete', 100.0)             # <<<<<<<<<<<<<<
 * 
 * 
*/
  __pyx_mstate_global->__pyx_tuple[3] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_kp_u_Dist_to_channel_MFD_1f_complete, __pyx_mstate_global->__pyx_float_100_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[3])) __PYX_ERR(0, 2676, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[3]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[3]);

  /* "pygeoprocessing/routing/routing.pyx":3128
 *                     stream_feature = ogr.Feature(
 *                         stream_layer.GetLayerDefn())
 *                     stream_feature.SetField('outlet', 0)             # <<<<<<<<<<<<<<
 *                     stream_layer.CreateFeature(stream_feature)
 *                     stream_fid = stream_feature.GetFID()
*/
  __pyx_mstate_global->__pyx_tuple[4] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_n_u_outlet, __pyx_mstate_global->__pyx_int_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[4])) __PYX_ERR(0, 3128, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[4]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[4]);

  /* "pygeoprocessing/routing/routing.pyx":3203
 *         # if no upstream it means it is an order 1 source stream
 *         if not upstream_id_list:
 *             stream_feature.SetField('order', 1)             # <<<<<<<<<<<<<<
 *         stream_feature.SetGeometry(stream_line)
 * 
*/
  __pyx_mstate_global->__pyx_tuple[5] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_n_u_order, __pyx_mstate_global->__pyx_int_1); if (unlikely(!__pyx_mstate_global->__pyx_tuple[5])) __PYX_ERR(0, 3203, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[5]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[5]);

  /* "pygeoprocessing/routing/routing.pyx":3237
 *         if stream_fid not in upstream_to_downstream_id:
 *             # it's an outlet so no downstream to process
 *             stream_feature.SetField('outlet', 1)             # <<<<<<<<<<<<<<
 *             stream_layer.SetFeature(stream_feature)
 *             outlet_fid_list.append(stream_feature.GetFID())
*/
  __pyx_mstate_global->__pyx_tuple[6] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_n_u_outlet, __pyx_mstate_global->__pyx_int_1); if (unlikely(!__pyx_mstate_global->__pyx_tuple[6])) __PYX_ERR(0, 3237, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[6]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[6]);

  /* "pygeoprocessing/routing/routing.pyx":3457
 * 
 *     stream_layer.DeleteField(
 *         stream_layer.FindFieldIndex('upstream_d8_dir', 1))             # <<<<<<<<<<<<<<
 *     stream_layer.CommitTransaction()
 *     stream_layer.StartTransaction()
*/
  __pyx_mstate_global->__pyx_tuple[7] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_n_u_upstream_d8_dir, __pyx_mstate_global->__pyx_int_1); if (unlikely(!__pyx_mstate_global->__pyx_tuple[7])) __PYX_ERR(0, 3457, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[7]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[7]);

  /* "pygeoprocessing/routing/routing.pyx":4301
 *             x_off_border = 1
 *         else:
 *             flow_dir_block[:, 0] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for top border and if so stripe nodata on the top margin
*/
  __pyx_mstate_global->__pyx_tuple[8] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_0); if (unlikely(!__pyx_mstate_global->__pyx_tuple[8])) __PYX_ERR(0, 4301, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[8]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[8]);

  /* "pygeoprocessing/routing/routing.pyx":4308
 *             y_off_border = 1
 *         else:
 *             flow_dir_block[0, :] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for right border and if so stripe nodata on the right margin
*/
  __pyx_mstate_global->__pyx_tuple[9] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_int_0, __pyx_mstate_global->__pyx_slice[0]); if (unlikely(!__pyx_mstate_global->__pyx_tuple[9])) __PYX_ERR(0, 4308, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[9]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[9]);

  /* "pygeoprocessing/routing/routing.pyx":4315
 *             win_xsize_border += 1
 *         else:
 *             flow_dir_block[:, -1] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Test for bottom border and if so stripe nodata on the bottom margin
*/
  __pyx_mstate_global->__pyx_tuple[10] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_slice[0], __pyx_mstate_global->__pyx_int_neg_1); if (unlikely(!__pyx_mstate_global->__pyx_tuple[10])) __PYX_ERR(0, 4315, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[10]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[10]);

  /* "pygeoprocessing/routing/routing.pyx":4322
 *             win_ysize_border += 1
 *         else:
 *             flow_dir_block[-1, :] = flow_dir_nodata             # <<<<<<<<<<<<<<
 * 
 *         # Read iterblock plus a possible margin on top/bottom/left/right side
*/
  __pyx_mstate_global->__pyx_tuple[11] = PyTuple_Pack(2, __pyx_mstate_global->__pyx_int_neg_1, __pyx_mstate_global->__pyx_slice[0]); if (unlikely(!__pyx_mstate_global->__pyx_tuple[11])) __PYX_ERR(0, 4322, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[11]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[11]);

  /* "pygeoprocessing/routing/routing.pyx":4558
 *     cdef int last_dir
 * 
 *     with GDALUseExceptions():             # <<<<<<<<<<<<<<
 * 
 *         if flow_accum_managed_raster.get(x_l, y_l) < flow_accum_threshold:
*/
  __pyx_mstate_global->__pyx_tuple[12] = PyTuple_Pack(3, Py_None, Py_None, Py_None); if (unlikely(!__pyx_mstate_global->__pyx_tuple[12])) __PYX_ERR(0, 4558, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[12]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[12]);

  /* "pygeoprocessing/routing/routing.pyx":3729
 * 
 * 
 * @gdal_use_exceptions             # <<<<<<<<<<<<<<
 * def calculate_subwatershed_boundary(
 *         d8_flow_dir_raster_path_band,
*/
  __pyx_mstate_global->__pyx_tuple[13] = PyTuple_Pack(2, ((PyObject*)__pyx_mstate_global->__pyx_int_1000000), ((PyObject*)Py_False)); if (unlikely(!__pyx_mstate_global->__pyx_tuple[13])) __PYX_ERR(0, 3729, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_mstate_global->__pyx_tuple[13]);
  __Pyx_GIVEREF(__pyx_mstate_global->__pyx_tuple[13]);
  #if CYTHON_IMMORTAL_CONSTANTS
  {
    PyObject **table = __pyx_mstate->__pyx_tuple;
    for (Py_ssize_t i=0; i<14; ++i) {
      #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      #if PY_VERSION_HEX < 0x030E0000
      if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)
      #else
      if (PyUnstable_Object_IsUniquelyReferenced(table[i]))
      #endif
      {
        Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);
      }
      #else
      Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);
      #endif
    }
  }
  #endif
  #if CYTHON_IMMORTAL_CONSTANTS
  {
    PyObject **table = __pyx_mstate->__pyx_slice;
    for (Py_ssize_t i=0; i<1; ++i) {
      #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      #if PY_VERSION_HEX < 0x030E0000
      if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)
      #else
      if (PyUnstable_Object_IsUniquelyReferenced(table[i]))
      #endif
      {
        Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);
      }
      #else
      Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);
      #endif
    }
  }
  #endif
  __Pyx_RefNannyFinishContext();
  return 0;
  __pyx_L1_error:;
  __Pyx_RefNannyFinishContext();
  return -1;
}
/* #### Code section: init_constants ### */

static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) {
  CYTHON_UNUSED_VAR(__pyx_mstate);
  {
    const struct { const unsigned int length: 13; } index[] = {{2},{3},{15},{34},{35},{36},{35},{60},{30},{36},{28},{17},{1},{1},{8},{54},{67},{18},{23},{10},{9},{24},{39},{29},{49},{7},{13},{29},{6},{62},{59},{44},{51},{39},{71},{55},{47},{45},{53},{70},{58},{66},{60},{68},{46},{53},{55},{63},{56},{63},{13},{13},{21},{10},{20},{15},{15},{23},{30},{2},{15},{9},{32},{39},{34},{4},{9},{19},{10},{18},{29},{57},{22},{17},{12},{16},{20},{21},{34},{21},{24},{8},{54},{18},{23},{39},{15},{26},{80},{21},{5},{11},{11},{8},{17},{10},{17},{6},{10},{13},{11},{21},{11},{36},{33},{13},{11},{11},{7},{9},{14},{10},{9},{17},{8},{11},{9},{11},{4},{5},{8},{15},{6},{10},{8},{14},{8},{12},{13},{2},{13},{6},{10},{12},{7},{9},{9},{6},{20},{11},{12},{23},{18},{22},{10},{8},{11},{16},{16},{5},{10},{1},{11},{6},{6},{18},{26},{13},{13},{18},{11},{8},{11},{13},{18},{10},{13},{10},{10},{31},{42},{31},{12},{10},{12},{20},{22},{14},{24},{17},{18},{11},{31},{25},{28},{13},{14},{23},{19},{4},{8},{13},{19},{1},{2},{26},{16},{28},{3},{8},{5},{12},{27},{19},{19},{13},{15},{11},{15},{11},{7},{7},{8},{15},{15},{16},{18},{10},{10},{15},{20},{28},{14},{15},{3},{21},{7},{9},{15},{14},{24},{16},{13},{15},{26},{28},{20},{15},{22},{34},{23},{25},{23},{17},{20},{14},{18},{14},{15},{16},{26},{14},{11},{11},{18},{13},{24},{5},{4},{6},{4},{6},{5},{8},{9},{5},{6},{9},{9},{9},{9},{6},{8},{27},{19},{10},{3},{12},{11},{9},{10},{15},{15},{25},{17},{6},{17},{21},{12},{23},{31},{21},{7},{10},{15},{25},{13},{17},{27},{20},{21},{8},{13},{14},{21},{11},{26},{28},{13},{23},{12},{17},{25},{27},{15},{22},{19},{29},{10},{15},{15},{20},{25},{12},{13},{15},{11},{10},{14},{8},{2},{2},{2},{2},{2},{2},{4},{19},{21},{18},{12},{9},{15},{6},{11},{1},{3},{4},{15},{5},{3},{4},{5},{4},{28},{12},{13},{8},{9},{30},{5},{5},{10},{1},{4},{11},{13},{13},{17},{13},{13},{4},{7},{9},{5},{16},{7},{5},{19},{18},{8},{8},{11},{3},{20},{23},{23},{3},{13},{9},{3},{20},{24},{9},{9},{7},{20},{10},{10},{6},{5},{10},{16},{8},{12},{8},{8},{11},{8},{6},{7},{7},{10},{8},{3},{20},{20},{7},{6},{27},{27},{18},{21},{15},{5},{11},{11},{11},{3},{8},{3},{7},{5},{11},{2},{5},{3},{25},{7},{16},{14},{11},{6},{20},{14},{10},{15},{12},{12},{12},{13},{8},{8},{5},{4},{7},{23},{13},{9},{5},{11},{12},{9},{31},{23},{21},{33},{22},{3},{10},{9},{6},{8},{15},{18},{6},{6},{14},{15},{31},{12},{12},{13},{28},{11},{16},{11},{10},{13},{13},{17},{6},{7},{5},{8},{8},{11},{6},{11},{5},{11},{12},{12},{12},{19},{12},{10},{7},{11},{11},{6},{13},{19},{10},{6},{24},{9},{18},{19},{8},{5},{27},{12},{11},{15},{14},{10},{12},{11},{9},{13},{12},{17},{13},{10},{13},{16},{18},{17},{8},{6},{22},{27},{20},{25},{14},{28},{38},{29},{25},{29},{20},{18},{25},{25},{25},{37},{8},{16},{8},{8},{10},{9},{4},{24},{7},{12},{19},{12},{20},{26},{9},{5},{20},{14},{14},{15},{23},{12},{13},{16},{12},{17},{16},{13},{19},{17},{21},{20},{11},{16},{14},{14},{22},{14},{25},{25},{5},{4},{4},{22},{5},{5},{6},{11},{17},{22},{19},{7},{18},{18},{17},{15},{17},{16},{13},{13},{23},{10},{9},{16},{9},{16},{3},{13},{13},{8},{10},{11},{16},{28},{26},{15},{11},{28},{12},{13},{16},{13},{13},{1},{3},{3},{3},{12},{3},{3},{2},{2},{2},{5},{4},{4},{7},{5},{4},{3},{3},{3},{12},{3},{3},{2},{2},{2},{5},{4},{4},{7},{5},{4},{1497},{2627},{1475},{194},{4124},{577},{1195},{1370},{868},{2025},{2048},{1948},{1578},{972},{87},{95}};
    #if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (11719 bytes) */
const char* const cstring = "BZh91AY&SY/\024\2547\000\020T\377\377\377\377\377\377\377\377\377\377\377\377\377\377\277\377\377\377\300@@@@@@@@@@@@\000@\000`7w\036\366\216\301\362\"D_xc\212\210A\013\251\2746\355\340\235\007A\350\007\207\260\000\314\367\000[\2169}\363\240$\201\336}f\345Q\347X\243\245t\353N!\255\261\221*\320Qx9\324]\356\222\333s\007\0355\007\r\r\000\373\354\355\217]]\267Z\351\3646\307R\311n\323\264\255e\335\335-n\335]\263\317\2627\336\316x\037@\005\025E\021UT\370I!\0042\0320 L  \0324\231\244\323\025<\243\304\364\247\246j\214{IO\302S\302\236\231 \007\220\321\351\023@\000i\240\020\204\023SH\247\246\221\350 \323F\232\00654\006'\251\240\003\324\003\003A\352\023\332=(jbd\321\246\2311\001)\210E%\t\001\352\000\003#M\000\000\000h\000\007\250\362'\250\323G\212x#\321\021\240\000\006\200\022iB\"5'\211=4\251\355&\324\233PmL\232\001\232\233Q\220\323\322z\232<\220\323\322i\260S \365=F\364\022=4OSj<\232\236\246\214\201(\202*z\206\206@\007\3522\207\250\311\352h\364\206\207\251\246\215=FOS\332\004C\324z\236M@\321\240=&\020\310\000d\000H\210 \010\232i\031M\252y4\321\251\212\237\250y5OP\311\220=#'\250\000\032\030\324~O\r\001*2i\246@\007\250?T\224\330\201\200\345Q\210\367\244w\024.\251\356\312p@e\366\365\356\234kmzx|\347\276\306\216\345\333S\234\326GZ\342\335\364c\027Z\264b\357j\253Z%cJE\210\312\225\005\tm\213*Tw\305\335\311\201\262\245\300\341\313G9\262\2531h;_\033;h\331\232&\020\254\025UJ\225\363\343\325\373&\262\202\037\200CU\021\r`\021\342\003\321\017\310\037\242\n4\255\021\305\301\362\226\014P\265w\227\227)\300\035\331We\031\2558\031\030\300*a\"&C\t2\\\206\002\343\033\353l\213A\254\325\225-\352\247\223\t\307s\0358\351&\351\343\241,\245@\362]\3266\214\270J\3021\334M\0261\330\243bV\207K\347\355w\231\2349mm!&cuX\2239c\331\\\243NQ\022\265T\233\013.,\206A\353z\277\367\367\276W\253\201\260\030\t\260\0107D\3317\003\210\017\177\213\200\031\201\302M\004\3418CS\362\001\371`\200\261D\020QAH\260Q\030*\242#\005X\214\200\260F*\202\310(\n#\010\261B*\250\013\030\305\"1\026+ \260PQ\021#\005\221dETETPY\004`\242""\305xs\231\342\007\020\234C\024\214\352T\371\004\204\\\221J\002\342\025\302\350\316\236U\367\202I`#\002\210\301`,0'\345\017\274Y\00211\000\251\206\006\006\227E\357\230\022tH\007@\221V\010\014\"\220Ea\005\200,$P\212(\020F1\002(\262\0139\306AIZYd\225*\n\020Y\005\026I\010\210r%\301n\257\262\330\255E&\340\027b\030\320\223g\202\251V\000\272\260\\\016\034\021T\221\250\221\207\363\005\210Q\200\230\322c\334\313$\221\215\222\3207K\023\014P\203c\023\020\324Y\032\331\032\240\314Kv\332CqB\nI\025T\200\253\000PTb\300\344\225\200\214\005\201YX\260\212\020\250\253$;A\2404i\033\0024Z\032-\r,\217\2402\340\230\014Z24\003\200\317\ttl\344\343\271\2727F\346\341\210\007\024i\260\324\346\206\2324\205\372R\226\232h\264F`\270\234\260\321\033\345\241\344\200\325\2660s\t\220$C\006\035\242\034\216\223\221\266\266\351\223\246\035i\005\202\252\202\305\026\021\024\212\212\261B0H\210\"*\200\244\212\242\243\010\211\311\202\243mb\214\n\212\005m\260\252\200e\005T+ \033lL\236B\003Qr*\026\264rA\250\203*B0\200\260\241eJ\241\024\2053\022\311(\333GR@t\tp3\327\225\332\254y\0207\304`\274\3522\367\260\274\334d\253\033.e\030\214p\326\221&\247\245\334(S\254\243j\257V\212\261VQ\347\014XW\"E\320\2532\335\344\035\214\036+\313\273DB\033\261:IYi\0214\220\323\220\361\335\2719\305\273\266\363\252\216\336\342\322\324\310a3J9\227\016zN\200\345\252\350y\244p]\016:!4\na\260\335j\222Z\002\320\324\335\0340\217\324\331 Z\256OEm\233\215\210D46\240\"f\001\2613e\260\033\010[$\032X\013!\244\0148#\270\301`\242\252\210\305QER\n\301b\212\221d\222)\026H\260Y\005\221\355Z\214J\205AaZ(\210\302\211X\211\326N\203\221\270v\236\002+\204M$8 Mt\201\260l\203d\266H\350K~\001\242\314\317C\016j\007P\211\320p\201\301\021\233\3640x\027\210\230)@\254\036\2007\026\351\032\006\342\337r\346E>\241%\272\016kg\323B\342\333|T\302i\244\246\002\010Hn\\\233\210\335nn-E\271\272.e\207\342\340\203~(8\255\214\033[\343\300\031I\221KJ\212\2202\224\023\211\244L\307\004t\207L\351'L:w\206\307gw\262N\350\222()\"\302#\"\"+\021\214E\212,\024\025\022\021I\005\005\210""\254\021Qb\207l\264\243m\004\245\025B\211X,\024\221hv\317\014;}=!\334\222\227\2664aS\265\021\022\344\350\244Q'.K+\027\267y\013D6-s\347\256\312o\206/h\222M\207\022\340\2406H\341I\022&t\006\351\033\243\230\262\250\274\250\026\340\034u2\241T(Z\301\016\022\324\226\347R%\221\0012\306P\244K\357hh_4\222\340j\270g\226Q\244\021\242_L\320\t2J\025\211\025*Q\nF\014hbve\013#\217\023d\033\026\014\003\010 k(/s\303\356\010(\210\n\240\010\221`\262H\261H\013\024\210\222(,\"\303\250V\261-XT\210\2022T\255\032\220\275g\316;t\275\264y\200:\271/?.\254\223\032)\226I\200\210\027&L\246\252\345\271.3\016\250N\251\324uO\020\345\303\007\303\274&4\337\026\323h|9\361C:\037{\200r:#C\223\326\201B\215\032\001\311\231\321\300\"\205\265\"\242\240\252\252/\313x;\000\n\224\024aO4\311}\353\202\342\250\212L\263\372\022ZB\320\025$\212%\304\342\013\212\\8w\367\307R\374\352\332\004\026Ie\227\245/\024R\230\213\2321\004\0244\017Q\310R\352\244$h\302'F\352AR\024\331)#JK}\357 dK8\313\356\344p=\205\347\376vM\332z\000\373\377\013\275\317\374\352C\375\236#\003\367\022\263^5\3168\271\312\234\251Aa\004\202H$\017\273\215/\337\377\2226\310\335\177\n\017\261\201\276d\377\327\335\307%L\270\257W\371\306\374.3\255\231\300\031\300[\003\356s\035\323\201\224U\002\307@>\376\360\366G\340n:\276>\367\376Xt\016Gc\317\250\235\273M(\331^\225\255_\230\232\013\326\304\2066\311\323\317\300I\371:\256\020~\320\351.I\330\251+{\355\277\212zw\r\310\261\376k\251\216\356\335\245\034`\230\002g\313,\3629\321\214Bw\307\014\022\276\365\016\302\362CwT\353\247\035s\205t\303\203\213\212\005\371~A\240\320d\314\264\332\347\366i\240M\204Go\234|\227\310\026\021Q\363\375h?H@};\207\324\323\343\301f\3203\213l\331o+\217\325DZ\314\202T\021\310\234\314r\244\007l\020cIv\320\271\303\235eK(aV\336/\037\215\264w\305\345\365\326\t0\205\202\263a.\027i\036X\311\210i\326\214\362,z\266T\224\316\264\020Q\2666\223\243j\225D^\010\006D\t\363%\335\221\255.\321|\310\013\006\320\234m]\322\250\322\331+'\244J\022\312zn\270l\303H;N\236]`\371\301w\266f\353\335U:\364\234H}Pr=\253""\355fr\316X\371\010\210\221\033\235\023\240\303\207\273\331\314\256\r\332\257\223J\2223f\265Z\325T\255fw;\313\030\216\026\260\021\227\017\245\005\200T\254\013oT\013 dY\373\331u\272\231~\032\036\360\352\nZ\010\205\275\333\327\253\326\232\302`m\307\\>D\3341\306\334\360 \210\352J\240U\005A\245\031d\t\327\362\232\215HJ\324\311\204\3140\304`h\312\222\303C\027\213\317{\332\374Y\n\032\233]#4LRR*P\024\244R\221Ho\031\226Ux\303\350\351\363\24701\332J\340(s!\3349\220\277z\227\3319\244\202\304!b\0001-;.\2703\014\031\330L\252g\t;A[<\213F\020Pi\007\021\220\203F\241$Nv\200\316\263\231\314Q\250\376\021]h\251T\310,\264\345\370\327\003\214\2555\247#\302\346\034\247\317\231P(\300\261\204\343\211dI\341\0275\314U-\321+\016\r\200X\007\0375\311Z.\245\246\226\246\340aZX\030\225\314D\316f\211\304,\217\343\007\026\335\310>\240\314f.\016\224\307D\232\305p\034[\314\334=^^\324=\210\234\314\317s\277\335\334\217i\177\327\223`rb\320h5;C\322\n\224\344\035\274v\234\2447D\364\366\tt)\255<\005L\213\034\3413\n\302\341pH\006\217\3447\362~F\303AAAOY\320b\251J\344/E\301#\274\370\023\270\001Z%\300\257a\245\006\222\225\246\256\262\307CTjp\3526\347\270\357Kn\320\302D\004\324\240\037&\360\331I\352\004\t\350\200t\350\023;\3407@t?!\002y\343SDb\214>I\037y\3068\357\304\253\241G\317\377\034\3776\355\376\002\300\255\031'\014\005=\207\217\3303E\242\026\215[l\273e\352\300\2549\374?\272L\247R\2205\325\314j\364\366\313\325\260\262\227\025\220x\367\025\270\2463v\301\357++\0162\020n\3575b\332~.\362R[\373X\345=\356\036\347\023A\311\273\2437\273\273\337\216\r\034{M\356\317\253V7\032\335\275\013\215{\030gC\212\361#\241\253W\265\342\271w\362\231\027\031\301\315=\016*\346y\002\005Y!$k\256\362<\224\373b\351\025U\217\202&\304\347\177\247\n\342E\202\212\272\262h0\366hy\225\325E\213\275\016Hkx\316\"y\343\346\"\275\375\261\206Ow*\017l\244\nd\327\342\314\016H;)$\264\210^\014XsZ\355\311\252\331aRxBX\215\347\363\354@{\240\270\322\240\241\024\006\370\234\344\370\236\366\322|:\372X\214\307\243!\325\302\353`bP\242k-\243)]!\024\253X\313X""\0321a\037\243\314\333u\003\016\020]\306+\033\247\235\206\302-\334-<j\270\344\214\346\0171\306\271k\233ff\310\356L\263\\\274\025\321\030\360\255Hp \243M\340\020\311\307&\r\221\2722\256\235\030v\263\020Y\204iWC\207\017?\3063\237Sfu\362\360\004\210\025\3405\357\367K8\035\237\r\306\216\0313K\031n\202SS\241\250u\211\\\\\2143O\3343f\315\240\314\263%\231,\302\262\3253\276u\306\354VR\312:\363\\x6\\\205r5\376KW\330\255\264V\242\324\026\253PW\246\224\305.\245\345m\021Y\227\340\244\nR0\316d\242\204\202\n\200Q\010(\002\323j\033.\\\370\334\035&X\221\213^\017\254\327\3556U\261\0312$H#\"\232\243fCd.\316x\376\312QJ)1,I\030\222\304\270\261o2\302\355\347\265\0170\226\302\006sD\246\265B\243\240\366\201\031\231\031\331&\356l\255\"\264\202\260\254U\325\235\253\250}\"\317\270\313~e2\023\224\311H\260U\203\352V\305\027[\002\263\337\361q|F\177\030\234\300\346I\314&c\202\340\312\262\213*0\376tdb\235{*9\"3\217\331\207\016d\030\201bA\211f\231Q\365\203c\311\316\340~cT\342\235\023\212u:\213\223\006\026\277\253\r|+T\244\34199>\351\272\370:\217\305\224\250\3132&\t\200\233\271\361M.s=\247,\223LLL)\203'\33066\240&\276J\214\353Y\307\307-\347K\277\367\372\275g\334|\347\207\364\371?\027k\261\343\355\274\316\212\322\005\234\004\263\2405 8\250\364~\027\341\375\2078\035\272~\002_\214U\342+z\322j\320\345\332\244\222\275\316MV\353x\230\225\232\322@&\3271\2222\322\222Tj\021\3151\3061GC\255\031p\210\205b \230\371\031\310\213\204\025ekf\261D\256\262\233\"\024\334\3161\262\272R\322\347\r\215\331\304:\026\240V\314(\346\261*b>\263\227\366\377X\215\014\262K\001\006\t^\025\365\244\336\367=\316\307-\n\377\355\304j\346\374\177\036\203\275\274\355_\355X\004\302U\242\264\253\016Jyz\375\253\307\020v\0068\365\345\373\307\205\020\374\271ic\217r\334\224\351V\205X\212\305Z\\z\353\347\r\202\227\217\250~\216\301\373\254k\277\r\265\346eYZEh\021\205\"\260E~3\266yC\276E\313\322=\201m\361k\353.\0062\0358\016MK:\256\267m\347\321\305\035\302-E\253(Z\270\200\270^\366\376\211\314-\334\317\262\277\302\252\241\243\373\253\267\007z""\322\017\340h\272\321\340\240W\"\345u\305\336*\256\360u5\357\272e0`0.\271\275.N\227\264\301\375\237\327lZ\2427\324\352\260\235\025\207t\370\010\210\200\241V\277O\325\307\223\327:\260B\276+\342\013\345\3512\355\375\347\341\271\347Ti\260\006\005\201\005~\310\265ud1\242QK)o\363l\345\353\007K\016\001`0\0300#\002\355\364\373\274\277\241\320\302\023\033\232\023\316\211\347S\247\247\203\361\367tvth\366\302\263\213I\214\233\021\262!\001\260\201n\010\357$yE\361++Z\326N\024R\224\265]i*XE0k14R\322\211M\303mG;3s|)0\032\030K+-]\221S\3016X\210\254N6\323\207\343\355\244\004E\310\362\310\204EB\264\324d\267N\327\321K\305fEf;\341\236\020\225Z\232\231+\t.\313yY\234x\365\352\263#\263|\275\037\202s\030\362dUm\3554\273\316\322\355\351\303\020\024\t,h(YVU\nM\263\363j\362T\372\255\257]\231i\341\324\347`j\312\304\214\200\225hEh+\"~E\216}u\217:\346\230\235\222\232z\306\3733_\322\276m\242\306\225)R\013 \225\"\244\010\001\014\206\214>\3063\036\232\001\211\210i\240iQS\344\3073\022\242\304\013\001\2121X\240\361\032\343\373|\036\371\2434,\300\315\031y\177c\207F\2068\343\211\177\372\371:\260\270\\\271\242\372\312\364\226\262#T\270\321\326\223\n\200F/o\370^ \240\213\310=\\\367\257)\005\030F\030vD\242$\017\320\277\365\317\303\312\301a?\215\305\237/\225\202\304\274\230\354'H\231\014\247\276[\240\274\300\233wwt\374\306LX\036\277\252T\366v\363\004K/\233\362h`\202\347\r\377\037\320>\t\022Is\242\003\031V(\355\313\360\014\017LR&.\333~U\372\377X\240\363\303t\341yg_\336;\rN\334Q\2544\240\003\226Rr\233\377\r\257]g\002\226\334l\241+\230\r\2104h\305\243\235\340\234\312\322\314\376d]\342\275\253\356Tm9\021\024;qS\302\341\033\"\371\317<\235v\025j:\240\321\307c#\272\010\274\263\006*\252\003i\305\234\273\305\023\326\317K\341\2441\222'\215q\336\253\300\235\327\267\034\206\323\262\351\203\020\252Y\212\345\225\030\221\276\366\326e\307z\353\031\214\202(q\034\rH\303\262\364\341x\315>\213lv\341\t\004\231\000dB\271\3334U\215\027\256q\313\266\315\211\344\354\376.\037h\200\272\351\254\031@\314\361`\300'\305k.\275\3354\340""\364\244L\220\231\016U\002H\340mw\306\226\361\030x\316\354Wr\331n\214\235\333\250\306_\230\2366\231\276N\344wn\323\310ou\261\025,!\203b\273T\230\275\332\307~8lna\276.&q\233q|w\335Y\362\3459^\272+\310\347\211n5\3373\033XAN\033oL\033\0208\010|\n\362\223Jw\316a0R3\325\017\r\2713\274pyqW\033\327`\360lgq\247\2056\253+c\227E\344\025\263:\307'\266\352\371\3743\330\270\232\246\252\232/\372\t\357\300\357\244@\365(Q!\246\214\314\221\365\177S\0046\244H\3008%\207\022\243j\016\2529Y\240/\336i\005Ft\264\201\344\352\2732\275\273k\316\337\242\201=\355\272\n\331\241d\010\r\237\217  B\325\001A\006\033~\3132`\033`v\211^R\302T\355\362\320\314\nk\340P\nxtj\202\213\024\032\201lDw\226+P\371Z\004\260\302\373q\3524\305Y,\206 \2706cA\034a\263t\224\232\334@u]\024M\215\226\324-\205D\244b\262\357Z\226\027\207H\242\357\200\332\2318\360)\220\361\344\356]\315 \035\204\221\330\004\273)%\312\200\354\370$7uk\343\247\tN\311P\214\261P\220J\330\216\022\303V^\220B!\203o\001_8U\2742<\r\251\311QG\\\215\345\246\014\2561\262\\\351\321\232\320RR\233L\030\251W\013\200\226\232`\205\361bOt\305\253.\222\032\253\0352\344bjYr&g\360\n\2732\347a\005pn'\204\026\267\242+\254\222Deaj\030\215\210fq}\246`\211\236\0308\002(\342\277R2\2402\001\224\014\202\246\222\034y*\327\370\312\374.\260\235\330Csr\2526\203T\260S\250\352\247c\211\315$\273#\250\360|9\230\265V\336P_C\021P\032m\242\245\037S\310\326\376),\300Y\322\331L\313j\221\234\243\347\306\244\245PXI\200\312f\273\025\310H\030,\021\213l\240\210\215\276\020|xC7\276w\247d\003\274C\261v\"ms\223\335\244\336\333\r\240l\017\237\205$\351a\303\025\205\"\034?\350\342\355\314\311\265\241\206\0276v\346-\273\340\256\213a\026M:\343fW\360\021Q\035\361#8\217\206\0140\3752V4\266\02601z3\311Xe\257\337\355\252\254v\362\316\276\007\321rf\203\311\350\324\200\246\335\270\013\200p\330\200\206\0173l\266fY\362\263z\346\026I\003\210\212\302(\306\300}\277\2028S,\2578\347\276\007\216\004\220\304O\234\355\324\240\342\004\363\346\025:\352B\365\316\000\347\332\366v\215\243\0029\020\214F\304+\2513\225""\321\020\030v\306\337\313@C\3131\034ju\035kkG4v\244\267\215\010[\310\336H\336Kj\214Y\264\361\340|\356v\210o\354\307\276h\215\362rH\341\354\200\346\213!\004z$\"\220(\245\262\230\237o\264\246\223\361\t\031\263#\211\204q\226V\245\334\351\026eFd^1p\030\301F\210>l\230\322I\031b\227\212j\320\276\224x\320d,k\226\333\241T)\232\200\304\375M\316\204\237A\\\007\340\341Ri\343\262T\n\020\312\306S=\264\236\224\005!;\322\332\363\314\333r!\223\360\337~\233C\354b\343\254\222\273S\215\224O9[\357\016\016\024@\203_\020y\326\"\020\246(\326M\r~\2016\323\010\361\263\343\030\333\032\006\364\216\241<56'\217T\"K\246\264b[<\270\222\250\272G]\313\337\"\016\033\260\307.\252\353Z-\302m\360c@\217\256\251\241\210\2756\265\343\006)S\276\345\036\360rr\017'\327\3211\203\305\007Z\261\020\245\241\0149s\331 ^\241/x\353\351\316\031\223\033\013\343\224H\213N\\cJ\255\257\214\252\313\206\322S0\323\207\001)6\214\365\342u\361K\205\360\350\243\033\005w;=F8#{g3\236Ag\370\316\270\252\246\036\254\357fLD\032\215Z\306)c$;Di1\344\351H\256)D\214\223\024\2137\221h\344<z+<\351\325I'\346\372\251\323@E\323\236N\262[\220\034\2109\0229\022\344\016B%\016\277L8z\2002\231\267\372\206U\034\000\346:\016\275\360\010\342\322\270t\332\330\035h\210Aev6\224\371<y\235\342\275\223\267n\221\225\255`\251\253\370\335J\374\256x\025\227u\230\370\360\251\364e=B7\364U!\267\304?X\234(gEu<7&G3\250n\224\254z\023\036\223,l04\007\030Q\364\225\223\222U\321\311-\365\207j\016\304\013\265\035\241\245\023\210R\367\364\374^\\\321\210\314\300Z\304\265}\032\341\230\271\001\\\214\326\rvpo$v\007\311p\360\260W\334\355\004V\313T\326\214\254biJ\325\250<\213\267\265v\210\355<?7\"\0015\003LlI\250\330jd\003\202>b\222\315\t\243\246@\314\231\t\274\214\005HZr\207)\363:\263\333\306\025y\255\275\232\235\177\251\200\374\343\245\016M\025\030\304W\365\311\271<\247d\354\234R\013\007\305\233\366\306O!\214\030m\0366N\361\241O\025\212\013'+\335\013\250\322\325\302\320\253\370\374/\267\023:&\363\371z\261\025\231\252\271\364\307O\002\235L\034\303m\266\312|\363'\304\221=d\235""\256\375\357\247\247\227G\000\"\341\302\256\245\027\227\256(\333\025<\\\004\264f\251\244\265t8\240\003\2609\306_\004\3434B\254\201\324)\355\032A\326\027L8\335\317GRoh\r\263\322q\326\341\217F\"\321\252\t`\244\256\370\215a\254\026\340\334-\300t\314\312L\265v\261\230\022\301|\277|u7\363\261\331\310\326BF\242\027\344>!D\263\275x:\260H\212\214 \275\3449 \347\220\371\207\210v\242s\3122\225\022\321\266\re\214\026\333i\262K\345\2530a\001\222\260\316\257\"\364\030Wq0\303=\356$\346\203\016\330a$L(\2748y\022\013\222 `\0221\261\264Y\222\023\226\372u1\026\245\306\323\030\213=F\022xi\345\343\331\260\214\273%\"\265lm$\227\032\364\360\246y6i\254\021.\016P0\224U\206O\033\033\3458\234+\332u\245\327<i\343\036\026\334\205\222\263\311\307.r\344D\266YP\223I\202\226\332\301\222\312\266\211Fa\016YH\035\344\016\266m\276O\037=\177#\211\307.r\r1\225:\2059\332+d\243,LZG{\r:J\370%gd\354d\260\352t\r\221E\r!=\177i\311%\325\226\302\024\357\235R\257\316\353*\377\021\326u\245\326\007YQ\\\324\200|\240S\360x\334\225)\021\326\367t\244(\3452\332\251\251\302\301u\206\345qC\007n\001fz{\035qf\370\330\356\357\333\343\272\000\275\373\261\201C01\276!\331\251@\335\332\267\016*8N\t\253\016\004\232\273:\362\213\322\013L$\205\203K\200\251i4\375\250Af\0257\\1$\350x\370I\306C,\234\346\336?\002\234\001D\266\362\223\n4\336\306\362\211rI\022I\r\303c\035d\231\303\216\324\261\237\211\360\322\036\317\262\313\013\016\354\312\26604\330\272\257\025L\005\250\241$\302%I\033\267\263\275\316|\303\220\035\217\035\240\361R\353/\241\304\376\025\343'\366\340Ou\345\027\005JQj\371\001_\327h\0029\245\3050\017\215\256d\305z\"\023\023u1\326\201\206B\340\003i\255e+|}\267\331\230\352\325\222|\340\224~\373\317tb\321\341\033.\331\206!\303\342IJ\255\014\315\303\021\204'\021\226<{\010\342\352\316x\344\220\320dd\215\314\373\331\020)\214\376\276\215i\324\343\227f0LK\306\207\300l\t\367\320\200\304\310\237\002\024\272\367\266\"P\250l\031\035\224\302\234A%3\000{/\257\212[\3111\320\324y\027\345\203\226D\030\311\325\313\226\233\230\014\337\252x\265""\205avD\333\r\261\370'\344\374\014\335!i\274fj\233X\311\312\334T\336\355\350\277_+q\350\300\313N\235#3\000mD\326\262\272\002\255\344\000a*cJ\223&\361,\343\312\377\271\276\030x\376\013d\221\273:\260\352\thH\034\220\216\220\200\324\200\"\000\353\243\247 H\224\201$\211\023\204o\212\264\333\334c\3316f\325\212\252\377\266\027\314C\303_g\003/8X<\224\\+9J\361\014\254\210hN\372\315\310\\\322\265\006\004\204\225z\357\272\340\355\272\030\206\242\234\225*>Fh\223Ie:\226\211\204Mf\260\330]A\tXB7b%\255-.\n5\264\3630B8\320\351\213\006f\305\267Ibw\263\316\353\355t \211Q\354h\342\220\354k\016\233,A\202\254\034\260\212\264\222\260\266\243t\222\305\204\021\212xr\013\251\244\035\210E{'\350\033d\007?\r\2400h2b&sr\2013q6\010\347\2149C\002r)\306 \300\226\255XfN\034\"I\037\037\314&\225\312\267\342\253\275\303\\\236Zao\205,\t\301\331\230@\274\031\301\rf\312\002mA\003\277\325\227\342\343\370t\205\275RZ\031g*\026\364)L\304\037\210\346_%\221\343\262\247<\261<~6\3534\306CO\214h9\312\305\266\222\264G6psf\314\270\301\211\205\230\242,\250\367+\222\3302\2620[q\270\003h\215@-b\332\226\322\023+\347\013\025\366\260\371hV>\031\364\312s4G\217hg\240g\017$\204\000\353\307W74t\016\356\343\003\004\030\260;\347\177\317ZR\352\300\242\226\247\317\207}\263\305\360o\217\032\037\005\021\002u\322\342\317\017\010U\260f\357\300\317\030\334\340\240\345\2660\210\223\022\023\177}\275\240\027\325ZH\240\235\177GgUTU\353\324 \345\010\203\226\272\035\377S\305\273R4\335wu\024\373$\261\346\265[:\3457F6\204f4\210\343\020=Fd\325\233a7\001\210+\303o\024\320\265,\027\022J\235)\345D\203;\010g\311\313\242Cf<\341C\206\202\035\331\005\371\301\203\033Hq\272\2070\343\243h\007t@\016\325\272\014\221\231\001\271\310\017%\226l\022K\3246\006\221lH\330\006\300\330u\010\374\031\253f\t\201\232\342vlq\361|\312\334\316\364\030F2b5@1gkG~n\361\217\004ea\343X\245\026\203(\"\225\021u\206c\351eC^\023g\200CB\304+\230\032IH\220\200@\342\351\206\211\335\031\220\030\t\001\236%\321<V~\256\rDf\374q)\303\026C\233E\202\257B^\372VA\003\226\216l\340\301\236""\234r\357\342\325o%\005\366\307\266l\266\003f< I6Pb\n&\030$\232\217\300i\234N\356\305\347<\"(\205\243e`X`(B\315\267\341A\202\275J|1\312\245\014\036\261\021!\010\343F\22466>3\0209\211\317|.$m\303\201\246\031h\355;\n\242Z\336s\221,r\232\312\352\301\323\243\036bE\322\014\216\252uP\000\\\237\r\351\222Z\266s,\334\313\253\247(\245Ft\026Z\320\350\245e'\340\211\330\261\021\313}\257$\236GSI\024E\022\340\341\333\240\r\242Kj\332%\265-\240m\224\226dV\315w\371\030\302\352\030\211\014\230\031\232\002\030\340\010\230\"\205\241\241*\310_zh\nD0l\271\311\223\000\363d\251\023\262\006O\270\360\340\017\351s\336\242=\017m+\024\264\r\032\037\227\034zS;\212(\010D\345]1\356k\305\313\366\005\367\340fL\331[es\274\022\237\001i\2545\241\032\321\254Z\322\204\010\3213#3fc\003%\261\016`\203\220\241dz3c\3054\330\200\304\013\0226)\320ad\t6qz\362g\317\314\351e\373\037\016\332\2502\355\221f\214\213\370\035\351\226gW]q\260\223\016\233\016\035X0\216\215\322Yz\313\021bV \262\305f\336[\214s\321\356\273f\334\366KTn^?,\316k''\302\222\300\362v\327\344\302\003\305\026\234\0368\310p\212\024M\010\246\275gX\216\264\035}}\375o\257(\006t\270\207\037\216%\376\313\267\2166\255\"`M\367\340l\246=5\241f\262a\337\241\016i\022\341\235\346\005\030\321\201\317\023\277k\031?\215\341l5\313\004\235i\n\333F\223\275\271\234\305\314\016h\346\273C\220\213+\026\013/\302\212$\212\tP)\333U(\223\016\371K\242\352\312\330\324\251T\252T\357\353Z\t\243@\276O\346\036\367\340~3?\3577\373<{\376\360\366\301\212\021\016\014\025\021S\376\030\t<A\220\367P\202\220I\366\222(\007\307aP\367\332\035\037\341C\360\212E\030\2402zDa\357}Q?\003\017\320\037t`\035\206\177~C\371\304,`!G\344\265R\030\022\001r>\305\344I9\036\261Z;\351\024\017|p'\016x\370\230\001\242r\367\022\376#\276h_{\315\"|\363$\313\001\302?\372\210\236H\311\210\"+\360\r\367e\321hy\304\031!\346\2601\364O\034\365p\037/\330o\216\237%\237\310\303n\022\373\362\226\033\304\213\r\331R\"\027\362\177\ta\371\357\312\032\237(e\"\375{Y2ZI\025V3\351\037\225\276\010\373\214\371\266\237\000S\323\300""\252\303\376\303%\254D\302\345\343\367\250e+\367\2138_[\377\010\314\027\337\002\374d\311\373A\360m\227!\350\263,\021X\202\177\321\004\237=\223\375\035\230\034\030l\236U\224O\271<\351\345\020}\242\303:C\350\036\351\2311\202\220\270O\242\236\250\237\327\370\316\0205\215p\330\207\230c\206xM\333\264\005\302e\220Qep\007\322!\237\264\237f2\037l\362\317\203\3225\251\364\326M\315\251\203\001\346ny\206M\000\222\214\335(\310e*W(V\013\353'\226yp<\323I\364\351\356Z&\231L\250\224g\257\261~\026\177\343w\017\272bM\344L\244\334\341\002\311\220O0'\264\036a@\336\014I>\240\377-/\343\211`\277\td\334\363\215\261=`\372\345\337\333\2455C\204\336\310\363\336\021\260\320\201\2429V\020VB\300`\326GH\214\246\240B\321\030\344o\314\246\001\333\321q\r\356\332\260\035A\025\323\002\035/T\364\217>P|\342\270\3151\320V@\341\307\030\213\017`\345%\016d\3200\322Q\205B\244\372\241\365\276\260S\375}-\360\302\300)Hy\371\365\017?CLm\370\251\270h\307\302N-*Q\037\357$\237\375\231\023)5/CB\262\220\014\317\002@\375\306\0363f\"SK\3002\014U^\237\356\207\306\364\375>\213\324)\\\313\033\004L\030>+\276=\014\037c\007\302\352g\206\r>\202a\220\025\030\t=\364\251\014';7\315\003s\372/\236\177I\347\375\232t\037\023\235Q\037@\333l\343\320\013\255\335m\266>'|\026z5\246\357\006\033E\036\021\225\343\350\302\316d6u\351Y\"QF=\022\260\017\207\223\243\316$y\275~XC\241_o@\244\006$o\350\275,\177\263\321z=\267\034]U\301\301F\363\271T\301\202\363\024=9\236N\207\035\030$/L\tQ\220\226r^\304\n\013\340^\206\031( \006\0221\226\312q\343~\035\246>\301\351S\324\364\241T\364\364S\321\307\341\326v\017N~'\324$>\2130:\346o\227\357\347\205\335\215\036\010\302\2012ir%G\350\310\234S\026$\220z\336#\032\256\247\254K\310\364!\304N\347\207@Y]\265\314.\312\264|c\307\253\362)\017\334`z\236\276\276\323\224s\266\000\367\346?\264\301\306\303\024\3433X\314'\333\nRI\376\235}\237ae\230+0\"\34685U(\271P\324\271\002\321\331\247\3169)\024\316\023\306\010)\277\207\237\323\363\263\007\242\016\035\005\353\177\313\363\177O\320\007\322},\357\202;\372\263Oq\021\203\025""\335\034g\000U\232@d\345\037\237\022\014^.\246p\\5\343\352\273g~\232a6\340\2436I\272f.\263\210\361\247C\271\354\253>\366\222=\350\373\021\346?\326 \212\320\364\315\273=-\204\377_\032*\371\240<\376z)\254\366\275\n\274\321\230\257\311\326\257.5\231\035\346:P|\252\255fah\360\254c\025EPZR\322\014\212\024Z\347\010\326*\014\253\n1\214\311\303\252\230\220>\303\201\273d%\366~a\023O4\371\250\217\317\366\300\250\377\345dI\346+\350\362\037Q[Xh\260\024/\322\250\262\221\274\202\025K\007e\\\3331\314,\222xL\313\224J\214X\021\255\261'Gd\021\005}7\232\275\026\261C}&\277\363\271-!R\263.\334#\375A\212;\217G\332O\347\200\231\"|\321+\317d\274\362/\273\272\003\325\232\204\252\300\217\272\260\227\2540\374\264\245\201\201\341\2100Z\021\263\2442(\3578\354-\344\025lc\211!I\210L\212\000bP\240g\244\022X\233\304\227\216\316\374\003%\327i\021*\t\272Y\343\334\364=\217_\345/\213\3553+\331\333O\334\377\216\260\\\"\252\330\300\363\362\0302\305\253\301\031\036[\004FhK\024 \235/\2241$\250h\215 \246++P\377\363\261U\026/\t7q\205\351\006D\232\341q\222\227\350\006\013\021\205\022\3160\366\220d\311\317\n\210\242\243I\236\303\271\032%\335\020/g\250\n/_\243\332\311^\312L\t\237\340\271\025\276\001#la\342\337]3\\\363q\272No\002\0062\021\3168\373x\322\232\255Q\207\204\034I\t\010\317\370\013j\303[\0042\243\366\372\222\364\372g\242\214;\235\035\t\376\013R{\227\300{F\240\232!\240\245\201t\033O\007\035J\232\330\273h\321p\2067\001\301\2232\372\374q\243!E\006\033Z}W2G\216\260p\022\330\215+AbLiy\301y\317O\376\021\346t\356=\016yL\024+\352=#S\003o\251\221\177\351\005\000\230\376\022\022E\276\324H\265Z%V\261!Y\366\207\314-\3400\330\336\007\256\005> `\004\220\310\342\006\225|\252$\210j\204\230\310>\326\240K>\362\351c4\017H{Oi\237\267\320zd\364\325{\222\253\003\271\226\250X\264\036\242\326=\204\262\306h\031'\264q:)T\210,\253\r\031_\nckZ\230\257\261\270\212\225\202\263\234\021\274\270\325X\265E\030\022\033\177eBX5\016\310\006~\246\261\252^\003\2440/k\374O\007\337\366}\242\363\3738i\330\033%\366e\006\205\347w\335\243=\376""\306!\004~\362g\010\371\027\2353\027`\231<\333R\313\367\303\330\241\340i\345\222\310E\270@\330+t\031\200\340\250\335R\201J\304#\005h~\357\233\335\366\277f\2175\327\312\017zY\372\360\331\346\325<\010\277\226\017D\2077\257\336\312\267 \325\03684%*yS\363\030o\214d\245\207N\222\t\215H+a%\035\007\244\250\367^l4P\303\014\026K\273\326\227w\234=]\307\251N\276Y\201>VU\003\313^\276H\222p\242-\346,\242\2448\217\253\017\225\331@\364\030V\032\214\314\215$\025Q\355\031fi\025\220\214\341\203L*\303\3772_2\017{\347\277\270=A\356&=\354\254\242\240\316\343\333\351\365\311\007\270\367\300O\274\274\300C\005y\201\014\205j\033U-Y\033@\013\264\301;Bh\003\177\315\340\323\274\214\2663\336hRqxi&\323\024\177\237\375\307\234\331\217\336\t\261D/w6zJ{\374\304\014\363yg^\005\202!\346\361\224_\317\315\224s\225p\261\232\275\372:\356\321a\313\"\320B\032\n\031W\356\252\307/;=\307\361\036\311\364\372\251'\255{h\\\217_\005\024\032/C\301\206=\225\320)\005\000\274\250\372\303\3158\261\217\261\226\264\n\256\026\301\027J\343*MH\273\034FA\031z\014\207b\260\010r\204\004\312\375\336\343\337\334\377\254\342=\313\325\334\247\3267g>\267\210\212\005\325\017\272\366(\275\344\326q\201/\265\220\303O\273\250\032f\2661\276\361C6\251\345\333\226T\344]\014\344\256_\240\376ak\233\343\371\221\356\373\007\271w+\345S\366\275\3045Y\363^K\371\242\306\353\314}\201K\241\354\271\005\210u\363\025k`\233\024\224\327\304\255\301\0207\235\362\364\237G\310\236\317=(z\344=e=\035\335\3218\" \307\334\360%3\331\\i\355\251\242T\312\310\201\242\250\023B\356\337\000}\252\031\274?\202\361c\342\236\005\257\004\252\247\207;\032\336f\263\306\017\2566\362yW\314C\242\037\251\356\307\231}\207u\360\363x8\202\343)\341h\004\316\001Iu\233\312\320\">\342k\231u\255\207\235A\377\024i\221jBV\241_\177\274\367\177Hk\334E|\334\370^k\264\375\376<\371h\304\242\277\230\"`\220\375\352\331j\267i\232.Z_s0\303\004\032Z\336\362\223\334~OW\273\272=^\305Q\226=?*-oz\275\n\277Y\357\307\203+\310\265e\030\277dE\t\337v\325\034\354@\300\304\006\323\206\014r\010\304\371g\253""\340/\256\375\344\367\037\037E\365\217ZV\243]\270\\{>\017c\235.a\303ni\340\3173\367\326\271\030\020\263\367\253\232\264\356\210\273\271$&P\333\366=\211\263\327\345\237\255\375\253\327\354\357\267\317o\306dg\267\336r2\357\304N\327\203\335\3619\312A\3159\346\341d\343\0243\356\276^\330\313(\321\225u?7w\003\320\274\376c\273\323\351=?9xE\214\"b\221\205\035\374\305\341\005\255\353\235>X\254\231\365\337\231\353\372\307\267\356g\262{H\366;G\026\246{)uH\270\224\261\3550\257\246r\024\305\301\372{\002\266C\205 \320R\216\251\363\007\301\365\275o\232~e\351>\317D\227\003\355\247\316\374\364\202\216\035|\321\235)\350\223\\4\262\375fh_l\250\317iD\375\256\036\265\007\257_\313\362}{\226z\306\247\215+\262,^\307\304\344\246\275\223\247\212G\222\3163\371\017\312_$\365O\350\223\347\017\344\223\370\375nz\376..L\021O7\0130\365\342\032\362\275\346]\374\356]\037h'\03733\317C\243>Y\"\364\310z\243P\201\352\036\301\321\351\374\277!\351;\317\350\"y\362E\347\221\020\364>7}\261\306F&=\036\227\336a\337\374\272\027\332\316\363y\272\007\275\326\024\266Zx\301]\003\033m\245\265\356\310r\262\030E+\201h\264\2662\316:\330z\301\002O\341\303\232_\253_g\317\342ny#V\257\204zk\322\364\317O\343\236\240\036\251\352\367C;\325\035l:w\325\312\236\251{\361\253\370=\357\211\361\377}\372F\257\336\270\355\023\324u\264O\216\234\024\344\006\004a\235R\261s)\371\313\013\324\025U\236\002\262\224E\014\232t\362Z\312\316\032\267\353\003\234\361\215l\242\251)\023\311Z\235UJ\315qU\365\022D\252\025\343\241IX\372^75U\364\236\347\020Y/\203 R\213:t\037\326dF\220\247\213\031N\210\306yRq\316\304\224\354G\230\250\3300\323\302N\235\365\273\277\352\371~\016\237\232m\302\373\222\367\0211\337G\261\312q\371\206o\331`\302f7\006J\374=\366d\302\203\033V\020m\234\234C\346\207<\3753\366#\366|\217\274\230{\217h\376\255\020\316\350\017\302@\332c\361\362\370\2173?(\274\260s\017\354\237k`\277#\374\243C|G\323\357Dx\231\316<\036\343\2070\313\317\241\332\034f\201\360\214\216\017\013\205\247?\3369\2070\307\346\253Hy\1770\366C\306q\366\367N\337\326\241P3""*\317\275\256*\0346c\363\243\303\331\362nC\250\230\3212=\363\202\204\323\037\253\3175\305\013\350\242_9g1\016F\027\260\222\022t\226m\311!\233\212\245\350h\305\330\363\027\275\014\335\326\242\232\205\320\226r\311\273}\226>\315=\327(\360'ze\361\014\210\263\364\353\367\3634\365\376\217\257\376\257\221\367\177Y\360~\342}CJ\376\303\340\355dF\030e\345\262k\373k/\220\320\266\227\022\273\262.I\305\267L\307\302\361I\0323\371\363\227\210\202m4eBrgN\346Y\245\254i\336\330\340s\220\327&\342\334\345\3245\354\256\026;\341\2079\357n\256\253\342\336\355\nw\032HhXFi9\232\346\272\313\207.C\273!\332l\316\333\241.\243\274\323EW\037\326\370\\3\013\211\203Z\214\335\313\223\t\334:]\236E\273\342\362\370u\234\017\034\024+V\256)\303d3\345\355 53\221\351\310\241\376:Y\0265-`\310'\200\031B\0242\025\213\313\273\316[\300\021\206\272\322\311\245\241_9\344\205,\320}7\261\367n\306\236\365<\313n\020\275p\277\034\356\0348\202\321v\254\316\352,GCQ5\332\350;\315\300\255\351\016]\013-\331Z\\\343e\230\345o1\265\014o/\274.>w\213\317G\213\361\214\261K,D\345\226t\314\201:\307QU\241\324\272n\370i\303=\031gv\271\025&\257Q\323R\323\032\364\010\303,\316ar\356#\304,\264\030\372\243aZ*\306\034\263g\023\255c.\371d\314\346q\313\233q\270Rh\344\333\344\315\026\356\2727D\357\000\232\007'7\"\266\256\322VsE\rh\340`J\021\311f[\267\256\036\223\247J\216\364\335K\217\317\3604`\356\216+\025\033\332\257\036\ri\357\005\337\262\311\323\263\215O\020\335\276\353\343\\:a\247o\2132*\333K\"\311\251\0274\035 M\325$\370\374~O{\221`\322(\326\230\351\301\312\235B\037\002\354\231\256\267\212\036~\231\272\271\217\265\3346\307\313\265\2028\273z\325\222\013\320\375\213s\302\232qx\357\027/\307m\226\363og)\305\267\006Nf\276\364\3232G\274\313\3415ZY|\347L\333\031<x\304\266\273\313\2538\016\343\302\255\r-3K\325\256B\342\356\351m\356%jL\030\004\251|O\235Om\276^\213\263\245\321\373U\315\234A\217\016\334\350\236i\333\253\240\004[4\314SC5#\332\025\203w\003gK\272Rb\3410\211\202\241\034\263N7\315\307y\343/j\351Y\316\354O\215\245\226Nt\313n\315\316p""\273\276l^7z\263\234\273\356MM>\2360\333\277(2g9\3152<W\274\\\322\326\361\332!\314\273f\343R\317\027tl\301S$Kp\241\327\004`\330\253\030K\"\342\236|\372\201\"\355B\261f\241b^\375G3\247N\313y2\333y\326,\357!\234\232\214F\215\t\336[\314\363\223\303\266\262p\342\\|\301~n7\317\n\371\224\3728\225\024\256NM\022\006\234\023\272\305OWj\010u\232\332\3253xs\210\263\227\317=LT\237\027\213C\"\206\222\254\002\024h3\307\354\272,hi\255\275\017\333;\221\357\226\361U\254\202\0303\r\264\264Dh\216\372\013R\362\026\307\215\232\206l;\345\201Z1\254\220\264\261J\325\020\353S\"H\273\207k\221\014\317\342\036\2126\t\270e7\006\235\210\207\202xO%\236\027 \034D\314\273\315\273\251\231v}\032\355\230\221Ul\357\243%\224\230\206Kj\207\260%\373F\330\304\006rLX\261\342\332\237o\310\262\317+\365<\244\277\010\337,d\355\330\227>\232\307\347\226D\263]2\232\331f\252*\027\025@\340]\252\222i\2207\345+\344\030\303\2619\265\271xm\263/9\244\224\255\363\204\263\005\210\230n\346\247\362\366\266W\227\033\267\001X_%\261Hp\215j\n\212\213Nl\250\224\003\204%k\024\310\3443!\210\313c\370\007\036\220\331ox\374_\034\230\364\363\305\231\202\361\\\247m%tY\222V\031\014\253\3028f\255d\026\313\274cBV\026\033\031\"\302\267\234\016\004\244\350\226\306X\213-\311\240\304\3034\347Xu\207\270\0176\025\312\223\346\035\353N\204?\374]\311\024\341B@\274R\260\334";
    PyObject *data = __Pyx_DecompressString(cstring, 11719, 2);
    if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error)
    const char* const bytes = __Pyx_PyBytes_AsString(data);
    #if !CYTHON_ASSUME_SAFE_MACROS
    if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) }
    #endif
    #elif (CYTHON_COMPRESS_STRINGS) != 0 /* compression: zlib (13243 bytes) */
const char* const cstring = "x\332\345|K[\023\331\332\266(h\324\240\004\003\006\r\230pF\005\r\242\355\251\355\027Eiw\333\332\034\244\317\235+\220\002\323B\002IP\330\273\273\367\0362\314\260\2065\254a\206\031f\350\260\206\031\326O\350\237\360\335\367\263\252*\225\200J\367\333\375\276\337w}\327\245d\255U\265\252\326\3419\334\317a\325\325\330Dbu\210\377\207b+\271\215\315u\255\250\315d\n\305X1\027[y\225\312f\265\365\330\314\355\330G\356\370\362\311L\363-\217w\212\371\324J1V(\346\265\324F\201\267\334\215%\256_\237\270\376\301{\016\365\230\325\314zQ\313\307r\333\305X&\353\336\031Kg\336h\3715-\353\335\374d=\3676\226ZY\331\3368\350\311\365\253\333\353\251b&\227=`\236rO:\223?\250\377\320\267\343C\033\343C\351\344\320\347\311\241/\223C\013\023\237%\227S\257'\212\231\325\321\225\324\372\n\237\252%\013\333\313o\361\233/\274\322\322\311\345\334v6\235\312\357\216\335\215y\215\261\345\355\314z:\223]\213\375\271^X\322\372\230\370\233*\246\226\327\265dZ\333\340PTK\006-1\264\324\007\357\225|}\267\327\323\331\221b,\257m\344\336h\261\242\266\261\311\271\257`-\213|S1\205\325-\306V\353\253\232O\025\270\017\353\251]\255~\333\233L!S\304\010\375\027\371\352L!\226\315\025c\251\330f\356-7o56y5\346\365Ja\034\233\273\261\342\253\024\366\2640\221\316\0248\013\374\254`,\371]YU\257\026+f6\264\330f>\267\242\025\n\350\215\225\321\262\274_\333Y\321\2644^\276\221\332\211mfv@\232\240\225u<{\033d\361\366\225\226\215\025\264T~\345\025_\271\232\313\3076\271\334\251\355X:\237\312d\377x\357\3346\377dpU\333\001K\024\256\252\305\343\365e\rwh\376\tf\265\267\261\\V\233\320v6\265\025\256\320\252K]\305\335M\215\013\242e\212\257\2604\351\3331<|c\225\273\\\214\255a\321F5\305\006IPv\352\325\272\226O:$\236L\337\306\344S\030d\032\217\376\310m\330\351\215\014\3706\237\312\026p\027I>\275\255\221\217\325m\261\2371\025\214\365#\217I\203X\362\033r\247\3331\207\035\316\037\262\233\026\313\223Q\013\037\273\235;\202\365\326\024o\374\221\233]\212\376H\247\325L6\265\036\333L\025\n\330\226\206\231\304R\331tlM\313mh\305\374\356\237\177\312\237\357y\330\031""\354\023a\251\364\317\333\205\342\006\205\340\177\247\357!\337\317\005\007\313jj\375?\266\243\005\010\020a\205\355Mg\262oS\353\257?\332I\356,hkj`\302N\030\354\237\354v\330\211\3717\243.g\356\306\376\\\277\372kE\236lf\212\005\331\377\365\365$\313\311\241B\262\341\212{;($SxE\331\267\212=J\346\2655\314!\271\221*(-\343\311\017oC\223\250a$\352\201\rW\275G\272wa\333\213\0314%\275\026tZ[\031\315dW9\253L\3665G\222)(\301\232\316\346<\206\020\321W\200\350[\321\034\341\007\231\235\335\336\330\334\235H\256@\346M\310\243S\371|\n\267\2462\353\244\221\\,\263\261\231\313\027\375\267mo\244\212\257\366\335A9\330/\013\330\377iBT<\032D\005\026\344\305\375h\302DpQ\025D\256\2100\273\033\333\337\342\323\215\373/6\250\316\330\370\270# \225\262\253\013\311\375\035)k\235\227\025\274\007`\357\274\255Q\332\303wM\251\031,3\230 \273\242\361\036iC\023Y\307\353\270\271\213U\256\023\316DCM\226\255\371\216\355bf\275\260\265\255\206}\025\353\230\203\372\312\356\202\024\265\315\202\243\204'\206\nT\277\205\355\315\315\\A-\366\262\006\215\344\250\350e\212\273\3426F*\n'S\034\021U=\341\262O}\036\r\333^o.\344W\2565\215\353Z\036\353\343\373\235\330\334\335\361\004\200\322\242.\267\254\346SM\257!\213i\311\342\253\274Vx\225[O'\361X\222\006\031\030\r\200)\034>\004>E\017\366iM\213}\017\\y5\226\230\270\376#dZq\033r\365Mj\035\272-S\270\033\303\344=\211\003:w7q\273\270:~\333\001+\\\372\351tz\326\241p\024\277\342\014\24777\327w\321\270Hb\000\361m<|\366\342\321\027\311\207O\027\027\036\t\251,\326\251\344\021E\214\346\374\005\224Q\245'\370\263\235w\232\237d\264\365\264*\272oz\222\317m|\375zY5>#T\232y\374d\372\345\263\305\344\354\342\323'O\222\217\346\037O/>}\361<\271\370\362\253g\217\223/\276be\301\275\347\305\302|r\372\233\247\013\311/\247\277\372\352\351\363\331\344\302\342\374\364\342\343\331og4A\257\352\345N\205/\177\274\303u\\\314\341\225\316Ei\236\321V\263O2\331\264T\236f\323\332\316\223\365\355\302\253G\251\225W\332\354t\362\345f\232C\236\231~\366\262\000@\276\242mr\302\205\331\231\305\344\303]^XL\002(\247""\212\267\246X|\232-\336\230d\341e\366u6\3676;\373\325\027\263\263\213\020a\356\234g\265\342\214@\200\207\273\317S\033X\212\342\223\2473\374\253F\304\022\307\201_\267\307\274\206\316EY\036\367\227CFy^(\370!\010\370\351\314S\221\037jE\213\317^\314\316>\236\177\361d\021\303\321\326\264|\275tk\n\345y-\265\376\342Ir~za\221w%\227\036?Z|1\377bS\313>\336I&\277\332\335\301\377\231\014\344\374s\010|\274\036\367\247\247\013\323\224i\363Z\001\357E\035\224\274\360\325\364\374\302\343\372.9\373\263\240\025\247\213\305|\006\334\204\005\246\255\302\026 \304/S\233\233\354\006\002\307Xv\027\274I/8\223^\250Oz\201\270=\265\216\227ky\r2c\201\334\343#\270\227Y\374\371:\017\362\225a%\001\002\001\372\2412\2644\336\242\301d(\020W\246\n\273\331\225Ln\002\262C8Q+\244\266\213\271\342v\326\221\374~\010\260\234Zy\255x\017S\\N\025`E\300\232\340S\244\262\252\306\232\024<,-\331\034o`1\213\235\\^\317\255\274N\212\340W\305\334\352*\036Th\250$\327!\003UK!\363O\3155nT\263[\331\361J\273I\261t\222\036\366O*\245\230T\262\253\360\021\233)\3716\227\177]\330\344\224>r\347\212\206\365+\346\222\220f\305\025H#(A\210\020\307\300MRDz\345\355U\252H\231\247\333\006\221\233Z\303\323\324\250\334\326\203jIl\353+y^2\271\262\016\360\227\204Q\205M\334`\025\333\223\2046\220=\340f\254\344\326\327\225\274*4\232v\373\036\306\313\020\227\220\356x\200\320y\262\260\236\333\324\n\276\013\256\024\364T\376J\016\003\243)\202EM7T\n\365Z\275\2274C5s\231\2346i\332\334\345\177\000\030me;\017Z-&E\375\255\000M\34660\332\025P\347*\210\026]\323\267\201N\352\030\244a\325\032\256\344`\207\371\352\315\323M'\263.i\246\265\345\355\265\206\227\370\312\315\257\360_R\304\3534Ajx3\225&\364\021\025\"\025*_\251\025\300a)\300\2334eCZ\004\253\313\026\252\226&\353\240XL%w\324\317.\267K\306\314_!\374\035R~\275\272\353U}\224\305z\363\3407\2741o\370\332\234\265\001p\313\035D\031\n\267$\261\222\240l\007n\220\372\010\361\234k\016\224IgRk9\330$\356[2yO]:\375\266\2665\254H&On\3678\262\316\232\"\030\352U\031\221Wk\232\214\327\356\276\314\255\027\362\005_\245""\010.\250Wi\367\373'H<Ej\364\330p5-\034\237\224\261+\254\3258t\247\315{\251\252\372\036\001\n=\240u\337\340\367\337\261\232>\250YM \227ti\312/n\323\320\216\257h\004d\265\314\332\253eP\256\333 \254\353\320\001\332\034f\303\356\372j.\331\371Z2i_\215p\335W\025H\355\253c\214\036g\203\213\325\"\2713P5\341b\377\352IQ\2017\267%\267\351\353\344\253$\353\242+]\000\307\341\317\016\377'\023\370\273\313\377(\221}\265\364\232\306\355\222\337B&\255i\033\233\305](<\020s2\251\0041~\26674\352Lm\013\330\016\254\230\327\\\030\242\034/\270e\007\370;\371\001\363\314wIZ\260a\256B\313\244W\345\037\027E\326IL\263W\334\225\242g\245IAf-%\021\007\242\265X\305\316\272l\356\2536R\215\357\202\333@M\346\3503\221\254\231l\312\265\372\366u\226F!'\247\334\314\014\3156b\363\023\232/\253>\202\333\352H\240^\022\366\365U\233\237V\277\340\257(\306\36254\213\243}\240\003[\263\277\215\233\343\310~O\007x\275\245B\311Y\257\371\004\247\317\016\366\233\304\007\014\337\271r\340\010y\315[\200\375\272\252\336\\\037\250H\237\206\007H\303AC\343\205\367?\320]Q\267\272\177dl=\240\337{g\222\255\227\352\373S\327\253\315j\266a\342\357}(\004\265W&'{\225\267\212qX\365\275N\244\211\224\352\206]ru;\273\222L\256]_K\254M\256\335X\233Z\273\271\226N\255\363\177r\033\370\322\343r\242\244\254H\000\220p\312Am\205\375\3261Z\212\256\261\006\\\365,\267\266\306\230@\321?\263\265\rr\316\332\346\3535\250\006\332!\231L2\233I\026\360\277\001!eh\010\241\003\373dh\324\340\317m\242+l\335NR\354\353\344&\236\351a\311L!\231\362\004?*\036\344FYd'~\225\252\345\325}p\220cN\025\213|N6\225%$\244m\232\027J/\374L\337,\377\203b\010\023\327\351\214\207\362\223\253nE\324FC\205\373\001\220Y\364\220\224T\326sk\"=\326\265\325\"\377cR|\346\006\227\n\002!\215\256@\313>\373\000\035\326\260\304\304\020\371\006 \241d\244\323DD\341\264$\261F\270\214\277\257\211\027\n\"p\0241`\361\270~B\016I\021\245\002\033\336\263\246ln\304\2552 P;\t\276\201\372E\"od\262\033Td\202\352\352~\003\266\371\204\222G\201l\337dO\026\324\003^\247\031\371\000\000\315\254f\260\330\312lI""\n\340#,\335\006\000W\3163\331\207,\025]\201\2323_W\237.\\\252\327\325\252d\223\334P\221p\005G\275\362W\234)\331\244C\312Z\032\305m\316=\233\314\347\336\342\202\354dV\255N\026*TQD2I\024\306\277\331,\325\0306L\275Ui\304\254\366\326%1\001\267b\244A\007B\331\251}P\177\223\007\301$\367\322\001p\304\275\264\357fo+\374\215.\260\021\267\237o%\235\"9\313)\346\262\353\273\271\265\274\232\250V\314m\026r\212\361E\037\313\037E'\271B\216|\237+\344\361/\231\302\\AdbU\213\322\247Y\r\036\343H\234\037\274\205\356\337\002\035\200x\221k\254\242\346\016Y\361\244\303\231P\222\260}VA\tX\024\247\315\301\tn-\223\256\227\004\001\270LM\201\341\224%\354\345\224e\203\235\362\033\215\266\207Sqo\336\025\022\244$\330L\355\222\001]_b\223\222\360\232\345VTd\255\205\216\024;\311\n\251\242r\311\2532\037\336\344\201l~r\363e\265\201\373\232\345\305n\243\347\271<\350a\r\327\245[n\223\3612\265\0320I\211\363\2644\n\253\231\235\315|&\227\317@\211\270,\300\367k\205z\325\365D\242\345\347\344\216\374\345\315?;\326\311\333\327\305&\377c\263\233\324uC:\277\311$\201\244b \207K\004\2009e\245\027\032*I7\206\220\024O\251O\2374\013r\247N\243\316-\346\013Ni\307\337\274\353T\336:\032\323Yt\025\177\315k\014\222A9\341\202\374\301\273\324@2\316\200\204)\362\033\020\215\240\264\\\321\2211\205\225\314\346\256\374\231\300\236\025\013~\270\356\224\005Dze\010\025wu\211\177\2355K\222\013\035\t#\026\255\230\275\205W)(\230]\347g\002\\\352\026\337\276^.\274\022_4\365\204\346\232\224\376\212Z8Q\022J\364A4ki\3657\351\267R\204\247\224\247\231\246\211*\010\3318CW-N\027%>7\327!Zw\212j\312\215\340\337\3419\331 \247ED\231S\346\226yE%\033\032-,\237\373C\225\204\267\3352=j\252\270\341\266\251m\364\317h\377\354T\203\343\304r\206\231Zo\030\260k\250,\357\372\037\342\337$_K\236nx>v\225\212\275\000\320\231\331)@\323\345V\233\304x\301iu$\264\022\355\212\376\334K\007\265\251\232\226\366DA\343\205\202J\016\360\271\351|\\Q\277\266\317<\336\177\327>+\251\361\242\317\367\327p\341@\203\303\177\221\232\300\327\346SFn\213_@\373om\330\253\003.\354\357q""\200\037\322\177\023$\037\235e*\034\236\342\242\202\027\327w\223\342{t\376b\270\362+;\257\340\n\254h1\371\212\033\233\311\003\034Y\322\214^\352'I\221\300r\023\362g\223\353!Q\256\336FH\376\376\320KQ\306\003\035\267M\034\354a2\237\333\331k\023Q\352\253A)y5\030\\xu\275\332\340^\3635o\324\313\300\217u\010\250x\322\357\224\364\227\205\271\032\032\000\016\032<\230\007\200\311}~\321}\r\311B\363]\212\354}\036\024_\261q\020\202\n\274\232\354\247WSr\020\314K\264\354\265\212\220\363j\340\026\237\333\306\367\"1t\2709\016\035l\323\317\202?;\370\277K\353\t8\206\224\344#\025\021\320\262\322\312\233)\341/\265A\252\250$\224\014\300\t\2155\351v\267\325\307\roSy\346\202\370\210\336\021\243\373\331\240\336\342\354c\275A\204j\275\272\231[\337]\313e\353\r\212\201\032\024\245SQCi\250\324\225\261\323\214\351\302\236S\216W\257\220\\\226\351\262\276\353^\330\365_x\275\214\177\317@\332\013P\301\230\241\252\244\362\363\252\"1B\371Uc\005[\221\222A/\276\242Z\"\267~\000\242~\3175P\234{\305]+\267\232I{\305\003L\032\367\032\375\177nYM\307\251\270(\302\255\313n\327\343$\030\363\316Nru'\271\276\223\314\356PP:\313\001\233\r\266\330Njgy'\263\223I.g\361\207\377\267\360\237\322f\2076\364\016\356\007\265\355&!\317\262\273\276\336\260\306v\223\333\273\251\335\345\335\314.{\343\017\377o\355\252\336\273\354M\033\341?-\277\037?\222\230\254\r\r\377\276s\364H[\334h\371=p\244\255\253\364X\017\351q\026O\356\005J-\265\340\0253Q\013\266\327\002\247\367n\226N\224\266\365\031\243\325\032|X\215W\321\334Y\272\254O\327:\236\276\013\325\302]v\353\371\322V\255\365\234un\324l\251\005\206\2149#U\013\234\254\005\202{\317\365\270\236\220\246Z\353\230\331[F\373\204\271V\236+\377\\=\206\347\264\366\352?\232\361Z f\264\030\235\306'f\034\257\224J\330\230\263[\317\225n\353\267\r\264\234\335{S\372\032\357\303\003\037\356ihM\240\322zA\357\327\037\033]F\312\370\255<w\360\353\277(m\351-\316\353\235W]\324?1\342\306]s\241\334b\267\366\033\343\346\226\352\262l\2360\267\312N\3774\356l\355*-\352\347\215\026+~\247\022\252\014V\322U\264\235+""=0\372\314-\353\372\347\357Z\336\205l\214aP_\303\323\235^\203f\252\326\032\261\"W\314\007\225\2203\024,v[\340?xKDo\307\235\301\001#a<4\326\3149\334+\225\031\216:\252\277\260\256\334\253$T\323#c\313<Y\016\325:FP8\252\226\345\264u\272W\377\332\230\256\005\243\372\264-\177Z/\352\237Y\227\357V\342\356\254\271\010\003\326\300'\345\255\n7\031;y\266\364o\3435\236\024\0346\326\313\303\2253U,M\270\364\205\276e\264\370\ng\367\376\2456\312)\330\262\351-\245\356R^\3573\362f\210/}l\204\214\270*t\03279,\322\301Pi\313\212|VyS\235\257\376f\275\374\332\372\372\233ZG\237\276l\360\375'c\372\266\361\004\367\265G\364\026=\212!\256\230\027\313\323\345\037\252\241\252\333\231\373\335f,a\206\037\274)\252?\301\313\003\275\372\222\221\000\215\236<\265\027\336[,\205K/\255\013\t+\361\004\323\n\366\350\227\324JN\353\013F+\326\360\215\371C%Z\235\253\235\031\020\322\272\211\035\307\003\346\364\025\220\327\202y\334\232\370\254\362\313\273\204\3572\207\034\002\351\007:JRn\337{\302\267\353\307\364;\3064\367\256\243t\274\244\201\372\036\351\273f\013V\245\20348\255/\312\312\370+\350\035\n[\347\270}\255\346L\371X9Q\013\337*\247\261S\221\270\321\203\025\001\327t(\2125\303\346b\371\\y\332\016w\375~Jz\215\241i\316\314\224w\205G\302\227IV\346n\345d\025\3146n\276,\307k\243cfOy\254r\243\262R\r\331\035\335\245\264u\341F\371\026H.\034\265\2427\313\213\025\271s\261L\356\254E&\314t9^\276Yi\253\274\254\016U\013\357\360v2l\344.\250:U\213\306\301C\032\247_\213\364\330\274\277\327\352\275]i\255L\273\227\022\030W\027\305D\307\221\256\036\375\004\366t\332x\251\350.\302\301\255\224/T\246*\305\352$\326:r\321\272x\305\274\001\332\216\366\332\221K\270\227\264|\272\234(O\327\232\253\212\222&\261\027m`\3073\030Kl\310\230\007\271\2353\037sE\360\210\337\203Gz\242\326\305D9\014\231\261ZyR\035\300;\242\223\345\301r\252\374\246\262\204\345\211\222\351\243q+>\211u\301\334_V\342\340\"U\250]O\224\273q\337\202,$\236\0268\3223l\r\315V\213\330\366h?\266\351\024\036\257\337\003\305\205l\\>\303\032\256PRa\257*\267\260\342\321K\372\016""\206\034\304pb\343\346\034\036\321{\305\034+O\225\363\225\363UJ\316\236>\253\367:H\213\313v\317\272\367\005\037=B\236\341\252E\270\316=\252\264mE\257\232\217\314-\273q\341\0232\372\373\225\207\025\255\232\260[\207\215US\204\3330\030\263\365\222\376\206\262\353\004\345GWi\t\203s\257\234\332\033)\205Jq\026\206\366\266\254\016\360\374\177Z\354\251\233\024\353\017\217\325\345y\307\221\266\363\245\2345t\263<g\335\372\307\2738\206\327\332Y\272\006\"\0353\023\326\325\377\252\266T;\253\211\3524_\362K\351\023=n\343E/\365Q\010\311\004y\240\2734GI\002\262\0340>\003\031\261\261\355\\\211\024\336v\234\312\341~\351\255\016\356;\263\227\021a{:Hu\260\303E\243\004\206\320>k\235\275^>\212-\313T\266j\3018\230\357ks\032K\322\326\253?\3245H\0220\334\005=^\227\340\344\340E+\256h0pr/\344H\360ac\003|\024\020)h|g\026\312q\273\265\273\224\332\327\361\223r\021$\340\353\330\247oP\202F\365Y\310\326\177\200^!\271{\365yP\343c0\361\201/\277S\tW\346\374\317\0305\333\241e\002}\024\367\306\317\344h\320\346\276)$\312}\225<\250\346Cs\241\230{\377\224\270\256#\024\345]V\327\210\361o\3209Tk\300B\257c\344\254Ip\312\261\362\r(R\010\342G\326\245kf\036\254\362\0107\005\316\354\275*\245(+Or7\264\322M\275\305\352\021%N\215*/n%\tN[\343\320\333\220\002\001O\303\2018@\360$J\264}o(\345\017\271\205B\330\n\203\272!Ipe\216/\321J\211\322\264\035\270L\025\331\243\367R\327*-5R\016\201\005\003J\346Ms\036\235\020\320\242\267]9\010\272=\273\367O\250\224-\325\326\254\244\306!\261\361\303\245\374\033\264\324\025\363V\271\263\374\200\364\356\323QQ\375\246q\034\263\370\240\372\211\350\307\365\324\207\365\016\273\237\003H:f\3342#\345(\250\247s\304x\013\311\275]\236\376\343\212\245\317\352\233@\337\"\250\243\343\234 \236/MJs\252\210\213\242g\346\364\224\276\345*\035\251\210F\021m\241\264\314\2009G\245\022<\022\272\314G\206K\263\230*(\301\016S\355\234\307n\204/\352\223\350\373\332\014Q%5T.\221\266\266\312\307Aia\362\363\226q\n\315\221\236Z\270O_7\373!\243\2449\017\302\212\\\324\247X\260!\367 \356@a\346\327\224\357\220\310\316""\220\344\366\353|a\304\321\037\320\024\267\360\350h\3148j\365\243T\336\246\276\271Q\236,/\271\272\304\016_1\247\000\317<\215\tY\026\0320\206\204)v\253-\265\216k\\\237\362\323\312\267\325\024\327\345<\365\340U\363I\231s\261.\216\233Kx\334\\cy\230\330\216O\206b\245\306\250\017\310\256\017\374\006\236:\013\021\002\205U\204\304\370B\200\241\277b\037Bwa-\260 \326\210H\222\312*$,\326\351\266\010 \314\233\214\357\350\220Z\224\270/J\320v\002\0222\332[\213\364\033W\315e\276\223=&\261Xld\371\006\0105\212\255y pt\360\2629,\222\350\370\221\370\215\362\020\204\300\244\202\001\261\317\260\204\tu\275\305\351,[Tk\332\242\353\326\365\231\3524\327:A\260p\2038\345\274u\376\252\371\220D\204!\325\"\220\r\265\236\233\345y\226{\344Y\374k\363\266\311r?\0372\245\224\371,\345 \010-J`\020\0334\036Z\303\264\026n\276k\251\305\356U&E[\263\031S J\240N\210\333\330\362)<9\246\324\036Vb\252R\257}ZY\204,uk\327\313m\030\312\3045\363My\316\306r\221bT\255\026M\224\273@M\261:\356z#\252\272\353\242>h\365\335\251t\343\241\021,\333\335\312p\365(\026\256\241,TD80l\215~*\243\214\210\006\001\332\030\306\330#\356\006>\201\310\304\312=\306B\341\355o\300\340\021\205\261\"2\007\274\272k\334|V\001\221OZ\223\217\253T\233!j\341.=e]\272\001\374\205+\243 \2279>E\210t\314\3542S\326\265G\325[\264\243FElv8t<a\256bYI\273\234\"W\277\241,7\333\341!kh\246:\303Q\366\351)\333\317]\357#\335C\301.\033\262\3623\354bt\310X4;\315O\260Q\350\366\324\032R\252\025;\262\206\256\355X\002?\245\035\025\355\325{\277a\017\375\273\206\035Q\223S\273\026\026*8^^\346\312\370\313\002\200\367MNx\366P3t\310\333>\334TE<`\037a\036\035'\240\226F\357\335\204\211d\037\001\211\016+\335\203\265\330\322\304\303T\222\3471\370(\271\241\027\210\356au\020\332\001\313\220r\311\323%V?Y\333\212\335\036\231\302]\207\221\221\t\350\260[ \311E\321c\256\214\354\323W\r\030\204g\367\200\026B%\000\220!\261\251`!\336\002\327\267\016@)\341\247\273\264J\313\331\2515CH\274\\|\003'O\t\210<z\244m\010\346f+\320\303\357\375\r\016\202\300\177\212\326\3511\321\023\000\004?\003\365""\005A\357\265\016<\363\204u\202[1e\215\260\205\356\203\206\033l\274k\030*;\324h\257\323\336n\360\026\330xk\273)v5\300\242\371]\271P\021dt\332\353]\232tQj\255\225\310\347\0254`\321x {\340s\r\354\022s\034\360*\30730ld\260z\007\372\006\034\320x\260o\000&\227>b\204\032\354\376p\351\005\336\377\367\232\375\037\264\370\t\354'\214\243\240W\024\342\336R\333\255\201:\302\272b\336\207\370\370\273\020\226\222\251\023\326W\363\326\374\202\017c\r\001hwc\241?\210\261\342F\267\261\365a\214\025\307\253\007 \222\316A~\216\213\361\376\337\301XP\002\267+-\002\364\201\261>\005rK\330\264\313=\240T\013\023\340r{\227\313\255\345\207e\r\026w\312&\237\276\0177\t;S\024(\263S\354\303\001\243\237\003\0001nQ\263\373*\027\225\261\031)\367\212:\217\215\231\373\354M;\312\306\310\240X*c\227ay\336\251<\2426SF\375\235\312S\032\335\242\324{\304\023\240_\025\271\033\216\033Q\345\000\210\031\255\006\305Li\0338q\t\302\360'AB\021QE\324\362}\260`h\035S\324\365\033\317 \306\207HM6z\372\204\321w\326\265\317D\213\352\377\304\362O\233\337c\345B\373\252\037\023\270\266\203\037\342\216I\244\324-\032\356\020\265L\310N>\204)\322_\231v@\002\340\215\333I\034\033\2400\321a\237\033\323\326\220\2034f\254Q\017\020\001R\014[\303D.Qw\206X\322-.\3467\345\037E&\363\256Zl\300\270\r\033\207\372z\020\330\307\346b;]j\343T\276O*\003\225f_\003U\220r8`D\327E\231Z\321k\244\276\262`\264\330\247\35028\345N\301\216Py@5\034\265&g\253\030\021\230\234\260\271\210}\217\210O\203JD3\357\252B\212\202h\311\250K\355\003\314\3766\n\324\265\322\034\314\336\323AG\270\352!O\204\003\322B\204_=\322vjO\032!\nNz\245\036\375\242\220\021\236\373\257R\034F\005\310\266\026h\337\233\023\343\025Z-%\005\232\231\211C\336\024\330;\rs\360sX\301$\377q(\303P\375\346?p\317\351\275\304\336L\251\2654\243\267\351s\230\301)*!\372p\345_\377\300\357O\216R\003\275\260\006\010Q\003\203\302\321\030\342\257\245iZ\245\347K\005\353\002\037\004Q\366\034\"\374Se\261\302v\245\035\013kU\034\324\235\245A\253{\230\254g\267R\344\275\345\\\006\200\251W@\236b\234v\227\2261\200o\331""\316\005\335\245\005}C\234U\255\024\020A0V\240\007\222\260@\035\320Q\n\212\253\021v\221yGLp\177\223u\345\2760j\303mw\313\013\024\323\376\246\373Tm\037{\330AM\237V\216Ao4\276\362\201\340\227\206\333n\213\263\340cM\007\014\354\200\246\367?\313Q\226\334\227y\021\310[\252\262h\206<U\356\327\200\001G\003\332\256\013\201~\222y\356\210\361O+\001\254PM\277\213\373\265\035\037\266\000\261\335\003\334\034\244\371\332\311\215\255\265\016\032/\254\033\217\300\233\001\277\002u\336\205\235\376\275\363H[\373\336\323\322\217D\n\266b\023(\211\326~c\204\217\250\265\212V\r\327\261M\2246\332\357g\216\264\r\033\342\370\272\004\\Q\200\322Y0\217\2317\314\025\n1^\275\250_1~\240\303\203/\010Y\035q\362\253O\317^6\2572\330\241\324gW)U\372\r\013\263\345\352: \245\016\250h\372\324\022J\265+\245\272O\001\037\244\244\317\227\376\t\031\013\335\034\334{,\217\336\242nk\003\034b\207\016*\025(\002M\030\267^\200\270\263\256(H\013\255Fw\200\025\206h\266F\376\213\3624F/\220X\177]\324\"\232uQ\311=\"N\321*\375\372\027\364\3274U\302`\330\243\250>\002\364\232\304\004\013\342\r>\017\312\234\252\024\252#\260j\350\025\235*\317\020\030\323\335I\014\035\276$\256\212\322Ti\027\323\211\214\251\2554\271\332]\335\266\254dGX\331M\220\333a\206X\226\215\323\262\335\376\212-\202t\022TS0\006\001\321\216\232\003\342H\237\205\222N\213\237\230\212\372\202>d]\022\317{\345&&*}n\350)\271\026\321\317\200D\n\322\017\212w\320\032t\220\371\220\361\222\316\223Z\004\030\313\032\006F\240\237;N\220\360\031(a\336(\n\346\016w\311\"R\200\313p\206@#\001\352\204A\343K*\336~zX\315\177\320\201\0223\316\010O@+\367\231o\331\202^\326\025\322m\244W\177\311(\224u}\232\376}z\216\273L\255\374\211\270\261\025\275B\004\372(\367\254u\226+IoT[\277\021\"\215\306\215\026\3360h\235\211\211+\353\375dg\223\354\350N\262\242\023\356[l\227\374\210\232.Y}\327\201u\246)\234\007au\005:\255N\230S\265\340%}\333\032\244Z\rR\233\002\220\205(qo\203d\202#\212\210\202\303\352\325\267K7\240\235\360\312a l\217\322\305\332\261\306y\3430:\220\251i\035\264\357\275,\215\352""\243V\377T\371y5n\007z\350\262\344\352z/D\033 \343\367\364E\362\315\201\356R\206\003\350\262\272\004\002\221\262oZ\243\304\320\352\222\021\370@\215>\254\375\305\000\261es\021\257\263.A\237\022\221\266\357\275\000W\005\025\344\306\013\3053>`\304\255\001\032h\301vV\203{S{\202\254\307\300\323O)\360\272K\353\256\027=b\235WQ\035\215\352\213&\001\267E\275\310\212\321\367\322</\361\0278\203\022\361\351\360\277\275\237&\354\326\016\253CI\022\210\323\220~\315\014[\343\004k\250\235\243s\260\246\334\344\004\001\037!\r\353\334\220\240s\342Z!\225\204'\234\352{CK\250\253\364\023\243f|\336\275\322\232>g;\023\247s+\030\321O+\271\246\014*e\224\005{ue\020\3421\223\014$\320\355\375\203\330\001s\216\231\363\255\030l'\260\347AJ\001\336\334o\365\337\007L\244p8\331KW2g\022\010Z\264\206H\020\277\230\367\304E\036\204\234\0317\277U\345\263{\377\226\250,d\311yB}\372\035 \307I\214\030/\266\tOk?S\0138&,p\346\r\301\304\270xc/e\235\245H\232\304\232w\214\212Tq\n\344\217\366\270!\256~o\217=\251|\201\366\240\nQ\316\355\343[\202\030\025$\017\354\235)e\331\325\244\313\022D\363AF\275\217g\037\027\031\005[\320\256\253\211\363\312z=\263\307\305\266D8\361\227\246B\220\334\262\310B}u\261\017\017\2509\001\245\241)\332!2\177\241/E\t\250g\364:\332\035\022\034\251\205\t\301i\204\205z]\031\037\227\315\007}\3353\327E(u\\\301\232\257K\036@\307e\363\212c\305upcD\276\321\233\006a\370C\371\"7\256\376\232\026\312AG\216G\365\3470e\010\254\302\324\354Kt1\261\033=7K\024K\265\210\230\346t\207\\qzG\256)\357\216w\201\021\2240\025yH|\315\230]\007n\301H\254n\345\323\013\307\254\2308yc\302cT0\375\3069\301\216P\014\227\005\254P\374\213\031\024\205\026\003/\322\"\354\255.\277;\372Nl\204\2045\010\372\253\r*g\374$=\217\216+\366\246y\334\374\331q\370\020\277\363\347\273\312V\265EA\371\0101|\2478\023\332\312K\225DE\331>\274\004%\364/A\024 M\2331\327)F\177#\372I\361X\024\314\313| \006\3333.a\224\236(\236\204Q\327\242\230\2062\364\345\341n\323mez9\021\003X\031\343\326\370\247\342\261\024\377\025uO\006\275\030>\036\034\302\326\306""\257\343\246A\272\251\006\207\370/\026?\350\246;xjw\345-\315\245\311\362\030\307_\223\227\007\253\350wO\352\365\013W\315/d\\X\345\3632\232\030\314\260\0010~\217\212\306\372\212\023fVlV\276\025\206\032\365\201\343*\244\005\306\230\374\016,%\\\215\211I\030\227\033i\023\023s\307\256\355\033zo\2771d\354\230;t\"\343\252\035\025\344E\363\357\212uE\364yu\250\252\026E\271*\225G\356\252\371e\245\223\343\341\266-U>\251\252\027\321\300N\324D \273\3451kL\271\362\006\305<wZ\305Zt\312b\020\036P&[\356/\227?\247\027\317+\332\321q\372*\313b|J`\334\216\214:@\267c\320\020\227\217\030\203\216i\350\270\360\\\261B\365\037\"\036\247(zAr\375D\014\005\253\203\246'\177\005\231z\267K\246\217d\322\314\224N\320\203\037\027i*V\021\215\234\204\250\020\232\233\003\014*1\013f\356\220\232\343r\223\220\242\323\026\342z\303\2302\266D|[\321[\2623xR\202\212\322A\320@\257V\007}\r\204\256\3723\263\305\032\023\217\2300$c\221\n\013\177&Q$\231N\220n\244K\260\036\274\002\304\357U\002\357\262\010G\340J\243\307!\003\277\204\216\333n\274\332\016\266\333>E\324\343\232y\256\006\270\004P)\362\276G\005Q\357\013y\007\225\345C\336l\037\221\025\353\220I\263\016\033\000\274xWIHP\212\262[85\271EJ\242ox\363%}\035\202s\216\330\201~\032\345<\t\366\021{\235e\220\034v\217y\255\302\014\202\366\013\020\347K\"4\261b\003V/Az\007Q\354](\3525 \327n\206\003\250\366/\033\317\350k\267\203\014\320\311+\373\364\014\307\030\321\317\322\017J\263d\177\213\247\253\373t\031\215h\020\025\203U\363?#\023\r\212\327B\247<\302\220\316\213w\014\270'\300\034\237-!!Q\357g\367~\203a\330bC\323J\371k\203=B\243\206\320\211R\276\266\352\327\315\3200\200\303\001\272\322\366\350W\0102\\r\t\276D\007\365\347-\214\2203q\242\225@\035fb'\235\330!z:\273\235T\007eP\316)g\365\277A\262$\211s\306,\215\324\256R\022\222\377[\312J\346:0\321\314Kn\260[)\030B\357\263G\231\252\004\010\330\340Qe\254n\225\340\365\257w\250\326\3213QY\266\374\260\234Rh\324\365lb\217\351\262\240\007\310\347\336\254G\205k\035\200En\224t\316\215$\203\305j\312\317\371\205\236\227\340\177-2\3000#""\243\305\330-\356\250\337\t\252P\334=e\301\370*\324YmX\245<V\366\261y\316|\316\210Q\334\347\377k\261\335`\211\035\225\364\234+\346\035\306\n\225\273Rb\314nf\317\264/\312\374\221^\344\357\243\200$n\203\230\222\277\0323\220\236\022\342\245\230V\240\303\223\226mN\366\002(\t\004t\2272\360Kz\233\351B\372\255\364\215HV7P\321^;#Q\024B\031\346c\234:\322\306\034\230S\314z\271f\305\005\253+L\324zI\377\227\370f\246U\213xv\035jR\013T\217\023\360\372\240\212\035xq\002\347)\312\321&\204\271\2400\\\200~\374\026\343\"\255b\207D\375\276\253\023\377\311\357u9N@\225\365\341\244x\330\001/\244s\260\177\253\2534_\332\326\2372a\361\275\376\255\210\036\244\037\305S,\216\243\347\246$\2615\370~\016h\272%Q5G\355x\374\242\"7\216\375\032\260\002\364\346\237\026\313\321\370\245,\314\361\253Pk\275\020\306\376\210\022q\n\304\312\027\364.\006\271j\355@\232\245\202@\360\031`0\255\254,\254\322\226RQG1}\010\320\004-\222A\272\266\337{5.\256\036I\001I8\206A\351\024\030\347K1\013\270\244\274k\210\356\357\217\336\325O\2074\231\363<w\243}onoC\305\035\224\364\334\327@\224\016\206d\006NH\217\373\nb[X\203\nT\372k?\212?\205\222\236\236\237\246\330\306\331\275\355\322tiI\237\324\177R\226\213\263\362\2520olK@_\274A\222Q\030\247\333\177\031\240\217Y\006Q&h<\027m\325\034\"\241\341\020\222\360\026\270\354\216\310\026J\016\032_hH\330\002\370\301\205\216k\330\360\027\031\177\217\010\322\235\243O\204k\330\325\343\200\334\255\337#\304\265\267ET\034c\362!\344\000\375\215\304\310C\306O\014\310C!\t\1775\024\353\221X\345\206\247\251\022\006\363\204I\347\264\013T:D\327%\206\236\230FL\274\335W\257\360Z/8`Q\201\214\2102\233#\227 y\332$\3248G+\345$&=J\303\301\361\351\224\243\225\037\2316IY/\202O\3314\217\353n\036_QB\373tU\324\335>b\251\014\320\001)\206\270_\241\325>\250\353\002N0\3669t^\300:\301\000\315Cc\305\032\233\251>\254\246|\"\253_\220b]\3739\336\200A\343\205#\372\353\036QyGcJ\237\355EH\275\300\244?w\332n\0351~\245\220;\310\203\313h\362\247e\211\315\321\326\276\240\374\301N\2567\367-\257lpU)\032\2226w\234\335\231\327""\002\r.J:\246\377\333\232xPq\272\000{\031w\350-zTMp\242\325-\272\\\343\236\362\255K\220v\346A\3208<\204\014\251yl\323\342S\233\177\204s\254(S5:\337=\260\276\375\336\372\376\007nx?\241\223\3136\323~\305\253\377\350\344\355\2664\352]\305I3\002Q\307d\265\330\326\243\207\201\2673\022\257\306\r\367H\261\302j\314\231}\301\374\022\261\315\024\347\035*@y\260\316\256\035Bg\017\222#D\321R\253\266\230\335\346\033\341M\367\0029\237&\374c\343\022X\003v]-\334+i\317c\324\205\0342\215\360\322+\010\337\033\222)\021\246\275|K\374\355\376b\224\253 \016\000\216*\340\254{D\002\226t\3701\265\246\241\302$pa\000\014\251P\236P\246\243\362\374.\311JRz\214`\313^0\005\245z\242*1\326O!`$\276\031Qa\376\270\312k[\256\264J\316-3\315\242\314\304\311H\322\317,\343|T\354\003\346<\200\323=\211\250\300\334\373Q\322#\007\031d\212Q\275\257`@\203*odD2@\006Uj\320\255O\312o+\0243C\223\222\364\241\352\2149\216\227\267+\217$;t\364z\271\275\262$\371\322\376\242J\334\036\245\001w\365\2367\203\321\253\346\347\345\307\225\020\226\371*o^\254\206\005\216\366\277\233q\342\354\327oW\332`\357\277\226\244\316\306\312T\371I\245\037\323\\\251vW\013\357&\254o\276\255\335~PY\256\036\255\016T\227\336\335x\227\252M\335\254]\277Q\276S\231\251\266T\317\277;\361\256\300'N)\303y\344\335y\353\253\271\332\324t\265\013\322\346\311l\365-:\014IL\366\003s\267\001\305\273\351\353j\337[\242H;W\272\345E()\357\024\251\347h\365\324N\016\202\302\030\353ne(\341\004M\211\001\330\213\377*\367K\314\000\260g\\\377M\344\215\342\372\020\315\273\177A\n\257H|\017\234\373#\364\313Kz\361\3104\251\232(\354_E\216\007C\245^\t!(\373\240I\262\016\356\213'\332\255A7P\344\"F\345\236\245\003r\236\236\035\373Cq\256z\232\211\333 \031-\375\304\237\2278$^\230\225\210\300J\345\203wG%\327\323/P\225\370ka~\317[\n.gJ.\274\n6$\321\212\003\304\376H\350\211\213%\211\006\344\215\2774\376\324\034z\332\037O\"^/\350\222\321y\\\022\302\016\214.\331\1772\2724\000\023\352,\304e[ETy\233\010\217.\210\306\204\312\217\270\306L\024;L\3257H\341KzC\375\252 dI\264\210\312\331\2010""\0238\251\307\025n\t2t\256p\323\272\310\333\323\020\026O\253\363\325\255\003\233T\276e'\004`\032\340\212*$6\010X\375\026\023\250\003\035\214\316\032\272/\254G\006\253{\365\304\305H\344uY\342\276\260\200n\3221Pm\253\212\233\210\270\240K\324a\255\177@%-\374P\351\022\251\003\304\265\313D\026\225\021w\337\221\334\227\350\267\317\227/P=0\037!\310w\262c\253)\031e\314D\210%\312]\326-\246)\304\034G+\347\360\013 }\310\336\327\205\3620\356eXx>*uJ\007\034\336\255o\271\251d*\204\017\014\363\313QFW?\225<z\346\211\211V\222\274i\032<W\224\265\356\3132\373\337<\266\360\245~\336\212\035\356\324B\250\324\007\300r\005\332b\313\376\023G\030\370\310\256\322C\360\312M7\006\333\370\024(Y\211\307\355;\316\320%\016\224\357\350\030\345\254\352\322L\235\200\"<hzR\310\213\034\310s\"z\2538\375\003#F\321\274'\n\021\353\331mu\217\360D\035a\\`\257\275\224\004\374\270WQ\301\023\312\3368\215\227.\311\345\030+\337\254\234V\273\240\244o\253:=\240P.7\366=i|\235\245PS\346\377\377\236\027\245\345\000\037J\035\310\321\276\350\263zU\004\371Nu\272\331\207\202\005\026\311\346e\334;R\255\213y(\344\360cD\262\252\220p\2561\253R \377_\343dQ\214\272eG'\344\324\025Sp\373\304\267R\317\260\362g\360\037t\263\347Ra\250\227\211d\347\270X\013\020\302\030\261\004\203\352X\317\237u/\231\212LY\216)\310\347e\237]\324\357\033o\310\022\rE\001s\300zVd\034\ry:\331%\372o\253\364UI\274\355\323\323B\n\323\256\254a\330G\340(M\234\303\344\377\036&\355Wn\227\200\206\274t\300\032\270\257\344\233\223\355\353\345\3517\334\310+w$\201=JFs\222\207\325i.\tb\360t\227{\233\362\241\364\216IF\231\233\372\353\317oW9\020[\266X\207P<\214'FG\300\316\243\345\001\006\325jQj\214-Z\031\361Z\323Y\010&\rP\322\235\002uR\327\322y\353\342\356\264>&\371\275\300\327O\005Y(t\316\235\270i\2648?\242\324>\264\017\203\326\340m'\350\346\256>\373\360\374\305\326_\264\r\266\273\272\014\246\304\342v,.\353\251\370\311\267\236\266J\321\007\224\035\006\006\3636\013\220v\2136\301s\350^M\340\177lPXD\302+\361\232dN\312\036\271\333\311\375\210\211\rz\374H|\302\234\263}[\312k""\227\245\003s6\245\344\204\245x\234\221\317_g\214H\270\202\333 ^\014\346\240l\271k\005>\350\361\037Oq3\374\206\350kv\221\316e9\017\213=\270k,\211\275\351/\222\366\343\177]\026\177\255i\251|d\355'eev\270\371\372Lg\371L\235}\264\233\262\307\235\010Tc\332x\335M\0218\371\373R\013\365\320\347\364\205QXo\271'\266oR\312\236\251\037\335\216\213\210&v\310UD\241-\003\314\000\305\363\315T\375\203\324J\222N\"Q\201\261\222`\356\207\216W\251-\246\340\264\204~\035\210\344\202\346K\312g\257\334\220q\243\227\236\212\203\263\322\272JIq\254Il^\334X\345\223\264\262\250\230\2301\366\023](\266\234\370\0267m`\257\265\236\242h\213\343X\034\260r0\217rSr\"\022\306s\361\250\010\254\371\250\327\366\314^jo\313\347\265\245~e8;p\r\320`\000\320M4r\217\336\t\226\245O\252\037{K\031\034P\221^\352j\236\353\216K\"\271\234\272\305x\2314p\314\270\213\305\315\252\014Di\"\346\271[\232\263\272/\213\226j\270o]R]\017l\262\316\221\361;|\336\027\307P\263b*YJ\034\307\030\033\227-\"\246\231\214\014\326\232\344\230\237\335+\300\330x@\251e&\366U#\300\367\303\306q\272\224h\271\215\320g\314\004\005\301n=\272|\230 \344\344\266p\007\216\355= \264\204\024kW\300\355\024\244\340'\340\377\264\234~\n\322\306s\317W2\036\2452$.\350\343\n$\210\352cD\261\317\215\277\331\301s\314V\002\nQ9\005\315\325\256\322\202D\030O\252@eC\225\201\266U'1_\245\302\235Pg\346Z\224\211#\370\222L\320\241\340\036,!\021\304T\250\000k\304\005\346\267@]G\231\355\300g(a2f\236\007\356\034\257\274\221\023D\220D<\250\007\321D\177\244d\240\215\2716$\345q\224\331l\372\277%x/\262\275\241*A;%\317\302\0240\204a\017\315\r\305\334\017\253B\353\343\246,m\240\024\204D\211\2504\221\332~\200\345\207R\375\002\322\007\3649\253/\201\225\030`\212\211gB\206KO\254\013ukO\310nQW\331<\334\357!\322b\250\324\315c/3b\232\245h\274'\344\017\017\350/\010\251\017\250\014*X\216*\355{\250\"g\003\316\356\255\010\253`g\245`;\230\360\276\330\217\215\025\202\374<x\347\206.\373L\213\367\027\025I\365U\354\000\335\024S\314\317\n\231\023b5:\371=\217%q\350dg\351\002\237\240R\274|\017$\203K""\3749\244_\241\201\215{\333U\322\3141\221\346\356\rA\311\\\0258*\256I\372\354\272\364,3&\250\242\247%\347\2064\362\255$\177H\220[\322\333\235^\035\002\272\215\204W\260\205\236\0362\002j\007\350\007\0100\345\023\222\322\231\326V\255^p\373\272\005\206o\317\225\006J\363\230GHr)\217\252\353\235\0075J\264X\360K\220\311K\030\377\016oQ\316=9}\312\204v\025\353-\226&\361\200\202\323]\035\322\230\205\326LS\220(\355\267N\034\303\340\315\033I-\220\342\216\033\342\377\247\036\326\277\221\334\263N\311\263\r\331\035|\247\343\030]\241\307\301\315\274\013\3650\261\220\3712\362\331\005\372\017\203\3143H0\214\362\022\002\345\264y\273|\273\"\351Iq\016\375W\002n^\0321.\232\237K\002\206\272\004\356\264;(\247\324\362\363\260&\223B\230\210`\357[w5[\331\275\024\035\3744\025\303]\374\027\352\264?\264K\0342s\327\260\255\3770\226\255\321\273r6@V\263\000+c\306\010\320\013c3@\316\234\007ze\316\226\177\205\255!UFb\316\251\304\363\250\372\264\211\257\320#\351u!\247(\347\200\334\346\373fc\361|\3517q\026\235\242\351\363\214a\375ZpP\374\273\321\362\217Uu\002^\314B1\336$Y\315o\316SKS\3325\251\177\320\235\357\314\3307G\377\357\262\340'\305\217H\307\371\377%\337\0358\350\233\001\007\277^\322y\031\014\371Ml\247\367\272\017\002\377_|.\300\032\235\255n\275\373\237\374\\@\243\327`\203Arj\203?\360\265\200\343\377O~-\000=\206\r\t\203\265\330\215\376\211\377\326\227\002\212\342\n\2168\007\240\234\357\006\210\267a\224\256\336\272\277\241\371\314\377\007\274\017\374\262\301\371C\371\034l\225\024\"\221&\311\300\374\213\334\010\037>\343/\013S,?\250\236\303\205\030M\215\030q\321\262\343\375\375\023\207\374\307\361\342K\2169\367\2613\376\336S\257\252c\330-r6qLt\211x\227i\360\177\360\370\275\212\244\361\034\274\234\353\276&\311\353\r'\356\345\324{(\014\264\261*\331\017\352\274\375u\241\205\210d\367t\313q\257\206\362\307\316\333\323\201/9\200\374\374\216{\304^\010\325w\304~\314\032\273_\231v\016\224\003\200-\251\330\342=\214\234\316v\177Q\366\364\177\364\250\274{\242\334ub\374\3023\363\373\017\312O\325\327\376\271J""\216}\357\372\327|'\273\017\177\244\273\344\234\347\036Q\037D\203\202\376\312\371\340[\324\323\3234L\377\374in\261r]\005\246r\234R\315\337}\333\357\002\366\342h*kjV@\271\327\375\020IS\177\323\341j\n\211VN\245\225$\342\213Q\320\003\347\332\317*\324\311\034\"9\020B\034W\264\316%D\233\001\030\377L\027\333\227\357\344\364Q\220A_\205\222\275\341u\270\303\013B][\267\250\023:|\303\243\225y\326:;*q\271\016\367l\021\n)\377i8Y\204\206\263\337v\353\005~3B\345\033\324\263\321\234@\013O<\251\374\327\013\n\231\215\363\354\234/\211\221\211X\267*}\325\255\277\343T\370\177U\217W\227\337\235\261\226\276a\374\271~*<~\230\017\277\251/\276}P\227\372\276\351\006\333\366>&\361\036]z\3520\272TN\035\267\210\353\256!\347\351\274XGWTn\210\257\342}\307\315M\223p\322\215Bb\016\370+\266\372\354\332\220\361\215\223M\020\025\317\257\322\030\317(\304\307x @\222\205$\264\313\203\310\356g\340n\320\\w\277\237\301\317\331$\030\241,\232\211\017\234\372\246\274\024\211\234\220,\341\210|\227d\t@<\342hY\361\266^\253vZ\217\276\263\276\373^\022\362o1R\n\363$L\247\354\337q\372\033\374c%>\177\327\372n\332\365\266SZ.X\327\345(\300dy\240\374\023\315\002\361\373J\220\302w\354[\226\312\032\274#\276\217\336\330\241\217u\313\001\360\313d\236!\314\"\301\254\322\311O\031\323\347cF\232\217\213\253C\3407oy\037\234\273\007\363\205\343\230s\334\311Sx\\t\330\370Yt\252\353b\221/\307\311\213\240\230\354\030\024\267H\374\352?\336i\326\302\217\326\217?\331jl\326U\306X\0071[\033\363\0374~\346\314\217\363S!\327\313\247\254\273\377x7\314\234\0135Z\t,\214\253\303\\\261\313\346\345\362\227LF\221o\311T@)\207=B~Z\035M\223\257\3424\236*w\216\215\337\256\370\223\315\362-JI\004}J\"\240\276\t*V\363\237\370&\250:\260}\230o\202\376M\242\375\203\037\032\375\200\237\370p\237\001m<\247<\367\277\366\035\316\007\300\240\017\253Ykq\311Z\372\372\217~\207S\254\375?\377m\315?n\265\234k\370@\246|zC\276\210T\353\345')&\325\267V\314\033\004\311\222%\276Ri\372\330%$\007\263?\350@m(\307\254\030\0219\370\333\371\014\246\355~|S}&\347\257\202\377*\376\327""\360qJ\t\250\332\374,\304-\347\023\222\202\325\325\261\272\240'\263D\376\323\305\273_`MH\"\332d\345k\312@\365\031\313\261\313\265AZ\356\027\025D\366>\022\351xd\234OC\324\371\372?-\202\352\024^\031\223/\257H4\346dpo\332j\227\263-NC\373\336w\244\033\365\031\322\271\3677\322\315\272\245\262\246:K}\222Y.y\353\0034\362\3259\032\221\013A\3139$\013\302\375\214\036bu*\270C\205e\266|\235\324\241#vj\355(\235\241A\372\177\000\345i\030Z";
    PyObject *data = __Pyx_DecompressString(cstring, 13243, 1);
    if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error)
    const char* const bytes = __Pyx_PyBytes_AsString(data);
    #if !CYTHON_ASSUME_SAFE_MACROS
    if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) }
    #endif
    #else /* compression: none (33066 bytes) */
const char* const bytes = ", .1f%.1f%% completeDist to channel D8 %.1f%% completeDist to channel MFD %.1f%% completeExtract streams MFD: 100.0% completeExtract streams MFD %.1f%% completeExtract streams MFD: filter out incomplete divergent streamsFlow accum MFD %.1f%% completeFlow accumulation D8 %.1f%% completeFlow dir MFD %.1f%% complete%Y-%m-%d_%H_%M_%S.?_bak.tif(calculate_subwatershed_boundary): watershed building (calculate_subwatershed_boundary): watershed building 100% completecompatable_dem.tifcompatible dem complete% complete completecouldn't remove temp dircreating target flow accum raster layercreating visited raster layerdem is not a power of 2, creating a copy that is.disablediscovery.tif(discovery time processing): enableexceeded max pixel fill count when searching for plateau drainexceeded max pixel fill count when searching for pour point exists, removing before creating a new one.expected flow dir type of either d8 or mfd but got (extract_strahler_streams_d8): all done(extract_strahler_streams_d8): commit transaction due to stream joining(extract_strahler_streams_d8): determining stream order(extract_strahler_streams_d8): determine rivers(extract_strahler_streams_d8): drain seeding (extract_strahler_streams_d8): drain seeding complete(extract_strahler_streams_d8): final pass on stream order and geometry(extract_strahler_streams_d8): final pass on stream order (extract_strahler_streams_d8): final pass on stream order complete(extract_strahler_streams_d8): flow accumulation adjustment (extract_strahler_streams_d8): flow accumulation adjustment complete(extract_strahler_streams_d8): seed the drains(extract_strahler_streams_d8): starting upstream walk(extract_strahler_streams_d8): stream segment creation (extract_strahler_streams_d8): stream segment creation complete(extract_strahler_streams_d8): stream order processing: (extract_strahler_streams_d8): stream order processing complete(fill pits): fill_pits_%s_(fill pits): completefinish.tifflat_region_mask.tif(flow dir d8): flow_d""ir_d8_%s_(flow dir d8): completeflow_dir_multiple_flow_dir_%s_gc(infer_sinks): isenabledno geometry for source point at numpy._core.multiarray failed to importnumpy._core.umath failed to import of \"order\"=1 out of bounds for \"outlet\"=1outlet detection: outlet detection: 0% completeoutlet detection: 100% complete -- committing transactionoutlet detection: done outlets completepit_mask.tif pixels completeplateau_distance.tifplateu_drain_mask.tifpygeoprocessing.geoprocessing_corepygeoprocessing.utilsquitting, too many steps raster.%s is supposed to be a raster band tuple but it's not. segments complete source points completesrc/pygeoprocessing/routing/routing.pyxstarting search stream fragments completetrace_threshold_proportion should be in the range [0.0, 1.0] actual value is: %s upstream direction: utf-8visited.tifAddGeometryAddPointApplyGeoTransformBLOCK_BITSCommitTransactionCreateCreateCopyCreateFeatureCreateFieldCreateGeometryFromWkbCreateLayerDEFAULT_GTIFF_CREATION_TUPLE_OPTIONSDEFAULT_OSR_AXIS_MAPPING_STRATEGYDeleteFeatureDeleteFieldExportToWkbFeatureFieldDefnFindFieldIndexFlushCacheGA_UpdateGDALUseExceptionsGDT_ByteGDT_Float64GDT_Int32GDT_UnknownGPKGGTiffGeometryGetDriverByNameGetFIDGetFeatureGetFieldGetGeometryRefGetLayerGetLayerDefnGetRasterBandIDImportFromWktLOGGEROFTIntegerOFTInteger64OFTRealOF_RASTEROF_VECTOROpenEx__Pyx_PyDict_NextRefReadAsArrayResetReadingSPARSE_CREATION_OPTIONSSetAttributeFilterSetAxisMappingStrategySetFeatureSetFieldSetGeometrySpatialReferenceStartTransactionUnionWriteArray_all_definedappendastypeasyncio.coroutinesautotune_flow_accumulationbacktrace_setbase_datatypebase_feature_countbase_nodatabasenameblock_arrayblock_offsetsblock_offsets_listblock_sizeboundary_listboundary_xboundary_y_build_discovery_finish_rasterscalculate_subwatershed_boundary_workspace_calculate_subwatershed_boundarycell_to_testcenter_valchannel_bandchannel_buffer_arraychannel_managed_rasterchannel_rasterchannel_raster_path_band__class_getitem__cline_in_traceba""ckcollectionscompatable_dem_raster_path_bandcompressed_integer_slopescompressed_upstream_flow_dirconnected_fidconnected_fidsconnected_upstream_fidscoord_to_stream_idscopycopyfilecurrent_pixelcustom_decay_factordd8d8_flow_dir_managed_rasterd8_flow_dir_moded8_flow_dir_raster_path_bandd_ndatatypedebugdecay_factordecay_factor_managed_rasterdecay_factor_nodatadecay_from_upstreamdecayed_valuedecaying_valuesdefaultdict_delete_featuredeleted_setdelta_xdelta_ydem_banddem_block_xsizedem_block_ysizedem_buffer_arraydem_managed_rasterdem_nodatadem_rasterdem_raster_infodem_raster_path_banddetect_lowest_drain_and_sinkdetect_outletsdiagonal_nodatadirdirection_drain_queuedirnamediscoverydiscovery_countdiscovery_infodiscovery_managed_rasterdiscovery_nodatadiscovery_srsdiscovery_stackdiscovery_time_raster_pathdist_to_channel_mfd_work_dirdistance_drain_queuedistance_nodatadistance_to_channel_d8distance_to_channel_managed_rasterdistance_to_channel_mfddistance_to_channel_stackdo_decayed_accumulationdownhill_neighbordownhill_slope_arraydownstream_demdownstream_featuredownstream_fiddownstream_geomdownstream_orderdownstream_to_upstream_idsdrain_distancedrain_pixeldrain_queuedrain_search_queuedrop_distancedrop_distance_collectionds_fads_xds_x_1ds_yds_y_1dtypeedge_diredge_sideemptyencode__enter__enumerateequal_varexceptionexists__exit__extract_strahler_streams_d8extract_streams_mfdfeature_idfidfid_to_orderfill_heightfill_pitsfill_queuefill_value_listfilled_dem_bandfilled_dem_managed_rasterfilled_dem_rasterfinishfinish_coordinatefinish_managed_rasterfinish_stackfinish_time_raster_pathflat_region_mask_managed_rasterflat_region_mask_pathfloat64flow_accumflow_accum_infoflow_accum_managed_rasterflow_accum_mrflow_accum_nodataflow_accum_raster_path_bandflow_accumulation_d8flow_accumulation_mfdflow_dirflow_dir_bandflow_dir_blockflow_dir_buffer_arrayflow_dir_d8flow_dir_d8_managed_rasterflow_dir_d8_raster_path_bandflow_dir_infoflow_dir_managed_rasterflow_dir_mfdflow_dir_mfd_bandflow_dir_mfd_buffer_arra""yflow_dir_mfd_managed_rasterflow_dir_mfd_mrflow_dir_mfd_path_bandflow_dir_mfd_rasterflow_dir_mfd_raster_path_bandflow_dir_nflow_dir_nodataflow_dir_rasterflow_dir_raster_infoflow_dir_raster_path_bandflow_dir_srsflow_dir_typeflow_dir_weightflow_nodataflow_pixelflow_threshold__func__g0g1g2g3g4g5gdalgdal_use_exceptions_generate_read_boundsgeoprocessing_coregeotransformgetLoggerget_raster_infogmtimegpkg_driverii_ni_sni_upstream_flowindexinfinfoint32int8_int_max_steps_per_watershedis_a_channel_is_coroutineis_drainis_outlet_is_raster_path_band_formattedisnanitemsiterblocksjjoinjoined_linelargest_blocklargest_slopelargest_slope_dirlast_flow_dirlast_log_timeleftleft_inlinemergeloadslocal_flow_accumlogginglowerlowest_drain_heightlowest_sink_height__main__makedirsmask_nodatamaxmax_pixel_fill_countmax_steps_per_watershedmax_upstream_flow_accummfdmfd_flow_dir_mfd_valueminmin_decay_proportionmin_flow_accum_thresholdmin_p_valmin_valuemkdtempmodified_offset_dict__module__multi_linen_colsn_dirn_distancen_drain_distancen_heightn_iterationsn_pixelsn_pointsn_processedn_pushedn_rowsn_slopen_stepsn_x_blocks__name__nannatural_drain_existsnew_raster_from_basenext_idnodatanodata_distance_drain_queuenodata_downhill_slope_arraynodata_drain_queuenodata_flow_dir_queuenodata_neighbornumpyoffset_dictoffset_infooffset_onlyogropen_setopsoptionsorderorder_countososgeoosrosr_axis_mapping_strategyout_dirout_dir_increaseoutet_basenameoutflow_diroutletoutlet_at_confluenceoutlet_featureoutlet_fidoutlet_fid_listoutlet_indexoutlet_layeroutlet_pointoutlet_vectoroutlet_xoutlet_yp_valpathpayloadpit_mask_managed_rasterpit_mask_pathpit_queuepixelpixel_countpixel_drainspixel_valplateau_distance_managed_rasterplateau_distance_nodataplateau_distance_pathplateau_drain_mask_managed_rasterplateu_drain_mask_pathpoppour_pointpreemptedprefixpriorityprocessed_nodesprocessed_segmentsproj_xproj_yprojection_wktpygeoprocessingpygeoprocessing.routing.routing__qualname__raster_coordraster_driverraster_driver_creation_tuplerast""er_inforaster_path_bandraster_sizeraster_srsraster_x_sizeraster_y_sizeraw_weight_nodataremovereverserightright_inriver_idriver_orderrmtreeroot_heightscipyscipy.statssearch_queuesearch_stacksearch_stepssegments_to_process__set_name__setdefaultshapelyshapely.opsshapely.wkbshutilsingle_outletsingle_outlet_tuplesink_pixelsortedsorted_stream_order_listsource_idsource_point_stacksource_stream_pointsplitextstatsstrahler_stream_vector_pathstream_arraystream_bandstream_basenamestream_featurestream_fidstream_layerstream_linestream_mrstream_nodatastream_orderstream_order_liststream_rasterstream_valstream_vectorstreams_by_orderstreams_to_processstreams_to_reteststrftimesuffixsum_of_downhill_slopessum_of_nodata_slope_weightssum_of_slope_weightssum_of_weighted_distancessum_of_weightstarget_discovery_raster_pathtarget_distance_to_channel_raster_pathtarget_filled_dem_raster_pathtarget_finish_raster_pathtarget_flow_accum_raster_pathtarget_flow_dir_pathtarget_offset_dicttarget_outlet_vector_pathtarget_stream_raster_pathtarget_stream_vector_pathtarget_watershed_boundary_vector_pathtempfileterminated_early__test__test_dirtest_orderthresh_fatime_tmp_decay_factor_nodatatmp_dirtmp_dir_roottmp_flow_dir_nodatatmp_work_dirtrace_flow_thresholdtrace_threshold_proportionttest_induint8upstream_all_definedupstream_coordupstream_countupstream_d8_dirupstream_decaying_valueupstream_demupstream_dirsupstream_featureupstream_fidupstream_fid_listupstream_fid_mapupstream_fidsupstream_flow_accumupstream_flow_dirupstream_flow_dir_sumupstream_flow_weightupstream_idupstream_id_listupstream_indexupstream_orderupstream_pixels_remainupstream_stackupstream_to_downstream_idupstream_transport_factorus_faus_xus_yuse_const_decay_factorutilsvaluevaluesvisit_countvisit_order_stackvisited_managed_rastervisited_raster_pathwarningwatershed_basenamewatershed_boundarywatershed_featurewatershed_layerwatershed_polygonwatershed_vectorweight_nodataweight_rasterweight_raster_path_bandweight_valwin_xsizewin_xsize_borderwin_ysize""win_ysize_borderwkbwkbLineStringwkbLinearRingwkbPointwkbPolygonworking_dirworking_dir_pathworking_downhill_slope_arrayworking_downhill_slope_sumworking_featureworking_fidworking_flow_accum_thresholdworking_geomworking_orderworking_river_idworking_stackworkspace_dirxx_fx_lx_nx_off_borderx_px_uxaxbxixi_bnxi_nxi_qxi_rootxi_snxoffy_fy_ly_ny_off_bordery_py_uyaybyiyi_bnyi_nyi_qyi_rootyi_snyoff\200\001\360\006\00012\330%&\360x\002\000\005!\240\001\360\010\000\005\025\220E\230\021\230!\360\010\000\005\t\210\010\220\001\330\014+\2501\330\014\r\330\010\013\2105\220\007\220u\230D\240\004\320$B\300!\3001\330\014\022\220*\230A\330\020I\310\021\330\024\025\340\004\027\220q\330\004\023\320\023(\250\001\330\010%\240Q\240a\330\010\t\330\010\014\210N\230!\2301\330\010%\240Q\330\004)\250\035\260a\330\010.\250g\260Q\260j\300\003\3001\330\004\035\230]\250!\330\010 \240\001\240\022\2407\250!\2501\330\010 \240\001\240\024\240Q\340\004\023\2208\2308\2401\330\010\017\210v\220W\230A\330\010\014\210B\210e\2208\2301\230A\330\004\032\230\"\230E\240\025\240a\240~\260Q\330\004\023\320\023(\250\001\330\010%\240Q\240a\330\010\t\330\010\014\210K\220q\230\001\330\010%\240Q\330\004\035\230]\250!\330\010\033\2307\240!\240:\250S\260\001\340\004\"\240-\250q\330\010%\240Q\240b\250\007\250q\260\001\330\010%\240Q\240d\250!\330\004\025\220T\230\027\240\001\320!9\270\021\270$\270d\300!\330\004\023\220>\240\036\250q\3200H\310\001\310\021\340\004\032\230$\230g\240Q\330\010%\240Q\240d\250$\250a\330\004\030\320\030+\250>\270\021\330\010%\240Q\240a\360\006\000\005\010\200q\330\010\030\230\r\240Q\330\014#\2401\240B\240g\250Q\250a\330\014#\2401\240D\250\001\330\010\034\230O\320+;\2701\330\014#\2401\240C\240q\250\t\260\021\330\020'\240q\250\002\250!\2501\330\010\013\320\013\035\230W\240A\330\014\034\230A\340\014\034\230A\340\004\033\230?\320*:\270!\330\010%\240Q\240a\330\004\023\320\023#\320#7\260q\270\001\360\006\000\005\t\210\017\220\177\240k\260\021\330\014&\240l\260&\270\016\300a\330\010\024\220K\230q\240\001""\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\320\030?\270v\300R\300~\320UW\320WX\330\020\036\230b\240\001\360\006\000\t \230u\240F\250!\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010 \240\005\240V\2501\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010\034\230F\240!\330\010\035\230V\2401\360\010\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010\034\230A\230S\240\004\240C\240v\250\\\270\034\300Q\330\016#\2407\250!\2505\260\001\340\010\035\230Q\230c\240\024\240S\250\006\320.?\270|\3101\330\016#\2407\250!\2505\260\001\360\006\000\t\021\220\001\330\010\020\220\001\360\006\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\032\230\"\230A\230T\240\021\240!\330\020\032\230\"\230A\230T\240\021\240!\360\006\000\021\024\320\023'\240q\250\004\250D\260\003\2601\330\0246\260d\270!\330\030!\240\031\250!\330\024\025\340\020\023\320\023(\250\001\250\024\250T\260\023\260A\340\024\025\360\n\000\021\024\320\023)\250\024\250Q\250i\260y\300\003\3001\330\024*\250$\250a\250y\270\t\300\021\330\024-\250U\260!\330()\250\031\260)\2703\270c\300\021\340\020\026\220d\320\0323\2606\270\021\330\024\034\320\0345\260T\270\021\330\024-\250T\260\021\330\024\025\330\030.\250d\260!\2605\270\005\270U\300%\300s\310!\330\024\027\220q\330\030:\270$\270a\330\034!\240\025\240e\2505\260\001\330\030\031\340\024\025\330\030\035\320\0358\270\004\270A\330\034!\240\025\240e\2501\360\n\000\025!\240\001\360\020\000\025\031\230\007\230u\240A\240U\320*:\270!\330\030*\250$\250c\260\032\2704\270t\3002\300Q\330\030\033\320\033+\2503\250a\330\034\035\340\030\037\230u\240C\240q\250\013\2601\260A\330\030\037\230u\240C\240q\250\013\2601\260A""\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\360\014\000\031\034\320\0331\260\024\260Q\260f\270F\300#\300Q\330\0342\260$\260a\260v\270V\3001\330\034(\250\001\330\034!\320!2\260!\330\0345\260U\270!\2701\330\0345\260U\270!\33001\260\026\260v\270S\300\003\3001\330\034\035\360\010\000\031&\320%G\300t\3101\330\034\"\240!\360\n\000\031\034\230;\240c\250\021\340\034\035\360\016\000\031\034\2301\330\034)\250\035\260d\270!\2706\300\021\330\034\037\230x\240q\250\014\260A\330 -\250Q\360\010\000\035+\250)\2604\260r\270\027\300\001\360\010\000\031\036\320\0350\260\001\340\030\035\320\035;\320;K\3101\330\034'\240r\250\021\360\n\000\025\030\220q\330\030\031\360\n\000\025\030\220u\320\034,\250C\250q\340\030:\270$\270a\330\034!\240\025\240e\2501\330\034!\320!<\270B\270e\3001\340\004&\240f\250A\330\004\032\230&\240\001\330\004\037\230v\240Q\330\004\007\200q\330\010\025\220V\2301\330\004\032\230&\240\001\330\004\n\210'\220\021\220!\330\004\n\210%\210q\320\0207\260q\200\001\34045\330%&\360B\003\000\005\025\220E\230\021\230!\360\020\000\005\027\220o\320%5\260Q\3206J\310!\3101\330\004\022\220/\240\021\240)\2501\320,@\300\001\300\022\3001\300A\330\004\007\200|\2207\230!\340\010\025\220U\230(\240!\2401\360\006\000\t\026\220Q\360\006\000\005\024\320\023#\240?\260!\2601\360\006\000\005\023\220!\360\006\000\005\006\330\010\013\210<\220w\230a\330\014\016\210i\220q\230\001\330\013\014\340\004\027\220x\230x\240q\330\010\014\210A\330\010\017\320\0170\260\002\260$\260i\270q\330\014!\240\024\240W\250A\360\n\000\005\035\230B\230e\2405\250\001\330\010\032\230!\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!8\270\004\270A\330\010\t\210\021\330\010%\240Q\330\004&\240m\2601\330\010\035\230W\240A\240Z\250s\260!\340\004\026\220a\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!7\260t\2701\330\010\t\210\021\330\010%\240Q\330\004\036\230m\2501\330\010\034\230G\2401\240J\250c\260\021\340\004\035\230R\230u\240E\250\021\330""\010\032\230!\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!9\270\024\270Q\330\010\t\210\021\330\010%\240Q\330\004(\250\r\260Q\330\010\036\230g\240Q\240j\260\003\2601\360\014\000\005\035\230B\230e\2405\250\001\330\010\032\230!\330\0041\260\036\270r\300\021\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!8\270\004\270A\330\010\t\210\021\330\010\030\230\001\230\021\330\010%\240Q\330\004&\240m\2601\330\010\035\230W\240A\240Z\250s\260!\360\006\000\005'\240a\330\004\025\320\025'\240\177\260a\260q\330\004\010\320\010\030\230\003\320\033+\2502\250S\260\003\2603\260a\330\014\034\230C\320\037/\250r\260\023\260C\260q\330\010\016\210h\220a\220q\330\010\t\330\014\016\210e\2205\230\001\320\031+\2501\330\014 \240\001\240\021\330\010\030\230\004\320\034,\250A\320-I\310\021\310!\330\010\025\220T\230\027\240\001\320!5\260Q\260d\270$\270a\330\010\025\220[\240\001\330\014+\2501\250D\260\001\330\014\024\320\0240\260\001\260\021\330\010\025\220Q\330\010\016\210e\2201\220A\340\010*\250!\330\004\031\230\035\240a\330\010'\240q\250\002\250'\260\021\260!\330\010'\240q\250\004\250A\360\006\000\005\022\220\024\220W\230A\330\010'\240q\250\004\250D\260\001\330\004\017\210z\230\036\240q\330\010'\240q\250\001\360\006\000\005\t\210\017\220\177\240k\260\021\330\014-\250\\\270\021\330\014\032\230!\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\320\030+\2506\260\022\260>\300\022\3001\330\020\036\230b\240\001\360\006\000\t\034\2305\240\006\240a\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010\030\230\006\230a\360\010\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010\030\230\001\230\023\230D\240\003\2406\250\030\260\034\270Q\330\022'\240w\250a\250u\260A\360\006\000\t\021\220\001\330""\010\020\220\001\360\006\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\036\320\036.\250a\250t\2601\330\020\023\2208\2301\230M\250\021\330\024\025\360\n\000\021\033\230\"\230A\230Q\230a\230q\330\020\032\230\"\230A\230Q\230a\230q\340\020\023\320\023*\250$\250a\330\030!\240\031\250#\250Q\340\024\025\360\014\000\021*\250\021\330\020\024\220G\2305\240\001\240\021\340\024(\250\001\250\027\260\001\330\024\033\2302\230Q\230k\250\021\250!\330\024\033\2302\230Q\230k\250\021\250!\330\024\037\320\037/\250q\260\006\260a\330\024\027\220x\230q\240\n\250!\330\030\031\330\024\036\230l\250\"\250A\330\024\027\220x\230r\240\021\330\030\033\2304\230r\240\021\340\034'\240q\330\030,\250A\250W\260A\330\0302\260!\340\020\023\320\023*\250\"\250A\330\0240\260\001\330\024\030\230\007\230u\240A\240Q\330\0306\260a\330\034 \240\002\320\"6\260a\260u\270A\330\0343\2602\260V\2704\270t\3002\300Q\340\024+\2504\250q\330\030!\240\031\250!\330\024\025\360\020\000\021#\240%\240\177\260a\260y\300\001\330\020/\250t\2601\260I\270Y\300a\360\n\000\021\027\220d\320\032,\250F\260!\330\024\033\320\033-\250V\2602\260Q\330\024\033\320\033-\250V\2602\260Q\330\024&\240d\250!\340\024+\2501\330\0242\260!\330\024\030\230\007\230u\240A\240Q\340\030,\250A\250W\260A\330\0303\2601\260G\2701\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034'\240q\340\034'\320'9\270\024\270Q\270f\300A\330\030\033\2308\2401\240J\250a\330\034&\240m\2604\260r\270\027\300\001\330\034;\2701\330\0347\260q\270\007\270q\330\034\035\330\030\"\240,\250b\260\001\330\030\033\2308\2402\240Q\330\034\035\330\030\033\2308\2403\240a\330\034\037\320\037>\270d\300!\330$*\250&\260\003\2601\360\006\000!3\260%\260q\33023\2606\270\021\330 ?\270t\3001\330$*\250&\260\001\330\034\035\330\030\033\2304\230r\240\021\330\034'\240q\330\030,\250A\250W\260A\330\0300\3200D""\300A\300Q\340\0241\260\021\330\0243\2601\330\024\027\320\027,\250B\250a\330\0307\260q\330\0305\260Q\330\0315\260R\260q\330\030\031\330\034\035\330\030\031\330\034\035\340\024\027\320\0272\260\"\260A\330\0304\260A\330\030\034\230G\2405\250\001\250\021\330\034:\270!\330 $\240B\320&B\300!\3005\310\001\330 ;\2702\270V\3001\330 $\240B\240a\330\030\033\320\0330\260\002\260!\340\0343\2604\260q\330 &\240f\250A\330\034;\2704\270q\330 &\240f\250A\330\034=\270T\300\021\330 &\240f\250A\330\0340\260\005\260Q\330./\250v\260Q\340\0347\260u\270A\330./\250v\260Q\330\0341\260\025\260a\330 !\360\006\000\021\024\320\023'\240v\250Q\360\010\000\025\033\230$\320\0369\270\026\270q\330\030\037\320\037:\270&\300\002\300!\330\030\037\320\037:\270&\300\002\300!\330\030/\250t\2601\330\034\"\240&\320(=\270V\3001\330\0307\260t\2701\270F\300&\310\001\330\0309\270\024\270Q\270f\300F\310!\330\030,\250E\260\021\330\0347\260v\270Q\330\030-\250T\260\021\330\0303\2604\260q\360\006\000\025-\250L\270\001\330\0242\3202E\300Q\360\006\000\021\025\220E\230\025\230a\320\0373\2605\270\001\330\024(\250\005\250Q\330\030,\250F\260!\330\024)\250\025\250a\320/C\3006\310\021\330\024(\250\004\250A\360\020\000\021\027\220d\320\032.\250f\260A\330\024\033\320\033/\250v\260R\260q\330\024\033\320\033/\250v\260R\260q\330\024(\250\004\250A\340\024%\320%D\300D\310\001\330\030\036\230a\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\340\030+\250?\270!\330\034%\240T\250\022\2507\260!\340\030\034\230I\320%7\260t\2701\330 &\240g\250S\260\r\270Q\330 ?\270t\3001\330$*\250&\260\002\260!\360\006\000\035<\2704\270q\330 &\240f\250A\330\0340\260\005\260Q\330./\250v\260Q\360\010\000\021\027\220d\320\032/\250v\260Q\330\024\033\320\0330\260\006\260b\270\001\330\024\033\320\0330\260\006\260b\270\001\330\024)\250\024\250Q\340\024%\320%D\300D\310\001\330\030\036""\230a\340\024+\2501\330\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\330\030,\250A\250W\260A\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\340\030\033\320\033-\250T\260\021\260&\270\006\270c\300\021\330\034\035\340\030%\320%D\300D\310\001\330\034\"\240!\330\030\033\230;\240c\250\021\330\034\035\330\030\033\230;\240b\250\001\330\034&\240m\2604\260r\270\027\300\001\330\0340\260\001\260\027\270\001\330\0344\260A\330\035!\320!B\300$\300a\330 &\240a\330\0341\260\025\260a\330./\250v\260Q\330\034=\270T\300\021\330 &\240f\250A\340\024\027\320\027,\250C\250q\330\030\031\330\0240\260\001\330\024\030\230\007\230u\240A\240Q\330\0306\260a\330\034 \240\002\320\"6\260a\260u\270A\330\0341\260\022\2606\270\024\270T\300\022\3001\330\024+\2504\250q\330\030\036\230f\240A\340\004\017\210q\330\004\021\220\021\330\004%\240V\2501\330\004\033\2306\240\021\330\004#\2406\250\021\330\004\026\220f\230A\330\004#\2406\250\021\330\004\n\210'\220\021\220!\330\004\n\210%\210q\320\0200\260\001\200\001\360\006\000\t\n\330%&\360B\002\000\005%\240A\330\004 \240\001\360\"\000\005\025\220E\230\021\230!\360\010\000\005\010\200t\320\013)\250\021\250!\330\010\016\210j\230\001\330\014E\300Q\330\020\021\330\004\007\320\007\037\230t\2404\320'E\300Q\330\014\r\330\010\016\210j\230\001\330\014E\300Q\330\020\021\340\004\n\210&\220\001\220\021\330\004\023\320\023(\250\001\330\010%\240Q\240d\250!\330\010\014\210N\230!\2301\330\010%\240Q\340\004 \240\r\250Q\330\010%\240W\250A\250Z\260s\270!\360\006\000\005\013\210&\220\001\220\021\330\004\023\2202\220U\230(\240!\2401\330\004\016\210h\220h\230a\230t\240>\260\027\270\001\330\004\032\230\"\230E\240\025\240a\240y\260\001\330\004\023\320\023(\250\001\330\010%\240Q\240d\250!\330\010\014\210K\220q\230\001\330\010&\240i\250q\330\004\035\230]\250!\330\010\033\2307\240!\240:\250S\260\001\340\004\036\230m\2501\330\010%\240Q\240b\250\007\250q\260""\001\330\010%\240Q\240d\250!\330\004\026\220d\230'\240\021\330\010%\240Q\240d\250$\250a\330\004\024\220O\240>\260\021\330\010%\240Q\240a\360\006\000\005\010\200q\330\010\030\230\r\240Q\330\014#\2401\240B\240g\250Q\250a\330\014#\2401\240D\250\001\330\010\034\230O\320+;\2701\330\014#\2401\240C\240q\250\t\260\021\330\020'\240q\250\002\250!\2501\330\010\013\320\013\035\230W\240A\330\014\034\230A\340\004\033\230?\320*:\270!\330\010%\240Q\240a\330\004\023\320\023#\320#7\260q\270\001\330\004\022\220.\240\002\240!\330\004\022\220!\340\004\n\210&\220\001\220\021\340\004\010\210\017\220\177\240k\260\021\330\014+\250<\260q\330\014\032\230!\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\320\030:\270&\300\002\300.\320PR\320RS\330\020\036\230b\240\001\360\006\000\t%\240E\250\026\250q\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010!\240\026\240q\360\010\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010!\240\021\240#\240T\250\023\250F\260-\270|\3101\330\022'\240w\250a\250u\260A\360\006\000\t\021\220\001\330\010\020\220\001\360\006\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\037\320\0378\270\001\270\024\270Q\330\020\023\220=\240\003\2401\340\024\025\340\020\024\220G\2305\240\001\240\021\330\024\031\230\035\240d\250$\250b\260\004\260B\260e\2703\270a\340\030\031\330\024\033\2302\230Q\230k\250\021\250!\330\024\033\2302\230Q\230k\250\021\250!\340\024\027\320\0270\260\001\260\026\260v\270S\300\001\360\010\000\031#\240\"\240A\240Q\240a\240q\330\030\"\240\"\240A\240Q\240a\240q\330\030\033\2301\330\034)\250\030\260\035\270d\300!\330 )\250\021\330\034\037\230x\240q\250\014\260A\330 -\250Q\340\034)\250\021\330\030$\240E""\250\021\330)*\250)\2609\270C\270q\330\030.\250d\260!\2609\270I\300Q\330\030'\240q\330\030\031\340\020\026\220d\230,\240f\250A\330\024!\240\034\250T\260\021\330\024 \240\004\240A\340\024\027\220u\230A\230V\2402\240^\2602\260Q\330\030(\250\005\250Q\250a\330\030\036\230e\2401\330\034\035\330\034\"\240\"\240L\260\002\260%\260q\270\001\340\024 \240\001\330\024\030\230\007\230u\240A\240Z\320/?\270q\330\030\037\230z\250\023\250A\250[\270\001\270\021\330\030\037\230z\250\023\250A\250[\270\001\270\021\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\340\034\035\330\030\031\330\034!\320!8\270\004\270A\270V\3001\330\030\031\330\0349\270\021\330 .\250a\250u\260B\260d\270\"\270A\330\030\033\320\0330\260\003\2601\340\034\035\330\030\031\330\0345\260T\270\021\270&\300\001\330\030\034\230H\240A\320%:\270!\330 $\240D\320(>\270d\300!\330$*\250!\340\034&\320&7\260q\330\034(\250\005\250Q\250a\330\034\037\230q\330 -\250X\260]\300$\300a\330$*\250!\330 #\2408\2501\250L\270\001\330$1\260\021\340 -\250Q\330\034(\250\005\250Q\330-.\250f\260F\270#\270Q\330\0342\260$\260a\260v\270V\3001\330\034+\2501\330\034(\250\001\330\034\035\330\0300\260\001\330\030\034\320\034/\250u\260A\260Q\330\034\035\330 =\270Q\330$4\260B\260d\270\"\270A\340\030\"\240!\330\0340\260\002\3202G\300q\330\034#\2401\330\024\027\220t\2301\330\0301\260\024\260Q\330\034&\240e\250:\260Q\330\034&\240a\330\004\035\230V\2401\330\004\033\2306\240\021\330\004\007\200q\330\010\025\220V\2301\330\004\032\230&\240\001\330\004\005\330\010\016\210g\220Q\220a\330\013\014\330\010\016\210j\230\001\230\021\330\004\n\210%\210q\320\0202\260!\200\001\360,\000\005\n\210\021\330\004\n\210!\330\004\t\210\021\330\004\n\210!\330\004\031\230\033\240E\250\021\330\004\007\200{\220!\2208\2302\230Q\330\010\r\210Q\330\010\032\230!\230;\240a\330\010\032\230!\320\033+\2501\330\004\007\200{\220!\2208\2302\230Q\330\010\r\210Q\330\010\032\230!\230;\240a\330\010\032\230!\320\033+\2501\330\004\010\210\013""\2201\220H\230B\230k\250\021\250-\260r\270\021\330\010\r\210Q\330\010\032\230!\320\033+\2501\330\004\010\210\013\2201\220H\230B\230k\250\021\250-\260r\270\021\330\010\r\210Q\330\010\032\230!\320\033+\2501\330\004\013\2101\210D\220\004\220D\230\005\230Q\200\001\360\n\000\t\n\330\010\t\330\010\t\330\010\t\330\"#\360F\002\000\005\025\220O\320#3\2601\330\010$\240A\240Q\330\004\007\200}\220A\220Q\330\010\027\220s\320\032+\2501\330\010\024\220N\240!\240=\260\001\260\021\330\010\024\320\024+\2501\250A\340\010\027\220q\330\004\022\220$\320\026&\240a\240q\340\004\024\220K\230w\240a\330\010#\2403\240c\250\023\250D\260\001\330\004\026\220b\230\005\230Y\240a\330\010\n\210%\210y\230\001\320\0313\2601\260A\330\004\023\220=\240\014\250A\330\010\031\230\036\240s\250!\330\004\020\220\014\230A\230S\240\n\250!\2509\260C\260q\330\004\020\220\014\230A\230S\240\n\250!\320+<\270C\270q\330\004\020\220\014\230A\230S\240\n\250!\250:\260S\270\001\330\004\020\220\014\230A\230S\240\n\250!\250<\260s\270!\330\004\020\220\014\230A\230S\240\n\250!\2509\260C\260q\330\004\020\220\014\230A\230S\240\n\250!\2509\260C\260q\330\004\020\220\014\230A\230S\240\n\250!\250=\270\003\2701\330\004\020\220\014\230A\230S\240\n\250!\320+>\270c\300\021\330\004\020\220\014\230A\230S\240\n\250!\2508\2603\260a\330\004\020\220\014\230A\230S\240\n\250!\2508\2603\260a\330\004\020\220\014\230A\230S\240\n\250!\250:\260S\270\001\330\004\020\220\014\230A\230S\240\n\250!\250:\260S\270\001\330\004\020\220\014\230A\230S\240\n\250!\2508\2603\260a\330\004\020\220\014\230A\230S\240\n\250!\2508\2603\260a\330\004\036\230m\2501\330\010$\240A\240R\240w\250a\250q\330\010$\240A\240T\250\021\340\004 \240\r\250Q\330\010#\2401\240B\240g\250Q\250a\330\010#\2401\240D\250\001\340\004\031\230\035\240a\330\010\034\230A\230R\230w\240a\240z\3201E\300Q\300d\310!\340\004\033\230?\320*:\270!\330\010$\240A\240S\250\001\250\031\260!\330\014(\250\001\250\022\2501\250A\330\004$\240O\3203C\3001\330\010#\2401\240C\240q\250\t\260\021\330\010#\2401\240B\240a""\240q\360\022\000\005\r\210I\220]\240!\2401\340\004\n\210%\210q\220\001\330\004\"\240'\250\022\2501\330\004\034\230A\340\004\024\220E\230\021\230!\360\010\000\005\034\2308\2401\360\016\000\005&\240Q\360\006\000\005\037\230a\230s\240#\240S\250\003\2503\250c\260\023\260A\360\016\000\005\033\230+\240\\\260\021\260!\360\022\000\005\021\320\020!\240\021\330\004\010\210\017\220\177\240k\260\021\330\014*\250,\260a\330\010\013\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\330\020\022\220!\320\023#\2401\240A\330\014\034\230E\240\021\240!\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\027\220z\240\022\2401\340\010\014\210E\220\025\220a\220q\330\014\020\220\005\220U\230!\2301\330\020\033\2301\330\020\026\220e\2302\230Q\330\020\026\220e\2302\230Q\330\020#\2408\320+D\300D\310\001\330\024\031\230\021\330\020\024\320\024%\240R\320'@\300\001\330\030 \240\001\320!3\2601\330\024\025\340\020\026\220e\320\0332\260$\260a\260u\270A\330\020\026\220d\230\"\230K\240q\250\001\330\020\026\220d\230\"\230K\240q\250\001\330\020\024\220D\230\002\230\"\230C\230t\2402\240R\240s\250$\250c\260\027\270\003\2704\270s\300'\310\021\330\030\035\320\0354\260D\270\001\330\034!\240\025\240c\250\021\330\024\037\230q\340\020\023\2204\220y\240\001\330\030)\250\022\2501\250A\250Q\360\006\000\025\026\340\020!\240\021\330\020\024\220E\230\025\230a\230q\330\024\032\230$\230b\240\013\2501\250A\330\024\032\230$\230b\240\013\2501\250A\340\024\027\220t\2302\230R\230s\240$\240b\250\002\250#\250T\260\023\260G\2703\270d\300#\300Q\330\030\031\330\024\032\230%\320\0376\260d\270!\2705\300\001\330\024\027\220t\2303\230a\330\030\031\330\024\030\230\016\240a\240s\250#\250T\260\021\330\034$\320$=\270T\300\021\330 %\240U\250#\250Q\330\030%\240Q\320&8\270\001\330\030*\250!\330\020\023\220?\240#\240R\240t\2504\250q\330\024\025\330\020\024\320\024&\240e\2501\250A\340\024%\240S\250\010\260\001\330\030$\240M\260\021\330\024\"\240)""\2501\250J\260a\330\024 \240\016\250a\250q\330\024!\240\036\250w\260a\330\024&\240e\320+C\3001\330\030\035\230U\240-\250q\3200A\300\021\330\024'\240r\250\025\250e\2607\270!\2701\330\004\n\210%\210q\330\010\t\340\004\n\210%\210q\220\001\330\004\017\320\017!\240\025\240a\360\010\000\005\"\240\021\360\006\000\005!\240\001\340\004\n\210$\320\016 \240\006\240a\330\010\013\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\340\020\022\220!\2208\2301\320\034.\250e\2607\270!\2701\340\014\034\230E\240\021\240!\360\006\000\t\037\320\0360\260\004\260A\330\010\032\230$\230a\340\010\022\320\022,\250A\330\014\037\230u\320$7\260q\330\014\037\230q\330\014\031\230\021\320\032+\2508\2601\330\014'\320'@\300\001\330\014&\240a\330\010\013\2108\2203\220a\330\014\022\220&\230\001\330\020\021\330\020\022\220!\320\023&\240f\250A\320-@\300\001\330&'\320':\270!\330\014\r\330\010\r\210U\220(\230(\320\"4\260N\300!\340\010\031\320\031+\2504\250q\330\014\037\230u\320$7\260q\340\010\031\230\034\240[\260\001\330\014\037\230q\330\010\026\220i\230q\330\014\025\320\025.\250d\260!\330\020#\2405\320(;\2701\330\010\026\220i\230q\240\010\320(;\2701\330\010\026\220i\230q\240\010\320(;\2701\330\010\026\220i\230q\240\n\250!\330\010\026\220i\230q\240\n\250!\330\010\026\220i\230q\240\010\250\001\330\010\026\220i\230q\240\010\250\001\330\010\026\220i\230q\330\014\037\320\0372\260!\360\010\000\t\r\210O\2301\330\014%\240Q\240a\330\020#\2401\360\006\000\t#\240!\320#6\260a\330\014\r\360\006\000\t\014\2104\210q\330\014\032\230)\2401\240I\250Q\330\010\026\220l\240!\2401\360\006\000\t\030\320\027)\250\024\250Q\250e\2601\330\010\030\230\r\240R\240q\330\010\026\220i\230q\320 1\260\021\330\010\026\220i\230q\330\014\025\320\025.\250d\260!\2605\270\001\330\010\026\220i\230q\240\r\250Q\330\010\024\220K\230q\240\001\340\004\n\210%\210q\330\010\t\340\004\n\210%\210q\220\001\340\004\020\320\020#\2401\240A\330\004\031\230\021\230/\250\024\320-?\270q\330\004\031\230\023\230A\230Q\330\004\026\220a\330\004""\n\210!\330\010\013\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\340\020\022\220!\320\023%\240Q\240c\250\021\250!\330\020\022\220!\2201\330\014\034\230E\240\021\240!\340\010\031\320\031+\2504\250q\260\001\330\010\025\220^\2407\250!\330\010\013\210;\220g\230Q\340\014\032\230)\2401\240J\250a\330\014\030\230\013\2401\240A\330\014\033\2307\240!\240>\260\027\270\001\330\014\035\230Q\330\014\r\330\010\031\320\0312\260!\2601\330\010\035\230\\\250\033\260A\260Q\330\010\013\320\013\035\230Y\240a\240y\260\007\260q\340\014!\240\021\330\014\r\330\010\"\320\"<\270A\270Q\360\006\000\t\035\230A\330\010\026\220a\330\010\014\320\014\034\230A\330\014\037\230|\250;\260a\260q\330\014\035\320\035-\250Y\260a\260q\330\014\017\210\177\230g\240Q\330\020!\240\027\250\001\250\021\360\010\000\021\037\230a\330\020\021\330\010\013\2104\210q\360\006\000\r\016\330\010)\250\021\250!\330\010\033\320\0333\2602\260Q\330\010\013\2103\210a\320\017)\250\022\2502\250Q\330\020(\250\002\250#\250Q\330\020(\250\002\250!\360\006\000\r!\240\001\330\010\032\230)\2401\240I\250Q\330\010\024\220K\230q\240\001\330\010\032\230'\240\021\240!\330\010\035\230Q\330\004\n\210%\210q\330\010\t\340\004\n\210%\210q\330\010\t\330\004\027\220q\330\004\010\210\016\220n\240I\250Q\250a\360\n\000\t\014\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\340\020\022\220!\220<\230q\240\006\240a\240s\250!\2501\340\014\034\230E\240\021\240!\330\010\027\220q\230\001\330\010\016\210a\330\014\030\320\030*\250!\330\014\030\320\030)\250\021\330\014\031\230\034\240T\250\021\330\014\035\230\\\250\033\260A\260Q\330\014\033\230>\250\031\260!\2601\340\014\020\220\r\230R\230|\2501\330\024\"\240)\2501\250L\270\007\270q\340\020\034\230G\2401\330\024.\250a\250q\360\010\000\021\035\230K\240q\250\001\330\020!\240\021\240!\340\020#\240;\250l\270!\2701\330\020+\250;\260l\300!\3001\330\020*\250+\260\\\300\021\300!\330\020\026\220a\330\024!\240\036\250t\2601\330\024%\240\\\260\033\270A\270Q\330\024\"""\240)\2501\250L\270\001\330\024 \240\013\2501\250A\330\024\034\230N\250)\2601\260A\330\024$\240A\240V\2507\260!\2601\330\024,\250A\250V\2607\270!\330\030&\240i\250q\260\001\330\024+\2501\250L\270\001\330\030/\250q\260\001\330\030&\240i\250q\260\001\330\024%\240Q\330\024\"\240'\250\021\330\0302\260!\2601\340\020/\250q\330\020\026\320\026/\250t\2601\330\024 \320 2\260!\330\024 \320 1\260\021\360\006\000\025\"\240\023\240A\240Q\330\024\032\230*\240A\240R\240s\250#\250Q\250a\330\030\034\230C\230q\320 8\270\001\270\035\300b\310\002\310!\330 #\2401\320$<\270A\330$.\250a\250t\2602\260Q\340\034\035\330\030\033\2308\2405\250\006\250j\270\001\330\0344\260A\260Q\330\0344\260A\260Z\270q\300\001\330\034&\240a\330\030\033\2306\240\022\240:\250S\260\005\260V\2701\270A\340\034\035\330\030&\240a\330\024\027\220{\240#\240S\250\001\250\021\340\030\031\340\0244\260A\340\024\030\230\t\240\025\240a\240s\250*\260A\260Q\360\006\000\031-\250A\360\006\000\031\034\2306\240\023\240A\330\034 \320 7\260q\270\001\330\030\033\2306\240\023\240A\330\034 \320 8\270\001\270\021\330\030\036\320\036.\250a\250q\330\034-\320-=\270Q\270f\300D\310\001\330\034 \240\016\250i\260q\270\t\300\021\330$%\360\010\000!0\250q\330$4\260A\330$%\330$%\330 !\330\034 \240\016\250i\260q\270\t\300\021\330$%\360\010\000!9\270\001\270\026\270w\300a\330$2\260)\2701\270A\330 7\260q\270\014\300A\330$;\2701\270A\330$2\260)\2701\270A\330 ,\250K\260q\270\001\330 1\260\027\270\001\270\021\330 !\340\034#\240>\260\031\270!\2701\330\034#\240>\260\031\270!\2701\330\034.\250n\270I\300Q\330 !\330\034&\320&@\300\001\330 &\240f\250A\330 -\250Q\320.?\270x\300q\330 !\330 9\270\021\330 !\330 !\330\034\037\230x\240s\250!\330 /\250q\330$4\260A\330$%\330$%\330 !\330\035\"\240%\240x\250x\260q\330 /\250q\340\034*\250,\260a\260q\330\034+\320+=\270T\300\021\300%\300q\330\034-\320-?\270t\3001\330 &\240a\330\034,\250M\270\022\2701\330\0344\260A\260V\2707\300!\330 !\330\034*\250)\2601\330 1\260\021\330\034*\250)\2601\330 )\320)B\300$\300a\330$)\250\021""\330\034*\250)\2601\330 -\250Q\330\034*\250)\2601\330 (\250\001\330\034*\250)\2601\330 (\250\001\330\034*\250)\2601\330 *\250!\330\034*\250)\2601\330 *\250!\330\034*\250)\2601\260H\270A\330\034*\250)\2601\260H\270A\340\034-\250W\260A\260Q\330\034(\250\013\2601\260A\340\030(\250\001\250\031\260!\330\020$\240A\340\004\033\2306\240\021\330\004\035\230V\2401\330\004\026\220f\230A\330\004\n\210%\210q\330\010\t\360\006\000\005\021\220\014\230A\330\010\024\220O\2401\320$7\260q\330\004\020\320\020\"\240!\330\004\020\320\020!\240\021\330\004\n\210%\210q\330\010\t\360\010\000\005\025\220A\330\010\014\210D\220\007\320\0272\260!\330\010\014\320\014&\240a\240q\330\004\023\2201\330\004\031\230\021\330\004\032\230#\230Q\230a\330\004\025\220Q\330\004\n\210!\330\010\013\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\340\020\022\220!\320\023*\250!\2501\340\014\034\230E\240\021\240!\330\010\036\230a\340\010\026\220m\2404\240q\360\006\000\t\035\320\0346\260a\260q\330\010\013\2101\330\014\032\230+\240\\\260\021\260!\330\014\020\320\020 \240\001\330\020\033\2301\230L\250\001\320);\2701\330\014\034\230C\230q\240\001\330\014\017\210{\230!\230?\250\"\250A\330\020!\240\021\330\014\030\230\001\230\037\250\001\340\014\030\230\001\230\037\250\001\340\010\032\230,\240k\260\021\260!\330\010\027\220y\240\001\240\031\250,\260a\260q\330\010\024\220K\230q\240\001\330\010\032\230!\340\010\013\210<\220w\230a\340\014\r\340\010\031\320\0312\260!\2601\330\010\031\320\0313\2601\260A\330\010\013\2103\210a\320\017\037\230s\240!\360\006\000\r\031\230\001\320\031+\250<\260q\270\001\330\014\020\220\014\230A\230Q\360\006\000\r'\240a\240q\330\020*\250!\2501\360\006\000\r\021\320\020 \320 :\270!\2701\330\020)\250\021\320*:\270!\330\014\020\320\020*\250!\2501\330\014\020\320\020)\250\021\250!\360\006\000\r\037\230l\250+\260Q\260a\330\014!\240\034\250[\270\001\270\021\330\014\036\320\0360\260\017\270q\330\014\033\230?\250/\270\021\360\n\000\r\032\230\034\240V\2501\250A\330\014\032\230#""\320\0353\2601\330\020\027\220t\230:\240Q\240g\250T\260\026\260q\330\024\031\230\021\230*\240L\260\005\260Q\340\014\036\230l\250!\2501\330\014\036\230i\240q\330\020\030\230\017\240y\260\001\260\021\330\014\036\230i\240q\330\020\030\230\017\240y\260\001\260\021\330\014\030\230\013\2401\240A\330\014\036\230a\330\014!\240\021\330\014\031\230\021\330\014\032\230!\360\006\000\r\031\230\016\240a\240q\330\014\027\220t\2301\230A\360\006\000\r\032\230\027\240\001\240\021\330\014\r\360\010\000\t \230q\330\010\014\320\014\035\230Q\330\014\017\210~\230S\240\001\340\020\021\330\014\017\210~\230W\240A\360\006\000\021(\240q\330\020\021\340\010\013\2104\210q\340\014\r\360\010\000\t\026\220W\230A\230Q\340\004\n\210%\210q\330\010\t\340\004\n\210%\210q\330\010\t\340\004\020\320\020\"\240!\330\004\023\2201\330\004\024\220A\330\004\n\210%\210q\220\001\200\001\360H\001\000\005'\240e\2501\330\004%\240U\250!\340\004\022\220!\330\004\021\220\021\340\004\026\220o\320%5\260Q\330\010\034\230A\230Q\360\010\000\005\010\200\177\220a\220y\240\001\240\023\240G\2501\330\010\025\220_\240A\240Y\250a\250q\340\010\025\220Q\340\004\023\320\023#\240?\260!\2601\340\004,\250M\270\021\330\010\034\230A\230R\230w\240a\240z\3201E\300Q\300d\310!\340\004 \240\005\240Q\240a\340\004\010\210\017\220\177\240k\260\021\330\014\"\240,\250f\260N\300!\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\330\020\021\330\020\022\220!\320\023%\240Q\240n\260B\260a\360\010\000\t\r\210F\220%\220q\230\003\2301\330\014\026\220b\230\001\230\021\330\014\020\220\006\220e\2301\230C\230q\330\020\032\230\"\230A\230Q\330\020\035\320\035/\250t\2601\260I\270Q\330\020\023\2208\2301\230L\250\001\330\024\025\340\020\024\220K\230r\320!5\260Q\330\030#\2402\240Q\340\024\025\360\006\000\021 \230q\330\020\024\220G\2305\240\001\240\021""\330\024\033\2307\240!\240;\250a\250q\330\024\033\2307\240!\240;\250a\250q\340\024\030\230\005\230R\230r\240\023\240E\250\023\250N\270!\330\034!\240\022\2402\240S\250\005\250S\260\001\340\030\033\230;\240b\250\001\340\0342\260!\330\034+\2509\260A\330\030'\240q\330\030\031\330\024\037\320\0371\260\024\260Q\260f\270A\330\024\027\220x\230q\240\n\250!\340\030\033\230;\240b\250\001\340\0342\260!\330\034+\2509\260A\330\030'\240q\330\030\031\330\024\027\220y\240\002\240!\340\030'\240q\330\030\031\330\020\023\2204\220}\240D\250\013\2602\260Q\330\024)\250\021\330\024\"\240)\2501\330\004\026\220f\230A\330\004\005\330\010\025\220Q\330\010\024\220A\200\001\360:\000\005\025\220M\240\026\240q\330\004\007\200~\220X\230V\2401\330\010\016\210j\230\001\330\014\r\330\016\017\210q\330\004!\240\036\250s\260!\360\n\000\005\026\220Q\360\n\000\005\023\220/\320!1\260\021\330\010!\240\021\240!\340\004\037\230{\250!\2509\260A\330\010!\240\021\240\"\240A\240Q\340\004\023\320\023#\240;\250a\250q\340\004\026\220d\230'\240\021\330\010!\240\021\240$\240d\250!\330\004\024\220O\240>\260\021\330\010!\240\021\240!\340\004\007\200{\220!\2201\330\010\025\220S\320\030)\250\021\330\010\022\220.\240\001\240\033\250A\250Q\340\010\025\220Q\340\004\022\220$\320\026&\240a\240q\340\004\007\200r\210\025\210g\220Q\220a\330\010\016\210h\220a\330\014 \240\001\240\021\340\010\n\210'\220\021\220!\330\004\024\220K\230w\240a\330\010#\2403\240c\250\023\250D\260\001\330\004\025\220R\220u\230I\240Q\330\010\n\210%\210y\230\001\320\0313\2601\260A\330\004\023\220=\240\014\250A\330\010\030\230\014\240C\240q\360\006\000\005\021\220\014\230A\230S\240\n\250!\2505\260\003\2601\330\004\020\220\014\230A\230S\240\n\250!\2505\260\003\2601\330\004\020\220\014\230A\230S\240\n\250!\2506\260\023\260A\330\004\020\320\020!\240\021\340\004 \240\005\240Q\240a\360\006\000\005\013\210%\210q\220\001\330\004\010\320\010\031\230\037\250\013\2601\330\014'\240|\2601\330\010\017\210}\230A\230Q\330\010\017\210}\230A\230Q\330\010\024\220M\240\021\240!""\330\010\024\220M\240\021\240!\360\n\000\t\032\230\025\230f\240A\330\r\026\220a\220s\230)\2401\240D\250\006\250e\2601\360\006\000\t\030\220q\330\010\013\2105\220\002\220!\330\014\033\2301\340\014\032\230$\230e\2401\360\006\000\t\030\220q\330\010\013\2105\220\002\220!\330\014\033\2301\340\014\032\230!\2308\2401\360\006\000\t\034\2301\330\010\013\2104\210q\220\n\230\"\230M\250\021\250!\330\014 \240\001\340\014\032\230%\230u\240A\360\006\000\t\034\2301\330\010\013\2104\210q\220\n\230\"\230M\250\021\250!\330\014 \240\001\340\014\032\230\"\230H\240A\360\010\000\t\027\220a\330\014\r\210Q\210m\2309\240A\240Q\240a\240q\330\014\r\210Q\210m\2309\240A\240Q\240a\240q\330\014\031\230\034\240Q\330\020\025\220T\230\021\230!\330\020\025\220T\230\021\230!\330\020\032\230)\2401\320$4\260A\260Q\330\020\032\230)\2401\320$4\260A\260]\300'\310\021\330\024\031\230\021\340\010\014\210F\220%\220q\230\003\2309\240A\240Q\330\014\017\210u\220A\220V\2302\230^\2502\250Q\330\020 \240\005\240Q\240a\330\020 \240\005\240R\240u\250B\250a\330\020\026\220e\2301\330\024*\250!\330\030\036\230b\240\016\250b\260\001\330\034*\250\"\250N\270!\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\033\230>\250\021\250$\250a\330\020\023\2209\230C\230q\330\024\025\340\020\034\230A\330\020\023\2201\340\024!\240\036\250q\330\030\032\230!\230;\240a\240q\330\030\032\230!\230;\240a\240q\360\010\000\025\030\220{\240#\240Q\330\030$\240A\360\006\000\025\031\230\t\240\025\240a\240q\360\030\000\031\034\2308\2402\240S\250\003\2505\260\001\260\024\260S\270\001\330\034\035\330\030%\240^\2601\330\034\036\230a\230{\250!\2501\330\034\036\230a\230{\250!\2501\330\030\033\230;\240c\250\021\330\034(\250\001\330\034\035\360\010\000\021\024\2201\330\024#\2403\240i\250q\260\003\2601\360\006\000\025\037\230b\240\001\240\024\240Q\240a\330\024\036\230b\240\001\240\024\240Q\240a\360\006\000\025\035\230I\240T\320);\2701\330\030#\2401\240A\330\030\037\230q\240\005\240W\250A\250Q\330\024 \240\t\250\021\250(\260!\330\024%\240S\250""\010\260\001\260\034\270]\310!\330\024\"\240,\250a\250q\340\024\"\240)\2501\250E\260\021\330\024\"\240)\2501\250E\260\021\330\024\"\240)\2501\250F\260!\330\024\037\230q\330\024 \240\016\250a\250q\330\024%\240Q\330\024#\2401\340\004\026\220a\330\004\024\220A\330\004\n\210%\210q\220\001\330\004\020\320\020\"\240!\330\004\023\2201\330\004\024\220A\330\004\n\210%\210q\220\001\200\001\360\010\000\t\n\330%&\360N\001\000\005\010\320\007\"\240\"\240B\240c\320)D\300B\300a\330\010\016\210j\230\001\330\014\r\330\"$\240A\340\004\026\220o\320%5\260Q\330\010#\2401\240A\330\004$\240O\2601\260I\270Q\330\010#\2401\240B\240a\240q\330\004\024\220A\360\006\000\005\024\320\023#\240?\260!\2601\340\004\023\320\023(\250\001\330\010#\2401\240D\250\001\330\010\014\210K\220q\230\001\330\010%\240Q\340\004'\240}\260A\330\010#\2401\240B\240g\250Q\250a\330\010#\2401\240D\250\001\330\004#\240=\260\001\330\010!\240\027\250\001\250\032\2603\260a\330\004)\250\035\260a\330\010\036\230a\230r\240\027\250\001\250\021\330\010\036\230a\230t\2401\360\014\000\005\006\330\010#\2402\240Q\330\004%\240Q\360\010\000\005 \230\177\320.>\270a\330\010\036\230a\230s\240!\2409\250A\320-C\3001\300B\300a\300q\360\016\000\005!\240\005\240Q\240a\340\004\010\320\010\031\230\037\250\013\2601\330\r(\250\004\250L\270\001\330\010\017\210}\230A\230Q\330\010\017\210}\230A\230Q\330\010\024\220M\240\021\240!\330\010\024\220M\240\021\240!\330\010\014\210F\220%\220q\230\001\330\014\026\220b\230\001\230\021\330\014\017\210u\220A\220V\2302\230^\2502\250Q\330\020 \240\005\240Q\240a\330\020 \240\005\240R\240u\250B\250a\330\020\026\220e\2301\320\034C\3006\310\022\310>\320Y[\320[\\\330\024\"\240\"\240A\330\014\020\220\006\220e\2301\230A\330\020\032\230\"\230A\230Q\330\020\035\230]\250$\250a\250y\270\001\330\020\023\2208\2301\230L\250\001\330\024\025\330\020\023\2209\230D\240\001\240\031\250)\2603\260a\330\024\025\330\020\031\230\024\230Q\230i\240y\260\001\330\020\023\220;\230b\240\001\330\024\025\340\020\037\230u\240O\2604\260q\270\t\300""\021\330\020\034\230A\330\020\024\220G\2305\240\001\240\021\330\024\031\230\035\240d\250$\250b\260\004\260B\260e\2703\270a\340\030\031\330\024\033\2307\240!\240;\250a\250q\330\024\033\2307\240!\240;\250a\250q\330\024\030\230\005\230R\230r\240\023\240E\250\023\250N\270!\330\034!\240\022\2402\240S\250\005\250S\260\001\340\030$\240A\330\030\031\330\024\027\220}\240D\250\001\250\026\250v\260S\270\001\330\030$\240A\330\030\031\330\020\023\2201\330\024\034\230E\240\037\260\001\260\031\270!\330\024\035\230T\240\021\240)\2509\260A\340\020\037\230q\330\020\026\220h\230e\2403\240b\250\001\330\024\033\2308\2406\250\022\2501\330\024\033\2308\2406\250\022\2501\330\024\034\230D\240\001\330\024$\240A\330\024\030\230\010\240\005\240Q\240a\330\030 \240\004\240A\240[\260\001\260\021\330\030 \240\004\240A\240[\260\001\260\021\330\030\034\230F\240\"\240B\240c\250\026\250s\260.\300\001\330 &\240b\250\002\250#\250V\2603\260a\330\034\035\330\030'\240u\250O\2704\270q\300\007\300q\330\030\033\230=\250\003\2501\330\034\035\330\030\035\230]\250!\330!/\250q\260\006\260b\270\004\270B\270e\3002\300Q\340\034)\250\025\250i\260t\2701\270G\3001\330\034\037\230{\250#\250R\250t\260;\270c\300\021\330 -\250]\270$\270a\330$+\2501\330 #\240;\250c\260\021\330$-\250T\260\021\260'\270\027\300\001\330$,\250E\260\021\33067\260w\270a\360\006\000%2\260\025\260a\33067\260w\270a\330$*\250-\260u\270C\270r\300\021\330(0\260\r\270V\3002\300Q\330(0\260\r\270V\3002\300Q\330(5\260T\270\021\330(7\260q\330,;\2704\270q\300\007\300q\330(,\250H\260E\270\021\270!\330,0\260\r\270T\300\024\300Q\300d\310\"\310D\320PR\320RS\33008\270\005\270Q\270k\310\021\310!\33008\270\005\270Q\270k\310\021\310!\33004\260F\270\"\270B\270c\300\026\300s\310.\320XY\3308>\270b\300\002\300#\300V\3103\310a\33045\33003\2609\270D\300\001\300\027\310\007\310s\320RS\3304=\270T\300\021\300'\310\027\320PQ\3304A\300\025\300a\330FG\300w\310a\330%0\260\003\2601\330$-\250T\260\021\260'\270\027\300\001\330$,\250E\260\021\33067\260w\270a\340\004\021\220\026\220q""\330\004\r\210V\2201\330\004\023\2206\230\021\330\004\n\210%\210q\220\001\330\004\031\230\024\230Q\230o\250[\270\001\330\t$\240D\250\014\260A\330\004\024\220D\230\007\230q\330\010#\2404\240{\260\"\260D\270\001\330\004\022\220-\230~\250Q\250a\330\004\010\320\010\031\230\021\330\010\027\220{\240,\250c\260\021\330\010\024\220A\220]\240#\240U\250!\330\010\023\220;\230a\330\014\032\230%\230}\250A\250Q\330\014\021\220\035\230a\230q\330\004\022\220!\330\004\024\220A\330\004\n\210%\210q\220\001\200\001\360$\000\005\025\220O\320#3\2601\330\010$\240A\240Q\340\004\014\210I\220]\240!\2401\330\004\005\330\010\025\220Q\220i\230q\320 <\270A\270R\270q\300\001\340\004\036\230m\2501\330\010$\240A\240R\240w\250a\250q\330\010$\240A\240T\250\021\330\004\023\320\023(\250\001\330\010$\240A\240T\250\021\330\010\014\210N\230\"\230A\330\004\037\230}\250A\330\010$\240G\2501\250J\260c\270\021\330\004\023\320\023(\250\001\330\010$\240A\240T\250\021\330\010\014\210N\230\"\230A\330\004\034\230M\250\021\330\010!\240\027\250\001\250\032\2603\260a\360\016\000\005!\240\001\340\004\017\210w\220b\230\001\330\004\022\220!\330\004 \240\005\240Q\240a\360\014\000\005\t\210\017\220\177\240k\260\021\330\014*\250,\260a\340\010\013\2105\220\001\220\025\220a\220~\240R\240q\330\014\022\220%\220q\330\020\021\330\020\022\220!\220;\230a\230x\240q\250\003\2501\330\014\034\230E\240\021\240!\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\027\220z\240\022\2401\340\010\014\210E\220\025\220a\220q\330\014\020\220\005\220U\230!\2301\330\020\026\220e\2302\230Q\330\020\026\220e\2302\230Q\340\020\026\220e\320\0332\260$\260a\260u\270A\330\020\023\2204\220s\230!\330\024\025\360\006\000\021\027\220d\230\"\230K\240q\250\001\330\020\026\220d\230\"\230K\240q\250\001\340\020\024\220D\230\002\230\"\230C\230t\2402\240R\240s\250$\250c\260\027\270\003\2704\270s\300'\310\021\330\030\035\320\0354\260D\270\001\330\034!\240\025\240c\250\021\330\024#\2405\250\017\260q""\270\005\270Q\330\024 \240\005\240[\260\001\260\025\260e\2701\340\020\026\220d\230/\250\026\250q\340\024#\240?\260$\260a\330\024#\2404\240q\340\024,\250D\260\001\330\030$\240E\250\034\260U\270!\330\024'\240q\340\024\037\230q\360\006\000\025\031\230\014\240E\250\021\250!\330\030\036\230l\250$\250b\260\013\2701\270I\300R\300q\330\030\036\230l\250$\250b\260\013\2701\270I\300R\300q\330\030\033\2304\230r\240\022\2403\240d\250\"\250B\250a\330 $\240C\240w\250c\260\024\260S\270\001\330\034\035\330\030 \240\005\320%<\270D\300\001\300\025\300a\330\030\033\2306\240\023\240A\330\034\035\330\030\033\230>\250\021\250*\260C\260q\330\034+\2505\260\017\270q\300\005\300Q\330\034(\250\001\360\010\000\025!\240\005\240Q\330\"#\330\034(\250\005\250\\\270\025\270a\360\006\000\025\030\220y\240\003\2401\330\030\037\230t\240<\250v\260S\270\001\330\037+\2504\250r\260\032\2703\270a\330\0340\260\014\270D\300\001\330\034(\250\004\250A\330\0341\260\024\260Q\330 1\260\025\3206G\300q\330 /\250q\260\001\330\030\033\2304\230|\2506\260\021\340\0340\260\014\270D\300\001\330\034(\250\004\250A\330\034-\250]\270!\330\034(\250\005\250Q\250a\340\004\033\2306\240\021\330\004\034\230F\240!\330\004\031\230\026\230q\200\001\360\006\000\t\n\330\010\t\330\010\t\330%&\360|\002\000\005\034\230=\250\r\260Q\330\004\007\320\007\033\2307\240!\330\010\030\230\001\330\010\022\220+\230Q\360\010\000\005\025\220E\230\021\230!\360\010\000\005\027\220o\320%5\260Q\3206J\310!\3101\330\004\022\220/\240\021\240)\2501\320,@\300\001\300\022\3001\300A\330\004\007\200|\2207\230!\340\010\025\220U\230(\240!\2401\360\006\000\t\026\220Q\360\006\000\005\024\320\023#\240?\260!\2601\360\006\000\005\023\220!\360\006\000\005\006\330\010\013\210<\220w\230a\330\014\016\210i\220q\230\001\330\013\014\340\004\027\220x\230x\240q\330\010\014\210M\230\027\320 0\260\002\260$\260i\270q\330\014!\240\024\240W\250A\360\n\000\005\035\230B\230e\2405\250\001\330\010\032\230!\330\004\021\220\036\230s\240+\250R\250q\340\004\023\320\023(\250\001\330\010\034""\230A\230T\320!8\270\004\270A\330\010\t\210\021\330\010%\240Q\330\004&\240m\2601\330\010\035\230W\240A\240Z\250s\260!\360\n\000\005\025\220B\220e\2305\240\001\320!3\2601\330\004\023\320\023(\250\001\330\010\034\230A\230T\240\037\260\004\260A\330\010\t\210\021\330\010%\240Q\330\004\036\230m\2501\330\010\025\220W\230A\230Z\240s\250!\360\006\000\005\025\220O\320#3\2601\330\010\034\230A\230S\240\001\240\021\330\004\023\320\023(\250\001\330\010\034\230A\230T\240\021\330\010\027\220q\230\001\330\010%\240Q\330\004\030\230\004\230G\2401\330\010'\240t\250;\260b\270\004\270A\330\004\026\320\026'\240~\260Q\260a\330\004\010\210\r\220_\240O\260;\270a\330\020\021\330\010\027\220{\240!\330\014\031\230\025\230k\250\021\250)\2605\270\013\3001\300A\330\004\023\220;\230a\330\004\025\220[\240\001\330\004\026\220a\330\004\030\230\001\330\004 \240\r\250Q\330\010%\240W\250A\250Z\260s\270!\360\006\000\005\022\220\021\360\006\000\005\t\210\017\220\177\240k\260\021\330\014\"\240,\250f\260N\300!\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\330\020\021\330\020\022\220!\320\023%\240Q\240n\260B\260a\360\010\000\t\r\210F\220%\220q\230\001\330\014\026\220b\230\001\230\021\330\014\020\220\006\220e\2301\230A\330\020\032\230\"\230A\230Q\360\010\000\021\036\320\0356\260d\270!\2709\300A\330\020\023\2208\2301\230L\250\001\330\024\025\340\020\023\320\0232\260$\260a\330\030!\240\031\250#\250Q\330\024\025\360\006\000\021\025\220N\240!\330\030 \240\003\2409\250A\330\030 \240\003\2401\330\024\025\360\006\000\021%\240A\330\020\"\240!\330\020\024\220G\2305\240\001\240\021\330\024\033\2307\240!\240;\250a\250q\330\024\033\2307\240!\240;\250a\250q\340\024\030\230\005\230R\230r\240\023\240E\250\023\250N\270!\330\034!\240\022\2402\240S\250\005\250S\260\001\330\030\033\2304\230q\340\034.\250a\330""\034\035\360\006\000\035\036\330\024\037\320\0378\270\004\270A\270V\3001\330\024\027\220x\230q\240\n\250!\330\030\033\2304\230q\340\034.\250a\330\034\035\360\006\000\035\036\330\024\027\220y\240\002\240!\340\030,\250A\330\030\031\340\020\023\320\023%\240S\250\001\340\024\025\360\010\000\021\035\230E\240\037\260\001\260\031\270!\330\020/\250t\2601\260I\270Y\300a\330\020'\240q\360\020\000\021 \230q\330\020\026\220d\230,\240f\250A\330\024\033\230<\240v\250R\250q\330\024\033\230<\240v\250R\250q\330\024 \240\004\240A\330\024\030\320\030-\250R\250r\260\021\330\034)\250\022\2501\340\030\036\230f\240A\330\034\035\340\030\036\230d\240,\250f\260A\330\034(\250\004\250A\330\030/\250q\330\030\031\330\024$\240A\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\037\230t\2401\330 7\260q\330\034\035\340\030#\320#<\270D\300\001\330\034\"\240!\330\030\033\2308\2401\240J\250a\330\034\037\230t\2401\330 7\260q\330\034\035\330\030\033\2309\240B\240a\330\0343\2601\330\034\035\340\030\033\320\033:\270$\270a\330 &\240f\250C\250q\340\034\035\330\030\033\2309\240C\240q\360\006\000\035)\250\005\250Q\330./\250v\260Q\330\034;\2704\270q\330 &\240f\250A\340\020\023\2204\220q\340\024%\240Q\330\030$\240I\250Q\330\034'\240s\250(\260#\260\\\300\021\330\034$\240C\240q\330\024\"\240!\330\024+\2504\250q\330\030!\240\031\250!\330\024\035\230U\240!\2401\360\n\000\021\036\230Q\330\020\036\230a\330\020\037\230q\330\020\026\220d\230)\2406\250\021\330\024\034\230I\240T\250\021\330\024\035\230T\240\021\330\024\033\2305\240\001\330\024\033\2305\240\001\360\006\000\025\031\320\030-\250R\250r\260\021\330\034)\250\022\2501\340\030\036\230f\240A\330\034\035\340\030$\320$8\270\001\330\030/\250q\330\030\031\330\024$\240A\360\006\000\025#\240%\240q\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401""\240K\250q\260\001\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\340\034\037\230t\2401\330 -\250Q\330 !\340 !\340\030\033\320\0332\260$\260a\330 &\240f\250C\250q\340\034\035\340\030/\250t\2601\260F\270&\300\001\340\030#\320#<\270D\300\001\300\026\300q\330\030\034\230N\250$\250e\2603\260a\330 $\240E\250\023\250A\330\034*\250!\330\034)\250\021\330\034\035\340\030\033\2308\2401\240J\250a\360\006\000\035 \230t\2401\360\006\000!.\250Q\340\034\035\330\030\033\2309\240B\240a\360\006\000\035*\250\021\330\034\035\360\010\000\031*\250\021\330\034&\240f\250A\330 +\2503\250e\2603\260l\300!\330 %\240S\250\001\330\030!\240\025\240a\240q\340\024\027\220q\340\030$\320$8\270\001\360\020\000\031#\240%\240\177\260a\260y\300\001\330\0301\260\024\260Q\330\034%\240Y\250a\360\006\000\021\027\220d\230*\240F\250!\330\024\033\230:\240V\2502\250Q\330\024\033\230:\240V\2502\250Q\330\024\036\230d\240!\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\330\030#\320#<\270D\300\001\300\026\300q\330\030\033\2308\2401\240J\250a\330\034\035\330\030\033\2309\240B\240a\330\0345\260T\270\021\330 &\240f\250A\330\034&\240e\250?\270!\2706\300\021\340\004\033\2306\240\021\330\004#\2406\250\021\330\004\035\230V\2401\330\004\n\210'\220\021\220!\330\004\n\210%\210q\220\001\200\001\360\010\000\t\n\330\010\t\360V\001\000\005\025\220H\230H\240A\330\010\017\210q\330\010\014\210B\210e\2205\230\001\330\014\016\210e\2208\2301\230A\330\004!\240\022\2405\250\005\250Q\250o\270Q\330\004\036\230b\240\005\240U\250!\250?\270!\360\010\000\005$\2401\330\010&\240a\330\010\t\340\004\n\210)\2201\330\010$\240B\240a\240q\360\010\000\005 \230}\250A\330\010\"\240'\250\021\250*\260C\260q\330\004\034\230M\250\021\330\010\037\230w\240a\240z\260\023\260A\330\004!\240\035\250a\330\010$\240A\240R\240w\250a""\250q\330\010$\240A\240T\250\021\340\004\025\220_\320$4\260A\330\010\t\330\004!\240\036\250q\260\t\270\021\270!\360\006\000\005\r\210I\220^\2401\240A\340\004\023\220>\240\021\240!\340\004\010\210\004\210D\220\004\220D\230\005\230Q\340\004\007\200~\220Q\220a\330\010\030\230\003\320\033,\250A\330\010\025\220^\2401\240N\260!\2601\340\010\030\230\001\330\004\022\220$\320\026&\240a\240q\340\004\007\200r\210\025\210g\220Q\220a\330\010\016\210h\220a\330\014\016\210a\210q\340\010\n\210'\220\021\220!\330\004\027\220{\240'\250\021\330\010/\250s\260#\260S\270\004\270A\330\004\031\230\022\2305\240\t\250\021\250\"\250E\260\031\270!\330\010.\250a\250q\330\004\026\320\026&\240l\260!\330\010\034\230O\2503\250a\330\004\023\220<\230q\240\003\240:\250Q\250n\270C\270q\330\004\023\220<\230q\330\010\013\210:\220Q\320\026*\250#\250Q\330\004\023\220<\230q\240\003\240:\250Q\250l\270#\270Q\330\004\023\220<\230q\240\003\240:\250Q\250l\270#\270Q\330\004\023\320\023$\240A\360\020\000\005!\240\005\240Q\240a\340\004\024\220D\230\007\230q\320 =\270T\300\021\330\004\023\220=\240\t\250\021\360\006\000\005\030\220{\240,\250a\250q\330\004\010\320\010\032\230!\330\010\017\210s\220!\220>\240\031\250!\2501\330\010\017\210s\220!\220>\240\031\250!\2501\330\010\030\230\002\230&\240\006\240g\250Q\330\014\032\230'\240\021\340\004\020\220\r\230Q\360\006\000\005\031\230\001\360\010\000\005\021\320\020#\2401\240A\340\004\010\210\003\210>\230\026\230q\240\001\330\r\016\210i\220q\230\n\240!\2407\250$\250d\260%\260q\330\014\024\220A\330\010\030\230\001\230\021\330\010\035\230Q\330\010\016\210a\330\014\032\230-\240r\250\021\330\014\033\2304\230q\240\001\330\014\036\230l\250+\260Q\260a\340\014\023\2203\220a\220\177\240i\250q\260\001\330\014\023\2203\220a\220\177\240i\250q\260\001\330\014\025\220S\230\001\230\037\250\t\260\021\260!\330\014\025\220S\230\001\230\037\250\t\260\021\260!\340\014\036\230f\240A\330\014\034\230A\330\020\024\220D\230\007\320\037/\250q\260\001\330\020\023\2204\220w\230a\330\014\017\210q\330""\020\035\230W\240A\240Q\340\020\035\230T\240\021\360\010\000\021\025\220O\2409\250A\250Y\260b\270\002\270!\330\030\034\230A\330\024\027\220q\340\030)\250\027\260\002\260-\270v\300Q\360\006\000\031*\250\027\260\001\330\035*\250(\260!\330\020\023\220?\240)\2501\250J\260c\270\021\360\006\000\025\034\2303\230a\230\177\250i\260q\270\001\330\024\033\2303\230a\230\177\250i\260q\270\001\330\024\027\220t\2301\360\010\000\031*\250\024\250Q\330\024%\240W\250B\250m\2706\300\021\340\004B\300!\360\006\000\005-\250A\340\004\010\210\010\220\014\230E\240\030\250\031\260!\2601\330\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\022\220%\220q\330\020\021\330\020\022\220\"\220E\230\021\230#\230Q\320\0361\260\021\260#\260Q\330\014\034\230E\240\021\240!\330\010\024\220F\320\0322\260$\260a\260u\270A\330\010\013\210:\220T\230\021\330\014\r\330\010\030\230\002\230%\230q\330\010\021\220\026\320\027,\250D\260\001\260\025\260a\330\010\023\2201\330\010\023\2201\340\010\035\230S\240\t\250\021\250#\250Q\330\010\026\220e\320\0335\260T\270\021\270%\270q\360\010\000\t\017\210c\220\021\220!\330\010\016\210c\220\021\220!\340\010\017\210{\230!\230<\240q\250\001\330\010\017\210{\230!\230<\240q\250\001\330\010\013\210<\220r\230\022\2303\230a\340\014\023\220;\230a\230|\2501\250A\330\014\023\220;\230a\230|\2501\250A\340\010\r\210V\2204\320\027)\250\021\250.\270\005\270Q\330\010\032\230)\2401\240E\250\021\360\010\000\t\022\220\032\2303\230a\360\006\000\t\014\210<\220r\230\022\2303\230a\340\014\030\230\001\330\014\030\230\001\230\021\230+\240R\240q\360\010\000\r\035\230K\240q\250\003\2502\250Q\330\014\030\230\001\330\014\030\230\014\240A\240S\250\002\250!\330\014\017\210}\230A\330\024\031\230\025\230n\250K\260q\330\024\034\230A\330\024.\250a\330\020\035\230Y\240a\240s\250\"\250A\330\020\034\230H\240A\240S\250\002\250!\330\020\027\220{\240!\2401\330\020\027\220{\240!\2401\340\020\035\230W\240B\240e\2501\340\010\022\220!\330\010\033\2301\330\010\t\340\014\023\220;\230a\230q\330\014\023\220;\230a""\230q\330\014\027\220{\240!\2401\330\014\027\220{\240!\2401\360\006\000\r\023\220#\220R\220r\230\021\230$\230b\240\002\240!\2401\330\014\022\220#\220R\220r\230\021\230$\230b\240\002\240!\2401\330\014\036\230i\240q\250\005\250Q\330\014\027\220q\330\014\017\210x\220r\230\021\330\020\026\220h\230a\230q\330\020#\2401\330\020\021\330\014\017\210t\2202\220R\220s\230$\230b\240\002\240#\240T\250\023\250G\2603\260d\270#\270Q\360\006\000\021\027\220l\240!\330\024\026\220a\220v\230Q\230a\330\024\026\220a\220x\230q\240\001\330\014\017\210z\230\024\230X\240Q\240c\250\022\2503\250c\260\021\340\020\027\220q\330\020\031\230\024\230Q\230c\240\022\2401\330\020#\2401\360\006\000\021\031\230\001\330\020\030\230\t\240\021\240!\330\020$\240A\330\014\026\220m\2401\330\020\025\220U\230&\240\013\2508\2608\2701\330\020*\250!\330\014\027\220}\240A\330\020\025\220U\230'\240\033\250H\260H\270A\330\020*\250!\330\014\017\210q\340\020\032\230!\330\020\035\230Y\240a\320'9\270\022\2701\330\020\033\2301\340\020\027\220{\240!\2401\330\020\027\220{\240!\2401\330\020#\2401\330\024\031\230\025\230a\330\024\037\230x\240q\330\024\025\330\024\025\330\021\022\340\020\027\220{\240!\2401\330\020\027\220{\240!\2401\340\020\035\230W\240B\240e\2501\360\006\000\021\035\230A\330\020\034\230J\240b\320(:\270\"\270A\340\014\017\210x\220s\230\"\230D\240\010\250\003\2501\340\020\021\340\010\034\230C\230x\240q\250\017\260}\300A\330\010\034\230C\230y\250\001\250\023\250A\330\010\031\230\034\240Q\240a\330\010\031\230\034\240Q\240a\330\010\031\230\031\240!\240>\260\021\330\010\031\230\031\240!\320#7\260q\330\010\031\230\031\240!\240<\250q\330\010\031\230\031\240!\240<\250q\330\010\027\220~\240Q\240a\360\n\000\t\r\210L\230\016\240a\330\014$\240D\250\001\250\034\260]\300!\330\004\023\320\023%\240Q\330\004\026\220a\330\004\027\220q\330\004\034\230F\240!\330\004\031\230\026\230q\330\004\036\230f\240A\330\004\n\210'\220\021\220!\330\004\n\210%\210q\330\010\t\200\001\360\006\000\t\n\330%&\360X\002\000\005\025\220E\230\021\230!""\360\010\000\005\027\220o\320%5\260Q\3206J\310!\3101\330\004\022\220/\240\021\240)\2501\320,@\300\001\300\022\3001\300A\330\004\007\200|\2207\230!\340\010\025\220U\230(\240!\2401\360\006\000\t\026\220Q\360\006\000\005\024\320\023#\240?\260!\2601\360\006\000\005\023\220!\360\006\000\005\006\330\010\013\210<\220w\230a\330\014\016\210i\220q\230\001\330\013\014\340\004\027\220x\230x\240q\330\010\014\210M\230\027\320 2\260\"\260D\270\t\300\021\330\014!\240\024\240W\250A\360\n\000\005\035\230B\230e\2405\250\001\330\010\032\230!\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!8\270\004\270A\330\010\t\210\021\330\010%\240Q\330\004&\240m\2601\330\010\035\230W\240A\240Z\250s\260!\340\004\026\220a\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!7\260t\2701\330\010\t\210\021\330\010%\240Q\330\004\036\230m\2501\330\010\034\230G\2401\240J\250c\260\021\360\014\000\005\035\230B\230e\2405\250\001\330\010\032\230!\330\004\023\320\023(\250\001\330\010\034\230A\230T\320!8\270\004\270A\330\010\n\210$\320\016\036\230a\230~\250R\250q\330\010%\240Q\330\004&\240m\2601\330\010\035\230W\240A\240Z\250s\260!\360\010\000\005'\240a\330\004\025\320\025'\240\177\260a\260q\330\004\010\320\010\030\230\003\320\033+\2502\250S\260\003\2603\260a\330\014\034\230C\320\037/\250r\260\023\260C\260q\330\010\016\210h\220a\220q\330\010\t\330\014\016\210e\2205\230\001\320\031+\2501\330\014 \240\001\240\021\330\010\030\230\004\320\034,\250A\320-I\310\021\310!\330\010\025\220T\230\027\240\001\320!5\260Q\260d\270$\270a\330\010\025\220[\240\001\330\014+\2501\250D\260\001\330\014\024\320\0240\260\001\260\021\330\010\025\220Q\330\010\016\210e\2201\220A\340\010*\250!\330\004\031\230\035\240a\330\010'\240q\250\002\250'\260\021\260!\330\010'\240q\250\004\250A\360\006\000\005\022\220\024\220W\230A\330\010'\240q\250\004\250D\260\001\330\004\017\210z\230\036\240q\320(G\300q\310\001\360\006\000\005\t\210\017\220\177\240k\260\021\330\014-\250\\\270\021\330\014\032\230!\330\010\024\220K\230q\240\001\330\010\024""\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\330\020\021\330\020\022\220!\320\023%\240Q\240m\2601\260A\360\010\000\t\034\2305\240\006\240a\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010\030\230\006\230a\360\006\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010\030\230\001\230\023\230D\240\003\2406\250\030\260\034\270Q\330\022'\240w\250a\250u\260A\360\006\000\t\021\220\001\330\010\020\220\001\360\006\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\036\320\036.\250a\250t\2601\330\020\023\2208\2301\230M\250\021\330\024\025\360\n\000\021\033\230\"\230A\230Q\230a\230q\330\020\032\230\"\230A\230Q\230a\230q\340\020\023\320\023*\250$\250a\330\030!\240\031\250#\250Q\340\024\025\360\n\000\021&\240Q\330\020 \240\001\340\020\024\220G\2305\240\001\240\021\330\024\033\2302\230Q\230k\250\021\250!\330\024\033\2302\230Q\230k\250\021\250!\330\024\037\320\037/\250q\260\006\260a\330\024\027\220x\230q\240\n\250!\330\030\031\330\024\036\230l\250\"\250A\330\024\027\220t\2302\230Q\340\030#\2401\330\024\027\220x\230r\240\021\330\030,\250A\330\030(\250\001\340\020\023\320\023%\240S\250\001\340\024+\2504\250q\330\030!\240\031\250!\330\024\025\360\010\000\021\035\230E\240\037\260\001\260\031\270!\330\020/\250t\2601\260I\270Y\300a\360\014\000\021\027\220d\230,\240f\250A\330\024\033\230<\240v\250R\250q\330\024\033\230<\240v\250R\250q\330\024 \240\004\240A\340\024)\250\021\330\024$\240A\330\024&\240a\330\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034'\240q\340\034'\320'9\270\024\270Q\270f\300A""\330\030\033\2308\2401\240J\250a\330\034\037\320\037/\250t\260>\300\023\300A\330 4\260A\330 2\260$\260b\270\001\330\034\035\330\030\"\240,\250b\260\001\330\030\033\2308\2402\240Q\330\034\035\330\030\033\2308\2403\240a\330\034\037\320\037>\270d\300!\330$*\250&\260\003\2601\360\006\000!-\250E\260\037\300\001\300\026\300q\330 ?\270t\3001\330$*\250&\260\001\330\034\035\330\030\033\2304\230r\240\021\330\034'\240q\330\030\033\2308\2402\240Q\330\034,\250A\330\0340\260\001\340\024\027\320\027)\250\023\250A\330\030\033\230>\250\022\2501\340\0343\2604\260q\330 &\240f\250A\330\034;\2704\270q\330 &\240f\250A\330\034'\240u\250O\2701\270F\300!\360\006\000\035/\250e\2601\330./\250v\260Q\330\0341\260\025\260a\260q\360\006\000\021\024\220;\230f\240A\360\010\000\025\033\230$\320\0360\260\006\260a\330\030\037\320\0371\260\026\260r\270\021\330\030\037\320\0371\260\026\260r\270\021\330\030/\250t\2601\330\034\"\240&\320(=\270V\3001\330\0307\260t\2701\270F\300&\310\001\330\030#\2405\250\001\320);\2706\300\021\330\030-\250T\260\021\330\030*\250$\250a\360\006\000\025-\250L\270\001\330\024)\320)<\270A\360\010\000\021\027\220d\230+\240V\2501\330\024\033\230;\240f\250B\250a\330\024\033\230;\240f\250B\250a\330\024\037\230t\2401\340\024%\320%D\300D\310\001\330\030\036\230a\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\340\030+\250?\270!\330\034%\240T\250\022\2507\260!\340\030\033\320\033-\250T\260\021\330 &\240f\250C\250|\2701\330 ?\270t\3001\330$*\250&\260\002\260!\360\006\000\0354\2604\260q\330 &\240f\250N\270!\2701\330\034;\2704\270q\330 &\240f\250A\330\034'\240u\250O\2701\270F\300!\330\004\017\210q\330\004\021\220\021\330\004\033\2306\240\021\330\004#\2406\250\021\330\004\026\220f\230A\330\004#\2406\250\021\330\004\n\210'\220\021\220!\330\004\n\210%\210q\220\001\200\001\360\006\000\t'\240a\330\010\t\330%&\360P""\002\000\005!\240\001\360\034\000\005\025\220E\230\021\230!\340\004\007\200t\320\013)\250\021\250!\330\010\016\210j\230\001\330\014E\300Q\330\020\021\330\004\007\320\007\037\230t\2404\320'E\300Q\330\014\r\330\010\016\210j\230\001\330\014E\300Q\330\020\021\340\004\030\230\001\330\004\023\320\023(\250\001\330\010!\240\021\240$\240a\330\010\014\210N\230!\2301\330\010%\240Q\330\004 \240\r\250Q\330\010%\240W\250A\250Z\260s\270!\340\004\036\230m\2501\330\010!\240\021\240\"\240G\2501\250A\330\010!\240\021\240$\240a\330\004\026\220d\230'\240\021\330\010!\240\021\240$\240d\250!\330\004\024\220O\240>\260\021\330\010!\240\021\240!\360\006\000\005\010\200q\330\010\030\230\r\240Q\330\014#\2401\240B\240g\250Q\250a\330\014#\2401\240D\250\001\330\010\034\230O\320+;\2701\330\014#\2401\240C\240q\250\t\260\021\330\020'\240q\250\002\250!\2501\330\010\013\320\013\035\230W\240A\330\014\034\230A\340\004)\250\021\330\004(\250\001\330\004\036\230a\340\004\007\320\007\033\2307\240!\330\010\"\240!\330\010\013\210:\220Q\320\026,\250E\260\021\330\014\033\2301\330\014%\240Q\340\014\017\210t\320\0231\260\021\260!\330\020\026\220j\240\001\330\024M\310Q\330\030\031\330\014*\250-\260q\330\020#\2401\240B\240g\250Q\250a\330\020#\2401\240D\250\001\330\014'\240\177\3206F\300a\330\020#\2401\240C\240q\250\t\260\021\260!\330\014\017\320\017(\250\003\2501\330\020&\240e\2501\250A\340\020&\240a\340\004\033\230?\320*:\270!\330\010!\240\021\240!\330\004\023\320\023#\320#7\260q\270\001\340\004\032\320\032.\250a\250y\270\001\330\010!\240\021\240\"\240A\240Q\330\004\007\320\007\033\2303\230a\330\010\032\230!\340\010\032\230!\360\010\000\005-\250A\330\004\010\210\017\220\177\240k\260\021\330\014'\240|\2606\270\036\300q\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\320\030@\300\006\300b\310\016""\320VX\320XY\330\020\036\230b\240\001\360\006\000\t!\240\005\240V\2501\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010\035\230V\2401\360\006\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010\035\230Q\230c\240\024\240S\250\006\250m\270<\300q\330\022'\240w\250a\250u\260A\360\006\000\t\021\220\001\330\010\020\220\001\360\n\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\033\320\0330\260\001\260\024\260Q\330\020\023\2209\230C\230q\330\024\025\340\020\027\220r\230\021\230+\240Q\240a\330\020\027\220r\230\021\230+\240Q\240a\340\020\023\320\023(\250\001\250\026\250v\260S\270\001\330\024\036\230b\240\001\240\021\240!\2401\330\024\036\230b\240\001\240\021\240!\2401\340\024\027\220q\330\030%\240X\250]\270$\270a\330\034%\240Q\330\030\033\2308\2401\240L\260\001\330\034)\250\021\340\030%\240Q\330\024 \240\005\240Q\330-.\250i\260y\300\003\3001\3303B\300!\360\010\000\021\027\220d\320\032-\250V\2601\330\024'\240t\2501\340\020\026\220d\230,\240f\250A\330\024!\240\034\250T\260\021\330\024 \240\004\240A\360\006\000\025\033\230$\320\0361\260\026\260q\330\0302\3202E\300V\3101\330\030+\2504\250q\330\030\033\320\0332\260/\300\022\320CZ\320Z[\330\034&\320&6\260e\2701\270A\340\024-\250Q\330\024\030\230\007\230u\240A\240Z\320/?\270q\330\030\037\230z\250\023\250A\250[\270\001\270\021\330\030\037\230z\250\023\250A\250[\270\001\270\021\330\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\340\034\035\330\030,\250E\3201H\310\004\310A\330\034\"\240!\330\030\033\320\033-\250S\3200@\300\001\330 2\260#\260^\3001\300A\340\034\035\340\030.\250a\330\0345\260T\270\021\270&\300\001\330\030\033\2308\2401\320$9\270\021\360\006\000\035 \230q\330 -\250X\260]\300$\300a\330$*\250!\330 #\2408\2501\250L\270\001\330$1\260\021\340 -\250Q\330\034\037\230q\330 *\320*:\270%\270q\33012\260!\3302=\270R\270q\360\006\000""\035'\320&7\260q\330\034(\250\005\250Q\250a\330\034(\250\005\250Q\33056\260f\270F\300#\300Q\330;J\310!\330\0345\260Q\330\034\035\340\030\033\2304\230q\330\034&\240j\260\001\340\024\027\220t\2301\360\010\000\031\034\2301\330\034\037\230q\330 <\270A\340 !\330$?\270t\3001\300J\310e\320S]\320]^\340 #\2408\2501\320,G\300q\330$@\300\001\340\034\"\240$\240j\3200@\300\006\300a\330 0\260\n\320:J\310&\320PQ\330 *\320*:\270$\270a\330 -\320-?\270q\330 *\250*\260M\300\021\330 3\2605\270\001\270\021\340\0301\260\024\260Q\330\034&\240e\250:\260Q\330\034&\240a\330\004\035\230V\2401\330\004\033\2306\240\021\330\004\007\200q\330\010\013\2104\210q\330\014'\240v\250Q\330\004\007\200q\330\010\025\220V\2301\330\004\n\210%\210q\320\0208\270\001\200\001\360\010\000\t\n\330%&\360r\001\000\005!\240\001\360\014\000\005\025\220E\230\021\230!\340\004\010\210\010\220\001\330\014*\250!\330\014\r\330\010\013\2105\220\007\220u\230D\240\004\320$B\300!\3001\330\014\022\220*\230A\330\020I\310\021\330\024\025\340\004\027\220q\330\004\023\320\023(\250\001\330\010$\240A\240Q\330\010\t\330\010\014\210N\230!\2301\330\010%\240Q\330\004)\250\035\260a\330\010.\250g\260Q\260j\300\003\3001\360\006\000\005\010\200q\330\010\030\230\r\240Q\330\014#\2401\240B\240g\250Q\250a\330\014#\2401\240D\250\001\330\010\034\230O\320+;\2701\330\014#\2401\240C\240q\250\t\260\021\330\020'\240q\250\002\250!\2501\330\010\013\320\013\035\230W\240A\330\014\034\230A\340\004\035\230]\250!\330\010 \240\001\240\022\2407\250!\2501\330\010 \240\001\240\024\240Q\340\004!\240\035\250a\330\010$\240A\240R\240w\250a\250q\330\010$\240A\240T\250\021\330\004\025\220T\230\027\240\001\320!9\270\021\270$\270d\300!\330\004\023\220>\240\036\250q\3200H\310\001\310\021\340\004\033\230?\320*:\270!\330\010$\240A\240Q\330\004\023\320\023#\320#7\260q\270\001\360\006\000\005\t\210\017\220\177\240k\260\021\330\014&\240l\260&\270\016\300a\330\010\024\220K\230q\240\001\330\010\024\220K\230q\240\001\330\010\017\210{\230!\2301\330\010\017\210{\230!\2301\340\010""\013\2105\220\001\220\026\220r\230\036\240r\250\021\330\014\034\230E\240\021\240!\330\014\034\230E\240\022\2405\250\002\250!\330\014\022\220%\220q\320\030>\270f\300B\300n\320TV\320VW\330\020\036\230b\240\001\360\006\000\t \230u\240F\250!\330\r\030\230\001\230\034\240Q\240c\250\033\260A\260\\\300\021\300!\330\014\022\220%\220q\330\010\034\230F\240!\360\010\000\t\n\210\024\210T\220\024\220U\320\0321\3201F\300a\330\014\031\230\037\250\001\330\010\034\230A\230S\240\004\240C\240v\250\\\270\034\300Q\330\016#\2407\250!\2505\260\001\360\006\000\t\021\220\001\330\010\020\220\001\360\006\000\t\r\210F\220%\220q\230\003\2309\240A\240Q\330\014\020\220\006\220e\2301\230C\230y\250\001\250\021\330\020\023\320\023'\240q\250\004\250D\260\003\2601\340\024\025\340\020)\250\025\250a\330\035\036\230e\2402\240Q\240d\250!\2503\250b\260\001\260\024\260Q\260c\270\021\340\020\026\220d\320\0323\2606\270\021\330\024\033\320\0334\260D\270\002\270!\330\024\033\320\0334\260D\270\002\270!\330\024 \320 9\270\024\270R\270q\330\024-\250T\260\021\340\0246\260d\270!\330\030\036\230f\240A\340\024\030\230\007\230u\240A\240Q\330\030\037\230t\2401\240K\250q\260\001\330\030\037\230t\2401\240K\250q\260\001\340\030\034\230E\240\022\2402\240S\250\005\250S\260\016\270a\330 %\240R\240r\250\023\250E\260\023\260A\330\034\035\340\030\033\320\0331\260\024\260Q\260f\270F\300#\300Q\360\006\000\035\036\340\030\034\320\0346\260d\270!\2706\300\026\300q\330 .\250a\250q\360\014\000\035 \230q\330 -\250]\270$\270a\270v\300Q\330 #\2408\2501\250L\270\001\330$1\260\021\340 .\250i\260t\2702\270W\300A\340\0345\260U\270!\330)*\330$/\250r\260\033\270F\300&\310\001\340\004&\240f\250A\330\004\036\230f\240A\330\004\032\230&\240\001\330\004\007\200q\330\010\025\220V\2301\200\001\340\004\007\200t\210:\220Q\320\026)\250\026\250q\330\010\017\210q\330\t\014\210A\320\r\037\230s\240!\330\010\017\210q\330\t\r\210Z\220q\320\030(\250\001\250\024\250Q\330\010\017\210q\330\t\r\210Z\220q\320\030(\250\001\250\024\250Q\330\010\017\210q\340\010\017""\210q\200\001\360$\000\005\022\220\036\230w\240a\330\004\007\200{\220#\220Q\330\010\031\320\0312\260!\330\014\r\330\010\014\320\014%\240Q\240a\330\010\013\210?\230#\230Q\330\014&\240a\330\020\037\230w\240a\240q\330\004\007\200{\220#\220Q\330\010\014\320\014&\240a\330\014\r\330\004\020\220\016\230a\230q";
    PyObject *data = NULL;
    CYTHON_UNUSED_VAR(__Pyx_DecompressString);
    #endif
    PyObject **stringtab = __pyx_mstate->__pyx_string_tab;
    Py_ssize_t pos = 0;
    for (int i = 0; i < 671; i++) {
      Py_ssize_t bytes_length = index[i].length;
      PyObject *string = PyUnicode_DecodeUTF8(bytes + pos, bytes_length, NULL);
      if (likely(string) && i >= 92) PyUnicode_InternInPlace(&string);
      if (unlikely(!string)) {
        Py_XDECREF(data);
        __PYX_ERR(0, 1, __pyx_L1_error)
      }
      stringtab[i] = string;
      pos += bytes_length;
    }
    for (int i = 671; i < 687; i++) {
      Py_ssize_t bytes_length = index[i].length;
      PyObject *string = PyBytes_FromStringAndSize(bytes + pos, bytes_length);
      stringtab[i] = string;
      pos += bytes_length;
      if (unlikely(!string)) {
        Py_XDECREF(data);
        __PYX_ERR(0, 1, __pyx_L1_error)
      }
    }
    Py_XDECREF(data);
    for (Py_ssize_t i = 0; i < 687; i++) {
      if (unlikely(PyObject_Hash(stringtab[i]) == -1)) {
        __PYX_ERR(0, 1, __pyx_L1_error)
      }
    }
    #if CYTHON_IMMORTAL_CONSTANTS
    {
      PyObject **table = stringtab + 671;
      for (Py_ssize_t i=0; i<16; ++i) {
        #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
        #if PY_VERSION_HEX < 0x030E0000
        if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)
        #else
        if (PyUnstable_Object_IsUniquelyReferenced(table[i]))
        #endif
        {
          Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);
        }
        #else
        Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);
        #endif
      }
    }
    #endif
  }
  {
    PyObject **numbertab = __pyx_mstate->__pyx_number_tab;
    double const c_constants[] = {1.25,100.0};
    for (int i = 0; i < 2; i++) {
      numbertab[i] = PyFloat_FromDouble(c_constants[i]);
      if (unlikely(!numbertab[i])) __PYX_ERR(0, 1, __pyx_L1_error)
    }
  }
  {
    PyObject **numbertab = __pyx_mstate->__pyx_number_tab + 2;
    int8_t const cint_constants_1[] = {0,-1,1,2,100};
    int32_t const cint_constants_4[] = {1000000L};
    for (int i = 0; i < 6; i++) {
      numbertab[i] = PyLong_FromLong((i < 5 ? cint_constants_1[i - 0] : cint_constants_4[i - 5]));
      if (unlikely(!numbertab[i])) __PYX_ERR(0, 1, __pyx_L1_error)
    }
  }
  #if CYTHON_IMMORTAL_CONSTANTS
  {
    PyObject **table = __pyx_mstate->__pyx_number_tab;
    for (Py_ssize_t i=0; i<8; ++i) {
      #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      #if PY_VERSION_HEX < 0x030E0000
      if (_Py_IsOwnedByCurrentThread(table[i]) && Py_REFCNT(table[i]) == 1)
      #else
      if (PyUnstable_Object_IsUniquelyReferenced(table[i]))
      #endif
      {
        Py_SET_REFCNT(table[i], _Py_IMMORTAL_REFCNT_LOCAL);
      }
      #else
      Py_SET_REFCNT(table[i], _Py_IMMORTAL_INITIAL_REFCNT);
      #endif
    }
  }
  #endif
  return 0;
  __pyx_L1_error:;
  return -1;
}
/* #### Code section: init_codeobjects ### */
typedef struct {
    unsigned int argcount : 4;
    unsigned int num_posonly_args : 1;
    unsigned int num_kwonly_args : 1;
    unsigned int nlocals : 7;
    unsigned int flags : 10;
    unsigned int first_line : 13;
} __Pyx_PyCode_New_function_description;
/* NewCodeObj.proto */
static PyObject* __Pyx_PyCode_New(
        const __Pyx_PyCode_New_function_description descr,
        PyObject * const *varnames,
        PyObject *filename,
        PyObject *funcname,
        PyObject *line_table,
        PyObject *tuple_dedup_map
);


static int __Pyx_CreateCodeObjects(__pyx_mstatetype *__pyx_mstate) {
  PyObject* tuple_dedup_map = PyDict_New();
  if (unlikely(!tuple_dedup_map)) return -1;
  {
    const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 8, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 183};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_target_offset_dict};
    __pyx_mstate_global->__pyx_codeobj_tab[0] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_generate_read_bounds, __pyx_mstate->__pyx_kp_b_iso88591_E_82Q_Q_a_1_82Q_Q_a_1_1HBk_r_Q, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[0])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {6, 0, 0, 56, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 227};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_dem_raster_path_band, __pyx_mstate->__pyx_n_u_target_filled_dem_raster_path, __pyx_mstate->__pyx_n_u_working_dir, __pyx_mstate->__pyx_n_u_max_pixel_fill_count, __pyx_mstate->__pyx_n_u_single_outlet_tuple, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_q, __pyx_mstate->__pyx_n_u_yi_q, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_downhill_neighbor, __pyx_mstate->__pyx_n_u_nodata_neighbor, __pyx_mstate->__pyx_n_u_natural_drain_exists, __pyx_mstate->__pyx_n_u_search_steps, __pyx_mstate->__pyx_n_u_search_queue, __pyx_mstate->__pyx_n_u_fill_queue, __pyx_mstate->__pyx_n_u_pixel, __pyx_mstate->__pyx_n_u_pit_queue, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_n_x_blocks, __pyx_mstate->__pyx_n_u_center_val, __pyx_mstate->__pyx_n_u_dem_nodata, __pyx_mstate->__pyx_n_u_fill_height, __pyx_mstate->__pyx_n_u_feature_id, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_single_outlet, __pyx_mstate->__pyx_n_u_outlet_x, __pyx_mstate->__pyx_n_u_outlet_y, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_dem_raster_info, __pyx_mstate->__pyx_n_u_base_nodata, __pyx_mstate->__pyx_n_u_mask_nodata, __pyx_mstate->__pyx_n_u_working_dir_path, __pyx_mstate->__pyx_n_u_flat_region_mask_path, __pyx_mstate->__pyx_n_u_flat_region_mask_managed_raster, __pyx_mstate->__pyx_n_u_pit_mask_path, __pyx_mstate->__pyx_n_u_pit_mask_managed_raster, __pyx_mstate->__pyx_n_u_base_datatype, __pyx_mstate->__pyx_n_u_filled_dem_raster, __pyx_mstate->__pyx_n_u_filled_dem_band, __pyx_mstate->__pyx_n_u_offset_info, __pyx_mstate->__pyx_n_u_block_array, __pyx_mstate->__pyx_n_u_filled_dem_managed_raster, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_n_height, __pyx_mstate->__pyx_n_u_pour_point};
    __pyx_mstate_global->__pyx_codeobj_tab[1] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_fill_pits_2, __pyx_mstate->__pyx_kp_b_iso88591_Q_7_Q_E_o_5Q6J_1_1_1A_7_U_1_Q_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[1])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 58, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 674};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_dem_raster_path_band, __pyx_mstate->__pyx_n_u_target_flow_dir_path, __pyx_mstate->__pyx_n_u_working_dir, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_dem_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_q, __pyx_mstate->__pyx_n_u_yi_q, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_root_height, __pyx_mstate->__pyx_n_u_n_height, __pyx_mstate->__pyx_n_u_dem_nodata, __pyx_mstate->__pyx_n_u_drain_distance, __pyx_mstate->__pyx_n_u_n_drain_distance, __pyx_mstate->__pyx_n_u_diagonal_nodata, __pyx_mstate->__pyx_n_u_search_queue, __pyx_mstate->__pyx_n_u_drain_queue, __pyx_mstate->__pyx_n_u_nodata_drain_queue, __pyx_mstate->__pyx_n_u_nodata_flow_dir_queue, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_dem_raster_info, __pyx_mstate->__pyx_n_u_base_nodata, __pyx_mstate->__pyx_n_u_mask_nodata, __pyx_mstate->__pyx_n_u_working_dir_path, __pyx_mstate->__pyx_n_u_flat_region_mask_path, __pyx_mstate->__pyx_n_u_flat_region_mask_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_plateau_distance_path, __pyx_mstate->__pyx_n_u_plateau_distance_managed_raster, __pyx_mstate->__pyx_n_u_compatable_dem_raster_path_band, __pyx_mstate->__pyx_n_u_dem_block_xsize, __pyx_mstate->__pyx_n_u_dem_block_ysize, __pyx_mstate->__pyx_n_u_raster_driver, __pyx_mstate->__pyx_n_u_dem_raster, __pyx_mstate->__pyx_n_u_dem_managed_raster, __pyx_mstate->__pyx_n_u_dem_band, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict, __pyx_mstate->__pyx_n_u_largest_slope_dir, __pyx_mstate->__pyx_n_u_largest_slope, __pyx_mstate->__pyx_n_u_n_slope};
    __pyx_mstate_global->__pyx_codeobj_tab[2] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_flow_dir_d8_2, __pyx_mstate->__pyx_kp_b_iso88591_X_E_o_5Q6J_1_1_1A_7_U_1_Q_1_wa, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[2])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {6, 0, 0, 56, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1044};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_raster_path_band, __pyx_mstate->__pyx_n_u_target_flow_accum_raster_path, __pyx_mstate->__pyx_n_u_weight_raster_path_band, __pyx_mstate->__pyx_n_u_custom_decay_factor, __pyx_mstate->__pyx_n_u_min_decay_proportion, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_flow_dir_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_flow_dir, __pyx_mstate->__pyx_n_u_upstream_flow_dir, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_upstream_flow_accum, __pyx_mstate->__pyx_n_u_weight_val, __pyx_mstate->__pyx_n_u_weight_nodata, __pyx_mstate->__pyx_n_u_search_stack, __pyx_mstate->__pyx_n_u_flow_pixel, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_flow_accum_nodata, __pyx_mstate->__pyx_n_u_flow_accum_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_raster, __pyx_mstate->__pyx_n_u_flow_dir_band, __pyx_mstate->__pyx_n_u_weight_raster, __pyx_mstate->__pyx_n_u_raw_weight_nodata, __pyx_mstate->__pyx_n_u_do_decayed_accumulation, __pyx_mstate->__pyx_n_u_use_const_decay_factor, __pyx_mstate->__pyx_n_u_decay_factor, __pyx_mstate->__pyx_n_u_decay_factor_nodata, __pyx_mstate->__pyx_n_u_decay_factor_managed_raster, __pyx_mstate->__pyx_n_u_tmp_decay_factor_nodata, __pyx_mstate->__pyx_n_u_flow_dir_raster_info, __pyx_mstate->__pyx_n_u_tmp_flow_dir_nodata, __pyx_mstate->__pyx_n_u_decay_from_upstream, __pyx_mstate->__pyx_n_u_upstream_transport_factor, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict, __pyx_mstate->__pyx_n_u_upstream_decaying_value, __pyx_mstate->__pyx_n_u_upstream_pixels_remain, __pyx_mstate->__pyx_n_u_decayed_value};
    __pyx_mstate_global->__pyx_codeobj_tab[3] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_flow_accumulation_d8, __pyx_mstate->__pyx_kp_b_iso88591_a_P_E_t_j_EQ_t4_EQ_j_EQ_a_N_1_Q, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[3])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 69, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1362};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_dem_raster_path_band, __pyx_mstate->__pyx_n_u_target_flow_dir_path, __pyx_mstate->__pyx_n_u_working_dir, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_dem_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_q, __pyx_mstate->__pyx_n_u_yi_q, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_root_height, __pyx_mstate->__pyx_n_u_n_height, __pyx_mstate->__pyx_n_u_dem_nodata, __pyx_mstate->__pyx_n_u_n_slope, __pyx_mstate->__pyx_n_u_drain_distance, __pyx_mstate->__pyx_n_u_n_drain_distance, __pyx_mstate->__pyx_n_u_drain_search_queue, __pyx_mstate->__pyx_n_u_downhill_slope_array, __pyx_mstate->__pyx_n_u_nodata_downhill_slope_array, __pyx_mstate->__pyx_n_u_working_downhill_slope_array, __pyx_mstate->__pyx_n_u_sum_of_slope_weights, __pyx_mstate->__pyx_n_u_sum_of_nodata_slope_weights, __pyx_mstate->__pyx_n_u_compressed_integer_slopes, __pyx_mstate->__pyx_n_u_distance_drain_queue, __pyx_mstate->__pyx_n_u_nodata_distance_drain_queue, __pyx_mstate->__pyx_n_u_direction_drain_queue, __pyx_mstate->__pyx_n_u_nodata_flow_dir_queue, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_dem_raster_info, __pyx_mstate->__pyx_n_u_base_nodata, __pyx_mstate->__pyx_n_u_mask_nodata, __pyx_mstate->__pyx_n_u_working_dir_path, __pyx_mstate->__pyx_n_u_flat_region_mask_path, __pyx_mstate->__pyx_n_u_flat_region_mask_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_plateu_drain_mask_path, __pyx_mstate->__pyx_n_u_plateau_drain_mask_managed_raste, __pyx_mstate->__pyx_n_u_plateau_distance_path, __pyx_mstate->__pyx_n_u_plateau_distance_nodata, __pyx_mstate->__pyx_n_u_plateau_distance_managed_raster, __pyx_mstate->__pyx_n_u_compatable_dem_raster_path_band, __pyx_mstate->__pyx_n_u_dem_block_xsize, __pyx_mstate->__pyx_n_u_dem_block_ysize, __pyx_mstate->__pyx_n_u_raster_driver, __pyx_mstate->__pyx_n_u_dem_raster, __pyx_mstate->__pyx_n_u_dem_managed_raster, __pyx_mstate->__pyx_n_u_dem_band, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict, __pyx_mstate->__pyx_n_u_sum_of_downhill_slopes, __pyx_mstate->__pyx_n_u_working_downhill_slope_sum, __pyx_mstate->__pyx_n_u__4, __pyx_mstate->__pyx_n_u_n_distance};
    __pyx_mstate_global->__pyx_codeobj_tab[4] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_flow_dir_mfd, __pyx_mstate->__pyx_kp_b_iso88591_45_B_E_o_5Q6J_1_1_1A_7_U_1_Q_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[4])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 51, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 1860};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_mfd_raster_path_band, __pyx_mstate->__pyx_n_u_target_flow_accum_raster_path, __pyx_mstate->__pyx_n_u_weight_raster_path_band, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_flow_dir_mfd_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_visit_count, __pyx_mstate->__pyx_n_u_pixel_count, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_i_upstream_flow, __pyx_mstate->__pyx_n_u_flow_dir_mfd, __pyx_mstate->__pyx_n_u_upstream_flow_weight, __pyx_mstate->__pyx_n_u_compressed_upstream_flow_dir, __pyx_mstate->__pyx_n_u_upstream_flow_dir_sum, __pyx_mstate->__pyx_n_u_upstream_flow_accum, __pyx_mstate->__pyx_n_u_flow_accum_nodata, __pyx_mstate->__pyx_n_u_weight_nodata, __pyx_mstate->__pyx_n_u_weight_val, __pyx_mstate->__pyx_n_u_search_stack, __pyx_mstate->__pyx_n_u_flow_pixel, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_flow_accum_managed_raster, __pyx_mstate->__pyx_n_u_tmp_dir_root, __pyx_mstate->__pyx_n_u_tmp_dir, __pyx_mstate->__pyx_n_u_visited_raster_path, __pyx_mstate->__pyx_n_u_visited_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_raster, __pyx_mstate->__pyx_n_u_flow_dir_band, __pyx_mstate->__pyx_n_u_weight_raster, __pyx_mstate->__pyx_n_u_raw_weight_nodata, __pyx_mstate->__pyx_n_u_flow_dir_raster_info, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict, __pyx_mstate->__pyx_n_u_preempted};
    __pyx_mstate_global->__pyx_codeobj_tab[5] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_flow_accumulation_mfd, __pyx_mstate->__pyx_kp_b_iso88591_B_A_E_t_j_EQ_t4_EQ_j_EQ_Qd_N_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[5])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {5, 0, 0, 41, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 2146};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_d8_raster_path_band, __pyx_mstate->__pyx_n_u_channel_raster_path_band, __pyx_mstate->__pyx_n_u_target_distance_to_channel_raste, __pyx_mstate->__pyx_n_u_weight_raster_path_band, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_channel_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_q, __pyx_mstate->__pyx_n_u_yi_q, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_distance_to_channel_stack, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_weight_val, __pyx_mstate->__pyx_n_u_pixel_val, __pyx_mstate->__pyx_n_u_weight_nodata, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_path, __pyx_mstate->__pyx_n_u_distance_nodata, __pyx_mstate->__pyx_n_u_distance_to_channel_managed_rast, __pyx_mstate->__pyx_n_u_weight_raster, __pyx_mstate->__pyx_n_u_raw_weight_nodata, __pyx_mstate->__pyx_n_u_channel_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_d8_managed_raster, __pyx_mstate->__pyx_n_u_channel_raster, __pyx_mstate->__pyx_n_u_channel_band, __pyx_mstate->__pyx_n_u_flow_dir_raster_info, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict};
    __pyx_mstate_global->__pyx_codeobj_tab[6] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_distance_to_channel_d8, __pyx_mstate->__pyx_kp_b_iso88591_r_E_5_uD_B_1_A_I_q_AQ_N_1_Q_a_g, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[6])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {5, 0, 0, 52, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 2346};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_mfd_raster_path_band, __pyx_mstate->__pyx_n_u_channel_raster_path_band, __pyx_mstate->__pyx_n_u_target_distance_to_channel_raste, __pyx_mstate->__pyx_n_u_weight_raster_path_band, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_channel_buffer_array, __pyx_mstate->__pyx_n_u_flow_dir_buffer_array, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_flow_dir_weight, __pyx_mstate->__pyx_n_u_mfd_value, __pyx_mstate->__pyx_n_u_is_a_channel, __pyx_mstate->__pyx_n_u_distance_to_channel_stack, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_weight_val, __pyx_mstate->__pyx_n_u_weight_nodata, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_path, __pyx_mstate->__pyx_n_u_distance_nodata, __pyx_mstate->__pyx_n_u_distance_to_channel_managed_rast, __pyx_mstate->__pyx_n_u_channel_managed_raster, __pyx_mstate->__pyx_n_u_tmp_work_dir, __pyx_mstate->__pyx_n_u_visited_raster_path, __pyx_mstate->__pyx_n_u_visited_managed_raster, __pyx_mstate->__pyx_n_u_flow_dir_mfd_managed_raster, __pyx_mstate->__pyx_n_u_channel_raster, __pyx_mstate->__pyx_n_u_channel_band, __pyx_mstate->__pyx_n_u_flow_dir_mfd_raster, __pyx_mstate->__pyx_n_u_flow_dir_mfd_band, __pyx_mstate->__pyx_n_u_weight_raster, __pyx_mstate->__pyx_n_u_raw_weight_nodata, __pyx_mstate->__pyx_n_u_flow_dir_raster_info, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_xa, __pyx_mstate->__pyx_n_u_xb, __pyx_mstate->__pyx_n_u_ya, __pyx_mstate->__pyx_n_u_yb, __pyx_mstate->__pyx_n_u_modified_offset_dict, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_pixel, __pyx_mstate->__pyx_n_u_preempted, __pyx_mstate->__pyx_n_u_n_distance};
    __pyx_mstate_global->__pyx_codeobj_tab[7] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_distance_to_channel_mfd, __pyx_mstate->__pyx_kp_b_iso88591_12_x_E_1_5_uD_B_1_A_I_q_Qa_N_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[7])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {6, 0, 0, 46, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 2679};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_accum_raster_path_band, __pyx_mstate->__pyx_n_u_flow_dir_mfd_path_band, __pyx_mstate->__pyx_n_u_flow_threshold, __pyx_mstate->__pyx_n_u_target_stream_raster_path, __pyx_mstate->__pyx_n_u_trace_threshold_proportion, __pyx_mstate->__pyx_n_u_raster_driver_creation_tuple, __pyx_mstate->__pyx_n_u_flow_accum_info, __pyx_mstate->__pyx_n_u_flow_accum_nodata, __pyx_mstate->__pyx_n_u_stream_nodata, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_flow_accum_mr, __pyx_mstate->__pyx_n_u_stream_mr, __pyx_mstate->__pyx_n_u_flow_dir_mfd_mr, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_i_sn, __pyx_mstate->__pyx_n_u_xi_sn, __pyx_mstate->__pyx_n_u_yi_sn, __pyx_mstate->__pyx_n_u_flow_dir_mfd, __pyx_mstate->__pyx_n_u_flow_accum, __pyx_mstate->__pyx_n_u_trace_flow_threshold, __pyx_mstate->__pyx_n_u_n_iterations, __pyx_mstate->__pyx_n_u_is_outlet, __pyx_mstate->__pyx_n_u_stream_val, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_open_set, __pyx_mstate->__pyx_n_u_backtrace_set, __pyx_mstate->__pyx_n_u_xi_bn, __pyx_mstate->__pyx_n_u_yi_bn, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_block_offsets, __pyx_mstate->__pyx_n_u_block_offsets_list, __pyx_mstate->__pyx_n_u_stream_raster, __pyx_mstate->__pyx_n_u_stream_band, __pyx_mstate->__pyx_n_u_stream_array};
    __pyx_mstate_global->__pyx_codeobj_tab[8] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_extract_streams_mfd, __pyx_mstate->__pyx_kp_b_iso88591_N_Bc_DBa_j_A_o_5Q_1A_O1IQ_1Baq, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[8])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 1, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 2887};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_raster_path_band};
    __pyx_mstate_global->__pyx_codeobj_tab[9] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_is_raster_path_band_formatted, __pyx_mstate->__pyx_kp_b_iso88591_t_Q_q_q_A_s_q_Zq_Q_q_Zq_Q_q_q, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[9])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {9, 0, 0, 113, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 2901};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_d8_raster_path_band, __pyx_mstate->__pyx_n_u_flow_accum_raster_path_band, __pyx_mstate->__pyx_n_u_dem_raster_path_band, __pyx_mstate->__pyx_n_u_target_stream_vector_path, __pyx_mstate->__pyx_n_u_min_flow_accum_threshold, __pyx_mstate->__pyx_n_u_river_order, __pyx_mstate->__pyx_n_u_min_p_val, __pyx_mstate->__pyx_n_u_autotune_flow_accumulation, __pyx_mstate->__pyx_n_u_osr_axis_mapping_strategy, __pyx_mstate->__pyx_n_u_flow_dir_info, __pyx_mstate->__pyx_n_u_flow_dir_srs, __pyx_mstate->__pyx_n_u_gpkg_driver, __pyx_mstate->__pyx_n_u_stream_vector, __pyx_mstate->__pyx_n_u_stream_basename, __pyx_mstate->__pyx_n_u_stream_layer, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_flow_accum_managed_raster, __pyx_mstate->__pyx_n_u_dem_managed_raster, __pyx_mstate->__pyx_n_u_flow_nodata, __pyx_mstate->__pyx_n_u_flow_accum_nodata, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_i, __pyx_mstate->__pyx_n_u_j, __pyx_mstate->__pyx_n_u_d, __pyx_mstate->__pyx_n_u_d_n, __pyx_mstate->__pyx_n_u_n_cols, __pyx_mstate->__pyx_n_u_n_rows, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_n_pixels, __pyx_mstate->__pyx_n_u_n_processed, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_source_point_stack, __pyx_mstate->__pyx_n_u_source_stream_point, __pyx_mstate->__pyx_n_u_x_l, __pyx_mstate->__pyx_n_u_y_l, __pyx_mstate->__pyx_n_u_x_n, __pyx_mstate->__pyx_n_u_y_n, __pyx_mstate->__pyx_n_u_upstream_count, __pyx_mstate->__pyx_n_u_upstream_index, __pyx_mstate->__pyx_n_u_upstream_dirs, __pyx_mstate->__pyx_n_u_local_flow_accum, __pyx_mstate->__pyx_n_u_is_drain, __pyx_mstate->__pyx_n_u_coord_to_stream_ids, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_stream_feature, __pyx_mstate->__pyx_n_u_stream_fid, __pyx_mstate->__pyx_n_u_n_points, __pyx_mstate->__pyx_n_u_downstream_to_upstream_ids, __pyx_mstate->__pyx_n_u_upstream_to_downstream_id, __pyx_mstate->__pyx_n_u_payload, __pyx_mstate->__pyx_n_u_x_u, __pyx_mstate->__pyx_n_u_y_u, __pyx_mstate->__pyx_n_u_ds_x_1, __pyx_mstate->__pyx_n_u_ds_y_1, __pyx_mstate->__pyx_n_u_upstream_id_list, __pyx_mstate->__pyx_n_u_stream_line, __pyx_mstate->__pyx_n_u_downstream_dem, __pyx_mstate->__pyx_n_u_upstream_id, __pyx_mstate->__pyx_n_u_upstream_dem, __pyx_mstate->__pyx_n_u_drop_distance, __pyx_mstate->__pyx_n_u_streams_to_process, __pyx_mstate->__pyx_n_u_base_feature_count, __pyx_mstate->__pyx_n_u_outlet_fid_list, __pyx_mstate->__pyx_n_u_downstream_fid, __pyx_mstate->__pyx_n_u_downstream_feature, __pyx_mstate->__pyx_n_u_connected_upstream_fids, __pyx_mstate->__pyx_n_u_stream_order_list, __pyx_mstate->__pyx_n_u_all_defined, __pyx_mstate->__pyx_n_u_upstream_fid, __pyx_mstate->__pyx_n_u_upstream_feature, __pyx_mstate->__pyx_n_u_upstream_order, __pyx_mstate->__pyx_n_u_sorted_stream_order_list, __pyx_mstate->__pyx_n_u_downstream_order, __pyx_mstate->__pyx_n_u_working_river_id, __pyx_mstate->__pyx_n_u_outlet_index, __pyx_mstate->__pyx_n_u_outlet_fid, __pyx_mstate->__pyx_n_u_search_stack, __pyx_mstate->__pyx_n_u_feature_id, __pyx_mstate->__pyx_n_u_stream_order, __pyx_mstate->__pyx_n_u_upstream_stack, __pyx_mstate->__pyx_n_u_streams_by_order, __pyx_mstate->__pyx_n_u_drop_distance_collection, __pyx_mstate->__pyx_n_u_max_upstream_flow_accum, __pyx_mstate->__pyx_n_u_order, __pyx_mstate->__pyx_n_u_working_flow_accum_threshold, __pyx_mstate->__pyx_n_u_test_order, __pyx_mstate->__pyx_n_u__4, __pyx_mstate->__pyx_n_u_p_val, __pyx_mstate->__pyx_n_u_streams_to_retest, __pyx_mstate->__pyx_n_u_ds_x, __pyx_mstate->__pyx_n_u_ds_y, __pyx_mstate->__pyx_n_u_upstream_d8_dir, __pyx_mstate->__pyx_n_u_working_stack, __pyx_mstate->__pyx_n_u_fid_to_order, __pyx_mstate->__pyx_n_u_processed_segments, __pyx_mstate->__pyx_n_u_segments_to_process, __pyx_mstate->__pyx_n_u_deleted_set, __pyx_mstate->__pyx_n_u_working_fid, __pyx_mstate->__pyx_n_u_upstream_fid_list, __pyx_mstate->__pyx_n_u_order_count, __pyx_mstate->__pyx_n_u_working_order, __pyx_mstate->__pyx_n_u_working_feature, __pyx_mstate->__pyx_n_u_connected_fids, __pyx_mstate->__pyx_n_u_downstream_geom, __pyx_mstate->__pyx_n_u_working_geom, __pyx_mstate->__pyx_n_u_multi_line, __pyx_mstate->__pyx_n_u_joined_line, __pyx_mstate->__pyx_n_u_upstream_all_defined, __pyx_mstate->__pyx_n_u_connected_fid, __pyx_mstate->__pyx_n_u_stream_feature, __pyx_mstate->__pyx_n_u_fid};
    __pyx_mstate_global->__pyx_codeobj_tab[10] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_extract_strahler_streams_d8, __pyx_mstate->__pyx_kp_b_iso88591_F_O_31_AQ_AQ_s_1_N_1A_q_aq_Kwa, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[10])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 33, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 3590};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_d8_raster_path_band, __pyx_mstate->__pyx_n_u_target_discovery_raster_path, __pyx_mstate->__pyx_n_u_target_finish_raster_path, __pyx_mstate->__pyx_n_u_flow_dir_info, __pyx_mstate->__pyx_n_u_n_cols, __pyx_mstate->__pyx_n_u_n_rows, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_discovery_managed_raster, __pyx_mstate->__pyx_n_u_finish_managed_raster, __pyx_mstate->__pyx_n_u_discovery_stack, __pyx_mstate->__pyx_n_u_finish_stack, __pyx_mstate->__pyx_n_u_raster_coord, __pyx_mstate->__pyx_n_u_finish_coordinate, __pyx_mstate->__pyx_n_u_discovery_count, __pyx_mstate->__pyx_n_u_n_processed, __pyx_mstate->__pyx_n_u_n_pixels, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_n_pushed, __pyx_mstate->__pyx_n_u_i, __pyx_mstate->__pyx_n_u_j, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_x_l, __pyx_mstate->__pyx_n_u_y_l, __pyx_mstate->__pyx_n_u_x_n, __pyx_mstate->__pyx_n_u_y_n, __pyx_mstate->__pyx_n_u_n_dir, __pyx_mstate->__pyx_n_u_test_dir, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_d_n};
    __pyx_mstate_global->__pyx_codeobj_tab[11] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_build_discovery_finish_rasters, __pyx_mstate->__pyx_kp_b_iso88591_O_31_AQ_I_1_Qiq_ARq_m1_ARwaq_AT, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[11])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {5, 0, 0, 82, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 3729};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_d8_flow_dir_raster_path_band, __pyx_mstate->__pyx_n_u_strahler_stream_vector_path, __pyx_mstate->__pyx_n_u_target_watershed_boundary_vector, __pyx_mstate->__pyx_n_u_max_steps_per_watershed, __pyx_mstate->__pyx_n_u_outlet_at_confluence, __pyx_mstate->__pyx_n_u_workspace_dir, __pyx_mstate->__pyx_n_u_discovery_time_raster_path, __pyx_mstate->__pyx_n_u_finish_time_raster_path, __pyx_mstate->__pyx_n_u_discovery_managed_raster, __pyx_mstate->__pyx_n_u_finish_managed_raster, __pyx_mstate->__pyx_n_u_d8_flow_dir_managed_raster, __pyx_mstate->__pyx_n_u_discovery_info, __pyx_mstate->__pyx_n_u_discovery_nodata, __pyx_mstate->__pyx_n_u_n_cols, __pyx_mstate->__pyx_n_u_n_rows, __pyx_mstate->__pyx_n_u_geotransform, __pyx_mstate->__pyx_n_u_g0, __pyx_mstate->__pyx_n_u_g1, __pyx_mstate->__pyx_n_u_g2, __pyx_mstate->__pyx_n_u_g3, __pyx_mstate->__pyx_n_u_g4, __pyx_mstate->__pyx_n_u_g5, __pyx_mstate->__pyx_n_u_discovery_srs, __pyx_mstate->__pyx_n_u_gpkg_driver, __pyx_mstate->__pyx_n_u_watershed_vector, __pyx_mstate->__pyx_n_u_watershed_basename, __pyx_mstate->__pyx_n_u_watershed_layer, __pyx_mstate->__pyx_n_u_x_l, __pyx_mstate->__pyx_n_u_y_l, __pyx_mstate->__pyx_n_u_outflow_dir, __pyx_mstate->__pyx_n_u_x_f, __pyx_mstate->__pyx_n_u_y_f, __pyx_mstate->__pyx_n_u_x_p, __pyx_mstate->__pyx_n_u_y_p, __pyx_mstate->__pyx_n_u_discovery, __pyx_mstate->__pyx_n_u_finish, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_stream_vector, __pyx_mstate->__pyx_n_u_stream_layer, __pyx_mstate->__pyx_n_u_upstream_fid_map, __pyx_mstate->__pyx_n_u_stream_feature, __pyx_mstate->__pyx_n_u_ds_x, __pyx_mstate->__pyx_n_u_ds_y, __pyx_mstate->__pyx_n_u_visit_order_stack, __pyx_mstate->__pyx_n_u__4, __pyx_mstate->__pyx_n_u_outlet_fid, __pyx_mstate->__pyx_n_u_working_stack, __pyx_mstate->__pyx_n_u_processed_nodes, __pyx_mstate->__pyx_n_u_working_fid, __pyx_mstate->__pyx_n_u_working_feature, __pyx_mstate->__pyx_n_u_us_x, __pyx_mstate->__pyx_n_u_us_y, __pyx_mstate->__pyx_n_u_ds_x_1, __pyx_mstate->__pyx_n_u_ds_y_1, __pyx_mstate->__pyx_n_u_upstream_coord, __pyx_mstate->__pyx_n_u_upstream_fids, __pyx_mstate->__pyx_n_u_edge_side, __pyx_mstate->__pyx_n_u_edge_dir, __pyx_mstate->__pyx_n_u_cell_to_test, __pyx_mstate->__pyx_n_u_out_dir_increase, __pyx_mstate->__pyx_n_u_left, __pyx_mstate->__pyx_n_u_right, __pyx_mstate->__pyx_n_u_n_steps, __pyx_mstate->__pyx_n_u_terminated_early, __pyx_mstate->__pyx_n_u_delta_x, __pyx_mstate->__pyx_n_u_delta_y, __pyx_mstate->__pyx_n_u_int_max_steps_per_watershed, __pyx_mstate->__pyx_n_u_index, __pyx_mstate->__pyx_n_u_stream_fid, __pyx_mstate->__pyx_n_u_boundary_list, __pyx_mstate->__pyx_n_u_outlet_x, __pyx_mstate->__pyx_n_u_outlet_y, __pyx_mstate->__pyx_n_u_watershed_boundary, __pyx_mstate->__pyx_n_u_left_in, __pyx_mstate->__pyx_n_u_right_in, __pyx_mstate->__pyx_n_u_out_dir, __pyx_mstate->__pyx_n_u_watershed_feature, __pyx_mstate->__pyx_n_u_watershed_polygon, __pyx_mstate->__pyx_n_u_boundary_x, __pyx_mstate->__pyx_n_u_boundary_y, __pyx_mstate->__pyx_n_u_x, __pyx_mstate->__pyx_n_u_fid};
    __pyx_mstate_global->__pyx_codeobj_tab[12] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_calculate_subwatershed_boundary_4, __pyx_mstate->__pyx_kp_b_iso88591_V_HHA_q_Be5_e81A_5_QoQ_b_U_1_a, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[12])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {1, 0, 0, 27, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4071};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_dem_raster_path_band, __pyx_mstate->__pyx_n_u_lowest_drain_height, __pyx_mstate->__pyx_n_u_lowest_sink_height, __pyx_mstate->__pyx_n_u_drain_pixel, __pyx_mstate->__pyx_n_u_sink_pixel, __pyx_mstate->__pyx_n_u_dem_raster_info, __pyx_mstate->__pyx_n_u_dem_nodata, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_dem_managed_raster, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_offset_dict, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_center_val, __pyx_mstate->__pyx_n_u_pixel_drains, __pyx_mstate->__pyx_n_u_i_n, __pyx_mstate->__pyx_n_u_xi_n, __pyx_mstate->__pyx_n_u_yi_n, __pyx_mstate->__pyx_n_u_n_height};
    __pyx_mstate_global->__pyx_codeobj_tab[13] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_detect_lowest_drain_and_sink, __pyx_mstate->__pyx_kp_b_iso88591_H_e1_U_o_5Q_AQ_ay_G1__AYaq_Q_1, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[13])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {3, 0, 0, 40, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4196};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_flow_dir_raster_path_band, __pyx_mstate->__pyx_n_u_flow_dir_type, __pyx_mstate->__pyx_n_u_target_outlet_vector_path, __pyx_mstate->__pyx_n_u_d8_flow_dir_mode, __pyx_mstate->__pyx_n_u_xoff, __pyx_mstate->__pyx_n_u_yoff, __pyx_mstate->__pyx_n_u_win_xsize, __pyx_mstate->__pyx_n_u_win_ysize, __pyx_mstate->__pyx_n_u_xi, __pyx_mstate->__pyx_n_u_yi, __pyx_mstate->__pyx_n_u_xi_root, __pyx_mstate->__pyx_n_u_yi_root, __pyx_mstate->__pyx_n_u_raster_x_size, __pyx_mstate->__pyx_n_u_raster_y_size, __pyx_mstate->__pyx_n_u_flow_dir, __pyx_mstate->__pyx_n_u_flow_dir_n, __pyx_mstate->__pyx_n_u_next_id, __pyx_mstate->__pyx_n_u_n_dir, __pyx_mstate->__pyx_n_u_is_outlet, __pyx_mstate->__pyx_n_u_x_off_border, __pyx_mstate->__pyx_n_u_y_off_border, __pyx_mstate->__pyx_n_u_win_xsize_border, __pyx_mstate->__pyx_n_u_win_ysize_border, __pyx_mstate->__pyx_n_u_flow_dir_block, __pyx_mstate->__pyx_n_u_raster_info, __pyx_mstate->__pyx_n_u_flow_dir_nodata, __pyx_mstate->__pyx_n_u_flow_dir_raster, __pyx_mstate->__pyx_n_u_flow_dir_band, __pyx_mstate->__pyx_n_u_raster_srs, __pyx_mstate->__pyx_n_u_gpkg_driver, __pyx_mstate->__pyx_n_u_outlet_vector, __pyx_mstate->__pyx_n_u_outet_basename, __pyx_mstate->__pyx_n_u_outlet_layer, __pyx_mstate->__pyx_n_u_last_log_time, __pyx_mstate->__pyx_n_u_block_offsets, __pyx_mstate->__pyx_n_u_current_pixel, __pyx_mstate->__pyx_n_u_outlet_point, __pyx_mstate->__pyx_n_u_proj_x, __pyx_mstate->__pyx_n_u_proj_y, __pyx_mstate->__pyx_n_u_outlet_feature};
    __pyx_mstate_global->__pyx_codeobj_tab[14] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_detect_outlets, __pyx_mstate->__pyx_kp_b_iso88591_M_q_XV1_j_q_s_Q_1_9A_AQ_aq_d_d, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[14])) goto bad;
  }
  {
    const __Pyx_PyCode_New_function_description descr = {4, 0, 0, 6, (unsigned int)(CO_OPTIMIZED|CO_NEWLOCALS), 4635};
    PyObject* const varnames[] = {__pyx_mstate->__pyx_n_u_stream_feature, __pyx_mstate->__pyx_n_u_stream_layer, __pyx_mstate->__pyx_n_u_upstream_to_downstream_id, __pyx_mstate->__pyx_n_u_downstream_to_upstream_ids, __pyx_mstate->__pyx_n_u_stream_fid, __pyx_mstate->__pyx_n_u_downstream_fid};
    __pyx_mstate_global->__pyx_codeobj_tab[15] = __Pyx_PyCode_New(descr, varnames, __pyx_mstate->__pyx_kp_u_src_pygeoprocessing_routing_rout, __pyx_mstate->__pyx_n_u_delete_feature, __pyx_mstate->__pyx_kp_b_iso88591_wa_Q_2_Qa_Q_a_waq_Q_a_aq, tuple_dedup_map); if (unlikely(!__pyx_mstate_global->__pyx_codeobj_tab[15])) goto bad;
  }
  Py_DECREF(tuple_dedup_map);
  return 0;
  bad:
  Py_DECREF(tuple_dedup_map);
  return -1;
}
/* #### Code section: init_globals ### */

static int __Pyx_InitGlobals(void) {
  /* PythonCompatibility.init */
  if (likely(__Pyx_init_co_variables() == 0)); else
  
  if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error)

  /* CommonTypesMetaclass.init */
  if (likely(__pyx_CommonTypesMetaclass_init(__pyx_m) == 0)); else
  
  if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error)

  /* CachedMethodType.init */
  #if CYTHON_COMPILING_IN_LIMITED_API
  {
      PyObject *typesModule=NULL;
      typesModule = PyImport_ImportModule("types");
      if (typesModule) {
          __pyx_mstate_global->__Pyx_CachedMethodType = PyObject_GetAttrString(typesModule, "MethodType");
          Py_DECREF(typesModule);
      }
  } // error handling follows
  #endif
  
  if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error)

  /* CythonFunctionShared.init */
  if (likely(__pyx_CyFunction_init(__pyx_m) == 0)); else
  
  if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L1_error)

  return 0;
  __pyx_L1_error:;
  return -1;
}
/* #### Code section: cleanup_globals ### */
/* #### Code section: cleanup_module ### */
/* #### Code section: main_method ### */
/* #### Code section: utility_code_pragmas ### */
#ifdef _MSC_VER
#pragma warning( push )
/* Warning 4127: conditional expression is constant
 * Cython uses constant conditional expressions to allow in inline functions to be optimized at
 * compile-time, so this warning is not useful
 */
#pragma warning( disable : 4127 )
#endif



/* #### Code section: utility_code_def ### */

/* --- Runtime support code --- */
/* Refnanny */
#if CYTHON_REFNANNY
static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
    PyObject *m = NULL, *p = NULL;
    void *r = NULL;
    m = PyImport_ImportModule(modname);
    if (!m) goto end;
    p = PyObject_GetAttrString(m, "RefNannyAPI");
    if (!p) goto end;
    r = PyLong_AsVoidPtr(p);
end:
    Py_XDECREF(p);
    Py_XDECREF(m);
    return (__Pyx_RefNannyAPIStruct *)r;
}
#endif

/* PyErrExceptionMatches (used by PyObjectGetAttrStrNoError) */
#if CYTHON_FAST_THREAD_STATE
static int __Pyx_PyErr_ExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
    Py_ssize_t i, n;
    n = PyTuple_GET_SIZE(tuple);
    for (i=0; i<n; i++) {
        if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
    }
    for (i=0; i<n; i++) {
        if (__Pyx_PyErr_GivenExceptionMatches(exc_type, PyTuple_GET_ITEM(tuple, i))) return 1;
    }
    return 0;
}
static CYTHON_INLINE int __Pyx_PyErr_ExceptionMatchesInState(PyThreadState* tstate, PyObject* err) {
    int result;
    PyObject *exc_type;
#if PY_VERSION_HEX >= 0x030C00A6
    PyObject *current_exception = tstate->current_exception;
    if (unlikely(!current_exception)) return 0;
    exc_type = (PyObject*) Py_TYPE(current_exception);
    if (exc_type == err) return 1;
#else
    exc_type = tstate->curexc_type;
    if (exc_type == err) return 1;
    if (unlikely(!exc_type)) return 0;
#endif
    #if CYTHON_AVOID_BORROWED_REFS
    Py_INCREF(exc_type);
    #endif
    if (unlikely(PyTuple_Check(err))) {
        result = __Pyx_PyErr_ExceptionMatchesTuple(exc_type, err);
    } else {
        result = __Pyx_PyErr_GivenExceptionMatches(exc_type, err);
    }
    #if CYTHON_AVOID_BORROWED_REFS
    Py_DECREF(exc_type);
    #endif
    return result;
}
#endif

/* PyErrFetchRestore (used by PyObjectGetAttrStrNoError) */
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
#if PY_VERSION_HEX >= 0x030C00A6
    PyObject *tmp_value;
    assert(type == NULL || (value != NULL && type == (PyObject*) Py_TYPE(value)));
    if (value) {
        #if CYTHON_COMPILING_IN_CPYTHON
        if (unlikely(((PyBaseExceptionObject*) value)->traceback != tb))
        #endif
            PyException_SetTraceback(value, tb);
    }
    tmp_value = tstate->current_exception;
    tstate->current_exception = value;
    Py_XDECREF(tmp_value);
    Py_XDECREF(type);
    Py_XDECREF(tb);
#else
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    tmp_type = tstate->curexc_type;
    tmp_value = tstate->curexc_value;
    tmp_tb = tstate->curexc_traceback;
    tstate->curexc_type = type;
    tstate->curexc_value = value;
    tstate->curexc_traceback = tb;
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
#endif
}
static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
#if PY_VERSION_HEX >= 0x030C00A6
    PyObject* exc_value;
    exc_value = tstate->current_exception;
    tstate->current_exception = 0;
    *value = exc_value;
    *type = NULL;
    *tb = NULL;
    if (exc_value) {
        *type = (PyObject*) Py_TYPE(exc_value);
        Py_INCREF(*type);
        #if CYTHON_COMPILING_IN_CPYTHON
        *tb = ((PyBaseExceptionObject*) exc_value)->traceback;
        Py_XINCREF(*tb);
        #else
        *tb = PyException_GetTraceback(exc_value);
        #endif
    }
#else
    *type = tstate->curexc_type;
    *value = tstate->curexc_value;
    *tb = tstate->curexc_traceback;
    tstate->curexc_type = 0;
    tstate->curexc_value = 0;
    tstate->curexc_traceback = 0;
#endif
}
#endif

/* PyObjectGetAttrStr (used by PyObjectGetAttrStrNoError) */
#if CYTHON_USE_TYPE_SLOTS
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
    PyTypeObject* tp = Py_TYPE(obj);
    if (likely(tp->tp_getattro))
        return tp->tp_getattro(obj, attr_name);
    return PyObject_GetAttr(obj, attr_name);
}
#endif

/* PyObjectGetAttrStrNoError (used by GetBuiltinName) */
#if __PYX_LIMITED_VERSION_HEX < 0x030d0000
static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) {
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
        __Pyx_PyErr_Clear();
}
#endif
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) {
    PyObject *result;
#if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
    (void) PyObject_GetOptionalAttr(obj, attr_name, &result);
    return result;
#else
#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS
    PyTypeObject* tp = Py_TYPE(obj);
    if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) {
        return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1);
    }
#endif
    result = __Pyx_PyObject_GetAttrStr(obj, attr_name);
    if (unlikely(!result)) {
        __Pyx_PyObject_GetAttrStr_ClearAttributeError();
    }
    return result;
#endif
}

/* GetBuiltinName */
static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
    PyObject* result = __Pyx_PyObject_GetAttrStrNoError(__pyx_mstate_global->__pyx_b, name);
    if (unlikely(!result) && !PyErr_Occurred()) {
        PyErr_Format(PyExc_NameError,
            "name '%U' is not defined", name);
    }
    return result;
}

/* GetTopmostException (used by SaveResetException) */
#if CYTHON_USE_EXC_INFO_STACK && CYTHON_FAST_THREAD_STATE
static _PyErr_StackItem *
__Pyx_PyErr_GetTopmostException(PyThreadState *tstate)
{
    _PyErr_StackItem *exc_info = tstate->exc_info;
    while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&
           exc_info->previous_item != NULL)
    {
        exc_info = exc_info->previous_item;
    }
    return exc_info;
}
#endif

/* SaveResetException */
#if CYTHON_FAST_THREAD_STATE
static CYTHON_INLINE void __Pyx__ExceptionSave(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) {
  #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
    _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
    PyObject *exc_value = exc_info->exc_value;
    if (exc_value == NULL || exc_value == Py_None) {
        *value = NULL;
        *type = NULL;
        *tb = NULL;
    } else {
        *value = exc_value;
        Py_INCREF(*value);
        *type = (PyObject*) Py_TYPE(exc_value);
        Py_INCREF(*type);
        *tb = PyException_GetTraceback(exc_value);
    }
  #elif CYTHON_USE_EXC_INFO_STACK
    _PyErr_StackItem *exc_info = __Pyx_PyErr_GetTopmostException(tstate);
    *type = exc_info->exc_type;
    *value = exc_info->exc_value;
    *tb = exc_info->exc_traceback;
    Py_XINCREF(*type);
    Py_XINCREF(*value);
    Py_XINCREF(*tb);
  #else
    *type = tstate->exc_type;
    *value = tstate->exc_value;
    *tb = tstate->exc_traceback;
    Py_XINCREF(*type);
    Py_XINCREF(*value);
    Py_XINCREF(*tb);
  #endif
}
static CYTHON_INLINE void __Pyx__ExceptionReset(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) {
  #if CYTHON_USE_EXC_INFO_STACK && PY_VERSION_HEX >= 0x030B00a4
    _PyErr_StackItem *exc_info = tstate->exc_info;
    PyObject *tmp_value = exc_info->exc_value;
    exc_info->exc_value = value;
    Py_XDECREF(tmp_value);
    Py_XDECREF(type);
    Py_XDECREF(tb);
  #else
    PyObject *tmp_type, *tmp_value, *tmp_tb;
    #if CYTHON_USE_EXC_INFO_STACK
    _PyErr_StackItem *exc_info = tstate->exc_info;
    tmp_type = exc_info->exc_type;
    tmp_value = exc_info->exc_value;
    tmp_tb = exc_info->exc_traceback;
    exc_info->exc_type = type;
    exc_info->exc_value = value;
    exc_info->exc_traceback = tb;
    #else
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
    tstate->exc_type = type;
    tstate->exc_value = value;
    tstate->exc_traceback = tb;
    #endif
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
  #endif
}
#endif

/* GetException */
#if CYTHON_FAST_THREAD_STATE
static int __Pyx__GetException(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb)
#else
static int __Pyx_GetException(PyObject **type, PyObject **value, PyObject **tb)
#endif
{
    PyObject *local_type = NULL, *local_value, *local_tb = NULL;
#if CYTHON_FAST_THREAD_STATE
    PyObject *tmp_type, *tmp_value, *tmp_tb;
  #if PY_VERSION_HEX >= 0x030C0000
    local_value = tstate->current_exception;
    tstate->current_exception = 0;
  #else
    local_type = tstate->curexc_type;
    local_value = tstate->curexc_value;
    local_tb = tstate->curexc_traceback;
    tstate->curexc_type = 0;
    tstate->curexc_value = 0;
    tstate->curexc_traceback = 0;
  #endif
#elif __PYX_LIMITED_VERSION_HEX > 0x030C0000
    local_value = PyErr_GetRaisedException();
#else
    PyErr_Fetch(&local_type, &local_value, &local_tb);
#endif
#if __PYX_LIMITED_VERSION_HEX > 0x030C0000
    if (likely(local_value)) {
        local_type = (PyObject*) Py_TYPE(local_value);
        Py_INCREF(local_type);
        local_tb = PyException_GetTraceback(local_value);
    }
#else
    PyErr_NormalizeException(&local_type, &local_value, &local_tb);
#if CYTHON_FAST_THREAD_STATE
    if (unlikely(tstate->curexc_type))
#else
    if (unlikely(PyErr_Occurred()))
#endif
        goto bad;
    if (local_tb) {
        if (unlikely(PyException_SetTraceback(local_value, local_tb) < 0))
            goto bad;
    }
#endif // __PYX_LIMITED_VERSION_HEX > 0x030C0000
    Py_XINCREF(local_tb);
    Py_XINCREF(local_type);
    Py_XINCREF(local_value);
    *type = local_type;
    *value = local_value;
    *tb = local_tb;
#if CYTHON_FAST_THREAD_STATE
    #if CYTHON_USE_EXC_INFO_STACK
    {
        _PyErr_StackItem *exc_info = tstate->exc_info;
      #if PY_VERSION_HEX >= 0x030B00a4
        tmp_value = exc_info->exc_value;
        exc_info->exc_value = local_value;
        tmp_type = NULL;
        tmp_tb = NULL;
        Py_XDECREF(local_type);
        Py_XDECREF(local_tb);
      #else
        tmp_type = exc_info->exc_type;
        tmp_value = exc_info->exc_value;
        tmp_tb = exc_info->exc_traceback;
        exc_info->exc_type = local_type;
        exc_info->exc_value = local_value;
        exc_info->exc_traceback = local_tb;
      #endif
    }
    #else
    tmp_type = tstate->exc_type;
    tmp_value = tstate->exc_value;
    tmp_tb = tstate->exc_traceback;
    tstate->exc_type = local_type;
    tstate->exc_value = local_value;
    tstate->exc_traceback = local_tb;
    #endif
    Py_XDECREF(tmp_type);
    Py_XDECREF(tmp_value);
    Py_XDECREF(tmp_tb);
#elif __PYX_LIMITED_VERSION_HEX >= 0x030b0000
    PyErr_SetHandledException(local_value);
    Py_XDECREF(local_value);
    Py_XDECREF(local_type);
    Py_XDECREF(local_tb);
#else
    PyErr_SetExcInfo(local_type, local_value, local_tb);
#endif
    return 0;
#if __PYX_LIMITED_VERSION_HEX <= 0x030C0000
bad:
    *type = 0;
    *value = 0;
    *tb = 0;
    Py_XDECREF(local_type);
    Py_XDECREF(local_value);
    Py_XDECREF(local_tb);
    return -1;
#endif
}

/* PyObjectCall (used by PyObjectFastCall) */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) {
    PyObject *result;
    ternaryfunc call = Py_TYPE(func)->tp_call;
    if (unlikely(!call))
        return PyObject_Call(func, arg, kw);
    if (unlikely(Py_EnterRecursiveCall(" while calling a Python object")))
        return NULL;
    result = (*call)(func, arg, kw);
    Py_LeaveRecursiveCall();
    if (unlikely(!result) && unlikely(!PyErr_Occurred())) {
        PyErr_SetString(
            PyExc_SystemError,
            "NULL result without error in PyObject_Call");
    }
    return result;
}
#endif

/* PyObjectCallMethO (used by PyObjectFastCall) */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) {
    PyObject *self, *result;
    PyCFunction cfunc;
    cfunc = __Pyx_CyOrPyCFunction_GET_FUNCTION(func);
    self = __Pyx_CyOrPyCFunction_GET_SELF(func);
    if (unlikely(Py_EnterRecursiveCall(" while calling a Python object")))
        return NULL;
    result = cfunc(self, arg);
    Py_LeaveRecursiveCall();
    if (unlikely(!result) && unlikely(!PyErr_Occurred())) {
        PyErr_SetString(
            PyExc_SystemError,
            "NULL result without error in PyObject_Call");
    }
    return result;
}
#endif

/* PyObjectFastCall */
#if PY_VERSION_HEX < 0x03090000 || CYTHON_COMPILING_IN_LIMITED_API
static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject * const*args, size_t nargs, PyObject *kwargs) {
    PyObject *argstuple;
    PyObject *result = 0;
    size_t i;
    argstuple = PyTuple_New((Py_ssize_t)nargs);
    if (unlikely(!argstuple)) return NULL;
    for (i = 0; i < nargs; i++) {
        Py_INCREF(args[i]);
        if (__Pyx_PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]) != (0)) goto bad;
    }
    result = __Pyx_PyObject_Call(func, argstuple, kwargs);
  bad:
    Py_DECREF(argstuple);
    return result;
}
#endif
#if CYTHON_VECTORCALL && !CYTHON_COMPILING_IN_LIMITED_API
  #if PY_VERSION_HEX < 0x03090000
    #define __Pyx_PyVectorcall_Function(callable) _PyVectorcall_Function(callable)
  #elif CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE vectorcallfunc __Pyx_PyVectorcall_Function(PyObject *callable) {
    PyTypeObject *tp = Py_TYPE(callable);
    #if defined(__Pyx_CyFunction_USED)
    if (__Pyx_CyFunction_CheckExact(callable)) {
        return __Pyx_CyFunction_func_vectorcall(callable);
    }
    #endif
    if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) {
        return NULL;
    }
    assert(PyCallable_Check(callable));
    Py_ssize_t offset = tp->tp_vectorcall_offset;
    assert(offset > 0);
    vectorcallfunc ptr;
    memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
    return ptr;
}
  #else
    #define __Pyx_PyVectorcall_Function(callable) PyVectorcall_Function(callable)
  #endif
#endif
static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject *const *args, size_t _nargs, PyObject *kwargs) {
    Py_ssize_t nargs = __Pyx_PyVectorcall_NARGS(_nargs);
#if CYTHON_COMPILING_IN_CPYTHON
    if (nargs == 0 && kwargs == NULL) {
        if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_NOARGS))
            return __Pyx_PyObject_CallMethO(func, NULL);
    }
    else if (nargs == 1 && kwargs == NULL) {
        if (__Pyx_CyOrPyCFunction_Check(func) && likely( __Pyx_CyOrPyCFunction_GET_FLAGS(func) & METH_O))
            return __Pyx_PyObject_CallMethO(func, args[0]);
    }
#endif
    if (kwargs == NULL) {
        #if CYTHON_VECTORCALL
          #if CYTHON_COMPILING_IN_LIMITED_API
            return PyObject_Vectorcall(func, args, _nargs, NULL);
          #else
            vectorcallfunc f = __Pyx_PyVectorcall_Function(func);
            if (f) {
                return f(func, args, _nargs, NULL);
            }
          #endif
        #endif
    }
    if (nargs == 0) {
        return __Pyx_PyObject_Call(func, __pyx_mstate_global->__pyx_empty_tuple, kwargs);
    }
    #if PY_VERSION_HEX >= 0x03090000 && !CYTHON_COMPILING_IN_LIMITED_API
    return PyObject_VectorcallDict(func, args, (size_t)nargs, kwargs);
    #else
    return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs);
    #endif
}

/* RaiseException */
static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause) {
    PyObject* owned_instance = NULL;
    if (tb == Py_None) {
        tb = 0;
    } else if (tb && !PyTraceBack_Check(tb)) {
        PyErr_SetString(PyExc_TypeError,
            "raise: arg 3 must be a traceback or None");
        goto bad;
    }
    if (value == Py_None)
        value = 0;
    if (PyExceptionInstance_Check(type)) {
        if (value) {
            PyErr_SetString(PyExc_TypeError,
                "instance exception may not have a separate value");
            goto bad;
        }
        value = type;
        type = (PyObject*) Py_TYPE(value);
    } else if (PyExceptionClass_Check(type)) {
        PyObject *instance_class = NULL;
        if (value && PyExceptionInstance_Check(value)) {
            instance_class = (PyObject*) Py_TYPE(value);
            if (instance_class != type) {
                int is_subclass = PyObject_IsSubclass(instance_class, type);
                if (!is_subclass) {
                    instance_class = NULL;
                } else if (unlikely(is_subclass == -1)) {
                    goto bad;
                } else {
                    type = instance_class;
                }
            }
        }
        if (!instance_class) {
            PyObject *args;
            if (!value)
                args = PyTuple_New(0);
            else if (PyTuple_Check(value)) {
                Py_INCREF(value);
                args = value;
            } else
                args = PyTuple_Pack(1, value);
            if (!args)
                goto bad;
            owned_instance = PyObject_Call(type, args, NULL);
            Py_DECREF(args);
            if (!owned_instance)
                goto bad;
            value = owned_instance;
            if (!PyExceptionInstance_Check(value)) {
                PyErr_Format(PyExc_TypeError,
                             "calling %R should have returned an instance of "
                             "BaseException, not %R",
                             type, Py_TYPE(value));
                goto bad;
            }
        }
    } else {
        PyErr_SetString(PyExc_TypeError,
            "raise: exception class must be a subclass of BaseException");
        goto bad;
    }
    if (cause) {
        PyObject *fixed_cause;
        if (cause == Py_None) {
            fixed_cause = NULL;
        } else if (PyExceptionClass_Check(cause)) {
            fixed_cause = PyObject_CallObject(cause, NULL);
            if (fixed_cause == NULL)
                goto bad;
        } else if (PyExceptionInstance_Check(cause)) {
            fixed_cause = cause;
            Py_INCREF(fixed_cause);
        } else {
            PyErr_SetString(PyExc_TypeError,
                            "exception causes must derive from "
                            "BaseException");
            goto bad;
        }
        PyException_SetCause(value, fixed_cause);
    }
    PyErr_SetObject(type, value);
    if (tb) {
#if PY_VERSION_HEX >= 0x030C00A6
        PyException_SetTraceback(value, tb);
#elif CYTHON_FAST_THREAD_STATE
        PyThreadState *tstate = __Pyx_PyThreadState_Current;
        PyObject* tmp_tb = tstate->curexc_traceback;
        if (tb != tmp_tb) {
            Py_INCREF(tb);
            tstate->curexc_traceback = tb;
            Py_XDECREF(tmp_tb);
        }
#else
        PyObject *tmp_type, *tmp_value, *tmp_tb;
        PyErr_Fetch(&tmp_type, &tmp_value, &tmp_tb);
        Py_INCREF(tb);
        PyErr_Restore(tmp_type, tmp_value, tb);
        Py_XDECREF(tmp_tb);
#endif
    }
bad:
    Py_XDECREF(owned_instance);
    return;
}

/* TupleAndListFromArray (used by fastcall) */
#if !CYTHON_COMPILING_IN_CPYTHON && CYTHON_METH_FASTCALL
static CYTHON_INLINE PyObject *
__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
{
    PyObject *res;
    Py_ssize_t i;
    if (n <= 0) {
        return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple);
    }
    res = PyTuple_New(n);
    if (unlikely(res == NULL)) return NULL;
    for (i = 0; i < n; i++) {
        if (unlikely(__Pyx_PyTuple_SET_ITEM(res, i, src[i]) < (0))) {
            Py_DECREF(res);
            return NULL;
        }
        Py_INCREF(src[i]);
    }
    return res;
}
#elif CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE void __Pyx_copy_object_array(PyObject *const *CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) {
    PyObject *v;
    Py_ssize_t i;
    for (i = 0; i < length; i++) {
        v = dest[i] = src[i];
        Py_INCREF(v);
    }
}
static CYTHON_INLINE PyObject *
__Pyx_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
{
    PyObject *res;
    if (n <= 0) {
        return __Pyx_NewRef(__pyx_mstate_global->__pyx_empty_tuple);
    }
    res = PyTuple_New(n);
    if (unlikely(res == NULL)) return NULL;
    __Pyx_copy_object_array(src, ((PyTupleObject*)res)->ob_item, n);
    return res;
}
static CYTHON_INLINE PyObject *
__Pyx_PyList_FromArray(PyObject *const *src, Py_ssize_t n)
{
    PyObject *res;
    if (n <= 0) {
        return PyList_New(0);
    }
    res = PyList_New(n);
    if (unlikely(res == NULL)) return NULL;
    __Pyx_copy_object_array(src, ((PyListObject*)res)->ob_item, n);
    return res;
}
#endif

/* BytesEquals (used by UnicodeEquals) */
static CYTHON_INLINE int __Pyx_PyBytes_Equals(PyObject* s1, PyObject* s2, int equals) {
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL ||\
        !(CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS)
    return PyObject_RichCompareBool(s1, s2, equals);
#else
    if (s1 == s2) {
        return (equals == Py_EQ);
    } else if (PyBytes_CheckExact(s1) & PyBytes_CheckExact(s2)) {
        const char *ps1, *ps2;
        Py_ssize_t length = PyBytes_GET_SIZE(s1);
        if (length != PyBytes_GET_SIZE(s2))
            return (equals == Py_NE);
        ps1 = PyBytes_AS_STRING(s1);
        ps2 = PyBytes_AS_STRING(s2);
        if (ps1[0] != ps2[0]) {
            return (equals == Py_NE);
        } else if (length == 1) {
            return (equals == Py_EQ);
        } else {
            int result;
#if CYTHON_USE_UNICODE_INTERNALS && (PY_VERSION_HEX < 0x030B0000)
            Py_hash_t hash1, hash2;
            hash1 = ((PyBytesObject*)s1)->ob_shash;
            hash2 = ((PyBytesObject*)s2)->ob_shash;
            if (hash1 != hash2 && hash1 != -1 && hash2 != -1) {
                return (equals == Py_NE);
            }
#endif
            result = memcmp(ps1, ps2, (size_t)length);
            return (equals == Py_EQ) ? (result == 0) : (result != 0);
        }
    } else if ((s1 == Py_None) & PyBytes_CheckExact(s2)) {
        return (equals == Py_NE);
    } else if ((s2 == Py_None) & PyBytes_CheckExact(s1)) {
        return (equals == Py_NE);
    } else {
        int result;
        PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
        if (!py_result)
            return -1;
        result = __Pyx_PyObject_IsTrue(py_result);
        Py_DECREF(py_result);
        return result;
    }
#endif
}

/* UnicodeEquals (used by fastcall) */
static CYTHON_INLINE int __Pyx_PyUnicode_Equals(PyObject* s1, PyObject* s2, int equals) {
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_GRAAL
    return PyObject_RichCompareBool(s1, s2, equals);
#else
    int s1_is_unicode, s2_is_unicode;
    if (s1 == s2) {
        goto return_eq;
    }
    s1_is_unicode = PyUnicode_CheckExact(s1);
    s2_is_unicode = PyUnicode_CheckExact(s2);
    if (s1_is_unicode & s2_is_unicode) {
        Py_ssize_t length, length2;
        int kind;
        void *data1, *data2;
        #if !CYTHON_COMPILING_IN_LIMITED_API
        if (unlikely(__Pyx_PyUnicode_READY(s1) < 0) || unlikely(__Pyx_PyUnicode_READY(s2) < 0))
            return -1;
        #endif
        length = __Pyx_PyUnicode_GET_LENGTH(s1);
        #if !CYTHON_ASSUME_SAFE_SIZE
        if (unlikely(length < 0)) return -1;
        #endif
        length2 = __Pyx_PyUnicode_GET_LENGTH(s2);
        #if !CYTHON_ASSUME_SAFE_SIZE
        if (unlikely(length2 < 0)) return -1;
        #endif
        if (length != length2) {
            goto return_ne;
        }
#if CYTHON_USE_UNICODE_INTERNALS
        {
            Py_hash_t hash1, hash2;
            hash1 = ((PyASCIIObject*)s1)->hash;
            hash2 = ((PyASCIIObject*)s2)->hash;
            if (hash1 != hash2 && hash1 != -1 && hash2 != -1) {
                goto return_ne;
            }
        }
#endif
        kind = __Pyx_PyUnicode_KIND(s1);
        if (kind != __Pyx_PyUnicode_KIND(s2)) {
            goto return_ne;
        }
        data1 = __Pyx_PyUnicode_DATA(s1);
        data2 = __Pyx_PyUnicode_DATA(s2);
        if (__Pyx_PyUnicode_READ(kind, data1, 0) != __Pyx_PyUnicode_READ(kind, data2, 0)) {
            goto return_ne;
        } else if (length == 1) {
            goto return_eq;
        } else {
            int result = memcmp(data1, data2, (size_t)(length * kind));
            return (equals == Py_EQ) ? (result == 0) : (result != 0);
        }
    } else if ((s1 == Py_None) & s2_is_unicode) {
        goto return_ne;
    } else if ((s2 == Py_None) & s1_is_unicode) {
        goto return_ne;
    } else {
        int result;
        PyObject* py_result = PyObject_RichCompare(s1, s2, equals);
        if (!py_result)
            return -1;
        result = __Pyx_PyObject_IsTrue(py_result);
        Py_DECREF(py_result);
        return result;
    }
return_eq:
    return (equals == Py_EQ);
return_ne:
    return (equals == Py_NE);
#endif
}

/* fastcall */
#if CYTHON_METH_FASTCALL
static CYTHON_INLINE PyObject * __Pyx_GetKwValue_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues, PyObject *s)
{
    Py_ssize_t i, n = __Pyx_PyTuple_GET_SIZE(kwnames);
    #if !CYTHON_ASSUME_SAFE_SIZE
    if (unlikely(n == -1)) return NULL;
    #endif
    for (i = 0; i < n; i++)
    {
        PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i);
        #if !CYTHON_ASSUME_SAFE_MACROS
        if (unlikely(!namei)) return NULL;
        #endif
        if (s == namei) return kwvalues[i];
    }
    for (i = 0; i < n; i++)
    {
        PyObject *namei = __Pyx_PyTuple_GET_ITEM(kwnames, i);
        #if !CYTHON_ASSUME_SAFE_MACROS
        if (unlikely(!namei)) return NULL;
        #endif
        int eq = __Pyx_PyUnicode_Equals(s, namei, Py_EQ);
        if (unlikely(eq != 0)) {
            if (unlikely(eq < 0)) return NULL;
            return kwvalues[i];
        }
    }
    return NULL;
}
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030d0000 || CYTHON_COMPILING_IN_LIMITED_API
CYTHON_UNUSED static PyObject *__Pyx_KwargsAsDict_FASTCALL(PyObject *kwnames, PyObject *const *kwvalues) {
    Py_ssize_t i, nkwargs;
    PyObject *dict;
#if !CYTHON_ASSUME_SAFE_SIZE
    nkwargs = PyTuple_Size(kwnames);
    if (unlikely(nkwargs < 0)) return NULL;
#else
    nkwargs = PyTuple_GET_SIZE(kwnames);
#endif
    dict = PyDict_New();
    if (unlikely(!dict))
        return NULL;
    for (i=0; i<nkwargs; i++) {
#if !CYTHON_ASSUME_SAFE_MACROS
        PyObject *key = PyTuple_GetItem(kwnames, i);
        if (!key) goto bad;
#else
        PyObject *key = PyTuple_GET_ITEM(kwnames, i);
#endif
        if (unlikely(PyDict_SetItem(dict, key, kwvalues[i]) < 0))
            goto bad;
    }
    return dict;
bad:
    Py_DECREF(dict);
    return NULL;
}
#endif
#endif

/* PyObjectCallOneArg (used by CallUnboundCMethod0) */
static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) {
    PyObject *args[2] = {NULL, arg};
    return __Pyx_PyObject_FastCall(func, args+1, 1 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
}

/* UnpackUnboundCMethod (used by CallUnboundCMethod0) */
#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000
static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *args, PyObject *kwargs) {
    PyObject *result;
    PyObject *selfless_args = PyTuple_GetSlice(args, 1, PyTuple_Size(args));
    if (unlikely(!selfless_args)) return NULL;
    result = PyObject_Call(method, selfless_args, kwargs);
    Py_DECREF(selfless_args);
    return result;
}
#elif CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x03090000
static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) {
        return _PyObject_Vectorcall
            (method, args ? args+1 : NULL, nargs ? nargs-1 : 0, kwnames);
}
#else
static PyObject *__Pyx_SelflessCall(PyObject *method, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) {
    return
#if PY_VERSION_HEX < 0x03090000
    _PyObject_Vectorcall
#else
    PyObject_Vectorcall
#endif
        (method, args ? args+1 : NULL, nargs ? (size_t) nargs-1 : 0, kwnames);
}
#endif
static PyMethodDef __Pyx_UnboundCMethod_Def = {
     "CythonUnboundCMethod",
     __PYX_REINTERPRET_FUNCION(PyCFunction, __Pyx_SelflessCall),
#if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030C0000
     METH_VARARGS | METH_KEYWORDS,
#else
     METH_FASTCALL | METH_KEYWORDS,
#endif
     NULL
};
static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) {
    PyObject *method, *result=NULL;
    method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name);
    if (unlikely(!method))
        return -1;
    result = method;
#if CYTHON_COMPILING_IN_CPYTHON
    if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type)))
    {
        PyMethodDescrObject *descr = (PyMethodDescrObject*) method;
        target->func = descr->d_method->ml_meth;
        target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS);
    } else
#endif
#if CYTHON_COMPILING_IN_PYPY
#else
    if (PyCFunction_Check(method))
#endif
    {
        PyObject *self;
        int self_found;
#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY
        self = PyObject_GetAttrString(method, "__self__");
        if (!self) {
            PyErr_Clear();
        }
#else
        self = PyCFunction_GET_SELF(method);
#endif
        self_found = (self && self != Py_None);
#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY
        Py_XDECREF(self);
#endif
        if (self_found) {
            PyObject *unbound_method = PyCFunction_New(&__Pyx_UnboundCMethod_Def, method);
            if (unlikely(!unbound_method)) return -1;
            Py_DECREF(method);
            result = unbound_method;
        }
    }
#if !CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    if (unlikely(target->method)) {
        Py_DECREF(result);
    } else
#endif
    target->method = result;
    return 0;
}

/* CallUnboundCMethod0 */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) {
    int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc);
    if (likely(was_initialized == 2 && cfunc->func)) {
        if (likely(cfunc->flag == METH_NOARGS))
            return __Pyx_CallCFunction(cfunc, self, NULL);
        if (likely(cfunc->flag == METH_FASTCALL))
            return __Pyx_CallCFunctionFast(cfunc, self, NULL, 0);
        if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS))
            return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, NULL, 0, NULL);
        if (likely(cfunc->flag == (METH_VARARGS | METH_KEYWORDS)))
            return __Pyx_CallCFunctionWithKeywords(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple, NULL);
        if (cfunc->flag == METH_VARARGS)
            return __Pyx_CallCFunction(cfunc, self, __pyx_mstate_global->__pyx_empty_tuple);
        return __Pyx__CallUnboundCMethod0(cfunc, self);
    }
#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    else if (unlikely(was_initialized == 1)) {
        __Pyx_CachedCFunction tmp_cfunc = {
#ifndef __cplusplus
            0
#endif
        };
        tmp_cfunc.type = cfunc->type;
        tmp_cfunc.method_name = cfunc->method_name;
        return __Pyx__CallUnboundCMethod0(&tmp_cfunc, self);
    }
#endif
    PyObject *result = __Pyx__CallUnboundCMethod0(cfunc, self);
    __Pyx_CachedCFunction_SetFinishedInitializing(cfunc);
    return result;
}
#endif
static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) {
    PyObject *result;
    if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL;
    result = __Pyx_PyObject_CallOneArg(cfunc->method, self);
    return result;
}

/* py_dict_items (used by OwnedDictNext) */
static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) {
    return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_items, d);
}

/* py_dict_values (used by OwnedDictNext) */
static CYTHON_INLINE PyObject* __Pyx_PyDict_Values(PyObject* d) {
    return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_values, d);
}

/* OwnedDictNext (used by ParseKeywordsImpl) */
#if CYTHON_AVOID_BORROWED_REFS
static int __Pyx_PyDict_NextRef(PyObject *p, PyObject **ppos, PyObject **pkey, PyObject **pvalue) {
    PyObject *next = NULL;
    if (!*ppos) {
        if (pvalue) {
            PyObject *dictview = pkey ? __Pyx_PyDict_Items(p) : __Pyx_PyDict_Values(p);
            if (unlikely(!dictview)) goto bad;
            *ppos = PyObject_GetIter(dictview);
            Py_DECREF(dictview);
        } else {
            *ppos = PyObject_GetIter(p);
        }
        if (unlikely(!*ppos)) goto bad;
    }
    next = PyIter_Next(*ppos);
    if (!next) {
        if (PyErr_Occurred()) goto bad;
        return 0;
    }
    if (pkey && pvalue) {
        *pkey = __Pyx_PySequence_ITEM(next, 0);
        if (unlikely(*pkey)) goto bad;
        *pvalue = __Pyx_PySequence_ITEM(next, 1);
        if (unlikely(*pvalue)) goto bad;
        Py_DECREF(next);
    } else if (pkey) {
        *pkey = next;
    } else {
        assert(pvalue);
        *pvalue = next;
    }
    return 1;
  bad:
    Py_XDECREF(next);
#if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000
    PyErr_FormatUnraisable("Exception ignored in __Pyx_PyDict_NextRef");
#else
    PyErr_WriteUnraisable(__pyx_mstate_global->__pyx_n_u_Pyx_PyDict_NextRef);
#endif
    if (pkey) *pkey = NULL;
    if (pvalue) *pvalue = NULL;
    return 0;
}
#else // !CYTHON_AVOID_BORROWED_REFS
static int __Pyx_PyDict_NextRef(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) {
    int result = PyDict_Next(p, ppos, pkey, pvalue);
    if (likely(result == 1)) {
        if (pkey) Py_INCREF(*pkey);
        if (pvalue) Py_INCREF(*pvalue);
    }
    return result;
}
#endif

/* RaiseDoubleKeywords (used by ParseKeywordsImpl) */
static void __Pyx_RaiseDoubleKeywordsError(
    const char* func_name,
    PyObject* kw_name)
{
    PyErr_Format(PyExc_TypeError,
        "%s() got multiple values for keyword argument '%U'", func_name, kw_name);
}

/* CallUnboundCMethod2 */
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject *__Pyx_CallUnboundCMethod2(__Pyx_CachedCFunction *cfunc, PyObject *self, PyObject *arg1, PyObject *arg2) {
    int was_initialized = __Pyx_CachedCFunction_GetAndSetInitializing(cfunc);
    if (likely(was_initialized == 2 && cfunc->func)) {
        PyObject *args[2] = {arg1, arg2};
        if (cfunc->flag == METH_FASTCALL) {
            return __Pyx_CallCFunctionFast(cfunc, self, args, 2);
        }
        if (cfunc->flag == (METH_FASTCALL | METH_KEYWORDS))
            return __Pyx_CallCFunctionFastWithKeywords(cfunc, self, args, 2, NULL);
    }
#if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    else if (unlikely(was_initialized == 1)) {
        __Pyx_CachedCFunction tmp_cfunc = {
#ifndef __cplusplus
            0
#endif
        };
        tmp_cfunc.type = cfunc->type;
        tmp_cfunc.method_name = cfunc->method_name;
        return __Pyx__CallUnboundCMethod2(&tmp_cfunc, self, arg1, arg2);
    }
#endif
    PyObject *result = __Pyx__CallUnboundCMethod2(cfunc, self, arg1, arg2);
    __Pyx_CachedCFunction_SetFinishedInitializing(cfunc);
    return result;
}
#endif
static PyObject* __Pyx__CallUnboundCMethod2(__Pyx_CachedCFunction* cfunc, PyObject* self, PyObject* arg1, PyObject* arg2){
    if (unlikely(!cfunc->func && !cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL;
#if CYTHON_COMPILING_IN_CPYTHON
    if (cfunc->func && (cfunc->flag & METH_VARARGS)) {
        PyObject *result = NULL;
        PyObject *args = PyTuple_New(2);
        if (unlikely(!args)) return NULL;
        Py_INCREF(arg1);
        PyTuple_SET_ITEM(args, 0, arg1);
        Py_INCREF(arg2);
        PyTuple_SET_ITEM(args, 1, arg2);
        if (cfunc->flag & METH_KEYWORDS)
            result = __Pyx_CallCFunctionWithKeywords(cfunc, self, args, NULL);
        else
            result = __Pyx_CallCFunction(cfunc, self, args);
        Py_DECREF(args);
        return result;
    }
#endif
    {
        PyObject *args[4] = {NULL, self, arg1, arg2};
        return __Pyx_PyObject_FastCall(cfunc->method, args+1, 3 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
    }
}

/* ParseKeywordsImpl (used by ParseKeywords) */
static int __Pyx_ValidateDuplicatePosArgs(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject ** const *first_kw_arg,
    const char* function_name)
{
    PyObject ** const *name = argnames;
    while (name != first_kw_arg) {
        PyObject *key = **name;
        int found = PyDict_Contains(kwds, key);
        if (unlikely(found)) {
            if (found == 1) __Pyx_RaiseDoubleKeywordsError(function_name, key);
            goto bad;
        }
        name++;
    }
    return 0;
bad:
    return -1;
}
#if CYTHON_USE_UNICODE_INTERNALS
static CYTHON_INLINE int __Pyx_UnicodeKeywordsEqual(PyObject *s1, PyObject *s2) {
    int kind;
    Py_ssize_t len = PyUnicode_GET_LENGTH(s1);
    if (len != PyUnicode_GET_LENGTH(s2)) return 0;
    kind = PyUnicode_KIND(s1);
    if (kind != PyUnicode_KIND(s2)) return 0;
    const void *data1 = PyUnicode_DATA(s1);
    const void *data2 = PyUnicode_DATA(s2);
    return (memcmp(data1, data2, (size_t) len * (size_t) kind) == 0);
}
#endif
static int __Pyx_MatchKeywordArg_str(
    PyObject *key,
    PyObject ** const argnames[],
    PyObject ** const *first_kw_arg,
    size_t *index_found,
    const char *function_name)
{
    PyObject ** const *name;
    #if CYTHON_USE_UNICODE_INTERNALS
    Py_hash_t key_hash = ((PyASCIIObject*)key)->hash;
    if (unlikely(key_hash == -1)) {
        key_hash = PyObject_Hash(key);
        if (unlikely(key_hash == -1))
            goto bad;
    }
    #endif
    name = first_kw_arg;
    while (*name) {
        PyObject *name_str = **name;
        #if CYTHON_USE_UNICODE_INTERNALS
        if (key_hash == ((PyASCIIObject*)name_str)->hash && __Pyx_UnicodeKeywordsEqual(name_str, key)) {
            *index_found = (size_t) (name - argnames);
            return 1;
        }
        #else
        #if CYTHON_ASSUME_SAFE_SIZE
        if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key))
        #endif
        {
            int cmp = PyUnicode_Compare(name_str, key);
            if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
            if (cmp == 0) {
                *index_found = (size_t) (name - argnames);
                return 1;
            }
        }
        #endif
        name++;
    }
    name = argnames;
    while (name != first_kw_arg) {
        PyObject *name_str = **name;
        #if CYTHON_USE_UNICODE_INTERNALS
        if (unlikely(key_hash == ((PyASCIIObject*)name_str)->hash)) {
            if (__Pyx_UnicodeKeywordsEqual(name_str, key))
                goto arg_passed_twice;
        }
        #else
        #if CYTHON_ASSUME_SAFE_SIZE
        if (PyUnicode_GET_LENGTH(name_str) == PyUnicode_GET_LENGTH(key))
        #endif
        {
            if (unlikely(name_str == key)) goto arg_passed_twice;
            int cmp = PyUnicode_Compare(name_str, key);
            if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad;
            if (cmp == 0) goto arg_passed_twice;
        }
        #endif
        name++;
    }
    return 0;
arg_passed_twice:
    __Pyx_RaiseDoubleKeywordsError(function_name, key);
    goto bad;
bad:
    return -1;
}
static int __Pyx_MatchKeywordArg_nostr(
    PyObject *key,
    PyObject ** const argnames[],
    PyObject ** const *first_kw_arg,
    size_t *index_found,
    const char *function_name)
{
    PyObject ** const *name;
    if (unlikely(!PyUnicode_Check(key))) goto invalid_keyword_type;
    name = first_kw_arg;
    while (*name) {
        int cmp = PyObject_RichCompareBool(**name, key, Py_EQ);
        if (cmp == 1) {
            *index_found = (size_t) (name - argnames);
            return 1;
        }
        if (unlikely(cmp == -1)) goto bad;
        name++;
    }
    name = argnames;
    while (name != first_kw_arg) {
        int cmp = PyObject_RichCompareBool(**name, key, Py_EQ);
        if (unlikely(cmp != 0)) {
            if (cmp == 1) goto arg_passed_twice;
            else goto bad;
        }
        name++;
    }
    return 0;
arg_passed_twice:
    __Pyx_RaiseDoubleKeywordsError(function_name, key);
    goto bad;
invalid_keyword_type:
    PyErr_Format(PyExc_TypeError,
        "%.200s() keywords must be strings", function_name);
    goto bad;
bad:
    return -1;
}
static CYTHON_INLINE int __Pyx_MatchKeywordArg(
    PyObject *key,
    PyObject ** const argnames[],
    PyObject ** const *first_kw_arg,
    size_t *index_found,
    const char *function_name)
{
    return likely(PyUnicode_CheckExact(key)) ?
        __Pyx_MatchKeywordArg_str(key, argnames, first_kw_arg, index_found, function_name) :
        __Pyx_MatchKeywordArg_nostr(key, argnames, first_kw_arg, index_found, function_name);
}
static void __Pyx_RejectUnknownKeyword(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject ** const *first_kw_arg,
    const char *function_name)
{
    #if CYTHON_AVOID_BORROWED_REFS
    PyObject *pos = NULL;
    #else
    Py_ssize_t pos = 0;
    #endif
    PyObject *key = NULL;
    __Pyx_BEGIN_CRITICAL_SECTION(kwds);
    while (
        #if CYTHON_AVOID_BORROWED_REFS
        __Pyx_PyDict_NextRef(kwds, &pos, &key, NULL)
        #else
        PyDict_Next(kwds, &pos, &key, NULL)
        #endif
    ) {
        PyObject** const *name = first_kw_arg;
        while (*name && (**name != key)) name++;
        if (!*name) {
            size_t index_found = 0;
            int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name);
            if (cmp != 1) {
                if (cmp == 0) {
                    PyErr_Format(PyExc_TypeError,
                        "%s() got an unexpected keyword argument '%U'",
                        function_name, key);
                }
                #if CYTHON_AVOID_BORROWED_REFS
                Py_DECREF(key);
                #endif
                break;
            }
        }
        #if CYTHON_AVOID_BORROWED_REFS
        Py_DECREF(key);
        #endif
    }
    __Pyx_END_CRITICAL_SECTION();
    #if CYTHON_AVOID_BORROWED_REFS
    Py_XDECREF(pos);
    #endif
    assert(PyErr_Occurred());
}
static int __Pyx_ParseKeywordDict(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject *values[],
    Py_ssize_t num_pos_args,
    Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs)
{
    PyObject** const *name;
    PyObject** const *first_kw_arg = argnames + num_pos_args;
    Py_ssize_t extracted = 0;
#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments)
    if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1;
#endif
    name = first_kw_arg;
    while (*name && num_kwargs > extracted) {
        PyObject * key = **name;
        PyObject *value;
        int found = 0;
        #if __PYX_LIMITED_VERSION_HEX >= 0x030d0000
        found = PyDict_GetItemRef(kwds, key, &value);
        #else
        value = PyDict_GetItemWithError(kwds, key);
        if (value) {
            Py_INCREF(value);
            found = 1;
        } else {
            if (unlikely(PyErr_Occurred())) goto bad;
        }
        #endif
        if (found) {
            if (unlikely(found < 0)) goto bad;
            values[name-argnames] = value;
            extracted++;
        }
        name++;
    }
    if (num_kwargs > extracted) {
        if (ignore_unknown_kwargs) {
            if (unlikely(__Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name) == -1))
                goto bad;
        } else {
            __Pyx_RejectUnknownKeyword(kwds, argnames, first_kw_arg, function_name);
            goto bad;
        }
    }
    return 0;
bad:
    return -1;
}
static int __Pyx_ParseKeywordDictToDict(
    PyObject *kwds,
    PyObject ** const argnames[],
    PyObject *kwds2,
    PyObject *values[],
    Py_ssize_t num_pos_args,
    const char* function_name)
{
    PyObject** const *name;
    PyObject** const *first_kw_arg = argnames + num_pos_args;
    Py_ssize_t len;
#if !CYTHON_COMPILING_IN_PYPY || defined(PyArg_ValidateKeywordArguments)
    if (unlikely(!PyArg_ValidateKeywordArguments(kwds))) return -1;
#endif
    if (PyDict_Update(kwds2, kwds) < 0) goto bad;
    name = first_kw_arg;
    while (*name) {
        PyObject *key = **name;
        PyObject *value;
#if !CYTHON_COMPILING_IN_LIMITED_API && (PY_VERSION_HEX >= 0x030d00A2 || defined(PyDict_Pop))
        int found = PyDict_Pop(kwds2, key, &value);
        if (found) {
            if (unlikely(found < 0)) goto bad;
            values[name-argnames] = value;
        }
#elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000
        int found = PyDict_GetItemRef(kwds2, key, &value);
        if (found) {
            if (unlikely(found < 0)) goto bad;
            values[name-argnames] = value;
            if (unlikely(PyDict_DelItem(kwds2, key) < 0)) goto bad;
        }
#else
    #if CYTHON_COMPILING_IN_CPYTHON
        value = _PyDict_Pop(kwds2, key, kwds2);
    #else
        value = __Pyx_CallUnboundCMethod2(&__pyx_mstate_global->__pyx_umethod_PyDict_Type_pop, kwds2, key, kwds2);
    #endif
        if (value == kwds2) {
            Py_DECREF(value);
        } else {
            if (unlikely(!value)) goto bad;
            values[name-argnames] = value;
        }
#endif
        name++;
    }
    len = PyDict_Size(kwds2);
    if (len > 0) {
        return __Pyx_ValidateDuplicatePosArgs(kwds, argnames, first_kw_arg, function_name);
    } else if (unlikely(len == -1)) {
        goto bad;
    }
    return 0;
bad:
    return -1;
}
static int __Pyx_ParseKeywordsTuple(
    PyObject *kwds,
    PyObject * const *kwvalues,
    PyObject ** const argnames[],
    PyObject *kwds2,
    PyObject *values[],
    Py_ssize_t num_pos_args,
    Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs)
{
    PyObject *key = NULL;
    PyObject** const * name;
    PyObject** const *first_kw_arg = argnames + num_pos_args;
    for (Py_ssize_t pos = 0; pos < num_kwargs; pos++) {
#if CYTHON_AVOID_BORROWED_REFS
        key = __Pyx_PySequence_ITEM(kwds, pos);
#else
        key = __Pyx_PyTuple_GET_ITEM(kwds, pos);
#endif
#if !CYTHON_ASSUME_SAFE_MACROS
        if (unlikely(!key)) goto bad;
#endif
        name = first_kw_arg;
        while (*name && (**name != key)) name++;
        if (*name) {
            PyObject *value = kwvalues[pos];
            values[name-argnames] = __Pyx_NewRef(value);
        } else {
            size_t index_found = 0;
            int cmp = __Pyx_MatchKeywordArg(key, argnames, first_kw_arg, &index_found, function_name);
            if (cmp == 1) {
                PyObject *value = kwvalues[pos];
                values[index_found] = __Pyx_NewRef(value);
            } else {
                if (unlikely(cmp == -1)) goto bad;
                if (kwds2) {
                    PyObject *value = kwvalues[pos];
                    if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad;
                } else if (!ignore_unknown_kwargs) {
                    goto invalid_keyword;
                }
            }
        }
        #if CYTHON_AVOID_BORROWED_REFS
        Py_DECREF(key);
        key = NULL;
        #endif
    }
    return 0;
invalid_keyword:
    PyErr_Format(PyExc_TypeError,
        "%s() got an unexpected keyword argument '%U'",
        function_name, key);
    goto bad;
bad:
    #if CYTHON_AVOID_BORROWED_REFS
    Py_XDECREF(key);
    #endif
    return -1;
}

/* ParseKeywords */
static int __Pyx_ParseKeywords(
    PyObject *kwds,
    PyObject * const *kwvalues,
    PyObject ** const argnames[],
    PyObject *kwds2,
    PyObject *values[],
    Py_ssize_t num_pos_args,
    Py_ssize_t num_kwargs,
    const char* function_name,
    int ignore_unknown_kwargs)
{
    if (CYTHON_METH_FASTCALL && likely(PyTuple_Check(kwds)))
        return __Pyx_ParseKeywordsTuple(kwds, kwvalues, argnames, kwds2, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs);
    else if (kwds2)
        return __Pyx_ParseKeywordDictToDict(kwds, argnames, kwds2, values, num_pos_args, function_name);
    else
        return __Pyx_ParseKeywordDict(kwds, argnames, values, num_pos_args, num_kwargs, function_name, ignore_unknown_kwargs);
}

/* RaiseArgTupleInvalid */
static void __Pyx_RaiseArgtupleInvalid(
    const char* func_name,
    int exact,
    Py_ssize_t num_min,
    Py_ssize_t num_max,
    Py_ssize_t num_found)
{
    Py_ssize_t num_expected;
    const char *more_or_less;
    if (num_found < num_min) {
        num_expected = num_min;
        more_or_less = "at least";
    } else {
        num_expected = num_max;
        more_or_less = "at most";
    }
    if (exact) {
        more_or_less = "exactly";
    }
    PyErr_Format(PyExc_TypeError,
                 "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)",
                 func_name, more_or_less, num_expected,
                 (num_expected == 1) ? "" : "s", num_found);
}

/* PyObjectFastCallMethod */
#if !CYTHON_VECTORCALL || PY_VERSION_HEX < 0x03090000
static PyObject *__Pyx_PyObject_FastCallMethod(PyObject *name, PyObject *const *args, size_t nargsf) {
    PyObject *result;
    PyObject *attr = PyObject_GetAttr(args[0], name);
    if (unlikely(!attr))
        return NULL;
    result = __Pyx_PyObject_FastCall(attr, args+1, nargsf - 1);
    Py_DECREF(attr);
    return result;
}
#endif

/* DictGetItem */
#if !CYTHON_COMPILING_IN_PYPY
static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) {
    PyObject *value;
    if (unlikely(__Pyx_PyDict_GetItemRef(d, key, &value) == 0)) { // no value, no error
        if (unlikely(PyTuple_Check(key))) {
            PyObject* args = PyTuple_Pack(1, key);
            if (likely(args)) {
                PyErr_SetObject(PyExc_KeyError, args);
                Py_DECREF(args);
            }
        } else {
            PyErr_SetObject(PyExc_KeyError, key);
        }
    }
    return value;
}
#endif

/* PyLongBinop */
#if !CYTHON_COMPILING_IN_PYPY
static PyObject* __Pyx_Fallback___Pyx_PyLong_SubtractObjC(PyObject *op1, PyObject *op2, int inplace) {
    return (inplace ? PyNumber_InPlaceSubtract : PyNumber_Subtract)(op1, op2);
}
#if CYTHON_USE_PYLONG_INTERNALS
static PyObject* __Pyx_Unpacked___Pyx_PyLong_SubtractObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
    CYTHON_MAYBE_UNUSED_VAR(inplace);
    CYTHON_UNUSED_VAR(zerodivision_check);
    const long b = intval;
    long a;
    const PY_LONG_LONG llb = intval;
    PY_LONG_LONG lla;
    if (unlikely(__Pyx_PyLong_IsZero(op1))) {
        return PyLong_FromLong(-intval);
    }
    const int is_positive = __Pyx_PyLong_IsPos(op1);
    const digit* digits = __Pyx_PyLong_Digits(op1);
    const Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
    if (likely(size == 1)) {
        a = (long) digits[0];
        if (!is_positive) a *= -1;
    } else {
        switch (size) {
            case 2:
                if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) {
                    a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
            case 3:
                if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) {
                    a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
            case 4:
                if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) {
                    a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
        }
        return PyLong_Type.tp_as_number->nb_subtract(op1, op2);
    }
    calculate_long:
        {
            long x;
            x = a - b;
            return PyLong_FromLong(x);
        }
    calculate_long_long:
        {
            PY_LONG_LONG llx;
            llx = lla - llb;
            return PyLong_FromLongLong(llx);
        }
    
}
#endif
static PyObject* __Pyx_Float___Pyx_PyLong_SubtractObjC(PyObject *float_val, long intval, int zerodivision_check) {
    CYTHON_UNUSED_VAR(zerodivision_check);
    const long b = intval;
    double a = __Pyx_PyFloat_AS_DOUBLE(float_val);
        double result;
        
        result = ((double)a) - (double)b;
        return PyFloat_FromDouble(result);
}
static CYTHON_INLINE PyObject* __Pyx_PyLong_SubtractObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
    CYTHON_MAYBE_UNUSED_VAR(intval);
    CYTHON_UNUSED_VAR(zerodivision_check);
    #if CYTHON_USE_PYLONG_INTERNALS
    if (likely(PyLong_CheckExact(op1))) {
        return __Pyx_Unpacked___Pyx_PyLong_SubtractObjC(op1, op2, intval, inplace, zerodivision_check);
    }
    #endif
    if (PyFloat_CheckExact(op1)) {
        return __Pyx_Float___Pyx_PyLong_SubtractObjC(op1, intval, zerodivision_check);
    }
    return __Pyx_Fallback___Pyx_PyLong_SubtractObjC(op1, op2, inplace);
}
#endif

/* PyLongBinop */
#if !CYTHON_COMPILING_IN_PYPY
static PyObject* __Pyx_Fallback___Pyx_PyLong_AddObjC(PyObject *op1, PyObject *op2, int inplace) {
    return (inplace ? PyNumber_InPlaceAdd : PyNumber_Add)(op1, op2);
}
#if CYTHON_USE_PYLONG_INTERNALS
static PyObject* __Pyx_Unpacked___Pyx_PyLong_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
    CYTHON_MAYBE_UNUSED_VAR(inplace);
    CYTHON_UNUSED_VAR(zerodivision_check);
    const long b = intval;
    long a;
    const PY_LONG_LONG llb = intval;
    PY_LONG_LONG lla;
    if (unlikely(__Pyx_PyLong_IsZero(op1))) {
        return __Pyx_NewRef(op2);
    }
    const int is_positive = __Pyx_PyLong_IsPos(op1);
    const digit* digits = __Pyx_PyLong_Digits(op1);
    const Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
    if (likely(size == 1)) {
        a = (long) digits[0];
        if (!is_positive) a *= -1;
    } else {
        switch (size) {
            case 2:
                if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) {
                    a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
            case 3:
                if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) {
                    a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
            case 4:
                if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) {
                    a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                    if (!is_positive) a *= -1;
                    goto calculate_long;
                } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT) {
                    lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                    if (!is_positive) lla *= -1;
                    goto calculate_long_long;
                }
                break;
        }
        return PyLong_Type.tp_as_number->nb_add(op1, op2);
    }
    calculate_long:
        {
            long x;
            x = a + b;
            return PyLong_FromLong(x);
        }
    calculate_long_long:
        {
            PY_LONG_LONG llx;
            llx = lla + llb;
            return PyLong_FromLongLong(llx);
        }
    
}
#endif
static PyObject* __Pyx_Float___Pyx_PyLong_AddObjC(PyObject *float_val, long intval, int zerodivision_check) {
    CYTHON_UNUSED_VAR(zerodivision_check);
    const long b = intval;
    double a = __Pyx_PyFloat_AS_DOUBLE(float_val);
        double result;
        
        result = ((double)a) + (double)b;
        return PyFloat_FromDouble(result);
}
static CYTHON_INLINE PyObject* __Pyx_PyLong_AddObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
    CYTHON_MAYBE_UNUSED_VAR(intval);
    CYTHON_UNUSED_VAR(zerodivision_check);
    #if CYTHON_USE_PYLONG_INTERNALS
    if (likely(PyLong_CheckExact(op1))) {
        return __Pyx_Unpacked___Pyx_PyLong_AddObjC(op1, op2, intval, inplace, zerodivision_check);
    }
    #endif
    if (PyFloat_CheckExact(op1)) {
        return __Pyx_Float___Pyx_PyLong_AddObjC(op1, intval, zerodivision_check);
    }
    return __Pyx_Fallback___Pyx_PyLong_AddObjC(op1, op2, inplace);
}
#endif

/* RaiseTooManyValuesToUnpack */
static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) {
    PyErr_Format(PyExc_ValueError,
                 "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected);
}

/* RaiseNeedMoreValuesToUnpack */
static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) {
    PyErr_Format(PyExc_ValueError,
                 "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack",
                 index, (index == 1) ? "" : "s");
}

/* IterFinish */
static CYTHON_INLINE int __Pyx_IterFinish(void) {
    PyObject* exc_type;
    __Pyx_PyThreadState_declare
    __Pyx_PyThreadState_assign
    exc_type = __Pyx_PyErr_CurrentExceptionType();
    if (unlikely(exc_type)) {
        if (unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration)))
            return -1;
        __Pyx_PyErr_Clear();
        return 0;
    }
    return 0;
}

/* UnpackItemEndCheck */
static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
    if (unlikely(retval)) {
        Py_DECREF(retval);
        __Pyx_RaiseTooManyValuesError(expected);
        return -1;
    }
    return __Pyx_IterFinish();
}

/* PyDictVersioning (used by GetModuleGlobalName) */
#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS
static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) {
    PyObject *dict = Py_TYPE(obj)->tp_dict;
    return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0;
}
static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) {
    PyObject **dictptr = NULL;
    Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset;
    if (offset) {
#if CYTHON_COMPILING_IN_CPYTHON
        dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj);
#else
        dictptr = _PyObject_GetDictPtr(obj);
#endif
    }
    return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0;
}
static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) {
    PyObject *dict = Py_TYPE(obj)->tp_dict;
    if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict)))
        return 0;
    return obj_dict_version == __Pyx_get_object_dict_version(obj);
}
#endif

/* GetModuleGlobalName */
#if CYTHON_USE_DICT_VERSIONS
static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value)
#else
static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
#endif
{
    PyObject *result;
#if CYTHON_COMPILING_IN_LIMITED_API
    if (unlikely(!__pyx_m)) {
        if (!PyErr_Occurred())
            PyErr_SetNone(PyExc_NameError);
        return NULL;
    }
    result = PyObject_GetAttr(__pyx_m, name);
    if (likely(result)) {
        return result;
    }
    PyErr_Clear();
#elif CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS
    if (unlikely(__Pyx_PyDict_GetItemRef(__pyx_mstate_global->__pyx_d, name, &result) == -1)) PyErr_Clear();
    __PYX_UPDATE_DICT_CACHE(__pyx_mstate_global->__pyx_d, result, *dict_cached_value, *dict_version)
    if (likely(result)) {
        return result;
    }
#else
    result = _PyDict_GetItem_KnownHash(__pyx_mstate_global->__pyx_d, name, ((PyASCIIObject *) name)->hash);
    __PYX_UPDATE_DICT_CACHE(__pyx_mstate_global->__pyx_d, result, *dict_cached_value, *dict_version)
    if (likely(result)) {
        return __Pyx_NewRef(result);
    }
    PyErr_Clear();
#endif
    return __Pyx_GetBuiltinName(name);
}

/* GetItemInt */
static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
    PyObject *r;
    if (unlikely(!j)) return NULL;
    r = PyObject_GetItem(o, j);
    Py_DECREF(j);
    return r;
}
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
                                                              int wraparound, int boundscheck, int unsafe_shared) {
    CYTHON_MAYBE_UNUSED_VAR(unsafe_shared);
#if CYTHON_ASSUME_SAFE_SIZE
    Py_ssize_t wrapped_i = i;
    if (wraparound & unlikely(i < 0)) {
        wrapped_i += PyList_GET_SIZE(o);
    }
    if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS)) {
        return __Pyx_PyList_GetItemRefFast(o, wrapped_i, unsafe_shared);
    } else
    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) {
        return __Pyx_NewRef(PyList_GET_ITEM(o, wrapped_i));
    }
    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
#else
    (void)wraparound;
    (void)boundscheck;
    return PySequence_GetItem(o, i);
#endif
}
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
                                                              int wraparound, int boundscheck, int unsafe_shared) {
    CYTHON_MAYBE_UNUSED_VAR(unsafe_shared);
#if CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    Py_ssize_t wrapped_i = i;
    if (wraparound & unlikely(i < 0)) {
        wrapped_i += PyTuple_GET_SIZE(o);
    }
    if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) {
        return __Pyx_NewRef(PyTuple_GET_ITEM(o, wrapped_i));
    }
    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
#else
    (void)wraparound;
    (void)boundscheck;
    return PySequence_GetItem(o, i);
#endif
}
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list,
                                                     int wraparound, int boundscheck, int unsafe_shared) {
    CYTHON_MAYBE_UNUSED_VAR(unsafe_shared);
#if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
    if (is_list || PyList_CheckExact(o)) {
        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
        if ((CYTHON_AVOID_BORROWED_REFS || CYTHON_AVOID_THREAD_UNSAFE_BORROWED_REFS)) {
            return __Pyx_PyList_GetItemRefFast(o, n, unsafe_shared);
        } else if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) {
            return __Pyx_NewRef(PyList_GET_ITEM(o, n));
        }
    } else
    #if !CYTHON_AVOID_BORROWED_REFS
    if (PyTuple_CheckExact(o)) {
        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
        if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) {
            return __Pyx_NewRef(PyTuple_GET_ITEM(o, n));
        }
    } else
    #endif
#endif
#if CYTHON_USE_TYPE_SLOTS && !CYTHON_COMPILING_IN_PYPY
    {
        PyMappingMethods *mm = Py_TYPE(o)->tp_as_mapping;
        PySequenceMethods *sm = Py_TYPE(o)->tp_as_sequence;
        if (!is_list && mm && mm->mp_subscript) {
            PyObject *r, *key = PyLong_FromSsize_t(i);
            if (unlikely(!key)) return NULL;
            r = mm->mp_subscript(o, key);
            Py_DECREF(key);
            return r;
        }
        if (is_list || likely(sm && sm->sq_item)) {
            if (wraparound && unlikely(i < 0) && likely(sm->sq_length)) {
                Py_ssize_t l = sm->sq_length(o);
                if (likely(l >= 0)) {
                    i += l;
                } else {
                    if (!PyErr_ExceptionMatches(PyExc_OverflowError))
                        return NULL;
                    PyErr_Clear();
                }
            }
            return sm->sq_item(o, i);
        }
    }
#else
    if (is_list || !PyMapping_Check(o)) {
        return PySequence_GetItem(o, i);
    }
#endif
    (void)wraparound;
    (void)boundscheck;
    return __Pyx_GetItemInt_Generic(o, PyLong_FromSsize_t(i));
}

/* ObjectGetItem */
#if CYTHON_USE_TYPE_SLOTS
static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject *index) {
    PyObject *runerr = NULL;
    Py_ssize_t key_value;
    key_value = __Pyx_PyIndex_AsSsize_t(index);
    if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) {
        return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1, 1);
    }
    if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) {
        __Pyx_TypeName index_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(index));
        PyErr_Clear();
        PyErr_Format(PyExc_IndexError,
            "cannot fit '" __Pyx_FMT_TYPENAME "' into an index-sized integer", index_type_name);
        __Pyx_DECREF_TypeName(index_type_name);
    }
    return NULL;
}
static PyObject *__Pyx_PyObject_GetItem_Slow(PyObject *obj, PyObject *key) {
    __Pyx_TypeName obj_type_name;
    if (likely(PyType_Check(obj))) {
        PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(obj, __pyx_mstate_global->__pyx_n_u_class_getitem);
        if (!meth) {
            PyErr_Clear();
        } else {
            PyObject *result = __Pyx_PyObject_CallOneArg(meth, key);
            Py_DECREF(meth);
            return result;
        }
    }
    obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj));
    PyErr_Format(PyExc_TypeError,
        "'" __Pyx_FMT_TYPENAME "' object is not subscriptable", obj_type_name);
    __Pyx_DECREF_TypeName(obj_type_name);
    return NULL;
}
static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject *key) {
    PyTypeObject *tp = Py_TYPE(obj);
    PyMappingMethods *mm = tp->tp_as_mapping;
    PySequenceMethods *sm = tp->tp_as_sequence;
    if (likely(mm && mm->mp_subscript)) {
        return mm->mp_subscript(obj, key);
    }
    if (likely(sm && sm->sq_item)) {
        return __Pyx_PyObject_GetIndex(obj, key);
    }
    return __Pyx_PyObject_GetItem_Slow(obj, key);
}
#endif

/* PyObjectVectorCallKwBuilder */
#if CYTHON_VECTORCALL
static int __Pyx_VectorcallBuilder_AddArg(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) {
    (void)__Pyx_PyObject_FastCallDict;
    if (__Pyx_PyTuple_SET_ITEM(builder, n, key) != (0)) return -1;
    Py_INCREF(key);
    args[n] = value;
    return 0;
}
CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, PyObject **args, int n) {
    (void)__Pyx_VectorcallBuilder_AddArgStr;
    if (unlikely(!PyUnicode_Check(key))) {
        PyErr_SetString(PyExc_TypeError, "keywords must be strings");
        return -1;
    }
    return __Pyx_VectorcallBuilder_AddArg(key, value, builder, args, n);
}
static int __Pyx_VectorcallBuilder_AddArgStr(const char *key, PyObject *value, PyObject *builder, PyObject **args, int n) {
    PyObject *pyKey = PyUnicode_FromString(key);
    if (!pyKey) return -1;
    return __Pyx_VectorcallBuilder_AddArg(pyKey, value, builder, args, n);
}
#else // CYTHON_VECTORCALL
CYTHON_UNUSED static int __Pyx_VectorcallBuilder_AddArg_Check(PyObject *key, PyObject *value, PyObject *builder, CYTHON_UNUSED PyObject **args, CYTHON_UNUSED int n) {
    if (unlikely(!PyUnicode_Check(key))) {
        PyErr_SetString(PyExc_TypeError, "keywords must be strings");
        return -1;
    }
    return PyDict_SetItem(builder, key, value);
}
#endif

/* PyObjectVectorCallMethodKwBuilder */
#if !CYTHON_VECTORCALL || PY_VERSION_HEX < 0x03090000
static PyObject *__Pyx_Object_VectorcallMethod_CallFromBuilder(PyObject *name, PyObject *const *args, size_t nargsf, PyObject *kwnames) {
    PyObject *result;
    PyObject *obj = PyObject_GetAttr(args[0], name);
    if (unlikely(!obj))
        return NULL;
    result = __Pyx_Object_Vectorcall_CallFromBuilder(obj, args+1, nargsf-1, kwnames);
    Py_DECREF(obj);
    return result;
}
#endif

/* CIntToDigits (used by CIntToPyUnicode) */
static const char DIGIT_PAIRS_10[2*10*10+1] = {
    "00010203040506070809"
    "10111213141516171819"
    "20212223242526272829"
    "30313233343536373839"
    "40414243444546474849"
    "50515253545556575859"
    "60616263646566676869"
    "70717273747576777879"
    "80818283848586878889"
    "90919293949596979899"
};
static const char DIGIT_PAIRS_8[2*8*8+1] = {
    "0001020304050607"
    "1011121314151617"
    "2021222324252627"
    "3031323334353637"
    "4041424344454647"
    "5051525354555657"
    "6061626364656667"
    "7071727374757677"
};
static const char DIGITS_HEX[2*16+1] = {
    "0123456789abcdef"
    "0123456789ABCDEF"
};

/* BuildPyUnicode (used by COrdinalToPyUnicode) */
static PyObject* __Pyx_PyUnicode_BuildFromAscii(Py_ssize_t ulength, const char* chars, int clength,
                                                int prepend_sign, char padding_char) {
    PyObject *uval;
    Py_ssize_t uoffset = ulength - clength;
#if CYTHON_USE_UNICODE_INTERNALS
    Py_ssize_t i;
    void *udata;
    uval = PyUnicode_New(ulength, 127);
    if (unlikely(!uval)) return NULL;
    udata = PyUnicode_DATA(uval);
    if (uoffset > 0) {
        i = 0;
        if (prepend_sign) {
            __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, 0, '-');
            i++;
        }
        for (; i < uoffset; i++) {
            __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, i, padding_char);
        }
    }
    for (i=0; i < clength; i++) {
        __Pyx_PyUnicode_WRITE(PyUnicode_1BYTE_KIND, udata, uoffset+i, chars[i]);
    }
#else
    {
        PyObject *sign = NULL, *padding = NULL;
        uval = NULL;
        if (uoffset > 0) {
            prepend_sign = !!prepend_sign;
            if (uoffset > prepend_sign) {
                padding = PyUnicode_FromOrdinal(padding_char);
                if (likely(padding) && uoffset > prepend_sign + 1) {
                    PyObject *tmp = PySequence_Repeat(padding, uoffset - prepend_sign);
                    Py_DECREF(padding);
                    padding = tmp;
                }
                if (unlikely(!padding)) goto done_or_error;
            }
            if (prepend_sign) {
                sign = PyUnicode_FromOrdinal('-');
                if (unlikely(!sign)) goto done_or_error;
            }
        }
        uval = PyUnicode_DecodeASCII(chars, clength, NULL);
        if (likely(uval) && padding) {
            PyObject *tmp = PyUnicode_Concat(padding, uval);
            Py_DECREF(uval);
            uval = tmp;
        }
        if (likely(uval) && sign) {
            PyObject *tmp = PyUnicode_Concat(sign, uval);
            Py_DECREF(uval);
            uval = tmp;
        }
done_or_error:
        Py_XDECREF(padding);
        Py_XDECREF(sign);
    }
#endif
    return uval;
}

/* COrdinalToPyUnicode (used by CIntToPyUnicode) */
static CYTHON_INLINE int __Pyx_CheckUnicodeValue(int value) {
    return value <= 1114111;
}
static PyObject* __Pyx_PyUnicode_FromOrdinal_Padded(int value, Py_ssize_t ulength, char padding_char) {
    Py_ssize_t padding_length = ulength - 1;
    if (likely((padding_length <= 250) && (value < 0xD800 || value > 0xDFFF))) {
        char chars[256];
        if (value <= 255) {
            memset(chars, padding_char, (size_t) padding_length);
            chars[ulength-1] = (char) value;
            return PyUnicode_DecodeLatin1(chars, ulength, NULL);
        }
        char *cpos = chars + sizeof(chars);
        if (value < 0x800) {
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0xc0 | (value & 0x1f));
        } else if (value < 0x10000) {
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0xe0 | (value & 0x0f));
        } else {
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0x80 | (value & 0x3f));
            value >>= 6;
            *--cpos = (char) (0xf0 | (value & 0x07));
        }
        cpos -= padding_length;
        memset(cpos, padding_char, (size_t) padding_length);
        return PyUnicode_DecodeUTF8(cpos, chars + sizeof(chars) - cpos, NULL);
    }
    if (value <= 127 && CYTHON_USE_UNICODE_INTERNALS) {
        const char chars[1] = {(char) value};
        return __Pyx_PyUnicode_BuildFromAscii(ulength, chars, 1, 0, padding_char);
    }
    {
        PyObject *uchar, *padding_uchar, *padding, *result;
        padding_uchar = PyUnicode_FromOrdinal(padding_char);
        if (unlikely(!padding_uchar)) return NULL;
        padding = PySequence_Repeat(padding_uchar, padding_length);
        Py_DECREF(padding_uchar);
        if (unlikely(!padding)) return NULL;
        uchar = PyUnicode_FromOrdinal(value);
        if (unlikely(!uchar)) {
            Py_DECREF(padding);
            return NULL;
        }
        result = PyUnicode_Concat(padding, uchar);
        Py_DECREF(padding);
        Py_DECREF(uchar);
        return result;
    }
}

/* CIntToPyUnicode */
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_unsigned_long(unsigned long value, Py_ssize_t width, char padding_char) {
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
    const unsigned long neg_one = (unsigned long) -1, const_zero = (unsigned long) 0;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
    const int is_unsigned = neg_one > const_zero;
    if (unlikely(!(is_unsigned || value == 0 || value > 0) ||
                    !(sizeof(value) <= 2 || value & ~ (unsigned long) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) {
        PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)");
        return NULL;
    }
    if (width <= 1) {
        return PyUnicode_FromOrdinal((int) value);
    }
    return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char);
}
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_unsigned_long(unsigned long value, Py_ssize_t width, char padding_char, char format_char) {
    char digits[sizeof(unsigned long)*3+2];
    char *dpos, *end = digits + sizeof(unsigned long)*3+2;
    const char *hex_digits = DIGITS_HEX;
    Py_ssize_t length, ulength;
    int prepend_sign, last_one_off;
    unsigned long remaining;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
    const unsigned long neg_one = (unsigned long) -1, const_zero = (unsigned long) 0;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
    const int is_unsigned = neg_one > const_zero;
    if (format_char == 'X') {
        hex_digits += 16;
        format_char = 'x';
    }
    remaining = value;
    last_one_off = 0;
    dpos = end;
    do {
        int digit_pos;
        switch (format_char) {
        case 'o':
            digit_pos = abs((int)(remaining % (8*8)));
            remaining = (unsigned long) (remaining / (8*8));
            dpos -= 2;
            memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);
            last_one_off = (digit_pos < 8);
            break;
        case 'd':
            digit_pos = abs((int)(remaining % (10*10)));
            remaining = (unsigned long) (remaining / (10*10));
            dpos -= 2;
            memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2);
            last_one_off = (digit_pos < 10);
            break;
        case 'x':
            *(--dpos) = hex_digits[abs((int)(remaining % 16))];
            remaining = (unsigned long) (remaining / 16);
            break;
        default:
            assert(0);
            break;
        }
    } while (unlikely(remaining != 0));
    assert(!last_one_off || *dpos == '0');
    dpos += last_one_off;
    length = end - dpos;
    ulength = length;
    prepend_sign = 0;
    if (!is_unsigned && value <= neg_one) {
        if (padding_char == ' ' || width <= length + 1) {
            *(--dpos) = '-';
            ++length;
        } else {
            prepend_sign = 1;
        }
        ++ulength;
    }
    if (width > ulength) {
        ulength = width;
    }
    if (ulength == 1) {
        return PyUnicode_FromOrdinal(*dpos);
    }
    return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char);
}

/* CIntToPyUnicode */
static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_unsigned_int(unsigned int value, Py_ssize_t width, char padding_char) {
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
    const unsigned int neg_one = (unsigned int) -1, const_zero = (unsigned int) 0;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
    const int is_unsigned = neg_one > const_zero;
    if (unlikely(!(is_unsigned || value == 0 || value > 0) ||
                    !(sizeof(value) <= 2 || value & ~ (unsigned int) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) {
        PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)");
        return NULL;
    }
    if (width <= 1) {
        return PyUnicode_FromOrdinal((int) value);
    }
    return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char);
}
static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_unsigned_int(unsigned int value, Py_ssize_t width, char padding_char, char format_char) {
    char digits[sizeof(unsigned int)*3+2];
    char *dpos, *end = digits + sizeof(unsigned int)*3+2;
    const char *hex_digits = DIGITS_HEX;
    Py_ssize_t length, ulength;
    int prepend_sign, last_one_off;
    unsigned int remaining;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
    const unsigned int neg_one = (unsigned int) -1, const_zero = (unsigned int) 0;
#ifdef __Pyx_HAS_GCC_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
    const int is_unsigned = neg_one > const_zero;
    if (format_char == 'X') {
        hex_digits += 16;
        format_char = 'x';
    }
    remaining = value;
    last_one_off = 0;
    dpos = end;
    do {
        int digit_pos;
        switch (format_char) {
        case 'o':
            digit_pos = abs((int)(remaining % (8*8)));
            remaining = (unsigned int) (remaining / (8*8));
            dpos -= 2;
            memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);
            last_one_off = (digit_pos < 8);
            break;
        case 'd':
            digit_pos = abs((int)(remaining % (10*10)));
            remaining = (unsigned int) (remaining / (10*10));
            dpos -= 2;
            memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2);
            last_one_off = (digit_pos < 10);
            break;
        case 'x':
            *(--dpos) = hex_digits[abs((int)(remaining % 16))];
            remaining = (unsigned int) (remaining / 16);
            break;
        default:
            assert(0);
            break;
        }
    } while (unlikely(remaining != 0));
    assert(!last_one_off || *dpos == '0');
    dpos += last_one_off;
    length = end - dpos;
    ulength = length;
    prepend_sign = 0;
    if (!is_unsigned && value <= neg_one) {
        if (padding_char == ' ' || width <= length + 1) {
            *(--dpos) = '-';
            ++length;
        } else {
            prepend_sign = 1;
        }
        ++ulength;
    }
    if (width > ulength) {
        ulength = width;
    }
    if (ulength == 1) {
        return PyUnicode_FromOrdinal(*dpos);
    }
    return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char);
}

/* JoinPyUnicode */
static PyObject* __Pyx_PyUnicode_Join(PyObject** values, Py_ssize_t value_count, Py_ssize_t result_ulength,
                                      Py_UCS4 max_char) {
#if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    PyObject *result_uval;
    int result_ukind, kind_shift;
    Py_ssize_t i, char_pos;
    void *result_udata;
    if (max_char > 1114111) max_char = 1114111;
    result_uval = PyUnicode_New(result_ulength, max_char);
    if (unlikely(!result_uval)) return NULL;
    result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND;
    kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1;
    result_udata = PyUnicode_DATA(result_uval);
    assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0);
    if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - result_ulength < 0))
        goto overflow;
    char_pos = 0;
    for (i=0; i < value_count; i++) {
        int ukind;
        Py_ssize_t ulength;
        void *udata;
        PyObject *uval = values[i];
        #if !CYTHON_COMPILING_IN_LIMITED_API
        if (__Pyx_PyUnicode_READY(uval) == (-1))
            goto bad;
        #endif
        ulength = __Pyx_PyUnicode_GET_LENGTH(uval);
        #if !CYTHON_ASSUME_SAFE_SIZE
        if (unlikely(ulength < 0)) goto bad;
        #endif
        if (unlikely(!ulength))
            continue;
        if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos))
            goto overflow;
        ukind = __Pyx_PyUnicode_KIND(uval);
        udata = __Pyx_PyUnicode_DATA(uval);
        if (ukind == result_ukind) {
            memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift));
        } else {
            #if PY_VERSION_HEX >= 0x030d0000
            if (unlikely(PyUnicode_CopyCharacters(result_uval, char_pos, uval, 0, ulength) < 0)) goto bad;
            #elif CYTHON_COMPILING_IN_CPYTHON || defined(_PyUnicode_FastCopyCharacters)
            _PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength);
            #else
            Py_ssize_t j;
            for (j=0; j < ulength; j++) {
                Py_UCS4 uchar = __Pyx_PyUnicode_READ(ukind, udata, j);
                __Pyx_PyUnicode_WRITE(result_ukind, result_udata, char_pos+j, uchar);
            }
            #endif
        }
        char_pos += ulength;
    }
    return result_uval;
overflow:
    PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string");
bad:
    Py_DECREF(result_uval);
    return NULL;
#else
    Py_ssize_t i;
    PyObject *result = NULL;
    PyObject *value_tuple = PyTuple_New(value_count);
    if (unlikely(!value_tuple)) return NULL;
    CYTHON_UNUSED_VAR(max_char);
    CYTHON_UNUSED_VAR(result_ulength);
    for (i=0; i<value_count; i++) {
        if (__Pyx_PyTuple_SET_ITEM(value_tuple, i, values[i]) != (0)) goto bad;
        Py_INCREF(values[i]);
    }
    result = PyUnicode_Join(__pyx_mstate_global->__pyx_empty_unicode, value_tuple);
bad:
    Py_DECREF(value_tuple);
    return result;
#endif
}

/* PyLongCompare */
static CYTHON_INLINE int __Pyx_PyLong_BoolNeObjC(PyObject *op1, PyObject *op2, long intval, long inplace) {
    CYTHON_MAYBE_UNUSED_VAR(intval);
    CYTHON_UNUSED_VAR(inplace);
    if (op1 == op2) {
        return 0;
    }
    #if CYTHON_USE_PYLONG_INTERNALS
    if (likely(PyLong_CheckExact(op1))) {
        int unequal;
        unsigned long uintval;
        Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
        const digit* digits = __Pyx_PyLong_Digits(op1);
        if (intval == 0) {
            return (__Pyx_PyLong_IsZero(op1) != 1);
        } else if (intval < 0) {
            if (__Pyx_PyLong_IsNonNeg(op1))
                return 1;
            intval = -intval;
        } else {
            if (__Pyx_PyLong_IsNeg(op1))
                return 1;
        }
        uintval = (unsigned long) intval;
#if PyLong_SHIFT * 4 < SIZEOF_LONG*8
        if (uintval >> (PyLong_SHIFT * 4)) {
            unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                 | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
        } else
#endif
#if PyLong_SHIFT * 3 < SIZEOF_LONG*8
        if (uintval >> (PyLong_SHIFT * 3)) {
            unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                 | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
        } else
#endif
#if PyLong_SHIFT * 2 < SIZEOF_LONG*8
        if (uintval >> (PyLong_SHIFT * 2)) {
            unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                 | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
        } else
#endif
#if PyLong_SHIFT * 1 < SIZEOF_LONG*8
        if (uintval >> (PyLong_SHIFT * 1)) {
            unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                 | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
        } else
#endif
            unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK));
        return (unequal != 0);
    }
    #endif
    if (PyFloat_CheckExact(op1)) {
        const long b = intval;
        double a = __Pyx_PyFloat_AS_DOUBLE(op1);
        return ((double)a != (double)b);
    }
    return __Pyx_PyObject_IsTrueAndDecref(
        PyObject_RichCompare(op1, op2, Py_NE));
}

/* ExtTypeTest */
static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
    __Pyx_TypeName obj_type_name;
    __Pyx_TypeName type_name;
    if (unlikely(!type)) {
        PyErr_SetString(PyExc_SystemError, "Missing type object");
        return 0;
    }
    if (likely(__Pyx_TypeCheck(obj, type)))
        return 1;
    obj_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(obj));
    type_name = __Pyx_PyType_GetFullyQualifiedName(type);
    PyErr_Format(PyExc_TypeError,
                 "Cannot convert " __Pyx_FMT_TYPENAME " to " __Pyx_FMT_TYPENAME,
                 obj_type_name, type_name);
    __Pyx_DECREF_TypeName(obj_type_name);
    __Pyx_DECREF_TypeName(type_name);
    return 0;
}

/* IsLittleEndian (used by BufferFormatCheck) */
static CYTHON_INLINE int __Pyx_Is_Little_Endian(void)
{
  union {
    uint32_t u32;
    uint8_t u8[4];
  } S;
  S.u32 = 0x01020304;
  return S.u8[0] == 4;
}

/* BufferFormatCheck (used by BufferGetAndValidate) */
static void __Pyx_BufFmt_Init(__Pyx_BufFmt_Context* ctx,
                              __Pyx_BufFmt_StackElem* stack,
                              const __Pyx_TypeInfo* type) {
  stack[0].field = &ctx->root;
  stack[0].parent_offset = 0;
  ctx->root.type = type;
  ctx->root.name = "buffer dtype";
  ctx->root.offset = 0;
  ctx->head = stack;
  ctx->head->field = &ctx->root;
  ctx->fmt_offset = 0;
  ctx->head->parent_offset = 0;
  ctx->new_packmode = '@';
  ctx->enc_packmode = '@';
  ctx->new_count = 1;
  ctx->enc_count = 0;
  ctx->enc_type = 0;
  ctx->is_complex = 0;
  ctx->is_valid_array = 0;
  ctx->struct_alignment = 0;
  while (type->typegroup == 'S') {
    ++ctx->head;
    ctx->head->field = type->fields;
    ctx->head->parent_offset = 0;
    type = type->fields->type;
  }
}
static int __Pyx_BufFmt_ParseNumber(const char** ts) {
    int count;
    const char* t = *ts;
    if (*t < '0' || *t > '9') {
      return -1;
    } else {
        count = *t++ - '0';
        while (*t >= '0' && *t <= '9') {
            count *= 10;
            count += *t++ - '0';
        }
    }
    *ts = t;
    return count;
}
static int __Pyx_BufFmt_ExpectNumber(const char **ts) {
    int number = __Pyx_BufFmt_ParseNumber(ts);
    if (number == -1)
        PyErr_Format(PyExc_ValueError,\
                     "Does not understand character buffer dtype format string ('%c')", **ts);
    return number;
}
static void __Pyx_BufFmt_RaiseUnexpectedChar(char ch) {
  PyErr_Format(PyExc_ValueError,
               "Unexpected format string character: '%c'", ch);
}
static const char* __Pyx_BufFmt_DescribeTypeChar(char ch, int is_complex) {
  switch (ch) {
    case '?': return "'bool'";
    case 'c': return "'char'";
    case 'b': return "'signed char'";
    case 'B': return "'unsigned char'";
    case 'h': return "'short'";
    case 'H': return "'unsigned short'";
    case 'i': return "'int'";
    case 'I': return "'unsigned int'";
    case 'l': return "'long'";
    case 'L': return "'unsigned long'";
    case 'q': return "'long long'";
    case 'Q': return "'unsigned long long'";
    case 'f': return (is_complex ? "'complex float'" : "'float'");
    case 'd': return (is_complex ? "'complex double'" : "'double'");
    case 'g': return (is_complex ? "'complex long double'" : "'long double'");
    case 'T': return "a struct";
    case 'O': return "Python object";
    case 'P': return "a pointer";
    case 's': case 'p': return "a string";
    case 0: return "end";
    default: return "unparsable format string";
  }
}
static size_t __Pyx_BufFmt_TypeCharToStandardSize(char ch, int is_complex) {
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    case 'h': case 'H': return 2;
    case 'i': case 'I': case 'l': case 'L': return 4;
    case 'q': case 'Q': return 8;
    case 'f': return (is_complex ? 8 : 4);
    case 'd': return (is_complex ? 16 : 8);
    case 'g': {
      PyErr_SetString(PyExc_ValueError, "Python does not define a standard format string size for long double ('g')..");
      return 0;
    }
    case 'O': case 'P': return sizeof(void*);
    default:
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
}
static size_t __Pyx_BufFmt_TypeCharToNativeSize(char ch, int is_complex) {
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    case 'h': case 'H': return sizeof(short);
    case 'i': case 'I': return sizeof(int);
    case 'l': case 'L': return sizeof(long);
    case 'q': case 'Q': return sizeof(PY_LONG_LONG);
    case 'f': return sizeof(float) * (is_complex ? 2 : 1);
    case 'd': return sizeof(double) * (is_complex ? 2 : 1);
    case 'g': return sizeof(long double) * (is_complex ? 2 : 1);
    case 'O': case 'P': return sizeof(void*);
    default: {
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
  }
}
typedef struct { char c; short x; } __Pyx_st_short;
typedef struct { char c; int x; } __Pyx_st_int;
typedef struct { char c; long x; } __Pyx_st_long;
typedef struct { char c; float x; } __Pyx_st_float;
typedef struct { char c; double x; } __Pyx_st_double;
typedef struct { char c; long double x; } __Pyx_st_longdouble;
typedef struct { char c; void *x; } __Pyx_st_void_p;
typedef struct { char c; PY_LONG_LONG x; } __Pyx_st_longlong;
static size_t __Pyx_BufFmt_TypeCharToAlignment(char ch, int is_complex) {
  CYTHON_UNUSED_VAR(is_complex);
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    case 'h': case 'H': return sizeof(__Pyx_st_short) - sizeof(short);
    case 'i': case 'I': return sizeof(__Pyx_st_int) - sizeof(int);
    case 'l': case 'L': return sizeof(__Pyx_st_long) - sizeof(long);
    case 'q': case 'Q': return sizeof(__Pyx_st_longlong) - sizeof(PY_LONG_LONG);
    case 'f': return sizeof(__Pyx_st_float) - sizeof(float);
    case 'd': return sizeof(__Pyx_st_double) - sizeof(double);
    case 'g': return sizeof(__Pyx_st_longdouble) - sizeof(long double);
    case 'P': case 'O': return sizeof(__Pyx_st_void_p) - sizeof(void*);
    default:
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
}
/* These are for computing the padding at the end of the struct to align
   on the first member of the struct. This will probably the same as above,
   but we don't have any guarantees.
 */
typedef struct { short x; char c; } __Pyx_pad_short;
typedef struct { int x; char c; } __Pyx_pad_int;
typedef struct { long x; char c; } __Pyx_pad_long;
typedef struct { float x; char c; } __Pyx_pad_float;
typedef struct { double x; char c; } __Pyx_pad_double;
typedef struct { long double x; char c; } __Pyx_pad_longdouble;
typedef struct { void *x; char c; } __Pyx_pad_void_p;
typedef struct { PY_LONG_LONG x; char c; } __Pyx_pad_longlong;
static size_t __Pyx_BufFmt_TypeCharToPadding(char ch, int is_complex) {
  CYTHON_UNUSED_VAR(is_complex);
  switch (ch) {
    case '?': case 'c': case 'b': case 'B': case 's': case 'p': return 1;
    case 'h': case 'H': return sizeof(__Pyx_pad_short) - sizeof(short);
    case 'i': case 'I': return sizeof(__Pyx_pad_int) - sizeof(int);
    case 'l': case 'L': return sizeof(__Pyx_pad_long) - sizeof(long);
    case 'q': case 'Q': return sizeof(__Pyx_pad_longlong) - sizeof(PY_LONG_LONG);
    case 'f': return sizeof(__Pyx_pad_float) - sizeof(float);
    case 'd': return sizeof(__Pyx_pad_double) - sizeof(double);
    case 'g': return sizeof(__Pyx_pad_longdouble) - sizeof(long double);
    case 'P': case 'O': return sizeof(__Pyx_pad_void_p) - sizeof(void*);
    default:
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
}
static char __Pyx_BufFmt_TypeCharToGroup(char ch, int is_complex) {
  switch (ch) {
    case 'c':
        return 'H';
    case 'b': case 'h': case 'i':
    case 'l': case 'q': case 's': case 'p':
        return 'I';
    case '?': case 'B': case 'H': case 'I': case 'L': case 'Q':
        return 'U';
    case 'f': case 'd': case 'g':
        return (is_complex ? 'C' : 'R');
    case 'O':
        return 'O';
    case 'P':
        return 'P';
    default: {
      __Pyx_BufFmt_RaiseUnexpectedChar(ch);
      return 0;
    }
  }
}
static void __Pyx_BufFmt_RaiseExpected(__Pyx_BufFmt_Context* ctx) {
  if (ctx->head == NULL || ctx->head->field == &ctx->root) {
    const char* expected;
    const char* quote;
    if (ctx->head == NULL) {
      expected = "end";
      quote = "";
    } else {
      expected = ctx->head->field->type->name;
      quote = "'";
    }
    PyErr_Format(PyExc_ValueError,
                 "Buffer dtype mismatch, expected %s%s%s but got %s",
                 quote, expected, quote,
                 __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex));
  } else {
    const __Pyx_StructField* field = ctx->head->field;
    const __Pyx_StructField* parent = (ctx->head - 1)->field;
    PyErr_Format(PyExc_ValueError,
                 "Buffer dtype mismatch, expected '%s' but got %s in '%s.%s'",
                 field->type->name, __Pyx_BufFmt_DescribeTypeChar(ctx->enc_type, ctx->is_complex),
                 parent->type->name, field->name);
  }
}
static int __Pyx_BufFmt_ProcessTypeChunk(__Pyx_BufFmt_Context* ctx) {
  char group;
  size_t size, offset, arraysize = 1;
  if (ctx->enc_type == 0) return 0;
  if (ctx->head->field->type->arraysize[0]) {
    int i, ndim = 0;
    if (ctx->enc_type == 's' || ctx->enc_type == 'p') {
        ctx->is_valid_array = ctx->head->field->type->ndim == 1;
        ndim = 1;
        if (ctx->enc_count != ctx->head->field->type->arraysize[0]) {
            PyErr_Format(PyExc_ValueError,
                         "Expected a dimension of size %zu, got %zu",
                         ctx->head->field->type->arraysize[0], ctx->enc_count);
            return -1;
        }
    }
    if (!ctx->is_valid_array) {
      PyErr_Format(PyExc_ValueError, "Expected %d dimensions, got %d",
                   ctx->head->field->type->ndim, ndim);
      return -1;
    }
    for (i = 0; i < ctx->head->field->type->ndim; i++) {
      arraysize *= ctx->head->field->type->arraysize[i];
    }
    ctx->is_valid_array = 0;
    ctx->enc_count = 1;
  }
  group = __Pyx_BufFmt_TypeCharToGroup(ctx->enc_type, ctx->is_complex);
  do {
    const __Pyx_StructField* field = ctx->head->field;
    const __Pyx_TypeInfo* type = field->type;
    if (ctx->enc_packmode == '@' || ctx->enc_packmode == '^') {
      size = __Pyx_BufFmt_TypeCharToNativeSize(ctx->enc_type, ctx->is_complex);
    } else {
      size = __Pyx_BufFmt_TypeCharToStandardSize(ctx->enc_type, ctx->is_complex);
    }
    if (ctx->enc_packmode == '@') {
      size_t align_at = __Pyx_BufFmt_TypeCharToAlignment(ctx->enc_type, ctx->is_complex);
      size_t align_mod_offset;
      if (align_at == 0) return -1;
      align_mod_offset = ctx->fmt_offset % align_at;
      if (align_mod_offset > 0) ctx->fmt_offset += align_at - align_mod_offset;
      if (ctx->struct_alignment == 0)
          ctx->struct_alignment = __Pyx_BufFmt_TypeCharToPadding(ctx->enc_type,
                                                                 ctx->is_complex);
    }
    if (type->size != size || type->typegroup != group) {
      if (type->typegroup == 'C' && type->fields != NULL) {
        size_t parent_offset = ctx->head->parent_offset + field->offset;
        ++ctx->head;
        ctx->head->field = type->fields;
        ctx->head->parent_offset = parent_offset;
        continue;
      }
      if ((type->typegroup == 'H' || group == 'H') && type->size == size) {
      } else {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return -1;
      }
    }
    offset = ctx->head->parent_offset + field->offset;
    if (ctx->fmt_offset != offset) {
      PyErr_Format(PyExc_ValueError,
                   "Buffer dtype mismatch; next field is at offset %" CYTHON_FORMAT_SSIZE_T "d but %" CYTHON_FORMAT_SSIZE_T "d expected",
                   (Py_ssize_t)ctx->fmt_offset, (Py_ssize_t)offset);
      return -1;
    }
    ctx->fmt_offset += size;
    if (arraysize)
      ctx->fmt_offset += (arraysize - 1) * size;
    --ctx->enc_count;
    while (1) {
      if (field == &ctx->root) {
        ctx->head = NULL;
        if (ctx->enc_count != 0) {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return -1;
        }
        break;
      }
      ctx->head->field = ++field;
      if (field->type == NULL) {
        --ctx->head;
        field = ctx->head->field;
        continue;
      } else if (field->type->typegroup == 'S') {
        size_t parent_offset = ctx->head->parent_offset + field->offset;
        if (field->type->fields->type == NULL) continue;
        field = field->type->fields;
        ++ctx->head;
        ctx->head->field = field;
        ctx->head->parent_offset = parent_offset;
        break;
      } else {
        break;
      }
    }
  } while (ctx->enc_count);
  ctx->enc_type = 0;
  ctx->is_complex = 0;
  return 0;
}
static int
__pyx_buffmt_parse_array(__Pyx_BufFmt_Context* ctx, const char** tsp)
{
    const char *ts = *tsp;
    int i = 0, number, ndim;
    ++ts;
    if (ctx->new_count != 1) {
        PyErr_SetString(PyExc_ValueError,
                        "Cannot handle repeated arrays in format string");
        return -1;
    }
    if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return -1;
    ndim = ctx->head->field->type->ndim;
    while (*ts && *ts != ')') {
        switch (*ts) {
            case ' ': case '\f': case '\r': case '\n': case '\t': case '\v':  continue;
            default:  break;
        }
        number = __Pyx_BufFmt_ExpectNumber(&ts);
        if (number == -1) return -1;
        if (i < ndim && (size_t) number != ctx->head->field->type->arraysize[i]) {
            PyErr_Format(PyExc_ValueError,
                        "Expected a dimension of size %zu, got %d",
                        ctx->head->field->type->arraysize[i], number);
            return -1;
        }
        if (*ts != ',' && *ts != ')') {
            PyErr_Format(PyExc_ValueError,
                                "Expected a comma in format string, got '%c'", *ts);
            return -1;
        }
        if (*ts == ',') ts++;
        i++;
    }
    if (i != ndim) {
        PyErr_Format(PyExc_ValueError, "Expected %d dimension(s), got %d",
                            ctx->head->field->type->ndim, i);
        return -1;
    }
    if (!*ts) {
        PyErr_SetString(PyExc_ValueError,
                        "Unexpected end of format string, expected ')'");
        return -1;
    }
    ctx->is_valid_array = 1;
    ctx->new_count = 1;
    *tsp = ++ts;
    return 0;
}
static const char* __Pyx_BufFmt_CheckString(__Pyx_BufFmt_Context* ctx, const char* ts) {
  int got_Z = 0;
  while (1) {
    switch(*ts) {
      case 0:
        if (ctx->enc_type != 0 && ctx->head == NULL) {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return NULL;
        }
        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
        if (ctx->head != NULL) {
          __Pyx_BufFmt_RaiseExpected(ctx);
          return NULL;
        }
        return ts;
      case ' ':
      case '\r':
      case '\n':
        ++ts;
        break;
      case '<':
        if (!__Pyx_Is_Little_Endian()) {
          PyErr_SetString(PyExc_ValueError, "Little-endian buffer not supported on big-endian compiler");
          return NULL;
        }
        ctx->new_packmode = '=';
        ++ts;
        break;
      case '>':
      case '!':
        if (__Pyx_Is_Little_Endian()) {
          PyErr_SetString(PyExc_ValueError, "Big-endian buffer not supported on little-endian compiler");
          return NULL;
        }
        ctx->new_packmode = '=';
        ++ts;
        break;
      case '=':
      case '@':
      case '^':
        ctx->new_packmode = *ts++;
        break;
      case 'T':
        {
          const char* ts_after_sub;
          size_t i, struct_count = ctx->new_count;
          size_t struct_alignment = ctx->struct_alignment;
          ctx->new_count = 1;
          ++ts;
          if (*ts != '{') {
            PyErr_SetString(PyExc_ValueError, "Buffer acquisition: Expected '{' after 'T'");
            return NULL;
          }
          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
          ctx->enc_type = 0;
          ctx->enc_count = 0;
          ctx->struct_alignment = 0;
          ++ts;
          ts_after_sub = ts;
          for (i = 0; i != struct_count; ++i) {
            ts_after_sub = __Pyx_BufFmt_CheckString(ctx, ts);
            if (!ts_after_sub) return NULL;
          }
          ts = ts_after_sub;
          if (struct_alignment) ctx->struct_alignment = struct_alignment;
        }
        break;
      case '}':
        {
          size_t alignment = ctx->struct_alignment;
          ++ts;
          if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
          ctx->enc_type = 0;
          if (alignment && ctx->fmt_offset % alignment) {
            ctx->fmt_offset += alignment - (ctx->fmt_offset % alignment);
          }
        }
        return ts;
      case 'x':
        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
        ctx->fmt_offset += ctx->new_count;
        ctx->new_count = 1;
        ctx->enc_count = 0;
        ctx->enc_type = 0;
        ctx->enc_packmode = ctx->new_packmode;
        ++ts;
        break;
      case 'Z':
        got_Z = 1;
        ++ts;
        if (*ts != 'f' && *ts != 'd' && *ts != 'g') {
          __Pyx_BufFmt_RaiseUnexpectedChar('Z');
          return NULL;
        }
        CYTHON_FALLTHROUGH;
      case '?': case 'c': case 'b': case 'B': case 'h': case 'H': case 'i': case 'I':
      case 'l': case 'L': case 'q': case 'Q':
      case 'f': case 'd': case 'g':
      case 'O': case 'p':
        if ((ctx->enc_type == *ts) && (got_Z == ctx->is_complex) &&
            (ctx->enc_packmode == ctx->new_packmode) && (!ctx->is_valid_array)) {
          ctx->enc_count += ctx->new_count;
          ctx->new_count = 1;
          got_Z = 0;
          ++ts;
          break;
        }
        CYTHON_FALLTHROUGH;
      case 's':
        if (__Pyx_BufFmt_ProcessTypeChunk(ctx) == -1) return NULL;
        ctx->enc_count = ctx->new_count;
        ctx->enc_packmode = ctx->new_packmode;
        ctx->enc_type = *ts;
        ctx->is_complex = got_Z;
        ++ts;
        ctx->new_count = 1;
        got_Z = 0;
        break;
      case ':':
        ++ts;
        while(*ts != ':') ++ts;
        ++ts;
        break;
      case '(':
        if (__pyx_buffmt_parse_array(ctx, &ts) < 0) return NULL;
        break;
      default:
        {
          int number = __Pyx_BufFmt_ExpectNumber(&ts);
          if (number == -1) return NULL;
          ctx->new_count = (size_t)number;
        }
    }
  }
}

/* BufferGetAndValidate */
  static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
    if (unlikely(info->buf == NULL)) return;
    if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
    PyBuffer_Release(info);
  }
  static void __Pyx_ZeroBuffer(Py_buffer* buf) {
    buf->buf = NULL;
    buf->obj = NULL;
    buf->strides = __Pyx_zeros;
    buf->shape = __Pyx_zeros;
    buf->suboffsets = __Pyx_minusones;
  }
  static int __Pyx__GetBufferAndValidate(
          Py_buffer* buf, PyObject* obj,  const __Pyx_TypeInfo* dtype, int flags,
          int nd, int cast, __Pyx_BufFmt_StackElem* stack)
  {
    buf->buf = NULL;
    if (unlikely(PyObject_GetBuffer(obj, buf, flags) == -1)) {
      __Pyx_ZeroBuffer(buf);
      return -1;
    }
    if (unlikely(buf->ndim != nd)) {
      PyErr_Format(PyExc_ValueError,
                   "Buffer has wrong number of dimensions (expected %d, got %d)",
                   nd, buf->ndim);
      goto fail;
    }
    if (!cast) {
      __Pyx_BufFmt_Context ctx;
      __Pyx_BufFmt_Init(&ctx, stack, dtype);
      if (!__Pyx_BufFmt_CheckString(&ctx, buf->format)) goto fail;
    }
    if (unlikely((size_t)buf->itemsize != dtype->size)) {
      PyErr_Format(PyExc_ValueError,
        "Item size of buffer (%" CYTHON_FORMAT_SSIZE_T "d byte%s) does not match size of '%s' (%" CYTHON_FORMAT_SSIZE_T "d byte%s)",
        buf->itemsize, (buf->itemsize > 1) ? "s" : "",
        dtype->name, (Py_ssize_t)dtype->size, (dtype->size > 1) ? "s" : "");
      goto fail;
    }
    if (buf->suboffsets == NULL) buf->suboffsets = __Pyx_minusones;
    return 0;
  fail:;
    __Pyx_SafeReleaseBuffer(buf);
    return -1;
  }
  
/* BufferFallbackError */
  static void __Pyx_RaiseBufferFallbackError(void) {
    PyErr_SetString(PyExc_ValueError,
       "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
  }
  
/* BufferIndexError */
  static void __Pyx_RaiseBufferIndexError(int axis) {
    PyErr_Format(PyExc_IndexError,
       "Out of bounds on buffer access (axis %d)", axis);
  }
  
/* pybytes_as_double (used by pyunicode_as_double) */
  static double __Pyx_SlowPyString_AsDouble(PyObject *obj) {
      PyObject *float_value = PyFloat_FromString(obj);
      if (likely(float_value)) {
          double value = __Pyx_PyFloat_AS_DOUBLE(float_value);
          Py_DECREF(float_value);
          return value;
      }
      return (double)-1;
  }
  static const char* __Pyx__PyBytes_AsDouble_Copy(const char* start, char* buffer, Py_ssize_t length) {
      int last_was_punctuation = 1;
      int parse_error_found = 0;
      Py_ssize_t i;
      for (i=0; i < length; i++) {
          char chr = start[i];
          int is_punctuation = (chr == '_') | (chr == '.') | (chr == 'e') | (chr == 'E');
          *buffer = chr;
          buffer += (chr != '_');
          parse_error_found |= last_was_punctuation & is_punctuation;
          last_was_punctuation = is_punctuation;
      }
      parse_error_found |= last_was_punctuation;
      *buffer = '\0';
      return unlikely(parse_error_found) ? NULL : buffer;
  }
  static double __Pyx__PyBytes_AsDouble_inf_nan(const char* start, Py_ssize_t length) {
      int matches = 1;
      char sign = start[0];
      int is_signed = (sign == '+') | (sign == '-');
      start += is_signed;
      length -= is_signed;
      switch (start[0]) {
          #ifdef Py_NAN
          case 'n':
          case 'N':
              if (unlikely(length != 3)) goto parse_failure;
              matches &= (start[1] == 'a' || start[1] == 'A');
              matches &= (start[2] == 'n' || start[2] == 'N');
              if (unlikely(!matches)) goto parse_failure;
              return (sign == '-') ? -Py_NAN : Py_NAN;
          #endif
          case 'i':
          case 'I':
              if (unlikely(length < 3)) goto parse_failure;
              matches &= (start[1] == 'n' || start[1] == 'N');
              matches &= (start[2] == 'f' || start[2] == 'F');
              if (likely(length == 3 && matches))
                  return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
              if (unlikely(length != 8)) goto parse_failure;
              matches &= (start[3] == 'i' || start[3] == 'I');
              matches &= (start[4] == 'n' || start[4] == 'N');
              matches &= (start[5] == 'i' || start[5] == 'I');
              matches &= (start[6] == 't' || start[6] == 'T');
              matches &= (start[7] == 'y' || start[7] == 'Y');
              if (unlikely(!matches)) goto parse_failure;
              return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
          case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
              break;
          default:
              goto parse_failure;
      }
      return 0.0;
  parse_failure:
      return -1.0;
  }
  static CYTHON_INLINE int __Pyx__PyBytes_AsDouble_IsSpace(char ch) {
      return (ch == 0x20) | !((ch < 0x9) | (ch > 0xd));
  }
  CYTHON_UNUSED static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length) {
      double value;
      Py_ssize_t i, digits;
      const char *last = start + length;
      char *end;
      while (__Pyx__PyBytes_AsDouble_IsSpace(*start))
          start++;
      while (start < last - 1 && __Pyx__PyBytes_AsDouble_IsSpace(last[-1]))
          last--;
      length = last - start;
      if (unlikely(length <= 0)) goto fallback;
      value = __Pyx__PyBytes_AsDouble_inf_nan(start, length);
      if (unlikely(value == -1.0)) goto fallback;
      if (value != 0.0) return value;
      digits = 0;
      for (i=0; i < length; digits += start[i++] != '_');
      if (likely(digits == length)) {
          value = PyOS_string_to_double(start, &end, NULL);
      } else if (digits < 40) {
          char number[40];
          last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
          if (unlikely(!last)) goto fallback;
          value = PyOS_string_to_double(number, &end, NULL);
      } else {
          char *number = (char*) PyMem_Malloc((digits + 1) * sizeof(char));
          if (unlikely(!number)) goto fallback;
          last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
          if (unlikely(!last)) {
              PyMem_Free(number);
              goto fallback;
          }
          value = PyOS_string_to_double(number, &end, NULL);
          PyMem_Free(number);
      }
      if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
          return value;
      }
  fallback:
      return __Pyx_SlowPyString_AsDouble(obj);
  }
  
/* ModInt[long] */
  static CYTHON_INLINE long __Pyx_mod_long(long a, long b, int b_is_constant) {
      long r = a % b;
      long adapt_python = (b_is_constant ?
          ((r != 0) & ((r < 0) ^ (b < 0))) :
          ((r != 0) & ((r ^ b) < 0))
      );
      return r + adapt_python * b;
  }
  
/* PyLongCompare */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_EqObjC(PyObject *op1, PyObject *op2, long intval, long inplace) {
      CYTHON_MAYBE_UNUSED_VAR(intval);
      CYTHON_UNUSED_VAR(inplace);
      if (op1 == op2) {
          Py_RETURN_TRUE;
      }
      #if CYTHON_USE_PYLONG_INTERNALS
      if (likely(PyLong_CheckExact(op1))) {
          int unequal;
          unsigned long uintval;
          Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
          const digit* digits = __Pyx_PyLong_Digits(op1);
          if (intval == 0) {
              if (__Pyx_PyLong_IsZero(op1) == 1) Py_RETURN_TRUE; else Py_RETURN_FALSE;
          } else if (intval < 0) {
              if (__Pyx_PyLong_IsNonNeg(op1))
                  Py_RETURN_FALSE;
              intval = -intval;
          } else {
              if (__Pyx_PyLong_IsNeg(op1))
                  Py_RETURN_FALSE;
          }
          uintval = (unsigned long) intval;
  #if PyLong_SHIFT * 4 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 4)) {
              unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 3 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 3)) {
              unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 2 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 2)) {
              unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 1 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 1)) {
              unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
              unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK));
          if (unequal == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE;
      }
      #endif
      if (PyFloat_CheckExact(op1)) {
          const long b = intval;
          double a = __Pyx_PyFloat_AS_DOUBLE(op1);
          if ((double)a == (double)b) Py_RETURN_TRUE; else Py_RETURN_FALSE;
      }
      return (
          PyObject_RichCompare(op1, op2, Py_EQ));
  }
  
/* CIntToPyUnicode */
  static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_long(long value, Py_ssize_t width, char padding_char) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const long neg_one = (long) -1, const_zero = (long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!(is_unsigned || value == 0 || value > 0) ||
                      !(sizeof(value) <= 2 || value & ~ (long) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) {
          PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)");
          return NULL;
      }
      if (width <= 1) {
          return PyUnicode_FromOrdinal((int) value);
      }
      return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char);
  }
  static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_long(long value, Py_ssize_t width, char padding_char, char format_char) {
      char digits[sizeof(long)*3+2];
      char *dpos, *end = digits + sizeof(long)*3+2;
      const char *hex_digits = DIGITS_HEX;
      Py_ssize_t length, ulength;
      int prepend_sign, last_one_off;
      long remaining;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const long neg_one = (long) -1, const_zero = (long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (format_char == 'X') {
          hex_digits += 16;
          format_char = 'x';
      }
      remaining = value;
      last_one_off = 0;
      dpos = end;
      do {
          int digit_pos;
          switch (format_char) {
          case 'o':
              digit_pos = abs((int)(remaining % (8*8)));
              remaining = (long) (remaining / (8*8));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 8);
              break;
          case 'd':
              digit_pos = abs((int)(remaining % (10*10)));
              remaining = (long) (remaining / (10*10));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 10);
              break;
          case 'x':
              *(--dpos) = hex_digits[abs((int)(remaining % 16))];
              remaining = (long) (remaining / 16);
              break;
          default:
              assert(0);
              break;
          }
      } while (unlikely(remaining != 0));
      assert(!last_one_off || *dpos == '0');
      dpos += last_one_off;
      length = end - dpos;
      ulength = length;
      prepend_sign = 0;
      if (!is_unsigned && value <= neg_one) {
          if (padding_char == ' ' || width <= length + 1) {
              *(--dpos) = '-';
              ++length;
          } else {
              prepend_sign = 1;
          }
          ++ulength;
      }
      if (width > ulength) {
          ulength = width;
      }
      if (ulength == 1) {
          return PyUnicode_FromOrdinal(*dpos);
      }
      return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char);
  }
  
/* PyObjectCall2Args (used by PyObjectCallMethod1) */
  static CYTHON_INLINE PyObject* __Pyx_PyObject_Call2Args(PyObject* function, PyObject* arg1, PyObject* arg2) {
      PyObject *args[3] = {NULL, arg1, arg2};
      return __Pyx_PyObject_FastCall(function, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
  }
  
/* PyObjectGetMethod (used by PyObjectCallMethod1) */
  #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
  static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) {
      PyObject *attr;
  #if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP
      __Pyx_TypeName type_name;
      PyTypeObject *tp = Py_TYPE(obj);
      PyObject *descr;
      descrgetfunc f = NULL;
      PyObject **dictptr, *dict;
      int meth_found = 0;
      assert (*method == NULL);
      if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) {
          attr = __Pyx_PyObject_GetAttrStr(obj, name);
          goto try_unpack;
      }
      if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) {
          return 0;
      }
      descr = _PyType_Lookup(tp, name);
      if (likely(descr != NULL)) {
          Py_INCREF(descr);
  #if defined(Py_TPFLAGS_METHOD_DESCRIPTOR) && Py_TPFLAGS_METHOD_DESCRIPTOR
          if (__Pyx_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR))
  #else
          #ifdef __Pyx_CyFunction_USED
          if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr)))
          #else
          if (likely(PyFunction_Check(descr) || __Pyx_IS_TYPE(descr, &PyMethodDescr_Type)))
          #endif
  #endif
          {
              meth_found = 1;
          } else {
              f = Py_TYPE(descr)->tp_descr_get;
              if (f != NULL && PyDescr_IsData(descr)) {
                  attr = f(descr, obj, (PyObject *)Py_TYPE(obj));
                  Py_DECREF(descr);
                  goto try_unpack;
              }
          }
      }
      dictptr = _PyObject_GetDictPtr(obj);
      if (dictptr != NULL && (dict = *dictptr) != NULL) {
          Py_INCREF(dict);
          attr = __Pyx_PyDict_GetItemStr(dict, name);
          if (attr != NULL) {
              Py_INCREF(attr);
              Py_DECREF(dict);
              Py_XDECREF(descr);
              goto try_unpack;
          }
          Py_DECREF(dict);
      }
      if (meth_found) {
          *method = descr;
          return 1;
      }
      if (f != NULL) {
          attr = f(descr, obj, (PyObject *)Py_TYPE(obj));
          Py_DECREF(descr);
          goto try_unpack;
      }
      if (likely(descr != NULL)) {
          *method = descr;
          return 0;
      }
      type_name = __Pyx_PyType_GetFullyQualifiedName(tp);
      PyErr_Format(PyExc_AttributeError,
                   "'" __Pyx_FMT_TYPENAME "' object has no attribute '%U'",
                   type_name, name);
      __Pyx_DECREF_TypeName(type_name);
      return 0;
  #else
      attr = __Pyx_PyObject_GetAttrStr(obj, name);
      goto try_unpack;
  #endif
  try_unpack:
  #if CYTHON_UNPACK_METHODS
      if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) {
          PyObject *function = PyMethod_GET_FUNCTION(attr);
          Py_INCREF(function);
          Py_DECREF(attr);
          *method = function;
          return 1;
      }
  #endif
      *method = attr;
      return 0;
  }
  #endif
  
/* PyObjectCallMethod1 (used by append) */
  #if !(CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000)))
  static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
      PyObject *result = __Pyx_PyObject_CallOneArg(method, arg);
      Py_DECREF(method);
      return result;
  }
  #endif
  static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg) {
  #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
      PyObject *args[2] = {obj, arg};
      (void) __Pyx_PyObject_CallOneArg;
      (void) __Pyx_PyObject_Call2Args;
      return PyObject_VectorcallMethod(method_name, args, 2 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
  #else
      PyObject *method = NULL, *result;
      int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
      if (likely(is_method)) {
          result = __Pyx_PyObject_Call2Args(method, obj, arg);
          Py_DECREF(method);
          return result;
      }
      if (unlikely(!method)) return NULL;
      return __Pyx__PyObject_CallMethod1(method, arg);
  #endif
  }
  
/* append */
  static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
      if (likely(PyList_CheckExact(L))) {
          if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return -1;
      } else {
          PyObject* retval = __Pyx_PyObject_CallMethod1(L, __pyx_mstate_global->__pyx_n_u_append, x);
          if (unlikely(!retval))
              return -1;
          Py_DECREF(retval);
      }
      return 0;
  }
  
/* CIntToPyUnicode */
  static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const int neg_one = (int) -1, const_zero = (int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!(is_unsigned || value == 0 || value > 0) ||
                      !(sizeof(value) <= 2 || value & ~ (int) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) {
          PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)");
          return NULL;
      }
      if (width <= 1) {
          return PyUnicode_FromOrdinal((int) value);
      }
      return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char);
  }
  static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_int(int value, Py_ssize_t width, char padding_char, char format_char) {
      char digits[sizeof(int)*3+2];
      char *dpos, *end = digits + sizeof(int)*3+2;
      const char *hex_digits = DIGITS_HEX;
      Py_ssize_t length, ulength;
      int prepend_sign, last_one_off;
      int remaining;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const int neg_one = (int) -1, const_zero = (int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (format_char == 'X') {
          hex_digits += 16;
          format_char = 'x';
      }
      remaining = value;
      last_one_off = 0;
      dpos = end;
      do {
          int digit_pos;
          switch (format_char) {
          case 'o':
              digit_pos = abs((int)(remaining % (8*8)));
              remaining = (int) (remaining / (8*8));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 8);
              break;
          case 'd':
              digit_pos = abs((int)(remaining % (10*10)));
              remaining = (int) (remaining / (10*10));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 10);
              break;
          case 'x':
              *(--dpos) = hex_digits[abs((int)(remaining % 16))];
              remaining = (int) (remaining / 16);
              break;
          default:
              assert(0);
              break;
          }
      } while (unlikely(remaining != 0));
      assert(!last_one_off || *dpos == '0');
      dpos += last_one_off;
      length = end - dpos;
      ulength = length;
      prepend_sign = 0;
      if (!is_unsigned && value <= neg_one) {
          if (padding_char == ' ' || width <= length + 1) {
              *(--dpos) = '-';
              ++length;
          } else {
              prepend_sign = 1;
          }
          ++ulength;
      }
      if (width > ulength) {
          ulength = width;
      }
      if (ulength == 1) {
          return PyUnicode_FromOrdinal(*dpos);
      }
      return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char);
  }
  
/* pop_index */
  static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) {
      PyObject *r;
      if (unlikely(!py_ix)) return NULL;
      r = __Pyx__PyObject_PopIndex(L, py_ix);
      Py_DECREF(py_ix);
      return r;
  }
  static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) {
      return __Pyx_PyObject_CallMethod1(L, __pyx_mstate_global->__pyx_n_u_pop, py_ix);
  }
  #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
  static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) {
      Py_ssize_t size = PyList_GET_SIZE(L);
      if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
          Py_ssize_t cix = ix;
          if (cix < 0) {
              cix += size;
          }
          if (likely(__Pyx_is_valid_index(cix, size))) {
              PyObject* v = PyList_GET_ITEM(L, cix);
              __Pyx_SET_SIZE(L, Py_SIZE(L) - 1);
              size -= 1;
              memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*));
              return v;
          }
      }
      if (py_ix == Py_None) {
          return __Pyx__PyObject_PopNewIndex(L, PyLong_FromSsize_t(ix));
      } else {
          return __Pyx__PyObject_PopIndex(L, py_ix);
      }
  }
  #endif
  
/* CIntToPyUnicode */
  static CYTHON_INLINE PyObject* __Pyx_uchar___Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const Py_ssize_t neg_one = (Py_ssize_t) -1, const_zero = (Py_ssize_t) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!(is_unsigned || value == 0 || value > 0) ||
                      !(sizeof(value) <= 2 || value & ~ (Py_ssize_t) 0x01fffff || __Pyx_CheckUnicodeValue((int) value)))) {
          PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000)");
          return NULL;
      }
      if (width <= 1) {
          return PyUnicode_FromOrdinal((int) value);
      }
      return __Pyx_PyUnicode_FromOrdinal_Padded((int) value, width, padding_char);
  }
  static CYTHON_INLINE PyObject* __Pyx____Pyx_PyUnicode_From_Py_ssize_t(Py_ssize_t value, Py_ssize_t width, char padding_char, char format_char) {
      char digits[sizeof(Py_ssize_t)*3+2];
      char *dpos, *end = digits + sizeof(Py_ssize_t)*3+2;
      const char *hex_digits = DIGITS_HEX;
      Py_ssize_t length, ulength;
      int prepend_sign, last_one_off;
      Py_ssize_t remaining;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const Py_ssize_t neg_one = (Py_ssize_t) -1, const_zero = (Py_ssize_t) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (format_char == 'X') {
          hex_digits += 16;
          format_char = 'x';
      }
      remaining = value;
      last_one_off = 0;
      dpos = end;
      do {
          int digit_pos;
          switch (format_char) {
          case 'o':
              digit_pos = abs((int)(remaining % (8*8)));
              remaining = (Py_ssize_t) (remaining / (8*8));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_8 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 8);
              break;
          case 'd':
              digit_pos = abs((int)(remaining % (10*10)));
              remaining = (Py_ssize_t) (remaining / (10*10));
              dpos -= 2;
              memcpy(dpos, DIGIT_PAIRS_10 + digit_pos * 2, 2);
              last_one_off = (digit_pos < 10);
              break;
          case 'x':
              *(--dpos) = hex_digits[abs((int)(remaining % 16))];
              remaining = (Py_ssize_t) (remaining / 16);
              break;
          default:
              assert(0);
              break;
          }
      } while (unlikely(remaining != 0));
      assert(!last_one_off || *dpos == '0');
      dpos += last_one_off;
      length = end - dpos;
      ulength = length;
      prepend_sign = 0;
      if (!is_unsigned && value <= neg_one) {
          if (padding_char == ' ' || width <= length + 1) {
              *(--dpos) = '-';
              ++length;
          } else {
              prepend_sign = 1;
          }
          ++ulength;
      }
      if (width > ulength) {
          ulength = width;
      }
      if (ulength == 1) {
          return PyUnicode_FromOrdinal(*dpos);
      }
      return __Pyx_PyUnicode_BuildFromAscii(ulength, dpos, (int) length, prepend_sign, padding_char);
  }
  
/* PyObjectCallNoArg (used by PyObjectCallMethod0) */
  static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
      PyObject *arg[2] = {NULL, NULL};
      return __Pyx_PyObject_FastCall(func, arg + 1, 0 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET);
  }
  
/* PyObjectCallMethod0 (used by pop) */
  static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) {
  #if CYTHON_VECTORCALL && (__PYX_LIMITED_VERSION_HEX >= 0x030C0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x03090000))
      PyObject *args[1] = {obj};
      (void) __Pyx_PyObject_CallOneArg;
      (void) __Pyx_PyObject_CallNoArg;
      return PyObject_VectorcallMethod(method_name, args, 1 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
  #else
      PyObject *method = NULL, *result = NULL;
      int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method);
      if (likely(is_method)) {
          result = __Pyx_PyObject_CallOneArg(method, obj);
          Py_DECREF(method);
          return result;
      }
      if (unlikely(!method)) goto bad;
      result = __Pyx_PyObject_CallNoArg(method);
      Py_DECREF(method);
  bad:
      return result;
  #endif
  }
  
/* pop */
  static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) {
      if (__Pyx_IS_TYPE(L, &PySet_Type)) {
          return PySet_Pop(L);
      }
      return __Pyx_PyObject_CallMethod0(L, __pyx_mstate_global->__pyx_n_u_pop);
  }
  #if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
  static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) {
      if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
          __Pyx_SET_SIZE(L, Py_SIZE(L) - 1);
          return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
      }
      return __Pyx_CallUnboundCMethod0(&__pyx_mstate_global->__pyx_umethod_PyList_Type_pop, L);
  }
  #endif
  
/* RaiseNoneIterError (used by UnpackTupleError) */
  static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) {
      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
  }
  
/* UnpackTupleError (used by UnpackTuple2) */
  static void __Pyx_UnpackTupleError(PyObject *t, Py_ssize_t index) {
      if (t == Py_None) {
        __Pyx_RaiseNoneNotIterableError();
      } else {
        Py_ssize_t size = __Pyx_PyTuple_GET_SIZE(t);
   #if !CYTHON_ASSUME_SAFE_SIZE
        if (unlikely(size < 0)) return;
   #endif
        if (size < index) {
          __Pyx_RaiseNeedMoreValuesError(size);
        } else {
          __Pyx_RaiseTooManyValuesError(index);
        }
      }
  }
  
/* UnpackTuple2 (used by dict_iter) */
  static CYTHON_INLINE int __Pyx_unpack_tuple2(
          PyObject* tuple, PyObject** value1, PyObject** value2, int is_tuple, int has_known_size, int decref_tuple) {
      if (likely(is_tuple || PyTuple_Check(tuple))) {
          Py_ssize_t size;
          if (has_known_size) {
              return __Pyx_unpack_tuple2_exact(tuple, value1, value2, decref_tuple);
          }
          size = __Pyx_PyTuple_GET_SIZE(tuple);
          if (likely(size == 2)) {
              return __Pyx_unpack_tuple2_exact(tuple, value1, value2, decref_tuple);
          }
          if (size >= 0) {
              __Pyx_UnpackTupleError(tuple, 2);
          }
          return -1;
      } else {
          return __Pyx_unpack_tuple2_generic(tuple, value1, value2, has_known_size, decref_tuple);
      }
  }
  static CYTHON_INLINE int __Pyx_unpack_tuple2_exact(
          PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2, int decref_tuple) {
      PyObject *value1 = NULL, *value2 = NULL;
  #if CYTHON_AVOID_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS
      value1 = __Pyx_PySequence_ITEM(tuple, 0);  if (unlikely(!value1)) goto bad;
      value2 = __Pyx_PySequence_ITEM(tuple, 1);  if (unlikely(!value2)) goto bad;
  #else
      value1 = PyTuple_GET_ITEM(tuple, 0);  Py_INCREF(value1);
      value2 = PyTuple_GET_ITEM(tuple, 1);  Py_INCREF(value2);
  #endif
      if (decref_tuple) {
          Py_DECREF(tuple);
      }
      *pvalue1 = value1;
      *pvalue2 = value2;
      return 0;
  #if CYTHON_AVOID_BORROWED_REFS || !CYTHON_ASSUME_SAFE_MACROS
  bad:
      Py_XDECREF(value1);
      Py_XDECREF(value2);
      if (decref_tuple) { Py_XDECREF(tuple); }
      return -1;
  #endif
  }
  static int __Pyx_unpack_tuple2_generic(PyObject* tuple, PyObject** pvalue1, PyObject** pvalue2,
                                         int has_known_size, int decref_tuple) {
      Py_ssize_t index;
      PyObject *value1 = NULL, *value2 = NULL, *iter = NULL;
      iternextfunc iternext;
      iter = PyObject_GetIter(tuple);
      if (unlikely(!iter)) goto bad;
      if (decref_tuple) { Py_DECREF(tuple); tuple = NULL; }
      iternext = __Pyx_PyObject_GetIterNextFunc(iter);
      value1 = iternext(iter); if (unlikely(!value1)) { index = 0; goto unpacking_failed; }
      value2 = iternext(iter); if (unlikely(!value2)) { index = 1; goto unpacking_failed; }
      if (!has_known_size && unlikely(__Pyx_IternextUnpackEndCheck(iternext(iter), 2))) goto bad;
      Py_DECREF(iter);
      *pvalue1 = value1;
      *pvalue2 = value2;
      return 0;
  unpacking_failed:
      if (!has_known_size && __Pyx_IterFinish() == 0)
          __Pyx_RaiseNeedMoreValuesError(index);
  bad:
      Py_XDECREF(iter);
      Py_XDECREF(value1);
      Py_XDECREF(value2);
      if (decref_tuple) { Py_XDECREF(tuple); }
      return -1;
  }
  
/* dict_iter */
  #if CYTHON_COMPILING_IN_PYPY
  #include <string.h>
  #endif
  static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name,
                                                     Py_ssize_t* p_orig_length, int* p_source_is_dict) {
      is_dict = is_dict || likely(PyDict_CheckExact(iterable));
      *p_source_is_dict = is_dict;
      if (is_dict) {
  #if !CYTHON_COMPILING_IN_PYPY
          *p_orig_length = PyDict_Size(iterable);
          Py_INCREF(iterable);
          return iterable;
  #else
          static PyObject *py_items = NULL, *py_keys = NULL, *py_values = NULL;
          PyObject **pp = NULL;
          if (method_name) {
              const char *name = PyUnicode_AsUTF8(method_name);
              if (strcmp(name, "iteritems") == 0) pp = &py_items;
              else if (strcmp(name, "iterkeys") == 0) pp = &py_keys;
              else if (strcmp(name, "itervalues") == 0) pp = &py_values;
              if (pp) {
                  if (!*pp) {
                      *pp = PyUnicode_FromString(name + 4);
                      if (!*pp)
                          return NULL;
                  }
                  method_name = *pp;
              }
          }
  #endif
      }
      *p_orig_length = 0;
      if (method_name) {
          PyObject* iter;
          iterable = __Pyx_PyObject_CallMethod0(iterable, method_name);
          if (!iterable)
              return NULL;
  #if !CYTHON_COMPILING_IN_PYPY
          if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable))
              return iterable;
  #endif
          iter = PyObject_GetIter(iterable);
          Py_DECREF(iterable);
          return iter;
      }
      return PyObject_GetIter(iterable);
  }
  #if !CYTHON_AVOID_BORROWED_REFS
  static CYTHON_INLINE int __Pyx_dict_iter_next_source_is_dict(
          PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos,
          PyObject** pkey, PyObject** pvalue, PyObject** pitem) {
      PyObject *key, *value;
      if (unlikely(orig_length != PyDict_Size(iter_obj))) {
          PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration");
          return -1;
      }
      if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) {
          return 0;
      }
      if (pitem) {
          PyObject* tuple = PyTuple_New(2);
          if (unlikely(!tuple)) {
              return -1;
          }
          Py_INCREF(key);
          Py_INCREF(value);
          #if CYTHON_ASSUME_SAFE_MACROS
          PyTuple_SET_ITEM(tuple, 0, key);
          PyTuple_SET_ITEM(tuple, 1, value);
          #else
          if (unlikely(PyTuple_SetItem(tuple, 0, key) < 0)) {
              Py_DECREF(value);
              Py_DECREF(tuple);
              return -1;
          }
          if (unlikely(PyTuple_SetItem(tuple, 1, value) < 0)) {
              Py_DECREF(tuple);
              return -1;
          }
          #endif
          *pitem = tuple;
      } else {
          if (pkey) {
              Py_INCREF(key);
              *pkey = key;
          }
          if (pvalue) {
              Py_INCREF(value);
              *pvalue = value;
          }
      }
      return 1;
  }
  #endif
  static CYTHON_INLINE int __Pyx_dict_iter_next(
          PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos,
          PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) {
      PyObject* next_item;
  #if !CYTHON_AVOID_BORROWED_REFS
      if (source_is_dict) {
          int result;
  #if PY_VERSION_HEX >= 0x030d0000 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_BEGIN_CRITICAL_SECTION(iter_obj);
  #endif
          result = __Pyx_dict_iter_next_source_is_dict(iter_obj, orig_length, ppos, pkey, pvalue, pitem);
  #if PY_VERSION_HEX >= 0x030d0000 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_END_CRITICAL_SECTION();
  #endif
          return result;
      } else if (PyTuple_CheckExact(iter_obj)) {
          Py_ssize_t pos = *ppos;
          Py_ssize_t tuple_size = __Pyx_PyTuple_GET_SIZE(iter_obj);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely(tuple_size < 0)) return -1;
          #endif
          if (unlikely(pos >= tuple_size)) return 0;
          *ppos = pos + 1;
          #if CYTHON_ASSUME_SAFE_MACROS
          next_item = PyTuple_GET_ITEM(iter_obj, pos);
          #else
          next_item = PyTuple_GetItem(iter_obj, pos);
          if (unlikely(!next_item)) return -1;
          #endif
          Py_INCREF(next_item);
      } else if (PyList_CheckExact(iter_obj)) {
          Py_ssize_t pos = *ppos;
          Py_ssize_t list_size = __Pyx_PyList_GET_SIZE(iter_obj);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely(list_size < 0)) return -1;
          #endif
          if (unlikely(pos >= list_size)) return 0;
          *ppos = pos + 1;
          next_item = __Pyx_PyList_GetItemRef(iter_obj, pos);
          if (unlikely(!next_item)) return -1;
      } else
  #endif
      {
          next_item = PyIter_Next(iter_obj);
          if (unlikely(!next_item)) {
              return __Pyx_IterFinish();
          }
      }
      if (pitem) {
          *pitem = next_item;
      } else if (pkey && pvalue) {
          if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1))
              return -1;
      } else if (pkey) {
          *pkey = next_item;
      } else {
          *pvalue = next_item;
      }
      return 1;
  }
  
/* PyObjectFormat */
  #if CYTHON_USE_UNICODE_WRITER
  static PyObject* __Pyx_PyObject_Format(PyObject* obj, PyObject* format_spec) {
      int ret;
      _PyUnicodeWriter writer;
      if (likely(PyFloat_CheckExact(obj))) {
          _PyUnicodeWriter_Init(&writer);
          ret = _PyFloat_FormatAdvancedWriter(
              &writer,
              obj,
              format_spec, 0, PyUnicode_GET_LENGTH(format_spec));
      } else if (likely(PyLong_CheckExact(obj))) {
          _PyUnicodeWriter_Init(&writer);
          ret = _PyLong_FormatAdvancedWriter(
              &writer,
              obj,
              format_spec, 0, PyUnicode_GET_LENGTH(format_spec));
      } else {
          return PyObject_Format(obj, format_spec);
      }
      if (unlikely(ret == -1)) {
          _PyUnicodeWriter_Dealloc(&writer);
          return NULL;
      }
      return _PyUnicodeWriter_Finish(&writer);
  }
  #endif
  
/* UnicodeConcatInPlace */
  # if CYTHON_COMPILING_IN_CPYTHON
  static int
  __Pyx_unicode_modifiable(PyObject *unicode, int unsafe_shared)
  {
      if (!__Pyx_IS_UNIQUELY_REFERENCED(unicode, unsafe_shared))
          return 0;
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX > 0x030F0000
      if (PyUnstable_Unicode_GET_CACHED_HASH(unicode) != -1)
          return 0;
  #endif
      if (!PyUnicode_CheckExact(unicode))
          return 0;
      if (PyUnicode_CHECK_INTERNED(unicode))
          return 0;
      return 1;
  }
  static CYTHON_INLINE PyObject *__Pyx_PyUnicode_ConcatInPlaceImpl(PyObject **p_left, PyObject *right, int unsafe_shared
          #if CYTHON_REFNANNY
          , void* __pyx_refnanny
          #endif
      ) {
      PyObject *left = *p_left;
      Py_ssize_t left_len, right_len, new_len;
      if (unlikely(__Pyx_PyUnicode_READY(left) == -1))
          return NULL;
      if (unlikely(__Pyx_PyUnicode_READY(right) == -1))
          return NULL;
      left_len = PyUnicode_GET_LENGTH(left);
      if (left_len == 0) {
          Py_INCREF(right);
          return right;
      }
      right_len = PyUnicode_GET_LENGTH(right);
      if (right_len == 0) {
          Py_INCREF(left);
          return left;
      }
      if (unlikely(left_len > PY_SSIZE_T_MAX - right_len)) {
          PyErr_SetString(PyExc_OverflowError,
                          "strings are too large to concat");
          return NULL;
      }
      new_len = left_len + right_len;
      if (__Pyx_unicode_modifiable(left, unsafe_shared)
              && PyUnicode_CheckExact(right)
              && PyUnicode_KIND(right) <= PyUnicode_KIND(left)
              && !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right))) {
          int ret;
          __Pyx_GIVEREF(*p_left);
          ret = PyUnicode_Resize(p_left, new_len);
          __Pyx_GOTREF(*p_left);
          if (unlikely(ret != 0))
              return NULL;
          #if PY_VERSION_HEX >= 0x030d0000
          if (unlikely(PyUnicode_CopyCharacters(*p_left, left_len, right, 0, right_len) < 0)) return NULL;
          #else
          _PyUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len);
          #endif
          __Pyx_INCREF(*p_left);
          __Pyx_GIVEREF(*p_left);
          return *p_left;
      } else {
          return __Pyx_PyUnicode_Concat(left, right);
      }
    }
  #endif
  
/* pyfrozenset_new (used by PySetContains) */
  static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
      if (it) {
          PyObject* result;
  #if CYTHON_COMPILING_IN_PYPY
          PyObject* args;
          args = PyTuple_Pack(1, it);
          if (unlikely(!args))
              return NULL;
          result = PyObject_Call((PyObject*)&PyFrozenSet_Type, args, NULL);
          Py_DECREF(args);
          return result;
  #else
          if (PyFrozenSet_CheckExact(it)) {
              Py_INCREF(it);
              return it;
          }
          result = PyFrozenSet_New(it);
          if (unlikely(!result))
              return NULL;
          if ((__PYX_LIMITED_VERSION_HEX >= 0x030A0000)
  #if CYTHON_COMPILING_IN_LIMITED_API
              || __Pyx_get_runtime_version() >= 0x030A0000
  #endif
              )
              return result;
          {
              Py_ssize_t size = __Pyx_PySet_GET_SIZE(result);
              if (likely(size > 0))
                  return result;
  #if !CYTHON_ASSUME_SAFE_SIZE
              if (unlikely(size < 0)) {
                  Py_DECREF(result);
                  return NULL;
              }
  #endif
          }
          Py_DECREF(result);
  #endif
      }
      return __Pyx_PyObject_CallNoArg((PyObject*) &PyFrozenSet_Type);
  }
  
/* PySetContains */
  static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) {
      int result = -1;
      if (PySet_Check(key) && PyErr_ExceptionMatches(PyExc_TypeError)) {
          PyObject *tmpkey;
          PyErr_Clear();
          tmpkey = __Pyx_PyFrozenSet_New(key);
          if (tmpkey != NULL) {
              result = PySet_Contains(set, tmpkey);
              Py_DECREF(tmpkey);
          }
      }
      return result;
  }
  static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq) {
      int result = PySet_Contains(set, key);
      if (unlikely(result < 0)) {
          result = __Pyx_PySet_ContainsUnhashable(set, key);
      }
      return unlikely(result < 0) ? result : (result == (eq == Py_EQ));
  }
  
/* PyLongCompare */
  static CYTHON_INLINE int __Pyx_PyLong_BoolEqObjC(PyObject *op1, PyObject *op2, long intval, long inplace) {
      CYTHON_MAYBE_UNUSED_VAR(intval);
      CYTHON_UNUSED_VAR(inplace);
      if (op1 == op2) {
          return 1;
      }
      #if CYTHON_USE_PYLONG_INTERNALS
      if (likely(PyLong_CheckExact(op1))) {
          int unequal;
          unsigned long uintval;
          Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
          const digit* digits = __Pyx_PyLong_Digits(op1);
          if (intval == 0) {
              return (__Pyx_PyLong_IsZero(op1) == 1);
          } else if (intval < 0) {
              if (__Pyx_PyLong_IsNonNeg(op1))
                  return 0;
              intval = -intval;
          } else {
              if (__Pyx_PyLong_IsNeg(op1))
                  return 0;
          }
          uintval = (unsigned long) intval;
  #if PyLong_SHIFT * 4 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 4)) {
              unequal = (size != 5) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[4] != ((uintval >> (4 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 3 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 3)) {
              unequal = (size != 4) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[3] != ((uintval >> (3 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 2 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 2)) {
              unequal = (size != 3) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)) | (digits[2] != ((uintval >> (2 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
  #if PyLong_SHIFT * 1 < SIZEOF_LONG*8
          if (uintval >> (PyLong_SHIFT * 1)) {
              unequal = (size != 2) || (digits[0] != (uintval & (unsigned long) PyLong_MASK))
                   | (digits[1] != ((uintval >> (1 * PyLong_SHIFT)) & (unsigned long) PyLong_MASK));
          } else
  #endif
              unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK));
          return (unequal == 0);
      }
      #endif
      if (PyFloat_CheckExact(op1)) {
          const long b = intval;
          double a = __Pyx_PyFloat_AS_DOUBLE(op1);
          return ((double)a == (double)b);
      }
      return __Pyx_PyObject_IsTrueAndDecref(
          PyObject_RichCompare(op1, op2, Py_EQ));
  }
  
/* PyLongBinop */
  #if !CYTHON_COMPILING_IN_PYPY
  static PyObject* __Pyx_Fallback___Pyx_PyLong_MultiplyObjC(PyObject *op1, PyObject *op2, int inplace) {
      return (inplace ? PyNumber_InPlaceMultiply : PyNumber_Multiply)(op1, op2);
  }
  #if CYTHON_USE_PYLONG_INTERNALS
  static PyObject* __Pyx_Unpacked___Pyx_PyLong_MultiplyObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
      CYTHON_MAYBE_UNUSED_VAR(inplace);
      CYTHON_UNUSED_VAR(zerodivision_check);
      const long b = intval;
      long a;
      const PY_LONG_LONG llb = intval;
      PY_LONG_LONG lla;
      if (unlikely(__Pyx_PyLong_IsZero(op1))) {
          return __Pyx_NewRef(op1);
      }
      const int is_positive = __Pyx_PyLong_IsPos(op1);
      const digit* digits = __Pyx_PyLong_Digits(op1);
      const Py_ssize_t size = __Pyx_PyLong_DigitCount(op1);
      if (likely(size == 1)) {
          a = (long) digits[0];
          if (!is_positive) a *= -1;
      } else {
          switch (size) {
              case 2:
                  if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT+30) {
                      a = (long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                      if (!is_positive) a *= -1;
                      goto calculate_long;
                  } else if (8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT+30) {
                      lla = (PY_LONG_LONG) (((((unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                      if (!is_positive) lla *= -1;
                      goto calculate_long_long;
                  }
                  break;
              case 3:
                  if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT+30) {
                      a = (long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                      if (!is_positive) a *= -1;
                      goto calculate_long;
                  } else if (8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT+30) {
                      lla = (PY_LONG_LONG) (((((((unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                      if (!is_positive) lla *= -1;
                      goto calculate_long_long;
                  }
                  break;
              case 4:
                  if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT+30) {
                      a = (long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                      if (!is_positive) a *= -1;
                      goto calculate_long;
                  } else if (8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT+30) {
                      lla = (PY_LONG_LONG) (((((((((unsigned PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (unsigned PY_LONG_LONG)digits[0]));
                      if (!is_positive) lla *= -1;
                      goto calculate_long_long;
                  }
                  break;
          }
          return PyLong_Type.tp_as_number->nb_multiply(op1, op2);
      }
      calculate_long:
          CYTHON_UNUSED_VAR(a);
          CYTHON_UNUSED_VAR(b);
          lla = a;
          goto calculate_long_long;
      calculate_long_long:
          {
              PY_LONG_LONG llx;
              llx = lla * llb;
              return PyLong_FromLongLong(llx);
          }
      
  }
  #endif
  static PyObject* __Pyx_Float___Pyx_PyLong_MultiplyObjC(PyObject *float_val, long intval, int zerodivision_check) {
      CYTHON_UNUSED_VAR(zerodivision_check);
      const long b = intval;
      double a = __Pyx_PyFloat_AS_DOUBLE(float_val);
          double result;
          
          result = ((double)a) * (double)b;
          return PyFloat_FromDouble(result);
  }
  static CYTHON_INLINE PyObject* __Pyx_PyLong_MultiplyObjC(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check) {
      CYTHON_MAYBE_UNUSED_VAR(intval);
      CYTHON_UNUSED_VAR(zerodivision_check);
      #if CYTHON_USE_PYLONG_INTERNALS
      if (likely(PyLong_CheckExact(op1))) {
          return __Pyx_Unpacked___Pyx_PyLong_MultiplyObjC(op1, op2, intval, inplace, zerodivision_check);
      }
      #endif
      if (PyFloat_CheckExact(op1)) {
          return __Pyx_Float___Pyx_PyLong_MultiplyObjC(op1, intval, zerodivision_check);
      }
      return __Pyx_Fallback___Pyx_PyLong_MultiplyObjC(op1, op2, inplace);
  }
  #endif
  
/* PyObjectLookupSpecial */
  #if CYTHON_USE_PYTYPE_LOOKUP && CYTHON_USE_TYPE_SLOTS
  static CYTHON_INLINE PyObject* __Pyx__PyObject_LookupSpecial(PyObject* obj, PyObject* attr_name, int with_error) {
      PyObject *res;
      PyTypeObject *tp = Py_TYPE(obj);
      res = _PyType_Lookup(tp, attr_name);
      if (likely(res)) {
          descrgetfunc f = Py_TYPE(res)->tp_descr_get;
          if (!f) {
              Py_INCREF(res);
          } else {
              res = f(res, obj, (PyObject *)tp);
          }
      } else if (with_error) {
          PyErr_SetObject(PyExc_AttributeError, attr_name);
      }
      return res;
  }
  #endif
  
/* AllocateExtensionType */
  static PyObject *__Pyx_AllocateExtensionType(PyTypeObject *t, int is_final) {
      if (is_final || likely(!__Pyx_PyType_HasFeature(t, Py_TPFLAGS_IS_ABSTRACT))) {
          allocfunc alloc_func = __Pyx_PyType_GetSlot(t, tp_alloc, allocfunc);
          return alloc_func(t, 0);
      } else {
          newfunc tp_new = __Pyx_PyType_TryGetSlot(&PyBaseObject_Type, tp_new, newfunc);
      #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000
          if (!tp_new) {
              PyObject *new_str = PyUnicode_FromString("__new__");
              if (likely(new_str)) {
                  PyObject *o = PyObject_CallMethodObjArgs((PyObject *)&PyBaseObject_Type, new_str, t, NULL);
                  Py_DECREF(new_str);
                  return o;
              } else
                  return NULL;
          } else
      #endif
          return tp_new(t, __pyx_mstate_global->__pyx_empty_tuple, 0);
      }
  }
  
/* CallTypeTraverse */
  #if !CYTHON_USE_TYPE_SPECS || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x03090000)
  #else
  static int __Pyx_call_type_traverse(PyObject *o, int always_call, visitproc visit, void *arg) {
      #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x03090000
      if (__Pyx_get_runtime_version() < 0x03090000) return 0;
      #endif
      if (!always_call) {
          PyTypeObject *base = __Pyx_PyObject_GetSlot(o, tp_base, PyTypeObject*);
          unsigned long flags = PyType_GetFlags(base);
          if (flags & Py_TPFLAGS_HEAPTYPE) {
              return 0;
          }
      }
      Py_VISIT((PyObject*)Py_TYPE(o));
      return 0;
  }
  #endif
  
/* LimitedApiGetTypeDict (used by SetItemOnTypeDict) */
  #if CYTHON_COMPILING_IN_LIMITED_API
  static Py_ssize_t __Pyx_GetTypeDictOffset(void) {
      PyObject *tp_dictoffset_o;
      Py_ssize_t tp_dictoffset;
      tp_dictoffset_o = PyObject_GetAttrString((PyObject*)(&PyType_Type), "__dictoffset__");
      if (unlikely(!tp_dictoffset_o)) return -1;
      tp_dictoffset = PyLong_AsSsize_t(tp_dictoffset_o);
      Py_DECREF(tp_dictoffset_o);
      if (unlikely(tp_dictoffset == 0)) {
          PyErr_SetString(
              PyExc_TypeError,
              "'type' doesn't have a dictoffset");
          return -1;
      } else if (unlikely(tp_dictoffset < 0)) {
          PyErr_SetString(
              PyExc_TypeError,
              "'type' has an unexpected negative dictoffset. "
              "Please report this as Cython bug");
          return -1;
      }
      return tp_dictoffset;
  }
  static PyObject *__Pyx_GetTypeDict(PyTypeObject *tp) {
      static Py_ssize_t tp_dictoffset = 0;
      if (unlikely(tp_dictoffset == 0)) {
          tp_dictoffset = __Pyx_GetTypeDictOffset();
          if (unlikely(tp_dictoffset == -1 && PyErr_Occurred())) {
              tp_dictoffset = 0; // try again next time?
              return NULL;
          }
      }
      return *(PyObject**)((char*)tp + tp_dictoffset);
  }
  #endif
  
/* SetItemOnTypeDict (used by FixUpExtensionType) */
  static int __Pyx__SetItemOnTypeDict(PyTypeObject *tp, PyObject *k, PyObject *v) {
      int result;
      PyObject *tp_dict;
  #if CYTHON_COMPILING_IN_LIMITED_API
      tp_dict = __Pyx_GetTypeDict(tp);
      if (unlikely(!tp_dict)) return -1;
  #else
      tp_dict = tp->tp_dict;
  #endif
      result = PyDict_SetItem(tp_dict, k, v);
      if (likely(!result)) {
          PyType_Modified(tp);
          if (unlikely(PyObject_HasAttr(v, __pyx_mstate_global->__pyx_n_u_set_name))) {
              PyObject *setNameResult = PyObject_CallMethodObjArgs(v, __pyx_mstate_global->__pyx_n_u_set_name,  (PyObject *) tp, k, NULL);
              if (!setNameResult) return -1;
              Py_DECREF(setNameResult);
          }
      }
      return result;
  }
  
/* FixUpExtensionType */
  static int __Pyx_fix_up_extension_type_from_spec(PyType_Spec *spec, PyTypeObject *type) {
  #if __PYX_LIMITED_VERSION_HEX > 0x030900B1
      CYTHON_UNUSED_VAR(spec);
      CYTHON_UNUSED_VAR(type);
      CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict);
  #else
      const PyType_Slot *slot = spec->slots;
      int changed = 0;
  #if !CYTHON_COMPILING_IN_LIMITED_API
      while (slot && slot->slot && slot->slot != Py_tp_members)
          slot++;
      if (slot && slot->slot == Py_tp_members) {
  #if !CYTHON_COMPILING_IN_CPYTHON
          const
  #endif  // !CYTHON_COMPILING_IN_CPYTHON)
              PyMemberDef *memb = (PyMemberDef*) slot->pfunc;
          while (memb && memb->name) {
              if (memb->name[0] == '_' && memb->name[1] == '_') {
                  if (strcmp(memb->name, "__weaklistoffset__") == 0) {
                      assert(memb->type == T_PYSSIZET);
                      assert(memb->flags == READONLY);
                      type->tp_weaklistoffset = memb->offset;
                      changed = 1;
                  }
                  else if (strcmp(memb->name, "__dictoffset__") == 0) {
                      assert(memb->type == T_PYSSIZET);
                      assert(memb->flags == READONLY);
                      type->tp_dictoffset = memb->offset;
                      changed = 1;
                  }
  #if CYTHON_METH_FASTCALL
                  else if (strcmp(memb->name, "__vectorcalloffset__") == 0) {
                      assert(memb->type == T_PYSSIZET);
                      assert(memb->flags == READONLY);
                      type->tp_vectorcall_offset = memb->offset;
                      changed = 1;
                  }
  #endif  // CYTHON_METH_FASTCALL
  #if !CYTHON_COMPILING_IN_PYPY
                  else if (strcmp(memb->name, "__module__") == 0) {
                      PyObject *descr;
                      assert(memb->type == T_OBJECT);
                      assert(memb->flags == 0 || memb->flags == READONLY);
                      descr = PyDescr_NewMember(type, memb);
                      if (unlikely(!descr))
                          return -1;
                      int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr);
                      Py_DECREF(descr);
                      if (unlikely(set_item_result < 0)) {
                          return -1;
                      }
                      changed = 1;
                  }
  #endif  // !CYTHON_COMPILING_IN_PYPY
              }
              memb++;
          }
      }
  #endif  // !CYTHON_COMPILING_IN_LIMITED_API
  #if !CYTHON_COMPILING_IN_PYPY
      slot = spec->slots;
      while (slot && slot->slot && slot->slot != Py_tp_getset)
          slot++;
      if (slot && slot->slot == Py_tp_getset) {
          PyGetSetDef *getset = (PyGetSetDef*) slot->pfunc;
          while (getset && getset->name) {
              if (getset->name[0] == '_' && getset->name[1] == '_' && strcmp(getset->name, "__module__") == 0) {
                  PyObject *descr = PyDescr_NewGetSet(type, getset);
                  if (unlikely(!descr))
                      return -1;
                  #if CYTHON_COMPILING_IN_LIMITED_API
                  PyObject *pyname = PyUnicode_FromString(getset->name);
                  if (unlikely(!pyname)) {
                      Py_DECREF(descr);
                      return -1;
                  }
                  int set_item_result = __Pyx_SetItemOnTypeDict(type, pyname, descr);
                  Py_DECREF(pyname);
                  #else
                  CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict);
                  int set_item_result = PyDict_SetItem(type->tp_dict, PyDescr_NAME(descr), descr);
                  #endif
                  Py_DECREF(descr);
                  if (unlikely(set_item_result < 0)) {
                      return -1;
                  }
                  changed = 1;
              }
              ++getset;
          }
      }
  #else
      CYTHON_UNUSED_VAR(__Pyx__SetItemOnTypeDict);
  #endif  // !CYTHON_COMPILING_IN_PYPY
      if (changed)
          PyType_Modified(type);
  #endif  // PY_VERSION_HEX > 0x030900B1
      return 0;
  }
  
/* ValidateBasesTuple (used by PyType_Ready) */
  #if CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_LIMITED_API || CYTHON_USE_TYPE_SPECS
  static int __Pyx_validate_bases_tuple(const char *type_name, Py_ssize_t dictoffset, PyObject *bases) {
      Py_ssize_t i, n;
  #if CYTHON_ASSUME_SAFE_SIZE
      n = PyTuple_GET_SIZE(bases);
  #else
      n = PyTuple_Size(bases);
      if (unlikely(n < 0)) return -1;
  #endif
      for (i = 1; i < n; i++)
      {
          PyTypeObject *b;
  #if CYTHON_AVOID_BORROWED_REFS
          PyObject *b0 = PySequence_GetItem(bases, i);
          if (!b0) return -1;
  #elif CYTHON_ASSUME_SAFE_MACROS
          PyObject *b0 = PyTuple_GET_ITEM(bases, i);
  #else
          PyObject *b0 = PyTuple_GetItem(bases, i);
          if (!b0) return -1;
  #endif
          b = (PyTypeObject*) b0;
          if (!__Pyx_PyType_HasFeature(b, Py_TPFLAGS_HEAPTYPE))
          {
              __Pyx_TypeName b_name = __Pyx_PyType_GetFullyQualifiedName(b);
              PyErr_Format(PyExc_TypeError,
                  "base class '" __Pyx_FMT_TYPENAME "' is not a heap type", b_name);
              __Pyx_DECREF_TypeName(b_name);
  #if CYTHON_AVOID_BORROWED_REFS
              Py_DECREF(b0);
  #endif
              return -1;
          }
          if (dictoffset == 0)
          {
              Py_ssize_t b_dictoffset = 0;
  #if CYTHON_USE_TYPE_SLOTS
              b_dictoffset = b->tp_dictoffset;
  #else
              PyObject *py_b_dictoffset = PyObject_GetAttrString((PyObject*)b, "__dictoffset__");
              if (!py_b_dictoffset) goto dictoffset_return;
              b_dictoffset = PyLong_AsSsize_t(py_b_dictoffset);
              Py_DECREF(py_b_dictoffset);
              if (b_dictoffset == -1 && PyErr_Occurred()) goto dictoffset_return;
  #endif
              if (b_dictoffset) {
                  {
                      __Pyx_TypeName b_name = __Pyx_PyType_GetFullyQualifiedName(b);
                      PyErr_Format(PyExc_TypeError,
                          "extension type '%.200s' has no __dict__ slot, "
                          "but base type '" __Pyx_FMT_TYPENAME "' has: "
                          "either add 'cdef dict __dict__' to the extension type "
                          "or add '__slots__ = [...]' to the base type",
                          type_name, b_name);
                      __Pyx_DECREF_TypeName(b_name);
                  }
  #if !CYTHON_USE_TYPE_SLOTS
                dictoffset_return:
  #endif
  #if CYTHON_AVOID_BORROWED_REFS
                  Py_DECREF(b0);
  #endif
                  return -1;
              }
          }
  #if CYTHON_AVOID_BORROWED_REFS
          Py_DECREF(b0);
  #endif
      }
      return 0;
  }
  #endif
  
/* PyType_Ready */
  CYTHON_UNUSED static int __Pyx_PyType_HasMultipleInheritance(PyTypeObject *t) {
      while (t) {
          PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*);
          if (bases) {
              return 1;
          }
          t = __Pyx_PyType_GetSlot(t, tp_base, PyTypeObject*);
      }
      return 0;
  }
  static int __Pyx_PyType_Ready(PyTypeObject *t) {
  #if CYTHON_USE_TYPE_SPECS || !CYTHON_COMPILING_IN_CPYTHON || defined(PYSTON_MAJOR_VERSION)
      (void)__Pyx_PyObject_CallMethod0;
  #if CYTHON_USE_TYPE_SPECS
      (void)__Pyx_validate_bases_tuple;
  #endif
      return PyType_Ready(t);
  #else
      int r;
      if (!__Pyx_PyType_HasMultipleInheritance(t)) {
          return PyType_Ready(t);
      }
      PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*);
      if (bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, bases) == -1))
          return -1;
  #if !defined(PYSTON_MAJOR_VERSION)
      {
          int gc_was_enabled;
      #if PY_VERSION_HEX >= 0x030A00b1
          gc_was_enabled = PyGC_Disable();
          (void)__Pyx_PyObject_CallMethod0;
      #else
          PyObject *ret, *py_status;
          PyObject *gc = NULL;
          #if (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM+0 >= 0x07030400) &&\
                  !CYTHON_COMPILING_IN_GRAAL
          gc = PyImport_GetModule(__pyx_mstate_global->__pyx_kp_u_gc);
          #endif
          if (unlikely(!gc)) gc = PyImport_Import(__pyx_mstate_global->__pyx_kp_u_gc);
          if (unlikely(!gc)) return -1;
          py_status = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_isenabled);
          if (unlikely(!py_status)) {
              Py_DECREF(gc);
              return -1;
          }
          gc_was_enabled = __Pyx_PyObject_IsTrue(py_status);
          Py_DECREF(py_status);
          if (gc_was_enabled > 0) {
              ret = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_disable);
              if (unlikely(!ret)) {
                  Py_DECREF(gc);
                  return -1;
              }
              Py_DECREF(ret);
          } else if (unlikely(gc_was_enabled == -1)) {
              Py_DECREF(gc);
              return -1;
          }
      #endif
          t->tp_flags |= Py_TPFLAGS_HEAPTYPE;
  #if PY_VERSION_HEX >= 0x030A0000
          t->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
  #endif
  #else
          (void)__Pyx_PyObject_CallMethod0;
  #endif
      r = PyType_Ready(t);
  #if !defined(PYSTON_MAJOR_VERSION)
          t->tp_flags &= ~Py_TPFLAGS_HEAPTYPE;
      #if PY_VERSION_HEX >= 0x030A00b1
          if (gc_was_enabled)
              PyGC_Enable();
      #else
          if (gc_was_enabled) {
              PyObject *tp, *v, *tb;
              PyErr_Fetch(&tp, &v, &tb);
              ret = __Pyx_PyObject_CallMethod0(gc, __pyx_mstate_global->__pyx_kp_u_enable);
              if (likely(ret || r == -1)) {
                  Py_XDECREF(ret);
                  PyErr_Restore(tp, v, tb);
              } else {
                  Py_XDECREF(tp);
                  Py_XDECREF(v);
                  Py_XDECREF(tb);
                  r = -1;
              }
          }
          Py_DECREF(gc);
      #endif
      }
  #endif
      return r;
  #endif
  }
  
/* TypeImport */
  #ifndef __PYX_HAVE_RT_ImportType_3_2_4
  #define __PYX_HAVE_RT_ImportType_3_2_4
  static PyTypeObject *__Pyx_ImportType_3_2_4(PyObject *module, const char *module_name, const char *class_name,
      size_t size, size_t alignment, enum __Pyx_ImportType_CheckSize_3_2_4 check_size)
  {
      PyObject *result = 0;
      Py_ssize_t basicsize;
      Py_ssize_t itemsize;
  #if defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API)
      PyObject *py_basicsize;
      PyObject *py_itemsize;
  #endif
      result = PyObject_GetAttrString(module, class_name);
      if (!result)
          goto bad;
      if (!PyType_Check(result)) {
          PyErr_Format(PyExc_TypeError,
              "%.200s.%.200s is not a type object",
              module_name, class_name);
          goto bad;
      }
  #if !( defined(Py_LIMITED_API) || (defined(CYTHON_COMPILING_IN_LIMITED_API) && CYTHON_COMPILING_IN_LIMITED_API) )
      basicsize = ((PyTypeObject *)result)->tp_basicsize;
      itemsize = ((PyTypeObject *)result)->tp_itemsize;
  #else
      if (size == 0) {
          return (PyTypeObject *)result;
      }
      py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
      if (!py_basicsize)
          goto bad;
      basicsize = PyLong_AsSsize_t(py_basicsize);
      Py_DECREF(py_basicsize);
      py_basicsize = 0;
      if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred())
          goto bad;
      py_itemsize = PyObject_GetAttrString(result, "__itemsize__");
      if (!py_itemsize)
          goto bad;
      itemsize = PyLong_AsSsize_t(py_itemsize);
      Py_DECREF(py_itemsize);
      py_itemsize = 0;
      if (itemsize == (Py_ssize_t)-1 && PyErr_Occurred())
          goto bad;
  #endif
      if (itemsize) {
          if (size % alignment) {
              alignment = size % alignment;
          }
          if (itemsize < (Py_ssize_t)alignment)
              itemsize = (Py_ssize_t)alignment;
      }
      if ((size_t)(basicsize + itemsize) < size) {
          PyErr_Format(PyExc_ValueError,
              "%.200s.%.200s size changed, may indicate binary incompatibility. "
              "Expected %zd from C header, got %zd from PyObject",
              module_name, class_name, size, basicsize+itemsize);
          goto bad;
      }
      if (check_size == __Pyx_ImportType_CheckSize_Error_3_2_4 &&
              ((size_t)basicsize > size || (size_t)(basicsize + itemsize) < size)) {
          PyErr_Format(PyExc_ValueError,
              "%.200s.%.200s size changed, may indicate binary incompatibility. "
              "Expected %zd from C header, got %zd-%zd from PyObject",
              module_name, class_name, size, basicsize, basicsize+itemsize);
          goto bad;
      }
      else if (check_size == __Pyx_ImportType_CheckSize_Warn_3_2_4 && (size_t)basicsize > size) {
          if (PyErr_WarnFormat(NULL, 0,
                  "%.200s.%.200s size changed, may indicate binary incompatibility. "
                  "Expected %zd from C header, got %zd from PyObject",
                  module_name, class_name, size, basicsize) < 0) {
              goto bad;
          }
      }
      return (PyTypeObject *)result;
  bad:
      Py_XDECREF(result);
      return NULL;
  }
  #endif
  
/* HasAttr (used by ImportImpl) */
  #if __PYX_LIMITED_VERSION_HEX < 0x030d0000
  static CYTHON_INLINE int __Pyx_HasAttr(PyObject *o, PyObject *n) {
      PyObject *r;
      if (unlikely(!PyUnicode_Check(n))) {
          PyErr_SetString(PyExc_TypeError,
                          "hasattr(): attribute name must be string");
          return -1;
      }
      r = __Pyx_PyObject_GetAttrStrNoError(o, n);
      if (!r) {
          return (unlikely(PyErr_Occurred())) ? -1 : 0;
      } else {
          Py_DECREF(r);
          return 1;
      }
  }
  #endif
  
/* ImportImpl (used by Import) */
  static int __Pyx__Import_GetModule(PyObject *qualname, PyObject **module) {
      PyObject *imported_module = PyImport_GetModule(qualname);
      if (unlikely(!imported_module)) {
          *module = NULL;
          if (PyErr_Occurred()) {
              return -1;
          }
          return 0;
      }
      *module = imported_module;
      return 1;
  }
  static int __Pyx__Import_Lookup(PyObject *qualname, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject **module) {
      PyObject *imported_module;
      PyObject *top_level_package_name;
      Py_ssize_t i;
      int status, module_found;
      Py_ssize_t dot_index;
      module_found = __Pyx__Import_GetModule(qualname, &imported_module);
      if (unlikely(!module_found || module_found == -1)) {
          *module = NULL;
          return module_found;
      }
      if (imported_names) {
          for (i = 0; i < len_imported_names; i++) {
              PyObject *imported_name = imported_names[i];
  #if __PYX_LIMITED_VERSION_HEX < 0x030d0000
              int has_imported_attribute = PyObject_HasAttr(imported_module, imported_name);
  #else
              int has_imported_attribute = PyObject_HasAttrWithError(imported_module, imported_name);
              if (unlikely(has_imported_attribute == -1)) goto error;
  #endif
              if (!has_imported_attribute) {
                  goto not_found;
              }
          }
          *module = imported_module;
          return 1;
      }
      dot_index = PyUnicode_FindChar(qualname, '.', 0, PY_SSIZE_T_MAX, 1);
      if (dot_index == -1) {
          *module = imported_module;
          return 1;
      }
      if (unlikely(dot_index == -2)) goto error;
      top_level_package_name = PyUnicode_Substring(qualname, 0, dot_index);
      if (unlikely(!top_level_package_name)) goto error;
      Py_DECREF(imported_module);
      status = __Pyx__Import_GetModule(top_level_package_name, module);
      Py_DECREF(top_level_package_name);
      return status;
  error:
      Py_DECREF(imported_module);
      *module = NULL;
      return -1;
  not_found:
      Py_DECREF(imported_module);
      *module = NULL;
      return 0;
  }
  static PyObject *__Pyx__Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, PyObject *moddict, int level) {
      PyObject *module = 0;
      PyObject *empty_dict = 0;
      PyObject *from_list = 0;
      int module_found;
      if (!qualname) {
          qualname = name;
      }
      module_found = __Pyx__Import_Lookup(qualname, imported_names, len_imported_names, &module);
      if (likely(module_found == 1)) {
          return module;
      } else if (unlikely(module_found == -1)) {
          return NULL;
      }
      empty_dict = PyDict_New();
      if (unlikely(!empty_dict))
          goto bad;
      if (imported_names) {
  #if CYTHON_COMPILING_IN_CPYTHON
          from_list = __Pyx_PyList_FromArray(imported_names, len_imported_names);
          if (unlikely(!from_list))
              goto bad;
  #else
          from_list = PyList_New(len_imported_names);
          if (unlikely(!from_list)) goto bad;
          for (Py_ssize_t i=0; i<len_imported_names; ++i) {
              if (PyList_SetItem(from_list, i, __Pyx_NewRef(imported_names[i])) < 0) goto bad;
          }
  #endif
      }
      if (level == -1) {
          const char* package_sep = strchr(__Pyx_MODULE_NAME, '.');
          if (package_sep != (0)) {
              module = PyImport_ImportModuleLevelObject(
                  name, moddict, empty_dict, from_list, 1);
              if (unlikely(!module)) {
                  if (unlikely(!PyErr_ExceptionMatches(PyExc_ImportError)))
                      goto bad;
                  PyErr_Clear();
              }
          }
          level = 0;
      }
      if (!module) {
          module = PyImport_ImportModuleLevelObject(
              name, moddict, empty_dict, from_list, level);
      }
  bad:
      Py_XDECREF(from_list);
      Py_XDECREF(empty_dict);
      return module;
  }
  
/* Import */
  static PyObject *__Pyx_Import(PyObject *name, PyObject *const *imported_names, Py_ssize_t len_imported_names, PyObject *qualname, int level) {
      return __Pyx__Import(name, imported_names, len_imported_names, qualname, __pyx_mstate_global->__pyx_d, level);
  }
  
/* ImportFrom */
  static PyObject* __Pyx_ImportFrom(PyObject* module, PyObject* name) {
      PyObject* value = __Pyx_PyObject_GetAttrStr(module, name);
      if (unlikely(!value) && PyErr_ExceptionMatches(PyExc_AttributeError)) {
          const char* module_name_str = 0;
          PyObject* module_name = 0;
          PyObject* module_dot = 0;
          PyObject* full_name = 0;
          PyErr_Clear();
          module_name_str = PyModule_GetName(module);
          if (unlikely(!module_name_str)) { goto modbad; }
          module_name = PyUnicode_FromString(module_name_str);
          if (unlikely(!module_name)) { goto modbad; }
          module_dot = PyUnicode_Concat(module_name, __pyx_mstate_global->__pyx_kp_u__2);
          if (unlikely(!module_dot)) { goto modbad; }
          full_name = PyUnicode_Concat(module_dot, name);
          if (unlikely(!full_name)) { goto modbad; }
          #if (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM  < 0x07030400) ||\
                  CYTHON_COMPILING_IN_GRAAL
          {
              PyObject *modules = PyImport_GetModuleDict();
              if (unlikely(!modules))
                  goto modbad;
              value = PyObject_GetItem(modules, full_name);
          }
          #else
          value = PyImport_GetModule(full_name);
          #endif
        modbad:
          Py_XDECREF(full_name);
          Py_XDECREF(module_dot);
          Py_XDECREF(module_name);
      }
      if (unlikely(!value)) {
          PyErr_Format(PyExc_ImportError, "cannot import name %S", name);
      }
      return value;
  }
  
/* dict_setdefault (used by FetchCommonType) */
  static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value) {
      PyObject* value;
  #if __PYX_LIMITED_VERSION_HEX >= 0x030F0000 || (!CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4)
      PyDict_SetDefaultRef(d, key, default_value, &value);
  #elif CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX >= 0x030C0000
      PyObject *args[] = {d, key, default_value};
      value = PyObject_VectorcallMethod(__pyx_mstate_global->__pyx_n_u_setdefault, args, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
  #elif CYTHON_COMPILING_IN_LIMITED_API
      value = PyObject_CallMethodObjArgs(d, __pyx_mstate_global->__pyx_n_u_setdefault, key, default_value, NULL);
  #else
      value = PyDict_SetDefault(d, key, default_value);
      if (unlikely(!value)) return NULL;
      Py_INCREF(value);
  #endif
      return value;
  }
  
/* AddModuleRef (used by FetchSharedCythonModule) */
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
    static PyObject *__Pyx_PyImport_AddModuleObjectRef(PyObject *name) {
        PyObject *module_dict = PyImport_GetModuleDict();
        PyObject *m;
        if (PyMapping_GetOptionalItem(module_dict, name, &m) < 0) {
            return NULL;
        }
        if (m != NULL && PyModule_Check(m)) {
            return m;
        }
        Py_XDECREF(m);
        m = PyModule_NewObject(name);
        if (m == NULL)
            return NULL;
        if (PyDict_CheckExact(module_dict)) {
            PyObject *new_m;
            (void)PyDict_SetDefaultRef(module_dict, name, m, &new_m);
            Py_DECREF(m);
            return new_m;
        } else {
             if (PyObject_SetItem(module_dict, name, m) != 0) {
                  Py_DECREF(m);
                  return NULL;
              }
              return m;
        }
    }
    static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) {
        PyObject *py_name = PyUnicode_FromString(name);
        if (!py_name) return NULL;
        PyObject *module = __Pyx_PyImport_AddModuleObjectRef(py_name);
        Py_DECREF(py_name);
        return module;
    }
  #elif __PYX_LIMITED_VERSION_HEX >= 0x030d0000
    #define __Pyx_PyImport_AddModuleRef(name) PyImport_AddModuleRef(name)
  #else
    static PyObject *__Pyx_PyImport_AddModuleRef(const char *name) {
        PyObject *module = PyImport_AddModule(name);
        Py_XINCREF(module);
        return module;
    }
  #endif
  
/* FetchSharedCythonModule (used by FetchCommonType) */
  static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
      return __Pyx_PyImport_AddModuleRef(__PYX_ABI_MODULE_NAME);
  }
  
/* FetchCommonType (used by CommonTypesMetaclass) */
  #if __PYX_LIMITED_VERSION_HEX < 0x030C0000
  static PyObject* __Pyx_PyType_FromMetaclass(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) {
      PyObject *result = __Pyx_PyType_FromModuleAndSpec(module, spec, bases);
      if (result && metaclass) {
          PyObject *old_tp = (PyObject*)Py_TYPE(result);
      Py_INCREF((PyObject*)metaclass);
  #if __PYX_LIMITED_VERSION_HEX >= 0x03090000
          Py_SET_TYPE(result, metaclass);
  #else
          result->ob_type = metaclass;
  #endif
          Py_DECREF(old_tp);
      }
      return result;
  }
  #else
  #define __Pyx_PyType_FromMetaclass(me, mo, s, b) PyType_FromMetaclass(me, mo, s, b)
  #endif
  static int __Pyx_VerifyCachedType(PyObject *cached_type,
                                 const char *name,
                                 Py_ssize_t expected_basicsize) {
      Py_ssize_t basicsize;
      if (!PyType_Check(cached_type)) {
          PyErr_Format(PyExc_TypeError,
              "Shared Cython type %.200s is not a type object", name);
          return -1;
      }
      if (expected_basicsize == 0) {
          return 0; // size is inherited, nothing useful to check
      }
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyObject *py_basicsize;
      py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__");
      if (unlikely(!py_basicsize)) return -1;
      basicsize = PyLong_AsSsize_t(py_basicsize);
      Py_DECREF(py_basicsize);
      py_basicsize = NULL;
      if (unlikely(basicsize == (Py_ssize_t)-1) && PyErr_Occurred()) return -1;
  #else
      basicsize = ((PyTypeObject*) cached_type)->tp_basicsize;
  #endif
      if (basicsize != expected_basicsize) {
          PyErr_Format(PyExc_TypeError,
              "Shared Cython type %.200s has the wrong size, try recompiling",
              name);
          return -1;
      }
      return 0;
  }
  static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyTypeObject *metaclass, PyObject *module, PyType_Spec *spec, PyObject *bases) {
      PyObject *abi_module = NULL, *cached_type = NULL, *abi_module_dict, *new_cached_type, *py_object_name;
      int get_item_ref_result;
      const char* object_name = strrchr(spec->name, '.');
      object_name = object_name ? object_name+1 : spec->name;
      py_object_name = PyUnicode_FromString(object_name);
      if (!py_object_name) return NULL;
      abi_module = __Pyx_FetchSharedCythonABIModule();
      if (!abi_module) goto done;
      abi_module_dict = PyModule_GetDict(abi_module);
      if (!abi_module_dict) goto done;
      get_item_ref_result = __Pyx_PyDict_GetItemRef(abi_module_dict, py_object_name, &cached_type);
      if (get_item_ref_result == 1) {
          if (__Pyx_VerifyCachedType(
                cached_type,
                object_name,
                spec->basicsize) < 0) {
              goto bad;
          }
          goto done;
      } else if (unlikely(get_item_ref_result == -1)) {
          goto bad;
      }
      cached_type = __Pyx_PyType_FromMetaclass(
          metaclass,
          CYTHON_USE_MODULE_STATE ? module : abi_module,
          spec, bases);
      if (unlikely(!cached_type)) goto bad;
      if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad;
      new_cached_type = __Pyx_PyDict_SetDefault(abi_module_dict, py_object_name, cached_type);
      if (unlikely(new_cached_type != cached_type)) {
          if (unlikely(!new_cached_type)) goto bad;
          Py_DECREF(cached_type);
          cached_type = new_cached_type;
          if (__Pyx_VerifyCachedType(
                  cached_type,
                  object_name,
                  spec->basicsize) < 0) {
              goto bad;
          }
          goto done;
      } else {
          Py_DECREF(new_cached_type);
      }
  done:
      Py_XDECREF(abi_module);
      Py_DECREF(py_object_name);
      assert(cached_type == NULL || PyType_Check(cached_type));
      return (PyTypeObject *) cached_type;
  bad:
      Py_XDECREF(cached_type);
      cached_type = NULL;
      goto done;
  }
  
/* CommonTypesMetaclass (used by CythonFunctionShared) */
  static PyObject* __pyx_CommonTypesMetaclass_get_module(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED void* context) {
      return PyUnicode_FromString(__PYX_ABI_MODULE_NAME);
  }
  #if __PYX_LIMITED_VERSION_HEX < 0x030A0000
  static PyObject* __pyx_CommonTypesMetaclass_call(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *args, CYTHON_UNUSED PyObject *kwds) {
      PyErr_SetString(PyExc_TypeError, "Cannot instantiate Cython internal types");
      return NULL;
  }
  static int __pyx_CommonTypesMetaclass_setattr(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *attr, CYTHON_UNUSED PyObject *value) {
      PyErr_SetString(PyExc_TypeError, "Cython internal types are immutable");
      return -1;
  }
  #endif
  static PyGetSetDef __pyx_CommonTypesMetaclass_getset[] = {
      {"__module__", __pyx_CommonTypesMetaclass_get_module, NULL, NULL, NULL},
      {0, 0, 0, 0, 0}
  };
  static PyType_Slot __pyx_CommonTypesMetaclass_slots[] = {
      {Py_tp_getset, (void *)__pyx_CommonTypesMetaclass_getset},
      #if __PYX_LIMITED_VERSION_HEX < 0x030A0000
      {Py_tp_call, (void*)__pyx_CommonTypesMetaclass_call},
      {Py_tp_new, (void*)__pyx_CommonTypesMetaclass_call},
      {Py_tp_setattro, (void*)__pyx_CommonTypesMetaclass_setattr},
      #endif
      {0, 0}
  };
  static PyType_Spec __pyx_CommonTypesMetaclass_spec = {
      __PYX_TYPE_MODULE_PREFIX "_common_types_metatype",
      0,
      0,
      Py_TPFLAGS_IMMUTABLETYPE |
      Py_TPFLAGS_DISALLOW_INSTANTIATION |
      Py_TPFLAGS_DEFAULT,
      __pyx_CommonTypesMetaclass_slots
  };
  static int __pyx_CommonTypesMetaclass_init(PyObject *module) {
      __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module);
      PyObject *bases = PyTuple_Pack(1, &PyType_Type);
      if (unlikely(!bases)) {
          return -1;
      }
      mstate->__pyx_CommonTypesMetaclassType = __Pyx_FetchCommonTypeFromSpec(NULL, module, &__pyx_CommonTypesMetaclass_spec, bases);
      Py_DECREF(bases);
      if (unlikely(mstate->__pyx_CommonTypesMetaclassType == NULL)) {
          return -1;
      }
      return 0;
  }
  
/* PyMethodNew (used by CythonFunctionShared) */
  #if CYTHON_COMPILING_IN_LIMITED_API
  static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) {
      PyObject *result;
      CYTHON_UNUSED_VAR(typ);
      if (!self)
          return __Pyx_NewRef(func);
      #if __PYX_LIMITED_VERSION_HEX >= 0x030C0000
      {
          PyObject *args[] = {func, self};
          result = PyObject_Vectorcall(__pyx_mstate_global->__Pyx_CachedMethodType, args, 2, NULL);
      }
      #else
      result = PyObject_CallFunctionObjArgs(__pyx_mstate_global->__Pyx_CachedMethodType, func, self, NULL);
      #endif
      return result;
  }
  #else
  static PyObject *__Pyx_PyMethod_New(PyObject *func, PyObject *self, PyObject *typ) {
      CYTHON_UNUSED_VAR(typ);
      if (!self)
          return __Pyx_NewRef(func);
      return PyMethod_New(func, self);
  }
  #endif
  
/* PyVectorcallFastCallDict (used by CythonFunctionShared) */
  #if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL
  static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
  {
      PyObject *res = NULL;
      PyObject *kwnames;
      PyObject **newargs;
      PyObject **kwvalues;
      Py_ssize_t i;
      #if CYTHON_AVOID_BORROWED_REFS
      PyObject *pos;
      #else
      Py_ssize_t pos;
      #endif
      size_t j;
      PyObject *key, *value;
      unsigned long keys_are_strings;
      #if !CYTHON_ASSUME_SAFE_SIZE
      Py_ssize_t nkw = PyDict_Size(kw);
      if (unlikely(nkw == -1)) return NULL;
      #else
      Py_ssize_t nkw = PyDict_GET_SIZE(kw);
      #endif
      newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0]));
      if (unlikely(newargs == NULL)) {
          PyErr_NoMemory();
          return NULL;
      }
      for (j = 0; j < nargs; j++) newargs[j] = args[j];
      kwnames = PyTuple_New(nkw);
      if (unlikely(kwnames == NULL)) {
          PyMem_Free(newargs);
          return NULL;
      }
      kwvalues = newargs + nargs;
      pos = 0;
      i = 0;
      keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS;
      while (__Pyx_PyDict_NextRef(kw, &pos, &key, &value)) {
          keys_are_strings &=
          #if CYTHON_COMPILING_IN_LIMITED_API
              PyType_GetFlags(Py_TYPE(key));
          #else
              Py_TYPE(key)->tp_flags;
          #endif
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely(PyTuple_SetItem(kwnames, i, key) < 0)) goto cleanup;
          #else
          PyTuple_SET_ITEM(kwnames, i, key);
          #endif
          kwvalues[i] = value;
          i++;
      }
      if (unlikely(!keys_are_strings)) {
          PyErr_SetString(PyExc_TypeError, "keywords must be strings");
          goto cleanup;
      }
      res = vc(func, newargs, nargs, kwnames);
  cleanup:
      #if CYTHON_AVOID_BORROWED_REFS
      Py_DECREF(pos);
      #endif
      Py_DECREF(kwnames);
      for (i = 0; i < nkw; i++)
          Py_DECREF(kwvalues[i]);
      PyMem_Free(newargs);
      return res;
  }
  static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
  {
      Py_ssize_t kw_size =
          likely(kw == NULL) ?
          0 :
  #if !CYTHON_ASSUME_SAFE_SIZE
          PyDict_Size(kw);
  #else
          PyDict_GET_SIZE(kw);
  #endif
      if (kw_size == 0) {
          return vc(func, args, nargs, NULL);
      }
  #if !CYTHON_ASSUME_SAFE_SIZE
      else if (unlikely(kw_size == -1)) {
          return NULL;
      }
  #endif
      return __Pyx_PyVectorcall_FastCallDict_kw(func, vc, args, nargs, kw);
  }
  #endif
  
/* CythonFunctionShared (used by CythonFunction) */
  #if CYTHON_COMPILING_IN_LIMITED_API
  static CYTHON_INLINE int __Pyx__IsSameCyOrCFunctionNoMethod(PyObject *func, void (*cfunc)(void)) {
      if (__Pyx_CyFunction_Check(func)) {
          return PyCFunction_GetFunction(((__pyx_CyFunctionObject*)func)->func) == (PyCFunction) cfunc;
      } else if (PyCFunction_Check(func)) {
          return PyCFunction_GetFunction(func) == (PyCFunction) cfunc;
      }
      return 0;
  }
  static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) {
      if ((PyObject*)Py_TYPE(func) == __pyx_mstate_global->__Pyx_CachedMethodType) {
          int result;
          PyObject *newFunc = PyObject_GetAttr(func, __pyx_mstate_global->__pyx_n_u_func);
          if (unlikely(!newFunc)) {
              PyErr_Clear(); // It's only an optimization, so don't throw an error
              return 0;
          }
          result = __Pyx__IsSameCyOrCFunctionNoMethod(newFunc, cfunc);
          Py_DECREF(newFunc);
          return result;
      }
      return __Pyx__IsSameCyOrCFunctionNoMethod(func, cfunc);
  }
  #else
  static CYTHON_INLINE int __Pyx__IsSameCyOrCFunction(PyObject *func, void (*cfunc)(void)) {
      if (PyMethod_Check(func)) {
          func = PyMethod_GET_FUNCTION(func);
      }
      return __Pyx_CyOrPyCFunction_Check(func) && __Pyx_CyOrPyCFunction_GET_FUNCTION(func) == (PyCFunction) cfunc;
  }
  #endif
  static CYTHON_INLINE void __Pyx__CyFunction_SetClassObj(__pyx_CyFunctionObject* f, PyObject* classobj) {
  #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
      __Pyx_Py_XDECREF_SET(
          __Pyx_CyFunction_GetClassObj(f),
              ((classobj) ? __Pyx_NewRef(classobj) : NULL));
  #else
      __Pyx_Py_XDECREF_SET(
          ((PyCMethodObject *) (f))->mm_class,
          (PyTypeObject*)((classobj) ? __Pyx_NewRef(classobj) : NULL));
  #endif
  }
  static PyObject *
  __Pyx_CyFunction_get_doc_locked(__pyx_CyFunctionObject *op)
  {
      if (unlikely(op->func_doc == NULL)) {
  #if CYTHON_COMPILING_IN_LIMITED_API
          op->func_doc = PyObject_GetAttrString(op->func, "__doc__");
          if (unlikely(!op->func_doc)) return NULL;
  #else
          if (((PyCFunctionObject*)op)->m_ml->ml_doc) {
              op->func_doc = PyUnicode_FromString(((PyCFunctionObject*)op)->m_ml->ml_doc);
              if (unlikely(op->func_doc == NULL))
                  return NULL;
          } else {
              Py_INCREF(Py_None);
              return Py_None;
          }
  #endif
      }
      Py_INCREF(op->func_doc);
      return op->func_doc;
  }
  static PyObject *
  __Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, void *closure) {
      PyObject *result;
      CYTHON_UNUSED_VAR(closure);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      result = __Pyx_CyFunction_get_doc_locked(op);
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static int
  __Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      if (value == NULL) {
          value = Py_None;
      }
      Py_INCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->func_doc, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  static PyObject *
  __Pyx_CyFunction_get_name_locked(__pyx_CyFunctionObject *op)
  {
      if (unlikely(op->func_name == NULL)) {
  #if CYTHON_COMPILING_IN_LIMITED_API
          op->func_name = PyObject_GetAttrString(op->func, "__name__");
  #else
          op->func_name = PyUnicode_InternFromString(((PyCFunctionObject*)op)->m_ml->ml_name);
  #endif
          if (unlikely(op->func_name == NULL))
              return NULL;
      }
      Py_INCREF(op->func_name);
      return op->func_name;
  }
  static PyObject *
  __Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, void *context)
  {
      PyObject *result = NULL;
      CYTHON_UNUSED_VAR(context);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      result = __Pyx_CyFunction_get_name_locked(op);
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static int
  __Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      if (unlikely(value == NULL || !PyUnicode_Check(value))) {
          PyErr_SetString(PyExc_TypeError,
                          "__name__ must be set to a string object");
          return -1;
      }
      Py_INCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->func_name, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  static PyObject *
  __Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      PyObject *result;
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      Py_INCREF(op->func_qualname);
      result = op->func_qualname;
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static int
  __Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      if (unlikely(value == NULL || !PyUnicode_Check(value))) {
          PyErr_SetString(PyExc_TypeError,
                          "__qualname__ must be set to a string object");
          return -1;
      }
      Py_INCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->func_qualname, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000
  static PyObject *
  __Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      if (unlikely(op->func_dict == NULL)) {
          op->func_dict = PyDict_New();
          if (unlikely(op->func_dict == NULL))
              return NULL;
      }
      Py_INCREF(op->func_dict);
      return op->func_dict;
  }
  #endif
  static PyObject *
  __Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, void *context)
  {
      CYTHON_UNUSED_VAR(context);
      Py_INCREF(op->func_globals);
      return op->func_globals;
  }
  static PyObject *
  __Pyx_CyFunction_get_closure(__pyx_CyFunctionObject *op, void *context)
  {
      CYTHON_UNUSED_VAR(op);
      CYTHON_UNUSED_VAR(context);
      Py_INCREF(Py_None);
      return Py_None;
  }
  static PyObject *
  __Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, void *context)
  {
      PyObject* result = (op->func_code) ? op->func_code : Py_None;
      CYTHON_UNUSED_VAR(context);
      Py_INCREF(result);
      return result;
  }
  static int
  __Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) {
      int result = 0;
      PyObject *res = op->defaults_getter((PyObject *) op);
      if (unlikely(!res))
          return -1;
      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
      op->defaults_tuple = PyTuple_GET_ITEM(res, 0);
      Py_INCREF(op->defaults_tuple);
      op->defaults_kwdict = PyTuple_GET_ITEM(res, 1);
      Py_INCREF(op->defaults_kwdict);
      #else
      op->defaults_tuple = __Pyx_PySequence_ITEM(res, 0);
      if (unlikely(!op->defaults_tuple)) result = -1;
      else {
          op->defaults_kwdict = __Pyx_PySequence_ITEM(res, 1);
          if (unlikely(!op->defaults_kwdict)) result = -1;
      }
      #endif
      Py_DECREF(res);
      return result;
  }
  static int
  __Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
      CYTHON_UNUSED_VAR(context);
      if (!value) {
          value = Py_None;
      } else if (unlikely(value != Py_None && !PyTuple_Check(value))) {
          PyErr_SetString(PyExc_TypeError,
                          "__defaults__ must be set to a tuple object");
          return -1;
      }
      PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__defaults__ will not "
                   "currently affect the values used in function calls", 1);
      Py_INCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->defaults_tuple, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  static PyObject *
  __Pyx_CyFunction_get_defaults_locked(__pyx_CyFunctionObject *op) {
      PyObject* result = op->defaults_tuple;
      if (unlikely(!result)) {
          if (op->defaults_getter) {
              if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL;
              result = op->defaults_tuple;
          } else {
              result = Py_None;
          }
      }
      Py_INCREF(result);
      return result;
  }
  static PyObject *
  __Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, void *context) {
      PyObject* result = NULL;
      CYTHON_UNUSED_VAR(context);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      result = __Pyx_CyFunction_get_defaults_locked(op);
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static int
  __Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
      CYTHON_UNUSED_VAR(context);
      if (!value) {
          value = Py_None;
      } else if (unlikely(value != Py_None && !PyDict_Check(value))) {
          PyErr_SetString(PyExc_TypeError,
                          "__kwdefaults__ must be set to a dict object");
          return -1;
      }
      PyErr_WarnEx(PyExc_RuntimeWarning, "changes to cyfunction.__kwdefaults__ will not "
                   "currently affect the values used in function calls", 1);
      Py_INCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->defaults_kwdict, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  static PyObject *
  __Pyx_CyFunction_get_kwdefaults_locked(__pyx_CyFunctionObject *op) {
      PyObject* result = op->defaults_kwdict;
      if (unlikely(!result)) {
          if (op->defaults_getter) {
              if (unlikely(__Pyx_CyFunction_init_defaults(op) < 0)) return NULL;
              result = op->defaults_kwdict;
          } else {
              result = Py_None;
          }
      }
      Py_INCREF(result);
      return result;
  }
  static PyObject *
  __Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, void *context) {
      PyObject* result;
      CYTHON_UNUSED_VAR(context);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      result = __Pyx_CyFunction_get_kwdefaults_locked(op);
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static int
  __Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
      CYTHON_UNUSED_VAR(context);
      if (!value || value == Py_None) {
          value = NULL;
      } else if (unlikely(!PyDict_Check(value))) {
          PyErr_SetString(PyExc_TypeError,
                          "__annotations__ must be set to a dict object");
          return -1;
      }
      Py_XINCREF(value);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      __Pyx_Py_XDECREF_SET(op->func_annotations, value);
      __Pyx_END_CRITICAL_SECTION();
      return 0;
  }
  static PyObject *
  __Pyx_CyFunction_get_annotations_locked(__pyx_CyFunctionObject *op) {
      PyObject* result = op->func_annotations;
      if (unlikely(!result)) {
          result = PyDict_New();
          if (unlikely(!result)) return NULL;
          op->func_annotations = result;
      }
      Py_INCREF(result);
      return result;
  }
  static PyObject *
  __Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, void *context) {
      PyObject *result;
      CYTHON_UNUSED_VAR(context);
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      result = __Pyx_CyFunction_get_annotations_locked(op);
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static PyObject *
  __Pyx_CyFunction_get_is_coroutine_value(__pyx_CyFunctionObject *op) {
      int is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
      if (is_coroutine) {
          PyObject *is_coroutine_value, *module, *fromlist, *marker = __pyx_mstate_global->__pyx_n_u_is_coroutine;
          fromlist = PyList_New(1);
          if (unlikely(!fromlist)) return NULL;
          Py_INCREF(marker);
  #if CYTHON_ASSUME_SAFE_MACROS
          PyList_SET_ITEM(fromlist, 0, marker);
  #else
          if (unlikely(PyList_SetItem(fromlist, 0, marker) < 0)) {
              Py_DECREF(marker);
              Py_DECREF(fromlist);
              return NULL;
          }
  #endif
          module = PyImport_ImportModuleLevelObject(__pyx_mstate_global->__pyx_n_u_asyncio_coroutines, NULL, NULL, fromlist, 0);
          Py_DECREF(fromlist);
          if (unlikely(!module)) goto ignore;
          is_coroutine_value = __Pyx_PyObject_GetAttrStr(module, marker);
          Py_DECREF(module);
          if (likely(is_coroutine_value)) {
              return is_coroutine_value;
          }
  ignore:
          PyErr_Clear();
      }
      return __Pyx_PyBool_FromLong(is_coroutine);
  }
  static PyObject *
  __Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, void *context) {
      PyObject *result;
      CYTHON_UNUSED_VAR(context);
      if (op->func_is_coroutine) {
          return __Pyx_NewRef(op->func_is_coroutine);
      }
      result = __Pyx_CyFunction_get_is_coroutine_value(op);
      if (unlikely(!result))
          return NULL;
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      if (op->func_is_coroutine) {
          Py_DECREF(result);
          result = __Pyx_NewRef(op->func_is_coroutine);
      } else {
          op->func_is_coroutine = __Pyx_NewRef(result);
      }
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static void __Pyx_CyFunction_raise_argument_count_error(__pyx_CyFunctionObject *func, const char* message, Py_ssize_t size) {
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL);
      if (!py_name) return;
      PyErr_Format(PyExc_TypeError,
          "%.200S() %s (%" CYTHON_FORMAT_SSIZE_T "d given)",
          py_name, message, size);
      Py_DECREF(py_name);
  #else
      const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name;
      PyErr_Format(PyExc_TypeError,
          "%.200s() %s (%" CYTHON_FORMAT_SSIZE_T "d given)",
          name, message, size);
  #endif
  }
  static void __Pyx_CyFunction_raise_type_error(__pyx_CyFunctionObject *func, const char* message) {
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyObject *py_name = __Pyx_CyFunction_get_name(func, NULL);
      if (!py_name) return;
      PyErr_Format(PyExc_TypeError,
          "%.200S() %s",
          py_name, message);
      Py_DECREF(py_name);
  #else
      const char* name = ((PyCFunctionObject*)func)->m_ml->ml_name;
      PyErr_Format(PyExc_TypeError,
          "%.200s() %s",
          name, message);
  #endif
  }
  #if CYTHON_COMPILING_IN_LIMITED_API
  static PyObject *
  __Pyx_CyFunction_get_module(__pyx_CyFunctionObject *op, void *context) {
      CYTHON_UNUSED_VAR(context);
      return PyObject_GetAttrString(op->func, "__module__");
  }
  static int
  __Pyx_CyFunction_set_module(__pyx_CyFunctionObject *op, PyObject* value, void *context) {
      CYTHON_UNUSED_VAR(context);
      return PyObject_SetAttrString(op->func, "__module__", value);
  }
  #endif
  static PyGetSetDef __pyx_CyFunction_getsets[] = {
      {"func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
      {"__doc__",  (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
      {"func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
      {"__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
      {"__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0},
  #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000
      {"func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0},
      {"__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)PyObject_GenericSetDict, 0, 0},
  #else
      {"func_dict", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0},
      {"__dict__", (getter)PyObject_GenericGetDict, (setter)PyObject_GenericSetDict, 0, 0},
  #endif
      {"func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
      {"__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
      {"func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
      {"__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0},
      {"func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
      {"__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0},
      {"func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
      {"__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0},
      {"__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0},
      {"__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0},
      {"_is_coroutine", (getter)__Pyx_CyFunction_get_is_coroutine, 0, 0, 0},
  #if CYTHON_COMPILING_IN_LIMITED_API
      {"__module__", (getter)__Pyx_CyFunction_get_module, (setter)__Pyx_CyFunction_set_module, 0, 0},
  #endif
      {0, 0, 0, 0, 0}
  };
  static PyMemberDef __pyx_CyFunction_members[] = {
  #if !CYTHON_COMPILING_IN_LIMITED_API
      {"__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), 0, 0},
  #endif
  #if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API
      {"__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0},
  #endif
  #if CYTHON_METH_FASTCALL
  #if CYTHON_COMPILING_IN_LIMITED_API
      {"__vectorcalloffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_vectorcall), READONLY, 0},
  #else
      {"__vectorcalloffset__", T_PYSSIZET, offsetof(PyCFunctionObject, vectorcall), READONLY, 0},
  #endif
  #if CYTHON_COMPILING_IN_LIMITED_API
      {"__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0},
  #else
      {"__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0},
  #endif
  #endif
      {0, 0, 0,  0, 0}
  };
  static PyObject *
  __Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, PyObject *args)
  {
      PyObject *result = NULL;
      CYTHON_UNUSED_VAR(args);
      __Pyx_BEGIN_CRITICAL_SECTION(m);
      Py_INCREF(m->func_qualname);
      result = m->func_qualname;
      __Pyx_END_CRITICAL_SECTION();
      return result;
  }
  static PyMethodDef __pyx_CyFunction_methods[] = {
      {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0},
      {0, 0, 0, 0}
  };
  #if CYTHON_COMPILING_IN_LIMITED_API
  #define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist)
  #else
  #define __Pyx_CyFunction_weakreflist(cyfunc) (((PyCFunctionObject*)cyfunc)->m_weakreflist)
  #endif
  static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname,
                                         PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) {
  #if !CYTHON_COMPILING_IN_LIMITED_API
      PyCFunctionObject *cf = (PyCFunctionObject*) op;
  #endif
      if (unlikely(op == NULL))
          return NULL;
  #if CYTHON_COMPILING_IN_LIMITED_API
      op->func = PyCFunction_NewEx(ml, (PyObject*)op, module);
      if (unlikely(!op->func)) return NULL;
  #endif
      op->flags = flags;
      __Pyx_CyFunction_weakreflist(op) = NULL;
  #if !CYTHON_COMPILING_IN_LIMITED_API
      cf->m_ml = ml;
      cf->m_self = (PyObject *) op;
  #endif
      Py_XINCREF(closure);
      op->func_closure = closure;
  #if !CYTHON_COMPILING_IN_LIMITED_API
      Py_XINCREF(module);
      cf->m_module = module;
  #endif
  #if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API
      op->func_dict = NULL;
  #endif
      op->func_name = NULL;
      Py_INCREF(qualname);
      op->func_qualname = qualname;
      op->func_doc = NULL;
  #if PY_VERSION_HEX < 0x030900B1 || CYTHON_COMPILING_IN_LIMITED_API
      op->func_classobj = NULL;
  #else
      ((PyCMethodObject*)op)->mm_class = NULL;
  #endif
      op->func_globals = globals;
      Py_INCREF(op->func_globals);
      Py_XINCREF(code);
      op->func_code = code;
      op->defaults = NULL;
      op->defaults_tuple = NULL;
      op->defaults_kwdict = NULL;
      op->defaults_getter = NULL;
      op->func_annotations = NULL;
      op->func_is_coroutine = NULL;
  #if CYTHON_METH_FASTCALL
      switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) {
      case METH_NOARGS:
          __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_NOARGS;
          break;
      case METH_O:
          __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_O;
          break;
      case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
          __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD;
          break;
      case METH_FASTCALL | METH_KEYWORDS:
          __Pyx_CyFunction_func_vectorcall(op) = __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS;
          break;
      case METH_VARARGS | METH_KEYWORDS:
          __Pyx_CyFunction_func_vectorcall(op) = NULL;
          break;
      default:
          PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction");
          Py_DECREF(op);
          return NULL;
      }
  #endif
      return (PyObject *) op;
  }
  static int
  __Pyx_CyFunction_clear(__pyx_CyFunctionObject *m)
  {
      Py_CLEAR(m->func_closure);
  #if CYTHON_COMPILING_IN_LIMITED_API
      Py_CLEAR(m->func);
  #else
      Py_CLEAR(((PyCFunctionObject*)m)->m_module);
  #endif
  #if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API
      Py_CLEAR(m->func_dict);
  #elif PY_VERSION_HEX < 0x030d0000
      _PyObject_ClearManagedDict((PyObject*)m);
  #else
      PyObject_ClearManagedDict((PyObject*)m);
  #endif
      Py_CLEAR(m->func_name);
      Py_CLEAR(m->func_qualname);
      Py_CLEAR(m->func_doc);
      Py_CLEAR(m->func_globals);
      Py_CLEAR(m->func_code);
  #if !CYTHON_COMPILING_IN_LIMITED_API
  #if PY_VERSION_HEX < 0x030900B1
      Py_CLEAR(__Pyx_CyFunction_GetClassObj(m));
  #else
      {
          PyObject *cls = (PyObject*) ((PyCMethodObject *) (m))->mm_class;
          ((PyCMethodObject *) (m))->mm_class = NULL;
          Py_XDECREF(cls);
      }
  #endif
  #endif
      Py_CLEAR(m->defaults_tuple);
      Py_CLEAR(m->defaults_kwdict);
      Py_CLEAR(m->func_annotations);
      Py_CLEAR(m->func_is_coroutine);
      Py_CLEAR(m->defaults);
      return 0;
  }
  static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m)
  {
      if (__Pyx_CyFunction_weakreflist(m) != NULL)
          PyObject_ClearWeakRefs((PyObject *) m);
      __Pyx_CyFunction_clear(m);
      __Pyx_PyHeapTypeObject_GC_Del(m);
  }
  static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m)
  {
      PyObject_GC_UnTrack(m);
      __Pyx__CyFunction_dealloc(m);
  }
  static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg)
  {
      {
          int e = __Pyx_call_type_traverse((PyObject*)m, 1, visit, arg);
          if (e) return e;
      }
      Py_VISIT(m->func_closure);
  #if CYTHON_COMPILING_IN_LIMITED_API
      Py_VISIT(m->func);
  #else
      Py_VISIT(((PyCFunctionObject*)m)->m_module);
  #endif
  #if PY_VERSION_HEX < 0x030C0000 || CYTHON_COMPILING_IN_LIMITED_API
      Py_VISIT(m->func_dict);
  #else
      {
          int e =
  #if PY_VERSION_HEX < 0x030d0000
              _PyObject_VisitManagedDict
  #else
              PyObject_VisitManagedDict
  #endif
                  ((PyObject*)m, visit, arg);
          if (e != 0) return e;
      }
  #endif
      __Pyx_VISIT_CONST(m->func_name);
      __Pyx_VISIT_CONST(m->func_qualname);
      Py_VISIT(m->func_doc);
      Py_VISIT(m->func_globals);
      __Pyx_VISIT_CONST(m->func_code);
  #if !CYTHON_COMPILING_IN_LIMITED_API
      Py_VISIT(__Pyx_CyFunction_GetClassObj(m));
  #endif
      Py_VISIT(m->defaults_tuple);
      Py_VISIT(m->defaults_kwdict);
      Py_VISIT(m->func_is_coroutine);
      Py_VISIT(m->defaults);
      return 0;
  }
  static PyObject*
  __Pyx_CyFunction_repr(__pyx_CyFunctionObject *op)
  {
      PyObject *repr;
      __Pyx_BEGIN_CRITICAL_SECTION(op);
      repr = PyUnicode_FromFormat("<cyfunction %U at %p>",
                                  op->func_qualname, (void *)op);
      __Pyx_END_CRITICAL_SECTION();
      return repr;
  }
  static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) {
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyObject *f = ((__pyx_CyFunctionObject*)func)->func;
      PyCFunction meth;
      int flags;
      meth = PyCFunction_GetFunction(f);
      if (unlikely(!meth)) return NULL;
      flags = PyCFunction_GetFlags(f);
      if (unlikely(flags < 0)) return NULL;
  #else
      PyCFunctionObject* f = (PyCFunctionObject*)func;
      PyCFunction meth = f->m_ml->ml_meth;
      int flags = f->m_ml->ml_flags;
  #endif
      Py_ssize_t size;
      switch (flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) {
      case METH_VARARGS:
          if (likely(kw == NULL || PyDict_Size(kw) == 0))
              return (*meth)(self, arg);
          break;
      case METH_VARARGS | METH_KEYWORDS:
          return (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, arg, kw);
      case METH_NOARGS:
          if (likely(kw == NULL || PyDict_Size(kw) == 0)) {
  #if CYTHON_ASSUME_SAFE_SIZE
              size = PyTuple_GET_SIZE(arg);
  #else
              size = PyTuple_Size(arg);
              if (unlikely(size < 0)) return NULL;
  #endif
              if (likely(size == 0))
                  return (*meth)(self, NULL);
              __Pyx_CyFunction_raise_argument_count_error(
                  (__pyx_CyFunctionObject*)func,
                  "takes no arguments", size);
              return NULL;
          }
          break;
      case METH_O:
          if (likely(kw == NULL || PyDict_Size(kw) == 0)) {
  #if CYTHON_ASSUME_SAFE_SIZE
              size = PyTuple_GET_SIZE(arg);
  #else
              size = PyTuple_Size(arg);
              if (unlikely(size < 0)) return NULL;
  #endif
              if (likely(size == 1)) {
                  PyObject *result, *arg0;
                  #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
                  arg0 = PyTuple_GET_ITEM(arg, 0);
                  #else
                  arg0 = __Pyx_PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL;
                  #endif
                  result = (*meth)(self, arg0);
                  #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS)
                  Py_DECREF(arg0);
                  #endif
                  return result;
              }
              __Pyx_CyFunction_raise_argument_count_error(
                  (__pyx_CyFunctionObject*)func,
                  "takes exactly one argument", size);
              return NULL;
          }
          break;
      default:
          PyErr_SetString(PyExc_SystemError, "Bad call flags for CyFunction");
          return NULL;
      }
      __Pyx_CyFunction_raise_type_error(
          (__pyx_CyFunctionObject*)func, "takes no keyword arguments");
      return NULL;
  }
  static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) {
      PyObject *self, *result;
  #if CYTHON_COMPILING_IN_LIMITED_API
      self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)func)->func);
      if (unlikely(!self) && PyErr_Occurred()) return NULL;
  #else
      self = ((PyCFunctionObject*)func)->m_self;
  #endif
      result = __Pyx_CyFunction_CallMethod(func, self, arg, kw);
      return result;
  }
  static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) {
      PyObject *result;
      __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func;
  #if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL
       __pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc);
      if (vc) {
  #if CYTHON_ASSUME_SAFE_MACROS && CYTHON_ASSUME_SAFE_SIZE
          return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw);
  #else
          (void) &__Pyx_PyVectorcall_FastCallDict;
          return PyVectorcall_Call(func, args, kw);
  #endif
      }
  #endif
      if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) {
          Py_ssize_t argc;
          PyObject *new_args;
          PyObject *self;
  #if CYTHON_ASSUME_SAFE_SIZE
          argc = PyTuple_GET_SIZE(args);
  #else
          argc = PyTuple_Size(args);
          if (unlikely(argc < 0)) return NULL;
  #endif
          new_args = PyTuple_GetSlice(args, 1, argc);
          if (unlikely(!new_args))
              return NULL;
          self = PyTuple_GetItem(args, 0);
          if (unlikely(!self)) {
              Py_DECREF(new_args);
              PyErr_Format(PyExc_TypeError,
                           "unbound method %.200S() needs an argument",
                           cyfunc->func_qualname);
              return NULL;
          }
          result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw);
          Py_DECREF(new_args);
      } else {
          result = __Pyx_CyFunction_Call(func, args, kw);
      }
      return result;
  }
  #if CYTHON_METH_FASTCALL && CYTHON_VECTORCALL
  static CYTHON_INLINE int __Pyx_CyFunction_Vectorcall_CheckArgs(__pyx_CyFunctionObject *cyfunc, Py_ssize_t nargs, PyObject *kwnames)
  {
      int ret = 0;
      if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) {
          if (unlikely(nargs < 1)) {
              __Pyx_CyFunction_raise_type_error(
                  cyfunc, "needs an argument");
              return -1;
          }
          ret = 1;
      }
      if (unlikely(kwnames) && unlikely(__Pyx_PyTuple_GET_SIZE(kwnames))) {
          __Pyx_CyFunction_raise_type_error(
              cyfunc, "takes no keyword arguments");
          return -1;
      }
      return ret;
  }
  static PyObject * __Pyx_CyFunction_Vectorcall_NOARGS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  {
      __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      PyObject *self;
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyCFunction meth = PyCFunction_GetFunction(cyfunc->func);
      if (unlikely(!meth)) return NULL;
  #else
      PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth;
  #endif
      switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) {
      case 1:
          self = args[0];
          args += 1;
          nargs -= 1;
          break;
      case 0:
  #if CYTHON_COMPILING_IN_LIMITED_API
          self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func);
          if (unlikely(!self) && PyErr_Occurred()) return NULL;
  #else
          self = ((PyCFunctionObject*)cyfunc)->m_self;
  #endif
          break;
      default:
          return NULL;
      }
      if (unlikely(nargs != 0)) {
          __Pyx_CyFunction_raise_argument_count_error(
              cyfunc, "takes no arguments", nargs);
          return NULL;
      }
      return meth(self, NULL);
  }
  static PyObject * __Pyx_CyFunction_Vectorcall_O(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  {
      __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      PyObject *self;
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyCFunction meth = PyCFunction_GetFunction(cyfunc->func);
      if (unlikely(!meth)) return NULL;
  #else
      PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth;
  #endif
      switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, kwnames)) {
      case 1:
          self = args[0];
          args += 1;
          nargs -= 1;
          break;
      case 0:
  #if CYTHON_COMPILING_IN_LIMITED_API
          self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func);
          if (unlikely(!self) && PyErr_Occurred()) return NULL;
  #else
          self = ((PyCFunctionObject*)cyfunc)->m_self;
  #endif
          break;
      default:
          return NULL;
      }
      if (unlikely(nargs != 1)) {
          __Pyx_CyFunction_raise_argument_count_error(
              cyfunc, "takes exactly one argument", nargs);
          return NULL;
      }
      return meth(self, args[0]);
  }
  static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  {
      __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      PyObject *self;
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyCFunction meth = PyCFunction_GetFunction(cyfunc->func);
      if (unlikely(!meth)) return NULL;
  #else
      PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth;
  #endif
      switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) {
      case 1:
          self = args[0];
          args += 1;
          nargs -= 1;
          break;
      case 0:
  #if CYTHON_COMPILING_IN_LIMITED_API
          self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func);
          if (unlikely(!self) && PyErr_Occurred()) return NULL;
  #else
          self = ((PyCFunctionObject*)cyfunc)->m_self;
  #endif
          break;
      default:
          return NULL;
      }
      return ((__Pyx_PyCFunctionFastWithKeywords)(void(*)(void))meth)(self, args, nargs, kwnames);
  }
  static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS_METHOD(PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
  {
      __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *)func;
      PyTypeObject *cls = (PyTypeObject *) __Pyx_CyFunction_GetClassObj(cyfunc);
      Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
      PyObject *self;
  #if CYTHON_COMPILING_IN_LIMITED_API
      PyCFunction meth = PyCFunction_GetFunction(cyfunc->func);
      if (unlikely(!meth)) return NULL;
  #else
      PyCFunction meth = ((PyCFunctionObject*)cyfunc)->m_ml->ml_meth;
  #endif
      switch (__Pyx_CyFunction_Vectorcall_CheckArgs(cyfunc, nargs, NULL)) {
      case 1:
          self = args[0];
          args += 1;
          nargs -= 1;
          break;
      case 0:
  #if CYTHON_COMPILING_IN_LIMITED_API
          self = PyCFunction_GetSelf(((__pyx_CyFunctionObject*)cyfunc)->func);
          if (unlikely(!self) && PyErr_Occurred()) return NULL;
  #else
          self = ((PyCFunctionObject*)cyfunc)->m_self;
  #endif
          break;
      default:
          return NULL;
      }
      #if PY_VERSION_HEX < 0x030e00A6
      size_t nargs_value = (size_t) nargs;
      #else
      Py_ssize_t nargs_value = nargs;
      #endif
      return ((__Pyx_PyCMethod)(void(*)(void))meth)(self, cls, args, nargs_value, kwnames);
  }
  #endif
  static PyType_Slot __pyx_CyFunctionType_slots[] = {
      {Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc},
      {Py_tp_repr, (void *)__Pyx_CyFunction_repr},
      {Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod},
      {Py_tp_traverse, (void *)__Pyx_CyFunction_traverse},
      {Py_tp_clear, (void *)__Pyx_CyFunction_clear},
      {Py_tp_methods, (void *)__pyx_CyFunction_methods},
      {Py_tp_members, (void *)__pyx_CyFunction_members},
      {Py_tp_getset, (void *)__pyx_CyFunction_getsets},
      {Py_tp_descr_get, (void *)__Pyx_PyMethod_New},
      {0, 0},
  };
  static PyType_Spec __pyx_CyFunctionType_spec = {
      __PYX_TYPE_MODULE_PREFIX "cython_function_or_method",
      sizeof(__pyx_CyFunctionObject),
      0,
  #ifdef Py_TPFLAGS_METHOD_DESCRIPTOR
      Py_TPFLAGS_METHOD_DESCRIPTOR |
  #endif
  #if CYTHON_METH_FASTCALL
  #if defined(Py_TPFLAGS_HAVE_VECTORCALL)
      Py_TPFLAGS_HAVE_VECTORCALL |
  #elif defined(_Py_TPFLAGS_HAVE_VECTORCALL)
      _Py_TPFLAGS_HAVE_VECTORCALL |
  #endif
  #endif // CYTHON_METH_FASTCALL
  #if PY_VERSION_HEX >= 0x030C0000 && !CYTHON_COMPILING_IN_LIMITED_API
      Py_TPFLAGS_MANAGED_DICT |
  #endif
      Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION |
      Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
      __pyx_CyFunctionType_slots
  };
  static int __pyx_CyFunction_init(PyObject *module) {
      __pyx_mstatetype *mstate = __Pyx_PyModule_GetState(module);
      mstate->__pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(
          mstate->__pyx_CommonTypesMetaclassType, module, &__pyx_CyFunctionType_spec, NULL);
      if (unlikely(mstate->__pyx_CyFunctionType == NULL)) {
          return -1;
      }
      return 0;
  }
  static CYTHON_INLINE PyObject *__Pyx_CyFunction_InitDefaults(PyObject *func, PyTypeObject *defaults_type) {
      __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
      m->defaults = PyObject_CallObject((PyObject*)defaults_type, NULL); // _PyObject_New(defaults_type);
      if (unlikely(!m->defaults))
          return NULL;
      return m->defaults;
  }
  static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) {
      __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
      m->defaults_tuple = tuple;
      Py_INCREF(tuple);
  }
  static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) {
      __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
      m->defaults_kwdict = dict;
      Py_INCREF(dict);
  }
  static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) {
      __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func;
      m->func_annotations = dict;
      Py_INCREF(dict);
  }
  
/* CythonFunction */
  static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname,
                                        PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) {
      PyObject *op = __Pyx_CyFunction_Init(
          PyObject_GC_New(__pyx_CyFunctionObject, __pyx_mstate_global->__pyx_CyFunctionType),
          ml, flags, qualname, closure, module, globals, code
      );
      if (likely(op)) {
          PyObject_GC_Track(op);
      }
      return op;
  }
  
/* CLineInTraceback (used by AddTraceback) */
  #if CYTHON_CLINE_IN_TRACEBACK && CYTHON_CLINE_IN_TRACEBACK_RUNTIME
  #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030A0000
  #define __Pyx_PyProbablyModule_GetDict(o) __Pyx_XNewRef(PyModule_GetDict(o))
  #elif !CYTHON_COMPILING_IN_CPYTHON || CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
  #define __Pyx_PyProbablyModule_GetDict(o) PyObject_GenericGetDict(o, NULL);
  #else
  PyObject* __Pyx_PyProbablyModule_GetDict(PyObject *o) {
      PyObject **dict_ptr = _PyObject_GetDictPtr(o);
      return dict_ptr ? __Pyx_XNewRef(*dict_ptr) : NULL;
  }
  #endif
  static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
      PyObject *use_cline = NULL;
      PyObject *ptype, *pvalue, *ptraceback;
      PyObject *cython_runtime_dict;
      CYTHON_MAYBE_UNUSED_VAR(tstate);
      if (unlikely(!__pyx_mstate_global->__pyx_cython_runtime)) {
          return c_line;
      }
      __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback);
      cython_runtime_dict = __Pyx_PyProbablyModule_GetDict(__pyx_mstate_global->__pyx_cython_runtime);
      if (likely(cython_runtime_dict)) {
          __PYX_PY_DICT_LOOKUP_IF_MODIFIED(
              use_cline, cython_runtime_dict,
              __Pyx_PyDict_SetDefault(cython_runtime_dict, __pyx_mstate_global->__pyx_n_u_cline_in_traceback, Py_False))
      }
      if (use_cline == NULL || use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) {
          c_line = 0;
      }
      Py_XDECREF(use_cline);
      Py_XDECREF(cython_runtime_dict);
      __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback);
      return c_line;
  }
  #endif
  
/* CodeObjectCache (used by AddTraceback) */
  static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) {
      int start = 0, mid = 0, end = count - 1;
      if (end >= 0 && code_line > entries[end].code_line) {
          return count;
      }
      while (start < end) {
          mid = start + (end - start) / 2;
          if (code_line < entries[mid].code_line) {
              end = mid;
          } else if (code_line > entries[mid].code_line) {
               start = mid + 1;
          } else {
              return mid;
          }
      }
      if (code_line <= entries[mid].code_line) {
          return mid;
      } else {
          return mid + 1;
      }
  }
  static __Pyx_CachedCodeObjectType *__pyx__find_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line) {
      __Pyx_CachedCodeObjectType* code_object;
      int pos;
      if (unlikely(!code_line) || unlikely(!code_cache->entries)) {
          return NULL;
      }
      pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line);
      if (unlikely(pos >= code_cache->count) || unlikely(code_cache->entries[pos].code_line != code_line)) {
          return NULL;
      }
      code_object = code_cache->entries[pos].code_object;
      Py_INCREF(code_object);
      return code_object;
  }
  static __Pyx_CachedCodeObjectType *__pyx_find_code_object(int code_line) {
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS
      (void)__pyx__find_code_object;
      return NULL; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just miss.
  #else
      struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache;
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      __pyx_nonatomic_int_type old_count = __pyx_atomic_incr_acq_rel(&code_cache->accessor_count);
      if (old_count < 0) {
          __pyx_atomic_decr_acq_rel(&code_cache->accessor_count);
          return NULL;
      }
  #endif
      __Pyx_CachedCodeObjectType *result = __pyx__find_code_object(code_cache, code_line);
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      __pyx_atomic_decr_acq_rel(&code_cache->accessor_count);
  #endif
      return result;
  #endif
  }
  static void __pyx__insert_code_object(struct __Pyx_CodeObjectCache *code_cache, int code_line, __Pyx_CachedCodeObjectType* code_object)
  {
      int pos, i;
      __Pyx_CodeObjectCacheEntry* entries = code_cache->entries;
      if (unlikely(!code_line)) {
          return;
      }
      if (unlikely(!entries)) {
          entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry));
          if (likely(entries)) {
              code_cache->entries = entries;
              code_cache->max_count = 64;
              code_cache->count = 1;
              entries[0].code_line = code_line;
              entries[0].code_object = code_object;
              Py_INCREF(code_object);
          }
          return;
      }
      pos = __pyx_bisect_code_objects(code_cache->entries, code_cache->count, code_line);
      if ((pos < code_cache->count) && unlikely(code_cache->entries[pos].code_line == code_line)) {
          __Pyx_CachedCodeObjectType* tmp = entries[pos].code_object;
          entries[pos].code_object = code_object;
          Py_INCREF(code_object);
          Py_DECREF(tmp);
          return;
      }
      if (code_cache->count == code_cache->max_count) {
          int new_max = code_cache->max_count + 64;
          entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc(
              code_cache->entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry));
          if (unlikely(!entries)) {
              return;
          }
          code_cache->entries = entries;
          code_cache->max_count = new_max;
      }
      for (i=code_cache->count; i>pos; i--) {
          entries[i] = entries[i-1];
      }
      entries[pos].code_line = code_line;
      entries[pos].code_object = code_object;
      code_cache->count++;
      Py_INCREF(code_object);
  }
  static void __pyx_insert_code_object(int code_line, __Pyx_CachedCodeObjectType* code_object) {
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING && !CYTHON_ATOMICS
      (void)__pyx__insert_code_object;
      return; // Most implementation should have atomics. But otherwise, don't make it thread-safe, just fail.
  #else
      struct __Pyx_CodeObjectCache *code_cache = &__pyx_mstate_global->__pyx_code_cache;
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      __pyx_nonatomic_int_type expected = 0;
      if (!__pyx_atomic_int_cmp_exchange(&code_cache->accessor_count, &expected, INT_MIN)) {
          return;
      }
  #endif
      __pyx__insert_code_object(code_cache, code_line, code_object);
  #if CYTHON_COMPILING_IN_CPYTHON_FREETHREADING
      __pyx_atomic_sub(&code_cache->accessor_count, INT_MIN);
  #endif
  #endif
  }
  
/* AddTraceback */
  #include "compile.h"
  #include "frameobject.h"
  #include "traceback.h"
  #if PY_VERSION_HEX >= 0x030b00a6 && !CYTHON_COMPILING_IN_LIMITED_API && !defined(PYPY_VERSION)
    #ifndef Py_BUILD_CORE
      #define Py_BUILD_CORE 1
    #endif
    #include "internal/pycore_frame.h"
  #endif
  #if CYTHON_COMPILING_IN_LIMITED_API
  static PyObject *__Pyx_PyCode_Replace_For_AddTraceback(PyObject *code, PyObject *scratch_dict,
                                                         PyObject *firstlineno, PyObject *name) {
      PyObject *replace = NULL;
      if (unlikely(PyDict_SetItemString(scratch_dict, "co_firstlineno", firstlineno))) return NULL;
      if (unlikely(PyDict_SetItemString(scratch_dict, "co_name", name))) return NULL;
      replace = PyObject_GetAttrString(code, "replace");
      if (likely(replace)) {
          PyObject *result = PyObject_Call(replace, __pyx_mstate_global->__pyx_empty_tuple, scratch_dict);
          Py_DECREF(replace);
          return result;
      }
      PyErr_Clear();
      return NULL;
  }
  static void __Pyx_AddTraceback(const char *funcname, int c_line,
                                 int py_line, const char *filename) {
      PyObject *code_object = NULL, *py_py_line = NULL, *py_funcname = NULL, *dict = NULL;
      PyObject *replace = NULL, *getframe = NULL, *frame = NULL;
      PyObject *exc_type, *exc_value, *exc_traceback;
      int success = 0;
      if (c_line) {
          c_line = __Pyx_CLineForTraceback(__Pyx_PyThreadState_Current, c_line);
      }
      PyErr_Fetch(&exc_type, &exc_value, &exc_traceback);
      code_object = __pyx_find_code_object(c_line ? -c_line : py_line);
      if (!code_object) {
          code_object = Py_CompileString("_getframe()", filename, Py_eval_input);
          if (unlikely(!code_object)) goto bad;
          py_py_line = PyLong_FromLong(py_line);
          if (unlikely(!py_py_line)) goto bad;
          if (c_line) {
              py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
          } else {
              py_funcname = PyUnicode_FromString(funcname);
          }
          if (unlikely(!py_funcname)) goto bad;
          dict = PyDict_New();
          if (unlikely(!dict)) goto bad;
          {
              PyObject *old_code_object = code_object;
              code_object = __Pyx_PyCode_Replace_For_AddTraceback(code_object, dict, py_py_line, py_funcname);
              Py_DECREF(old_code_object);
          }
          if (unlikely(!code_object)) goto bad;
          __pyx_insert_code_object(c_line ? -c_line : py_line, code_object);
      } else {
          dict = PyDict_New();
      }
      getframe = PySys_GetObject("_getframe");
      if (unlikely(!getframe)) goto bad;
      if (unlikely(PyDict_SetItemString(dict, "_getframe", getframe))) goto bad;
      frame = PyEval_EvalCode(code_object, dict, dict);
      if (unlikely(!frame) || frame == Py_None) goto bad;
      success = 1;
    bad:
      PyErr_Restore(exc_type, exc_value, exc_traceback);
      Py_XDECREF(code_object);
      Py_XDECREF(py_py_line);
      Py_XDECREF(py_funcname);
      Py_XDECREF(dict);
      Py_XDECREF(replace);
      if (success) {
          PyTraceBack_Here(
              (struct _frame*)frame);
      }
      Py_XDECREF(frame);
  }
  #else
  static PyCodeObject* __Pyx_CreateCodeObjectForTraceback(
              const char *funcname, int c_line,
              int py_line, const char *filename) {
      PyCodeObject *py_code = NULL;
      PyObject *py_funcname = NULL;
      if (c_line) {
          py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line);
          if (!py_funcname) goto bad;
          funcname = PyUnicode_AsUTF8(py_funcname);
          if (!funcname) goto bad;
      }
      py_code = PyCode_NewEmpty(filename, funcname, py_line);
      Py_XDECREF(py_funcname);
      return py_code;
  bad:
      Py_XDECREF(py_funcname);
      return NULL;
  }
  static void __Pyx_AddTraceback(const char *funcname, int c_line,
                                 int py_line, const char *filename) {
      PyCodeObject *py_code = 0;
      PyFrameObject *py_frame = 0;
      PyThreadState *tstate = __Pyx_PyThreadState_Current;
      PyObject *ptype, *pvalue, *ptraceback;
      if (c_line) {
          c_line = __Pyx_CLineForTraceback(tstate, c_line);
      }
      py_code = __pyx_find_code_object(c_line ? -c_line : py_line);
      if (!py_code) {
          __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback);
          py_code = __Pyx_CreateCodeObjectForTraceback(
              funcname, c_line, py_line, filename);
          if (!py_code) {
              /* If the code object creation fails, then we should clear the
                 fetched exception references and propagate the new exception */
              Py_XDECREF(ptype);
              Py_XDECREF(pvalue);
              Py_XDECREF(ptraceback);
              goto bad;
          }
          __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback);
          __pyx_insert_code_object(c_line ? -c_line : py_line, py_code);
      }
      py_frame = PyFrame_New(
          tstate,            /*PyThreadState *tstate,*/
          py_code,           /*PyCodeObject *code,*/
          __pyx_mstate_global->__pyx_d,    /*PyObject *globals,*/
          0                  /*PyObject *locals*/
      );
      if (!py_frame) goto bad;
      __Pyx_PyFrame_SetLineNumber(py_frame, py_line);
      PyTraceBack_Here(py_frame);
  bad:
      Py_XDECREF(py_code);
      Py_XDECREF(py_frame);
  }
  #endif
  
/* CIntFromPyVerify */
  #define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\
      __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0)
  #define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\
      __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1)
  #define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\
      {\
          func_type value = func_value;\
          if (sizeof(target_type) < sizeof(func_type)) {\
              if (unlikely(value != (func_type) (target_type) value)) {\
                  func_type zero = 0;\
                  if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\
                      return (target_type) -1;\
                  if (is_unsigned && unlikely(value < zero))\
                      goto raise_neg_overflow;\
                  else\
                      goto raise_overflow;\
              }\
          }\
          return (target_type) value;\
      }
  
/* Declarations */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #ifdef __cplusplus
      static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
        return ::std::complex< float >(x, y);
      }
    #else
      static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
        return x + y*(__pyx_t_float_complex)_Complex_I;
      }
    #endif
  #else
      static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
        __pyx_t_float_complex z;
        z.real = x;
        z.imag = y;
        return z;
      }
  #endif
  
/* Arithmetic */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #else
      static CYTHON_INLINE int __Pyx_c_eq_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
         return (a.real == b.real) && (a.imag == b.imag);
      }
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_sum_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
          __pyx_t_float_complex z;
          z.real = a.real + b.real;
          z.imag = a.imag + b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_diff_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
          __pyx_t_float_complex z;
          z.real = a.real - b.real;
          z.imag = a.imag - b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_prod_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
          __pyx_t_float_complex z;
          z.real = a.real * b.real - a.imag * b.imag;
          z.imag = a.real * b.imag + a.imag * b.real;
          return z;
      }
      #if 1
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
          if (b.imag == 0) {
              return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else if (fabsf(b.real) >= fabsf(b.imag)) {
              if (b.real == 0 && b.imag == 0) {
                  return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.imag);
              } else {
                  float r = b.imag / b.real;
                  float s = (float)(1.0) / (b.real + b.imag * r);
                  return __pyx_t_float_complex_from_parts(
                      (a.real + a.imag * r) * s, (a.imag - a.real * r) * s);
              }
          } else {
              float r = b.real / b.imag;
              float s = (float)(1.0) / (b.imag + b.real * r);
              return __pyx_t_float_complex_from_parts(
                  (a.real * r + a.imag) * s, (a.imag * r - a.real) * s);
          }
      }
      #else
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_quot_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
          if (b.imag == 0) {
              return __pyx_t_float_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else {
              float denom = b.real * b.real + b.imag * b.imag;
              return __pyx_t_float_complex_from_parts(
                  (a.real * b.real + a.imag * b.imag) / denom,
                  (a.imag * b.real - a.real * b.imag) / denom);
          }
      }
      #endif
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_neg_float(__pyx_t_float_complex a) {
          __pyx_t_float_complex z;
          z.real = -a.real;
          z.imag = -a.imag;
          return z;
      }
      static CYTHON_INLINE int __Pyx_c_is_zero_float(__pyx_t_float_complex a) {
         return (a.real == 0) && (a.imag == 0);
      }
      static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_conj_float(__pyx_t_float_complex a) {
          __pyx_t_float_complex z;
          z.real =  a.real;
          z.imag = -a.imag;
          return z;
      }
      #if 1
          static CYTHON_INLINE float __Pyx_c_abs_float(__pyx_t_float_complex z) {
            #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
              return sqrtf(z.real*z.real + z.imag*z.imag);
            #else
              return hypotf(z.real, z.imag);
            #endif
          }
          static CYTHON_INLINE __pyx_t_float_complex __Pyx_c_pow_float(__pyx_t_float_complex a, __pyx_t_float_complex b) {
              __pyx_t_float_complex z;
              float r, lnr, theta, z_r, z_theta;
              if (b.imag == 0 && b.real == (int)b.real) {
                  if (b.real < 0) {
                      float denom = a.real * a.real + a.imag * a.imag;
                      a.real = a.real / denom;
                      a.imag = -a.imag / denom;
                      b.real = -b.real;
                  }
                  switch ((int)b.real) {
                      case 0:
                          z.real = 1;
                          z.imag = 0;
                          return z;
                      case 1:
                          return a;
                      case 2:
                          return __Pyx_c_prod_float(a, a);
                      case 3:
                          z = __Pyx_c_prod_float(a, a);
                          return __Pyx_c_prod_float(z, a);
                      case 4:
                          z = __Pyx_c_prod_float(a, a);
                          return __Pyx_c_prod_float(z, z);
                  }
              }
              if (a.imag == 0) {
                  if (a.real == 0) {
                      return a;
                  } else if ((b.imag == 0) && (a.real >= 0)) {
                      z.real = powf(a.real, b.real);
                      z.imag = 0;
                      return z;
                  } else if (a.real > 0) {
                      r = a.real;
                      theta = 0;
                  } else {
                      r = -a.real;
                      theta = atan2f(0.0, -1.0);
                  }
              } else {
                  r = __Pyx_c_abs_float(a);
                  theta = atan2f(a.imag, a.real);
              }
              lnr = logf(r);
              z_r = expf(lnr * b.real - theta * b.imag);
              z_theta = theta * b.real + lnr * b.imag;
              z.real = z_r * cosf(z_theta);
              z.imag = z_r * sinf(z_theta);
              return z;
          }
      #endif
  #endif
  
/* Declarations */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #ifdef __cplusplus
      static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
        return ::std::complex< double >(x, y);
      }
    #else
      static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
        return x + y*(__pyx_t_double_complex)_Complex_I;
      }
    #endif
  #else
      static CYTHON_INLINE __pyx_t_double_complex __pyx_t_double_complex_from_parts(double x, double y) {
        __pyx_t_double_complex z;
        z.real = x;
        z.imag = y;
        return z;
      }
  #endif
  
/* Arithmetic */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #else
      static CYTHON_INLINE int __Pyx_c_eq_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
         return (a.real == b.real) && (a.imag == b.imag);
      }
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_sum_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
          __pyx_t_double_complex z;
          z.real = a.real + b.real;
          z.imag = a.imag + b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_diff_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
          __pyx_t_double_complex z;
          z.real = a.real - b.real;
          z.imag = a.imag - b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_prod_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
          __pyx_t_double_complex z;
          z.real = a.real * b.real - a.imag * b.imag;
          z.imag = a.real * b.imag + a.imag * b.real;
          return z;
      }
      #if 1
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
          if (b.imag == 0) {
              return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else if (fabs(b.real) >= fabs(b.imag)) {
              if (b.real == 0 && b.imag == 0) {
                  return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.imag);
              } else {
                  double r = b.imag / b.real;
                  double s = (double)(1.0) / (b.real + b.imag * r);
                  return __pyx_t_double_complex_from_parts(
                      (a.real + a.imag * r) * s, (a.imag - a.real * r) * s);
              }
          } else {
              double r = b.real / b.imag;
              double s = (double)(1.0) / (b.imag + b.real * r);
              return __pyx_t_double_complex_from_parts(
                  (a.real * r + a.imag) * s, (a.imag * r - a.real) * s);
          }
      }
      #else
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_quot_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
          if (b.imag == 0) {
              return __pyx_t_double_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else {
              double denom = b.real * b.real + b.imag * b.imag;
              return __pyx_t_double_complex_from_parts(
                  (a.real * b.real + a.imag * b.imag) / denom,
                  (a.imag * b.real - a.real * b.imag) / denom);
          }
      }
      #endif
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_neg_double(__pyx_t_double_complex a) {
          __pyx_t_double_complex z;
          z.real = -a.real;
          z.imag = -a.imag;
          return z;
      }
      static CYTHON_INLINE int __Pyx_c_is_zero_double(__pyx_t_double_complex a) {
         return (a.real == 0) && (a.imag == 0);
      }
      static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_conj_double(__pyx_t_double_complex a) {
          __pyx_t_double_complex z;
          z.real =  a.real;
          z.imag = -a.imag;
          return z;
      }
      #if 1
          static CYTHON_INLINE double __Pyx_c_abs_double(__pyx_t_double_complex z) {
            #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
              return sqrt(z.real*z.real + z.imag*z.imag);
            #else
              return hypot(z.real, z.imag);
            #endif
          }
          static CYTHON_INLINE __pyx_t_double_complex __Pyx_c_pow_double(__pyx_t_double_complex a, __pyx_t_double_complex b) {
              __pyx_t_double_complex z;
              double r, lnr, theta, z_r, z_theta;
              if (b.imag == 0 && b.real == (int)b.real) {
                  if (b.real < 0) {
                      double denom = a.real * a.real + a.imag * a.imag;
                      a.real = a.real / denom;
                      a.imag = -a.imag / denom;
                      b.real = -b.real;
                  }
                  switch ((int)b.real) {
                      case 0:
                          z.real = 1;
                          z.imag = 0;
                          return z;
                      case 1:
                          return a;
                      case 2:
                          return __Pyx_c_prod_double(a, a);
                      case 3:
                          z = __Pyx_c_prod_double(a, a);
                          return __Pyx_c_prod_double(z, a);
                      case 4:
                          z = __Pyx_c_prod_double(a, a);
                          return __Pyx_c_prod_double(z, z);
                  }
              }
              if (a.imag == 0) {
                  if (a.real == 0) {
                      return a;
                  } else if ((b.imag == 0) && (a.real >= 0)) {
                      z.real = pow(a.real, b.real);
                      z.imag = 0;
                      return z;
                  } else if (a.real > 0) {
                      r = a.real;
                      theta = 0;
                  } else {
                      r = -a.real;
                      theta = atan2(0.0, -1.0);
                  }
              } else {
                  r = __Pyx_c_abs_double(a);
                  theta = atan2(a.imag, a.real);
              }
              lnr = log(r);
              z_r = exp(lnr * b.real - theta * b.imag);
              z_theta = theta * b.real + lnr * b.imag;
              z.real = z_r * cos(z_theta);
              z.imag = z_r * sin(z_theta);
              return z;
          }
      #endif
  #endif
  
/* Declarations */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
    #ifdef __cplusplus
      static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) {
        return ::std::complex< long double >(x, y);
      }
    #else
      static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) {
        return x + y*(__pyx_t_long_double_complex)_Complex_I;
      }
    #endif
  #else
      static CYTHON_INLINE __pyx_t_long_double_complex __pyx_t_long_double_complex_from_parts(long double x, long double y) {
        __pyx_t_long_double_complex z;
        z.real = x;
        z.imag = y;
        return z;
      }
  #endif
  
/* Arithmetic */
  #if CYTHON_CCOMPLEX && (1) && (!0 || __cplusplus)
  #else
      static CYTHON_INLINE int __Pyx_c_eq_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
         return (a.real == b.real) && (a.imag == b.imag);
      }
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_sum_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
          __pyx_t_long_double_complex z;
          z.real = a.real + b.real;
          z.imag = a.imag + b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_diff_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
          __pyx_t_long_double_complex z;
          z.real = a.real - b.real;
          z.imag = a.imag - b.imag;
          return z;
      }
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_prod_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
          __pyx_t_long_double_complex z;
          z.real = a.real * b.real - a.imag * b.imag;
          z.imag = a.real * b.imag + a.imag * b.real;
          return z;
      }
      #if 1
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
          if (b.imag == 0) {
              return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else if (fabsl(b.real) >= fabsl(b.imag)) {
              if (b.real == 0 && b.imag == 0) {
                  return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.imag);
              } else {
                  long double r = b.imag / b.real;
                  long double s = (long double)(1.0) / (b.real + b.imag * r);
                  return __pyx_t_long_double_complex_from_parts(
                      (a.real + a.imag * r) * s, (a.imag - a.real * r) * s);
              }
          } else {
              long double r = b.real / b.imag;
              long double s = (long double)(1.0) / (b.imag + b.real * r);
              return __pyx_t_long_double_complex_from_parts(
                  (a.real * r + a.imag) * s, (a.imag * r - a.real) * s);
          }
      }
      #else
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_quot_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
          if (b.imag == 0) {
              return __pyx_t_long_double_complex_from_parts(a.real / b.real, a.imag / b.real);
          } else {
              long double denom = b.real * b.real + b.imag * b.imag;
              return __pyx_t_long_double_complex_from_parts(
                  (a.real * b.real + a.imag * b.imag) / denom,
                  (a.imag * b.real - a.real * b.imag) / denom);
          }
      }
      #endif
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_neg_long__double(__pyx_t_long_double_complex a) {
          __pyx_t_long_double_complex z;
          z.real = -a.real;
          z.imag = -a.imag;
          return z;
      }
      static CYTHON_INLINE int __Pyx_c_is_zero_long__double(__pyx_t_long_double_complex a) {
         return (a.real == 0) && (a.imag == 0);
      }
      static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_conj_long__double(__pyx_t_long_double_complex a) {
          __pyx_t_long_double_complex z;
          z.real =  a.real;
          z.imag = -a.imag;
          return z;
      }
      #if 1
          static CYTHON_INLINE long double __Pyx_c_abs_long__double(__pyx_t_long_double_complex z) {
            #if !defined(HAVE_HYPOT) || defined(_MSC_VER)
              return sqrtl(z.real*z.real + z.imag*z.imag);
            #else
              return hypotl(z.real, z.imag);
            #endif
          }
          static CYTHON_INLINE __pyx_t_long_double_complex __Pyx_c_pow_long__double(__pyx_t_long_double_complex a, __pyx_t_long_double_complex b) {
              __pyx_t_long_double_complex z;
              long double r, lnr, theta, z_r, z_theta;
              if (b.imag == 0 && b.real == (int)b.real) {
                  if (b.real < 0) {
                      long double denom = a.real * a.real + a.imag * a.imag;
                      a.real = a.real / denom;
                      a.imag = -a.imag / denom;
                      b.real = -b.real;
                  }
                  switch ((int)b.real) {
                      case 0:
                          z.real = 1;
                          z.imag = 0;
                          return z;
                      case 1:
                          return a;
                      case 2:
                          return __Pyx_c_prod_long__double(a, a);
                      case 3:
                          z = __Pyx_c_prod_long__double(a, a);
                          return __Pyx_c_prod_long__double(z, a);
                      case 4:
                          z = __Pyx_c_prod_long__double(a, a);
                          return __Pyx_c_prod_long__double(z, z);
                  }
              }
              if (a.imag == 0) {
                  if (a.real == 0) {
                      return a;
                  } else if ((b.imag == 0) && (a.real >= 0)) {
                      z.real = powl(a.real, b.real);
                      z.imag = 0;
                      return z;
                  } else if (a.real > 0) {
                      r = a.real;
                      theta = 0;
                  } else {
                      r = -a.real;
                      theta = atan2l(0.0, -1.0);
                  }
              } else {
                  r = __Pyx_c_abs_long__double(a);
                  theta = atan2l(a.imag, a.real);
              }
              lnr = logl(r);
              z_r = expl(lnr * b.real - theta * b.imag);
              z_theta = theta * b.real + lnr * b.imag;
              z.real = z_r * cosl(z_theta);
              z.imag = z_r * sinl(z_theta);
              return z;
          }
      #endif
  #endif
  
/* CIntFromPy */
  static CYTHON_INLINE PY_LONG_LONG __Pyx_PyLong_As_PY_LONG_LONG(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const PY_LONG_LONG neg_one = (PY_LONG_LONG) -1, const_zero = (PY_LONG_LONG) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          PY_LONG_LONG val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (PY_LONG_LONG) -1;
          val = __Pyx_PyLong_As_PY_LONG_LONG(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(PY_LONG_LONG) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) >= 2 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((((PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(PY_LONG_LONG) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) >= 3 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((((((PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(PY_LONG_LONG) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) >= 4 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((((((((PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (PY_LONG_LONG) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(PY_LONG_LONG) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(PY_LONG_LONG, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(PY_LONG_LONG, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(PY_LONG_LONG) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((PY_LONG_LONG)-1)*(((((PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(PY_LONG_LONG) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) ((((((PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(PY_LONG_LONG) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((PY_LONG_LONG)-1)*(((((((PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(PY_LONG_LONG) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) ((((((((PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(PY_LONG_LONG) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) (((PY_LONG_LONG)-1)*(((((((((PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(PY_LONG_LONG) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(PY_LONG_LONG, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(PY_LONG_LONG) - 1 > 4 * PyLong_SHIFT)) {
                              return (PY_LONG_LONG) ((((((((((PY_LONG_LONG)digits[3]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[2]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[1]) << PyLong_SHIFT) | (PY_LONG_LONG)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(PY_LONG_LONG) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(PY_LONG_LONG, long, PyLong_AsLong(x))
          } else if ((sizeof(PY_LONG_LONG) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(PY_LONG_LONG, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          PY_LONG_LONG val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (PY_LONG_LONG) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (PY_LONG_LONG) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (PY_LONG_LONG) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (PY_LONG_LONG) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(PY_LONG_LONG) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((PY_LONG_LONG) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(PY_LONG_LONG) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((PY_LONG_LONG) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((PY_LONG_LONG) 1) << (sizeof(PY_LONG_LONG) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (PY_LONG_LONG) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to PY_LONG_LONG");
      return (PY_LONG_LONG) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to PY_LONG_LONG");
      return (PY_LONG_LONG) -1;
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_PY_LONG_LONG(PY_LONG_LONG value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const PY_LONG_LONG neg_one = (PY_LONG_LONG) -1, const_zero = (PY_LONG_LONG) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(PY_LONG_LONG) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(PY_LONG_LONG) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(PY_LONG_LONG) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(PY_LONG_LONG),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(PY_LONG_LONG));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* CIntFromPy */
  static CYTHON_INLINE long __Pyx_PyLong_As_long(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const long neg_one = (long) -1, const_zero = (long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          long val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (long) -1;
          val = __Pyx_PyLong_As_long(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) >= 2 * PyLong_SHIFT)) {
                              return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) >= 3 * PyLong_SHIFT)) {
                              return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) >= 4 * PyLong_SHIFT)) {
                              return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (long) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(long) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(long) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(long, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(long) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) {
                              return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(long) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) {
                              return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(long) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) {
                              return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(long) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) {
                              return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(long) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) {
                              return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(long) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(long) - 1 > 4 * PyLong_SHIFT)) {
                              return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(long) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x))
          } else if ((sizeof(long) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          long val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (long) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (long) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (long) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (long) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(long) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((long) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(long) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((long) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((long) 1) << (sizeof(long) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (long) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to long");
      return (long) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to long");
      return (long) -1;
  }
  
/* CIntFromPy */
  static CYTHON_INLINE int __Pyx_PyLong_As_int(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const int neg_one = (int) -1, const_zero = (int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          int val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (int) -1;
          val = __Pyx_PyLong_As_int(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) >= 2 * PyLong_SHIFT)) {
                              return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) >= 3 * PyLong_SHIFT)) {
                              return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) >= 4 * PyLong_SHIFT)) {
                              return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (int) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(int) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(int) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(int, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(int) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) {
                              return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(int) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) {
                              return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(int) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) {
                              return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(int) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) {
                              return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(int) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) {
                              return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(int) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(int) - 1 > 4 * PyLong_SHIFT)) {
                              return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(int) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x))
          } else if ((sizeof(int) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          int val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (int) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (int) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (int) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (int) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(int) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((int) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(int) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((int) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((int) 1) << (sizeof(int) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (int) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to int");
      return (int) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to int");
      return (int) -1;
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_long(long value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const long neg_one = (long) -1, const_zero = (long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(long) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(long) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(long) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(long),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(long));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_int(int value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const int neg_one = (int) -1, const_zero = (int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(int) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(int) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(int) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(int),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(int));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* CIntFromPy */
  static CYTHON_INLINE unsigned int __Pyx_PyLong_As_unsigned_int(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const unsigned int neg_one = (unsigned int) -1, const_zero = (unsigned int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          unsigned int val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (unsigned int) -1;
          val = __Pyx_PyLong_As_unsigned_int(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(unsigned int, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(unsigned int) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) >= 2 * PyLong_SHIFT)) {
                              return (unsigned int) (((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(unsigned int) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) >= 3 * PyLong_SHIFT)) {
                              return (unsigned int) (((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(unsigned int) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) >= 4 * PyLong_SHIFT)) {
                              return (unsigned int) (((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (unsigned int) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(unsigned int) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(unsigned int, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(unsigned int) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT)) {
                              return (unsigned int) (((unsigned int)-1)*(((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(unsigned int) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT)) {
                              return (unsigned int) ((((((unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(unsigned int) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT)) {
                              return (unsigned int) (((unsigned int)-1)*(((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(unsigned int) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT)) {
                              return (unsigned int) ((((((((unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(unsigned int) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT)) {
                              return (unsigned int) (((unsigned int)-1)*(((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(unsigned int) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned int) - 1 > 4 * PyLong_SHIFT)) {
                              return (unsigned int) ((((((((((unsigned int)digits[3]) << PyLong_SHIFT) | (unsigned int)digits[2]) << PyLong_SHIFT) | (unsigned int)digits[1]) << PyLong_SHIFT) | (unsigned int)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(unsigned int) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned int, long, PyLong_AsLong(x))
          } else if ((sizeof(unsigned int) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned int, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          unsigned int val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (unsigned int) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (unsigned int) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (unsigned int) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (unsigned int) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(unsigned int) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((unsigned int) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(unsigned int) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((unsigned int) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((unsigned int) 1) << (sizeof(unsigned int) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (unsigned int) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to unsigned int");
      return (unsigned int) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to unsigned int");
      return (unsigned int) -1;
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_int(unsigned int value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const unsigned int neg_one = (unsigned int) -1, const_zero = (unsigned int) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(unsigned int) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned int) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(unsigned int) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(unsigned int) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned int) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(unsigned int),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(unsigned int));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* CIntFromPy */
  static CYTHON_INLINE unsigned long __Pyx_PyLong_As_unsigned_long(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const unsigned long neg_one = (unsigned long) -1, const_zero = (unsigned long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          unsigned long val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (unsigned long) -1;
          val = __Pyx_PyLong_As_unsigned_long(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(unsigned long, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(unsigned long) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) >= 2 * PyLong_SHIFT)) {
                              return (unsigned long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) >= 3 * PyLong_SHIFT)) {
                              return (unsigned long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) >= 4 * PyLong_SHIFT)) {
                              return (unsigned long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (unsigned long) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(unsigned long) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned long, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(unsigned long) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(unsigned long, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(unsigned long) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 2 * PyLong_SHIFT)) {
                              return (unsigned long) (((unsigned long)-1)*(((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(unsigned long) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 2 * PyLong_SHIFT)) {
                              return (unsigned long) ((((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(unsigned long) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 3 * PyLong_SHIFT)) {
                              return (unsigned long) (((unsigned long)-1)*(((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 3 * PyLong_SHIFT)) {
                              return (unsigned long) ((((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(unsigned long) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 4 * PyLong_SHIFT)) {
                              return (unsigned long) (((unsigned long)-1)*(((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(unsigned long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(unsigned long) - 1 > 4 * PyLong_SHIFT)) {
                              return (unsigned long) ((((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(unsigned long) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned long, long, PyLong_AsLong(x))
          } else if ((sizeof(unsigned long) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(unsigned long, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          unsigned long val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (unsigned long) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (unsigned long) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (unsigned long) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (unsigned long) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(unsigned long) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((unsigned long) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(unsigned long) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((unsigned long) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((unsigned long) 1) << (sizeof(unsigned long) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (unsigned long) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to unsigned long");
      return (unsigned long) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to unsigned long");
      return (unsigned long) -1;
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_long(unsigned long value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const unsigned long neg_one = (unsigned long) -1, const_zero = (unsigned long) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(unsigned long) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned long) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(unsigned long) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(unsigned long) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned long) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(unsigned long),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(unsigned long));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* CIntFromPy */
  static CYTHON_INLINE size_t __Pyx_PyLong_As_size_t(PyObject *x) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const size_t neg_one = (size_t) -1, const_zero = (size_t) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (unlikely(!PyLong_Check(x))) {
          size_t val;
          PyObject *tmp = __Pyx_PyNumber_Long(x);
          if (!tmp) return (size_t) -1;
          val = __Pyx_PyLong_As_size_t(tmp);
          Py_DECREF(tmp);
          return val;
      }
      if (is_unsigned) {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (unlikely(__Pyx_PyLong_IsNeg(x))) {
              goto raise_neg_overflow;
          } else if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(size_t, __Pyx_compact_upylong, __Pyx_PyLong_CompactValueUnsigned(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_DigitCount(x)) {
                  case 2:
                      if ((8 * sizeof(size_t) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) >= 2 * PyLong_SHIFT)) {
                              return (size_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(size_t) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) >= 3 * PyLong_SHIFT)) {
                              return (size_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(size_t) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) >= 4 * PyLong_SHIFT)) {
                              return (size_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
                          }
                      }
                      break;
              }
          }
  #endif
  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030C00A7
          if (unlikely(Py_SIZE(x) < 0)) {
              goto raise_neg_overflow;
          }
  #else
          {
              int result = PyObject_RichCompareBool(x, Py_False, Py_LT);
              if (unlikely(result < 0))
                  return (size_t) -1;
              if (unlikely(result == 1))
                  goto raise_neg_overflow;
          }
  #endif
          if ((sizeof(size_t) <= sizeof(unsigned long))) {
              __PYX_VERIFY_RETURN_INT_EXC(size_t, unsigned long, PyLong_AsUnsignedLong(x))
          } else if ((sizeof(size_t) <= sizeof(unsigned PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(size_t, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
          }
      } else {
  #if CYTHON_USE_PYLONG_INTERNALS
          if (__Pyx_PyLong_IsCompact(x)) {
              __PYX_VERIFY_RETURN_INT(size_t, __Pyx_compact_pylong, __Pyx_PyLong_CompactValue(x))
          } else {
              const digit* digits = __Pyx_PyLong_Digits(x);
              assert(__Pyx_PyLong_DigitCount(x) > 1);
              switch (__Pyx_PyLong_SignedDigitCount(x)) {
                  case -2:
                      if ((8 * sizeof(size_t) - 1 > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 2 * PyLong_SHIFT)) {
                              return (size_t) (((size_t)-1)*(((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
                  case 2:
                      if ((8 * sizeof(size_t) > 1 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 2 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 2 * PyLong_SHIFT)) {
                              return (size_t) ((((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
                  case -3:
                      if ((8 * sizeof(size_t) - 1 > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 3 * PyLong_SHIFT)) {
                              return (size_t) (((size_t)-1)*(((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
                  case 3:
                      if ((8 * sizeof(size_t) > 2 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 3 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 3 * PyLong_SHIFT)) {
                              return (size_t) ((((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
                  case -4:
                      if ((8 * sizeof(size_t) - 1 > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 4 * PyLong_SHIFT)) {
                              return (size_t) (((size_t)-1)*(((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
                  case 4:
                      if ((8 * sizeof(size_t) > 3 * PyLong_SHIFT)) {
                          if ((8 * sizeof(unsigned long) > 4 * PyLong_SHIFT)) {
                              __PYX_VERIFY_RETURN_INT(size_t, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0])))
                          } else if ((8 * sizeof(size_t) - 1 > 4 * PyLong_SHIFT)) {
                              return (size_t) ((((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])));
                          }
                      }
                      break;
              }
          }
  #endif
          if ((sizeof(size_t) <= sizeof(long))) {
              __PYX_VERIFY_RETURN_INT_EXC(size_t, long, PyLong_AsLong(x))
          } else if ((sizeof(size_t) <= sizeof(PY_LONG_LONG))) {
              __PYX_VERIFY_RETURN_INT_EXC(size_t, PY_LONG_LONG, PyLong_AsLongLong(x))
          }
      }
      {
          size_t val;
          int ret = -1;
  #if PY_VERSION_HEX >= 0x030d00A6 && !CYTHON_COMPILING_IN_LIMITED_API
          Py_ssize_t bytes_copied = PyLong_AsNativeBytes(
              x, &val, sizeof(val), Py_ASNATIVEBYTES_NATIVE_ENDIAN | (is_unsigned ? Py_ASNATIVEBYTES_UNSIGNED_BUFFER | Py_ASNATIVEBYTES_REJECT_NEGATIVE : 0));
          if (unlikely(bytes_copied == -1)) {
          } else if (unlikely(bytes_copied > (Py_ssize_t) sizeof(val))) {
              goto raise_overflow;
          } else {
              ret = 0;
          }
  #elif PY_VERSION_HEX < 0x030d0000 && !(CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_LIMITED_API) || defined(_PyLong_AsByteArray)
          int one = 1; int is_little = (int)*(unsigned char *)&one;
          unsigned char *bytes = (unsigned char *)&val;
          ret = _PyLong_AsByteArray((PyLongObject *)x,
                                      bytes, sizeof(val),
                                      is_little, !is_unsigned);
  #else
          PyObject *v;
          PyObject *stepval = NULL, *mask = NULL, *shift = NULL;
          int bits, remaining_bits, is_negative = 0;
          int chunk_size = (sizeof(long) < 8) ? 30 : 62;
          if (likely(PyLong_CheckExact(x))) {
              v = __Pyx_NewRef(x);
          } else {
              v = PyNumber_Long(x);
              if (unlikely(!v)) return (size_t) -1;
              assert(PyLong_CheckExact(v));
          }
          {
              int result = PyObject_RichCompareBool(v, Py_False, Py_LT);
              if (unlikely(result < 0)) {
                  Py_DECREF(v);
                  return (size_t) -1;
              }
              is_negative = result == 1;
          }
          if (is_unsigned && unlikely(is_negative)) {
              Py_DECREF(v);
              goto raise_neg_overflow;
          } else if (is_negative) {
              stepval = PyNumber_Invert(v);
              Py_DECREF(v);
              if (unlikely(!stepval))
                  return (size_t) -1;
          } else {
              stepval = v;
          }
          v = NULL;
          val = (size_t) 0;
          mask = PyLong_FromLong((1L << chunk_size) - 1); if (unlikely(!mask)) goto done;
          shift = PyLong_FromLong(chunk_size); if (unlikely(!shift)) goto done;
          for (bits = 0; bits < (int) sizeof(size_t) * 8 - chunk_size; bits += chunk_size) {
              PyObject *tmp, *digit;
              long idigit;
              digit = PyNumber_And(stepval, mask);
              if (unlikely(!digit)) goto done;
              idigit = PyLong_AsLong(digit);
              Py_DECREF(digit);
              if (unlikely(idigit < 0)) goto done;
              val |= ((size_t) idigit) << bits;
              tmp = PyNumber_Rshift(stepval, shift);
              if (unlikely(!tmp)) goto done;
              Py_DECREF(stepval); stepval = tmp;
          }
          Py_DECREF(shift); shift = NULL;
          Py_DECREF(mask); mask = NULL;
          {
              long idigit = PyLong_AsLong(stepval);
              if (unlikely(idigit < 0)) goto done;
              remaining_bits = ((int) sizeof(size_t) * 8) - bits - (is_unsigned ? 0 : 1);
              if (unlikely(idigit >= (1L << remaining_bits)))
                  goto raise_overflow;
              val |= ((size_t) idigit) << bits;
          }
          if (!is_unsigned) {
              if (unlikely(val & (((size_t) 1) << (sizeof(size_t) * 8 - 1))))
                  goto raise_overflow;
              if (is_negative)
                  val = ~val;
          }
          ret = 0;
      done:
          Py_XDECREF(shift);
          Py_XDECREF(mask);
          Py_XDECREF(stepval);
  #endif
          if (unlikely(ret))
              return (size_t) -1;
          return val;
      }
  raise_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "value too large to convert to size_t");
      return (size_t) -1;
  raise_neg_overflow:
      PyErr_SetString(PyExc_OverflowError,
          "can't convert negative value to size_t");
      return (size_t) -1;
  }
  
/* CIntToPy */
  static CYTHON_INLINE PyObject* __Pyx_PyLong_From_unsigned_PY_LONG_LONG(unsigned PY_LONG_LONG value) {
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #endif
      const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG) -1, const_zero = (unsigned PY_LONG_LONG) 0;
  #ifdef __Pyx_HAS_GCC_DIAGNOSTIC
  #pragma GCC diagnostic pop
  #endif
      const int is_unsigned = neg_one > const_zero;
      if (is_unsigned) {
          if (sizeof(unsigned PY_LONG_LONG) < sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long)) {
              return PyLong_FromUnsignedLong((unsigned long) value);
  #if !CYTHON_COMPILING_IN_PYPY
          } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned PY_LONG_LONG)) {
              return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value);
  #endif
          }
      } else {
          if (sizeof(unsigned PY_LONG_LONG) <= sizeof(long)) {
              return PyLong_FromLong((long) value);
          } else if (sizeof(unsigned PY_LONG_LONG) <= sizeof(PY_LONG_LONG)) {
              return PyLong_FromLongLong((PY_LONG_LONG) value);
          }
      }
      {
          unsigned char *bytes = (unsigned char *)&value;
  #if !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d00A4
          if (is_unsigned) {
              return PyLong_FromUnsignedNativeBytes(bytes, sizeof(value), -1);
          } else {
              return PyLong_FromNativeBytes(bytes, sizeof(value), -1);
          }
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX < 0x030d0000
          int one = 1; int little = (int)*(unsigned char *)&one;
          return _PyLong_FromByteArray(bytes, sizeof(unsigned PY_LONG_LONG),
                                       little, !is_unsigned);
  #else
          int one = 1; int little = (int)*(unsigned char *)&one;
          PyObject *from_bytes, *result = NULL, *kwds = NULL;
          PyObject *py_bytes = NULL, *order_str = NULL;
          from_bytes = PyObject_GetAttrString((PyObject*)&PyLong_Type, "from_bytes");
          if (!from_bytes) return NULL;
          py_bytes = PyBytes_FromStringAndSize((char*)bytes, sizeof(unsigned PY_LONG_LONG));
          if (!py_bytes) goto limited_bad;
          order_str = PyUnicode_FromString(little ? "little" : "big");
          if (!order_str) goto limited_bad;
          {
              PyObject *args[3+(CYTHON_VECTORCALL ? 1 : 0)] = { NULL, py_bytes, order_str };
              if (!is_unsigned) {
                  kwds = __Pyx_MakeVectorcallBuilderKwds(1);
                  if (!kwds) goto limited_bad;
                  if (__Pyx_VectorcallBuilder_AddArgStr("signed", __Pyx_NewRef(Py_True), kwds, args+3, 0) < 0) goto limited_bad;
              }
              result = __Pyx_Object_Vectorcall_CallFromBuilder(from_bytes, args+1, 2 | __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET, kwds);
          }
          limited_bad:
          Py_XDECREF(kwds);
          Py_XDECREF(order_str);
          Py_XDECREF(py_bytes);
          Py_XDECREF(from_bytes);
          return result;
  #endif
      }
  }
  
/* FormatTypeName */
  #if CYTHON_COMPILING_IN_LIMITED_API && __PYX_LIMITED_VERSION_HEX < 0x030d0000
  static __Pyx_TypeName
  __Pyx_PyType_GetFullyQualifiedName(PyTypeObject* tp)
  {
      PyObject *module = NULL, *name = NULL, *result = NULL;
      #if __PYX_LIMITED_VERSION_HEX < 0x030b0000
      name = __Pyx_PyObject_GetAttrStr((PyObject *)tp,
                                                 __pyx_mstate_global->__pyx_n_u_qualname);
      #else
      name = PyType_GetQualName(tp);
      #endif
      if (unlikely(name == NULL) || unlikely(!PyUnicode_Check(name))) goto bad;
      module = __Pyx_PyObject_GetAttrStr((PyObject *)tp,
                                                 __pyx_mstate_global->__pyx_n_u_module);
      if (unlikely(module == NULL) || unlikely(!PyUnicode_Check(module))) goto bad;
      if (PyUnicode_CompareWithASCIIString(module, "builtins") == 0) {
          result = name;
          name = NULL;
          goto done;
      }
      result = PyUnicode_FromFormat("%U.%U", module, name);
      if (unlikely(result == NULL)) goto bad;
    done:
      Py_XDECREF(name);
      Py_XDECREF(module);
      return result;
    bad:
      PyErr_Clear();
      if (name) {
          result = name;
          name = NULL;
      } else {
          result = __Pyx_NewRef(__pyx_mstate_global->__pyx_kp_u__3);
      }
      goto done;
  }
  #endif
  
/* FastTypeChecks */
  #if CYTHON_COMPILING_IN_CPYTHON
  static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) {
      while (a) {
          a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*);
          if (a == b)
              return 1;
      }
      return b == &PyBaseObject_Type;
  }
  static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) {
      PyObject *mro;
      if (a == b) return 1;
      mro = a->tp_mro;
      if (likely(mro)) {
          Py_ssize_t i, n;
          n = PyTuple_GET_SIZE(mro);
          for (i = 0; i < n; i++) {
              if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
                  return 1;
          }
          return 0;
      }
      return __Pyx_InBases(a, b);
  }
  static CYTHON_INLINE int __Pyx_IsAnySubtype2(PyTypeObject *cls, PyTypeObject *a, PyTypeObject *b) {
      PyObject *mro;
      if (cls == a || cls == b) return 1;
      mro = cls->tp_mro;
      if (likely(mro)) {
          Py_ssize_t i, n;
          n = PyTuple_GET_SIZE(mro);
          for (i = 0; i < n; i++) {
              PyObject *base = PyTuple_GET_ITEM(mro, i);
              if (base == (PyObject *)a || base == (PyObject *)b)
                  return 1;
          }
          return 0;
      }
      return __Pyx_InBases(cls, a) || __Pyx_InBases(cls, b);
  }
  static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) {
      if (exc_type1) {
          return __Pyx_IsAnySubtype2((PyTypeObject*)err, (PyTypeObject*)exc_type1, (PyTypeObject*)exc_type2);
      } else {
          return __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2);
      }
  }
  static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
      Py_ssize_t i, n;
      assert(PyExceptionClass_Check(exc_type));
      n = PyTuple_GET_SIZE(tuple);
      for (i=0; i<n; i++) {
          if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
      }
      for (i=0; i<n; i++) {
          PyObject *t = PyTuple_GET_ITEM(tuple, i);
          if (likely(PyExceptionClass_Check(t))) {
              if (__Pyx_inner_PyErr_GivenExceptionMatches2(exc_type, NULL, t)) return 1;
          } else {
          }
      }
      return 0;
  }
  static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) {
      if (likely(err == exc_type)) return 1;
      if (likely(PyExceptionClass_Check(err))) {
          if (likely(PyExceptionClass_Check(exc_type))) {
              return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
          } else if (likely(PyTuple_Check(exc_type))) {
              return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type);
          } else {
          }
      }
      return PyErr_GivenExceptionMatches(err, exc_type);
  }
  static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) {
      assert(PyExceptionClass_Check(exc_type1));
      assert(PyExceptionClass_Check(exc_type2));
      if (likely(err == exc_type1 || err == exc_type2)) return 1;
      if (likely(PyExceptionClass_Check(err))) {
          return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2);
      }
      return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2));
  }
  #endif
  
/* GetRuntimeVersion */
  #if __PYX_LIMITED_VERSION_HEX < 0x030b0000
  void __Pyx_init_runtime_version(void) {
      if (__Pyx_cached_runtime_version == 0) {
          const char* rt_version = Py_GetVersion();
          unsigned long version = 0;
          unsigned long factor = 0x01000000UL;
          unsigned int digit = 0;
          int i = 0;
          while (factor) {
              while ('0' <= rt_version[i] && rt_version[i] <= '9') {
                  digit = digit * 10 + (unsigned int) (rt_version[i] - '0');
                  ++i;
              }
              version += factor * digit;
              if (rt_version[i] != '.')
                  break;
              digit = 0;
              factor >>= 8;
              ++i;
          }
          __Pyx_cached_runtime_version = version;
      }
  }
  #endif
  static unsigned long __Pyx_get_runtime_version(void) {
  #if __PYX_LIMITED_VERSION_HEX >= 0x030b0000
      return Py_Version & ~0xFFUL;
  #else
      return __Pyx_cached_runtime_version;
  #endif
  }
  
/* CheckBinaryVersion */
  static int __Pyx_check_binary_version(unsigned long ct_version, unsigned long rt_version, int allow_newer) {
      const unsigned long MAJOR_MINOR = 0xFFFF0000UL;
      if ((rt_version & MAJOR_MINOR) == (ct_version & MAJOR_MINOR))
          return 0;
      if (likely(allow_newer && (rt_version & MAJOR_MINOR) > (ct_version & MAJOR_MINOR)))
          return 1;
      {
          char message[200];
          PyOS_snprintf(message, sizeof(message),
                        "compile time Python version %d.%d "
                        "of module '%.100s' "
                        "%s "
                        "runtime version %d.%d",
                         (int) (ct_version >> 24), (int) ((ct_version >> 16) & 0xFF),
                         __Pyx_MODULE_NAME,
                         (allow_newer) ? "was newer than" : "does not match",
                         (int) (rt_version >> 24), (int) ((rt_version >> 16) & 0xFF)
         );
          return PyErr_WarnEx(NULL, message, 1);
      }
  }
  
/* NewCodeObj */
  #if CYTHON_COMPILING_IN_LIMITED_API
      static PyObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f,
                                         PyObject *code, PyObject *c, PyObject* n, PyObject *v,
                                         PyObject *fv, PyObject *cell, PyObject* fn,
                                         PyObject *name, int fline, PyObject *lnos) {
          PyObject *exception_table = NULL;
          PyObject *types_module=NULL, *code_type=NULL, *result=NULL;
          #if __PYX_LIMITED_VERSION_HEX < 0x030b0000
          PyObject *version_info;
          PyObject *py_minor_version = NULL;
          #endif
          long minor_version = 0;
          PyObject *type, *value, *traceback;
          PyErr_Fetch(&type, &value, &traceback);
          #if __PYX_LIMITED_VERSION_HEX >= 0x030b0000
          minor_version = 11;
          #else
          if (!(version_info = PySys_GetObject("version_info"))) goto end;
          if (!(py_minor_version = PySequence_GetItem(version_info, 1))) goto end;
          minor_version = PyLong_AsLong(py_minor_version);
          Py_DECREF(py_minor_version);
          if (minor_version == -1 && PyErr_Occurred()) goto end;
          #endif
          if (!(types_module = PyImport_ImportModule("types"))) goto end;
          if (!(code_type = PyObject_GetAttrString(types_module, "CodeType"))) goto end;
          if (minor_version <= 7) {
              (void)p;
              result = PyObject_CallFunction(code_type, "iiiiiOOOOOOiOOO", a, k, l, s, f, code,
                            c, n, v, fn, name, fline, lnos, fv, cell);
          } else if (minor_version <= 10) {
              result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOiOOO", a,p, k, l, s, f, code,
                            c, n, v, fn, name, fline, lnos, fv, cell);
          } else {
              if (!(exception_table = PyBytes_FromStringAndSize(NULL, 0))) goto end;
              result = PyObject_CallFunction(code_type, "iiiiiiOOOOOOOiOOOO", a,p, k, l, s, f, code,
                            c, n, v, fn, name, name, fline, lnos, exception_table, fv, cell);
          }
      end:
          Py_XDECREF(code_type);
          Py_XDECREF(exception_table);
          Py_XDECREF(types_module);
          if (type) {
              PyErr_Restore(type, value, traceback);
          }
          return result;
      }
  #elif PY_VERSION_HEX >= 0x030B0000
    static PyCodeObject* __Pyx__PyCode_New(int a, int p, int k, int l, int s, int f,
                                           PyObject *code, PyObject *c, PyObject* n, PyObject *v,
                                           PyObject *fv, PyObject *cell, PyObject* fn,
                                           PyObject *name, int fline, PyObject *lnos) {
      PyCodeObject *result;
      result =
        #if PY_VERSION_HEX >= 0x030C0000
          PyUnstable_Code_NewWithPosOnlyArgs
        #else
          PyCode_NewWithPosOnlyArgs
        #endif
          (a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, name, fline, lnos, __pyx_mstate_global->__pyx_empty_bytes);
      #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030c00A1
      if (likely(result))
          result->_co_firsttraceable = 0;
      #endif
      return result;
    }
  #elif !CYTHON_COMPILING_IN_PYPY
    #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
            PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
  #else
    #define __Pyx__PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
            PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
  #endif
  static PyObject* __Pyx_PyCode_New(
          const __Pyx_PyCode_New_function_description descr,
          PyObject * const *varnames,
          PyObject *filename,
          PyObject *funcname,
          PyObject *line_table,
          PyObject *tuple_dedup_map
  ) {
      PyObject *code_obj = NULL, *varnames_tuple_dedup = NULL, *code_bytes = NULL;
      Py_ssize_t var_count = (Py_ssize_t) descr.nlocals;
      PyObject *varnames_tuple = PyTuple_New(var_count);
      if (unlikely(!varnames_tuple)) return NULL;
      for (Py_ssize_t i=0; i < var_count; i++) {
          Py_INCREF(varnames[i]);
          if (__Pyx_PyTuple_SET_ITEM(varnames_tuple, i, varnames[i]) != (0)) goto done;
      }
      #if CYTHON_COMPILING_IN_LIMITED_API
      varnames_tuple_dedup = PyDict_GetItem(tuple_dedup_map, varnames_tuple);
      if (!varnames_tuple_dedup) {
          if (unlikely(PyDict_SetItem(tuple_dedup_map, varnames_tuple, varnames_tuple) < 0)) goto done;
          varnames_tuple_dedup = varnames_tuple;
      }
      #else
      varnames_tuple_dedup = PyDict_SetDefault(tuple_dedup_map, varnames_tuple, varnames_tuple);
      if (unlikely(!varnames_tuple_dedup)) goto done;
      #endif
      #if CYTHON_AVOID_BORROWED_REFS
      Py_INCREF(varnames_tuple_dedup);
      #endif
      if (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table != NULL && !CYTHON_COMPILING_IN_GRAAL) {
          Py_ssize_t line_table_length = __Pyx_PyBytes_GET_SIZE(line_table);
          #if !CYTHON_ASSUME_SAFE_SIZE
          if (unlikely(line_table_length == -1)) goto done;
          #endif
          Py_ssize_t code_len = (line_table_length * 2 + 4) & ~3LL;
          code_bytes = PyBytes_FromStringAndSize(NULL, code_len);
          if (unlikely(!code_bytes)) goto done;
          char* c_code_bytes = PyBytes_AsString(code_bytes);
          if (unlikely(!c_code_bytes)) goto done;
          memset(c_code_bytes, 0, (size_t) code_len);
      }
      code_obj = (PyObject*) __Pyx__PyCode_New(
          (int) descr.argcount,
          (int) descr.num_posonly_args,
          (int) descr.num_kwonly_args,
          (int) descr.nlocals,
          0,
          (int) descr.flags,
          code_bytes ? code_bytes : __pyx_mstate_global->__pyx_empty_bytes,
          __pyx_mstate_global->__pyx_empty_tuple,
          __pyx_mstate_global->__pyx_empty_tuple,
          varnames_tuple_dedup,
          __pyx_mstate_global->__pyx_empty_tuple,
          __pyx_mstate_global->__pyx_empty_tuple,
          filename,
          funcname,
          (int) descr.first_line,
          (__PYX_LIMITED_VERSION_HEX >= (0x030b0000) && line_table) ? line_table : __pyx_mstate_global->__pyx_empty_bytes
      );
  done:
      Py_XDECREF(code_bytes);
      #if CYTHON_AVOID_BORROWED_REFS
      Py_XDECREF(varnames_tuple_dedup);
      #endif
      Py_DECREF(varnames_tuple);
      return code_obj;
  }
  
/* DecompressString */
  static PyObject *__Pyx_DecompressString(const char *s, Py_ssize_t length, int algo) {
      PyObject *module = NULL, *decompress, *compressed_bytes, *decompressed;
      const char* module_name = algo == 3 ? "compression.zstd" : algo == 2 ? "bz2" : "zlib";
      PyObject *methodname = PyUnicode_FromString("decompress");
      if (unlikely(!methodname)) return NULL;
      #if __PYX_LIMITED_VERSION_HEX >= 0x030e0000
      if (algo == 3) {
          PyObject *fromlist = Py_BuildValue("[O]", methodname);
          if (unlikely(!fromlist)) goto bad;
          module = PyImport_ImportModuleLevel("compression.zstd", NULL, NULL, fromlist, 0);
          Py_DECREF(fromlist);
      } else
      #endif
          module = PyImport_ImportModule(module_name);
      if (unlikely(!module)) goto import_failed;
      decompress = PyObject_GetAttr(module, methodname);
      if (unlikely(!decompress)) goto import_failed;
      {
          #ifdef __cplusplus
              char *memview_bytes = const_cast<char*>(s);
          #else
              #if defined(__clang__)
                #pragma clang diagnostic push
                #pragma clang diagnostic ignored "-Wcast-qual"
              #elif !defined(__INTEL_COMPILER) && defined(__GNUC__)
                #pragma GCC diagnostic push
                #pragma GCC diagnostic ignored "-Wcast-qual"
              #endif
              char *memview_bytes = (char*) s;
              #if defined(__clang__)
                #pragma clang diagnostic pop
              #elif !defined(__INTEL_COMPILER) && defined(__GNUC__)
                #pragma GCC diagnostic pop
              #endif
          #endif
          #if CYTHON_COMPILING_IN_LIMITED_API && !defined(PyBUF_READ)
          int memview_flags = 0x100;
          #else
          int memview_flags = PyBUF_READ;
          #endif
          compressed_bytes = PyMemoryView_FromMemory(memview_bytes, length, memview_flags);
      }
      if (unlikely(!compressed_bytes)) {
          Py_DECREF(decompress);
          goto bad;
      }
      decompressed = PyObject_CallFunctionObjArgs(decompress, compressed_bytes, NULL);
      Py_DECREF(compressed_bytes);
      Py_DECREF(decompress);
      Py_DECREF(module);
      Py_DECREF(methodname);
      return decompressed;
  import_failed:
      PyErr_Format(PyExc_ImportError,
          "Failed to import '%.20s.decompress' - cannot initialise module strings. "
          "String compression was configured with the C macro 'CYTHON_COMPRESS_STRINGS=%d'.",
          module_name, algo);
  bad:
      Py_XDECREF(module);
      Py_DECREF(methodname);
      return NULL;
  }
  
#include <string.h>
static CYTHON_INLINE Py_ssize_t __Pyx_ssize_strlen(const char *s) {
    size_t len = strlen(s);
    if (unlikely(len > (size_t) PY_SSIZE_T_MAX)) {
        PyErr_SetString(PyExc_OverflowError, "byte string is too long");
        return -1;
    }
    return (Py_ssize_t) len;
}
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
    Py_ssize_t len = __Pyx_ssize_strlen(c_str);
    if (unlikely(len < 0)) return NULL;
    return __Pyx_PyUnicode_FromStringAndSize(c_str, len);
}
static CYTHON_INLINE PyObject* __Pyx_PyByteArray_FromString(const char* c_str) {
    Py_ssize_t len = __Pyx_ssize_strlen(c_str);
    if (unlikely(len < 0)) return NULL;
    return PyByteArray_FromStringAndSize(c_str, len);
}
static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) {
    Py_ssize_t ignore;
    return __Pyx_PyObject_AsStringAndSize(o, &ignore);
}
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8
static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
    if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL;
#if CYTHON_COMPILING_IN_LIMITED_API
    {
        const char* result;
        Py_ssize_t unicode_length;
        CYTHON_MAYBE_UNUSED_VAR(unicode_length); // only for __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
        #if __PYX_LIMITED_VERSION_HEX < 0x030A0000
        if (unlikely(PyArg_Parse(o, "s#", &result, length) < 0)) return NULL;
        #else
        result = PyUnicode_AsUTF8AndSize(o, length);
        #endif
        #if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
        unicode_length = PyUnicode_GetLength(o);
        if (unlikely(unicode_length < 0)) return NULL;
        if (unlikely(unicode_length != *length)) {
            PyUnicode_AsASCIIString(o);
            return NULL;
        }
        #endif
        return result;
    }
#else
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
    if (likely(PyUnicode_IS_ASCII(o))) {
        *length = PyUnicode_GET_LENGTH(o);
        return PyUnicode_AsUTF8(o);
    } else {
        PyUnicode_AsASCIIString(o);
        return NULL;
    }
#else
    return PyUnicode_AsUTF8AndSize(o, length);
#endif
#endif
}
#endif
static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_UTF8
    if (PyUnicode_Check(o)) {
        return __Pyx_PyUnicode_AsStringAndSize(o, length);
    } else
#endif
    if (PyByteArray_Check(o)) {
#if (CYTHON_ASSUME_SAFE_SIZE && CYTHON_ASSUME_SAFE_MACROS) || (CYTHON_COMPILING_IN_PYPY && (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)))
        *length = PyByteArray_GET_SIZE(o);
        return PyByteArray_AS_STRING(o);
#else
        *length = PyByteArray_Size(o);
        if (*length == -1) return NULL;
        return PyByteArray_AsString(o);
#endif
    } else
    {
        char* result;
        int r = PyBytes_AsStringAndSize(o, &result, length);
        if (unlikely(r < 0)) {
            return NULL;
        } else {
            return result;
        }
    }
}
static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
   int is_true = x == Py_True;
   if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
   else return PyObject_IsTrue(x);
}
static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) {
    int retval;
    if (unlikely(!x)) return -1;
    retval = __Pyx_PyObject_IsTrue(x);
    Py_DECREF(x);
    return retval;
}
static PyObject* __Pyx_PyNumber_LongWrongResultType(PyObject* result) {
    __Pyx_TypeName result_type_name = __Pyx_PyType_GetFullyQualifiedName(Py_TYPE(result));
    if (PyLong_Check(result)) {
        if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
                "__int__ returned non-int (type " __Pyx_FMT_TYPENAME ").  "
                "The ability to return an instance of a strict subclass of int is deprecated, "
                "and may be removed in a future version of Python.",
                result_type_name)) {
            __Pyx_DECREF_TypeName(result_type_name);
            Py_DECREF(result);
            return NULL;
        }
        __Pyx_DECREF_TypeName(result_type_name);
        return result;
    }
    PyErr_Format(PyExc_TypeError,
                 "__int__ returned non-int (type " __Pyx_FMT_TYPENAME ")",
                 result_type_name);
    __Pyx_DECREF_TypeName(result_type_name);
    Py_DECREF(result);
    return NULL;
}
static CYTHON_INLINE PyObject* __Pyx_PyNumber_Long(PyObject* x) {
#if CYTHON_USE_TYPE_SLOTS
  PyNumberMethods *m;
#endif
  PyObject *res = NULL;
  if (likely(PyLong_Check(x)))
      return __Pyx_NewRef(x);
#if CYTHON_USE_TYPE_SLOTS
  m = Py_TYPE(x)->tp_as_number;
  if (likely(m && m->nb_int)) {
      res = m->nb_int(x);
  }
#else
  if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) {
      res = PyNumber_Long(x);
  }
#endif
  if (likely(res)) {
      if (unlikely(!PyLong_CheckExact(res))) {
          return __Pyx_PyNumber_LongWrongResultType(res);
      }
  }
  else if (!PyErr_Occurred()) {
      PyErr_SetString(PyExc_TypeError,
                      "an integer is required");
  }
  return res;
}
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
  Py_ssize_t ival;
  PyObject *x;
  if (likely(PyLong_CheckExact(b))) {
    #if CYTHON_USE_PYLONG_INTERNALS
    if (likely(__Pyx_PyLong_IsCompact(b))) {
        return __Pyx_PyLong_CompactValue(b);
    } else {
      const digit* digits = __Pyx_PyLong_Digits(b);
      const Py_ssize_t size = __Pyx_PyLong_SignedDigitCount(b);
      switch (size) {
         case 2:
           if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) {
             return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
         case -2:
           if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) {
             return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
         case 3:
           if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) {
             return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
         case -3:
           if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) {
             return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
         case 4:
           if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) {
             return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
         case -4:
           if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) {
             return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0]));
           }
           break;
      }
    }
    #endif
    return PyLong_AsSsize_t(b);
  }
  x = PyNumber_Index(b);
  if (!x) return -1;
  ival = PyLong_AsSsize_t(x);
  Py_DECREF(x);
  return ival;
}
static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject* o) {
  if (sizeof(Py_hash_t) == sizeof(Py_ssize_t)) {
    return (Py_hash_t) __Pyx_PyIndex_AsSsize_t(o);
  } else {
    Py_ssize_t ival;
    PyObject *x;
    x = PyNumber_Index(o);
    if (!x) return -1;
    ival = PyLong_AsLong(x);
    Py_DECREF(x);
    return ival;
  }
}
static CYTHON_INLINE PyObject *__Pyx_Owned_Py_None(int b) {
    CYTHON_UNUSED_VAR(b);
    return __Pyx_NewRef(Py_None);
}
static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) {
  return __Pyx_NewRef(b ? Py_True: Py_False);
}
static CYTHON_INLINE PyObject * __Pyx_PyLong_FromSize_t(size_t ival) {
    return PyLong_FromSize_t(ival);
}


  /* MultiPhaseInitModuleState */
  #if CYTHON_PEP489_MULTI_PHASE_INIT && CYTHON_USE_MODULE_STATE
  #ifndef CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
  #if (CYTHON_COMPILING_IN_LIMITED_API || PY_VERSION_HEX >= 0x030C0000)
    #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 1
  #else
    #define CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE 0
  #endif
  #endif
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE && !CYTHON_ATOMICS
  #error "Module state with PEP489 requires atomics. Currently that's one of\
   C11, C++11, gcc atomic intrinsics or MSVC atomic intrinsics"
  #endif
  #if !CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
  #define __Pyx_ModuleStateLookup_Lock()
  #define __Pyx_ModuleStateLookup_Unlock()
  #elif !CYTHON_COMPILING_IN_LIMITED_API && PY_VERSION_HEX >= 0x030d0000
  static PyMutex __Pyx_ModuleStateLookup_mutex = {0};
  #define __Pyx_ModuleStateLookup_Lock() PyMutex_Lock(&__Pyx_ModuleStateLookup_mutex)
  #define __Pyx_ModuleStateLookup_Unlock() PyMutex_Unlock(&__Pyx_ModuleStateLookup_mutex)
  #elif defined(__cplusplus) && __cplusplus >= 201103L
  #include <mutex>
  static std::mutex __Pyx_ModuleStateLookup_mutex;
  #define __Pyx_ModuleStateLookup_Lock() __Pyx_ModuleStateLookup_mutex.lock()
  #define __Pyx_ModuleStateLookup_Unlock() __Pyx_ModuleStateLookup_mutex.unlock()
  #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201112L) && !defined(__STDC_NO_THREADS__)
  #include <threads.h>
  static mtx_t __Pyx_ModuleStateLookup_mutex;
  static once_flag __Pyx_ModuleStateLookup_mutex_once_flag = ONCE_FLAG_INIT;
  static void __Pyx_ModuleStateLookup_initialize_mutex(void) {
      mtx_init(&__Pyx_ModuleStateLookup_mutex, mtx_plain);
  }
  #define __Pyx_ModuleStateLookup_Lock()\
    call_once(&__Pyx_ModuleStateLookup_mutex_once_flag, __Pyx_ModuleStateLookup_initialize_mutex);\
    mtx_lock(&__Pyx_ModuleStateLookup_mutex)
  #define __Pyx_ModuleStateLookup_Unlock() mtx_unlock(&__Pyx_ModuleStateLookup_mutex)
  #elif defined(HAVE_PTHREAD_H)
  #include <pthread.h>
  static pthread_mutex_t __Pyx_ModuleStateLookup_mutex = PTHREAD_MUTEX_INITIALIZER;
  #define __Pyx_ModuleStateLookup_Lock() pthread_mutex_lock(&__Pyx_ModuleStateLookup_mutex)
  #define __Pyx_ModuleStateLookup_Unlock() pthread_mutex_unlock(&__Pyx_ModuleStateLookup_mutex)
  #elif defined(_WIN32)
  #include <Windows.h>  // synchapi.h on its own doesn't work
  static SRWLOCK __Pyx_ModuleStateLookup_mutex = SRWLOCK_INIT;
  #define __Pyx_ModuleStateLookup_Lock() AcquireSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex)
  #define __Pyx_ModuleStateLookup_Unlock() ReleaseSRWLockExclusive(&__Pyx_ModuleStateLookup_mutex)
  #else
  #error "No suitable lock available for CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE.\
   Requires C standard >= C11, or C++ standard >= C++11,\
   or pthreads, or the Windows 32 API, or Python >= 3.13."
  #endif
  typedef struct {
      int64_t id;
      PyObject *module;
  } __Pyx_InterpreterIdAndModule;
  typedef struct {
      char interpreter_id_as_index;
      Py_ssize_t count;
      Py_ssize_t allocated;
      __Pyx_InterpreterIdAndModule table[1];
  } __Pyx_ModuleStateLookupData;
  #define __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE 32
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
  static __pyx_atomic_int_type __Pyx_ModuleStateLookup_read_counter = 0;
  #endif
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
  static __pyx_atomic_ptr_type __Pyx_ModuleStateLookup_data = 0;
  #else
  static __Pyx_ModuleStateLookupData* __Pyx_ModuleStateLookup_data = NULL;
  #endif
  static __Pyx_InterpreterIdAndModule* __Pyx_State_FindModuleStateLookupTableLowerBound(
          __Pyx_InterpreterIdAndModule* table,
          Py_ssize_t count,
          int64_t interpreterId) {
      __Pyx_InterpreterIdAndModule* begin = table;
      __Pyx_InterpreterIdAndModule* end = begin + count;
      if (begin->id == interpreterId) {
          return begin;
      }
      while ((end - begin) > __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) {
          __Pyx_InterpreterIdAndModule* halfway = begin + (end - begin)/2;
          if (halfway->id == interpreterId) {
              return halfway;
          }
          if (halfway->id < interpreterId) {
              begin = halfway;
          } else {
              end = halfway;
          }
      }
      for (; begin < end; ++begin) {
          if (begin->id >= interpreterId) return begin;
      }
      return begin;
  }
  static PyObject *__Pyx_State_FindModule(CYTHON_UNUSED void* dummy) {
      int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get());
      if (interpreter_id == -1) return NULL;
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
      __Pyx_ModuleStateLookupData* data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data);
      {
          __pyx_atomic_incr_acq_rel(&__Pyx_ModuleStateLookup_read_counter);
          if (likely(data)) {
              __Pyx_ModuleStateLookupData* new_data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_acquire(&__Pyx_ModuleStateLookup_data);
              if (likely(data == new_data)) {
                  goto read_finished;
              }
          }
          __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter);
          __Pyx_ModuleStateLookup_Lock();
          __pyx_atomic_incr_relaxed(&__Pyx_ModuleStateLookup_read_counter);
          data = (__Pyx_ModuleStateLookupData*)__pyx_atomic_pointer_load_relaxed(&__Pyx_ModuleStateLookup_data);
          __Pyx_ModuleStateLookup_Unlock();
      }
    read_finished:;
  #else
      __Pyx_ModuleStateLookupData* data = __Pyx_ModuleStateLookup_data;
  #endif
      __Pyx_InterpreterIdAndModule* found = NULL;
      if (unlikely(!data)) goto end;
      if (data->interpreter_id_as_index) {
          if (interpreter_id < data->count) {
              found = data->table+interpreter_id;
          }
      } else {
          found = __Pyx_State_FindModuleStateLookupTableLowerBound(
              data->table, data->count, interpreter_id);
      }
    end:
      {
          PyObject *result=NULL;
          if (found && found->id == interpreter_id) {
              result = found->module;
          }
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
          __pyx_atomic_decr_acq_rel(&__Pyx_ModuleStateLookup_read_counter);
  #endif
          return result;
      }
  }
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
  static void __Pyx_ModuleStateLookup_wait_until_no_readers(void) {
      while (__pyx_atomic_load(&__Pyx_ModuleStateLookup_read_counter) != 0);
  }
  #else
  #define __Pyx_ModuleStateLookup_wait_until_no_readers()
  #endif
  static int __Pyx_State_AddModuleInterpIdAsIndex(__Pyx_ModuleStateLookupData **old_data, PyObject* module, int64_t interpreter_id) {
      Py_ssize_t to_allocate = (*old_data)->allocated;
      while (to_allocate <= interpreter_id) {
          if (to_allocate == 0) to_allocate = 1;
          else to_allocate *= 2;
      }
      __Pyx_ModuleStateLookupData *new_data = *old_data;
      if (to_allocate != (*old_data)->allocated) {
           new_data = (__Pyx_ModuleStateLookupData *)realloc(
              *old_data,
              sizeof(__Pyx_ModuleStateLookupData)+(to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule));
          if (!new_data) {
              PyErr_NoMemory();
              return -1;
          }
          for (Py_ssize_t i = new_data->allocated; i < to_allocate; ++i) {
              new_data->table[i].id = i;
              new_data->table[i].module = NULL;
          }
          new_data->allocated = to_allocate;
      }
      new_data->table[interpreter_id].module = module;
      if (new_data->count < interpreter_id+1) {
          new_data->count = interpreter_id+1;
      }
      *old_data = new_data;
      return 0;
  }
  static void __Pyx_State_ConvertFromInterpIdAsIndex(__Pyx_ModuleStateLookupData *data) {
      __Pyx_InterpreterIdAndModule *read = data->table;
      __Pyx_InterpreterIdAndModule *write = data->table;
      __Pyx_InterpreterIdAndModule *end = read + data->count;
      for (; read<end; ++read) {
          if (read->module) {
              write->id = read->id;
              write->module = read->module;
              ++write;
          }
      }
      data->count = write - data->table;
      for (; write<end; ++write) {
          write->id = 0;
          write->module = NULL;
      }
      data->interpreter_id_as_index = 0;
  }
  static int __Pyx_State_AddModule(PyObject* module, CYTHON_UNUSED void* dummy) {
      int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get());
      if (interpreter_id == -1) return -1;
      int result = 0;
      __Pyx_ModuleStateLookup_Lock();
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
      __Pyx_ModuleStateLookupData *old_data = (__Pyx_ModuleStateLookupData *)
              __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0);
  #else
      __Pyx_ModuleStateLookupData *old_data = __Pyx_ModuleStateLookup_data;
  #endif
      __Pyx_ModuleStateLookupData *new_data = old_data;
      if (!new_data) {
          new_data = (__Pyx_ModuleStateLookupData *)calloc(1, sizeof(__Pyx_ModuleStateLookupData));
          if (!new_data) {
              result = -1;
              PyErr_NoMemory();
              goto end;
          }
          new_data->allocated = 1;
          new_data->interpreter_id_as_index = 1;
      }
      __Pyx_ModuleStateLookup_wait_until_no_readers();
      if (new_data->interpreter_id_as_index) {
          if (interpreter_id < __PYX_MODULE_STATE_LOOKUP_SMALL_SIZE) {
              result = __Pyx_State_AddModuleInterpIdAsIndex(&new_data, module, interpreter_id);
              goto end;
          }
          __Pyx_State_ConvertFromInterpIdAsIndex(new_data);
      }
      {
          Py_ssize_t insert_at = 0;
          {
              __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound(
                  new_data->table, new_data->count, interpreter_id);
              assert(lower_bound);
              insert_at = lower_bound - new_data->table;
              if (unlikely(insert_at < new_data->count && lower_bound->id == interpreter_id)) {
                  lower_bound->module = module;
                  goto end;  // already in table, nothing more to do
              }
          }
          if (new_data->count+1 >= new_data->allocated) {
              Py_ssize_t to_allocate = (new_data->count+1)*2;
              new_data =
                  (__Pyx_ModuleStateLookupData*)realloc(
                      new_data,
                      sizeof(__Pyx_ModuleStateLookupData) +
                      (to_allocate-1)*sizeof(__Pyx_InterpreterIdAndModule));
              if (!new_data) {
                  result = -1;
                  new_data = old_data;
                  PyErr_NoMemory();
                  goto end;
              }
              new_data->allocated = to_allocate;
          }
          ++new_data->count;
          int64_t last_id = interpreter_id;
          PyObject *last_module = module;
          for (Py_ssize_t i=insert_at; i<new_data->count; ++i) {
              int64_t current_id = new_data->table[i].id;
              new_data->table[i].id = last_id;
              last_id = current_id;
              PyObject *current_module = new_data->table[i].module;
              new_data->table[i].module = last_module;
              last_module = current_module;
          }
      }
    end:
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
      __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, new_data);
  #else
      __Pyx_ModuleStateLookup_data = new_data;
  #endif
      __Pyx_ModuleStateLookup_Unlock();
      return result;
  }
  static int __Pyx_State_RemoveModule(CYTHON_UNUSED void* dummy) {
      int64_t interpreter_id = PyInterpreterState_GetID(__Pyx_PyInterpreterState_Get());
      if (interpreter_id == -1) return -1;
      __Pyx_ModuleStateLookup_Lock();
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
      __Pyx_ModuleStateLookupData *data = (__Pyx_ModuleStateLookupData *)
              __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, 0);
  #else
      __Pyx_ModuleStateLookupData *data = __Pyx_ModuleStateLookup_data;
  #endif
      if (data->interpreter_id_as_index) {
          if (interpreter_id < data->count) {
              data->table[interpreter_id].module = NULL;
          }
          goto done;
      }
      {
          __Pyx_ModuleStateLookup_wait_until_no_readers();
          __Pyx_InterpreterIdAndModule* lower_bound = __Pyx_State_FindModuleStateLookupTableLowerBound(
              data->table, data->count, interpreter_id);
          if (!lower_bound) goto done;
          if (lower_bound->id != interpreter_id) goto done;
          __Pyx_InterpreterIdAndModule *end = data->table+data->count;
          for (;lower_bound<end-1; ++lower_bound) {
              lower_bound->id = (lower_bound+1)->id;
              lower_bound->module = (lower_bound+1)->module;
          }
      }
      --data->count;
      if (data->count == 0) {
          free(data);
          data = NULL;
      }
    done:
  #if CYTHON_MODULE_STATE_LOOKUP_THREAD_SAFE
      __pyx_atomic_pointer_exchange(&__Pyx_ModuleStateLookup_data, data);
  #else
      __Pyx_ModuleStateLookup_data = data;
  #endif
      __Pyx_ModuleStateLookup_Unlock();
      return 0;
  }
  #endif
  
/* #### Code section: utility_code_pragmas_end ### */
#ifdef _MSC_VER
#pragma warning( pop )
#endif



/* #### Code section: end ### */
#endif /* Py_PYTHON_H */
