Generated by Cython 0.29.37

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

Raw output: sam_cyutils.c

+001: """
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 002: 
 003: $ python setup.py build_ext -i
 004: 
 005: $ python setup.py develop
 006: 
 007: """
 008: 
 009: import cython
+010: import numpy as np
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 011: cimport numpy as np
+012: np.import_array()
  __pyx_t_2 = __pyx_f_5numpy_import_array(); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 12, __pyx_L1_error)
 013: 
 014: from scipy.optimize.cython_optimize cimport brentq
 015: 
 016: from libc.stdio cimport printf, fflush, stdout
 017: from libc.stdlib cimport malloc, free
 018: # make sure to use c-native math functions instead of python/numpy
 019: from libc.math cimport pow, sqrt, M_PI, NAN, log10, sin, cos
 020: 
+021: import holodeck as holo
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_holodeck, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 21, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_holo, __pyx_t_1) < 0) __PYX_ERR(0, 21, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 022: from holodeck.cyutils cimport interp_at_index, _interp_between_vals
 023: 
 024: 
 025: # ---- Define Parameters
 026: 
 027: 
 028: # ---- Define Constants
 029: 
+030: cdef double MY_NWTG = 6.6742999e-08
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_NWTG = 6.6742999e-08;
+031: cdef double MY_SPLC = 29979245800.0
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SPLC = 29979245800.0;
+032: cdef double MY_MPC = 3.08567758e+24
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC = 3.08567758e+24;
+033: cdef double MY_MSOL = 1.988409870698051e+33
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_MSOL = 1.988409870698051e+33;
+034: cdef double MY_YR = 31557600.0
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_YR = 31557600.0;
+035: cdef double MY_SCHW = 1.4852320538237328e-28     #: Schwarzschild Constant  2*G/c^2  [cm]
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SCHW = 1.4852320538237328e-28;
+036: cdef double GW_DADT_SEP_CONST = - 64.0 * pow(MY_NWTG, 3) / 5.0 / pow(MY_SPLC, 5)
  __pyx_t_3 = ((-64.0 * pow(__pyx_v_8holodeck_4sams_11sam_cyutils_MY_NWTG, 3.0)) / 5.0);
  __pyx_t_4 = pow(__pyx_v_8holodeck_4sams_11sam_cyutils_MY_SPLC, 5.0);
  if (unlikely(__pyx_t_4 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 36, __pyx_L1_error)
  }
  __pyx_v_8holodeck_4sams_11sam_cyutils_GW_DADT_SEP_CONST = (__pyx_t_3 / __pyx_t_4);
 037: 
+038: cdef double MY_PC = MY_MPC / 1.0e6
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_PC = (__pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC / 1.0e6);
+039: cdef double MY_GYR = MY_YR * 1.0e9
  __pyx_v_8holodeck_4sams_11sam_cyutils_MY_GYR = (__pyx_v_8holodeck_4sams_11sam_cyutils_MY_YR * 1.0e9);
+040: cdef double KEPLER_CONST_FREQ = (1.0 / (2.0*M_PI)) * sqrt(MY_NWTG)
  __pyx_t_4 = (2.0 * M_PI);
  if (unlikely(__pyx_t_4 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 40, __pyx_L1_error)
  }
  __pyx_v_8holodeck_4sams_11sam_cyutils_KEPLER_CONST_FREQ = ((1.0 / __pyx_t_4) * sqrt(__pyx_v_8holodeck_4sams_11sam_cyutils_MY_NWTG));
+041: cdef double KEPLER_CONST_SEPA = pow(MY_NWTG, 1.0/3.0) / pow(2.0*M_PI, 2.0/3.0)
  __pyx_t_4 = pow(__pyx_v_8holodeck_4sams_11sam_cyutils_MY_NWTG, (1.0 / 3.0));
  __pyx_t_3 = pow((2.0 * M_PI), (2.0 / 3.0));
  if (unlikely(__pyx_t_3 == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 41, __pyx_L1_error)
  }
  __pyx_v_8holodeck_4sams_11sam_cyutils_KEPLER_CONST_SEPA = (__pyx_t_4 / __pyx_t_3);
+042: cdef double FOUR_PI_SPLC_OVER_MPC = 4 * M_PI * MY_SPLC / MY_MPC
  __pyx_t_3 = ((4.0 * M_PI) * __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SPLC);
  if (unlikely(__pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 42, __pyx_L1_error)
  }
  __pyx_v_8holodeck_4sams_11sam_cyutils_FOUR_PI_SPLC_OVER_MPC = (__pyx_t_3 / __pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC);
 043: 
 044: 
 045: @cython.cdivision(True)
+046: cpdef double hard_gw(double mtot, double mrat, double sepa):
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_1hard_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static double __pyx_f_8holodeck_4sams_11sam_cyutils_hard_gw(double __pyx_v_mtot, double __pyx_v_mrat, double __pyx_v_sepa, CYTHON_UNUSED int __pyx_skip_dispatch) {
  double __pyx_v_dadt;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("hard_gw", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_1hard_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_1hard_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  double __pyx_v_mtot;
  double __pyx_v_mrat;
  double __pyx_v_sepa;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("hard_gw (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_mtot,&__pyx_n_s_mrat,&__pyx_n_s_sepa,0};
    PyObject* values[3] = {0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mtot)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mrat)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_gw", 1, 3, 3, 1); __PYX_ERR(0, 46, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sepa)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_gw", 1, 3, 3, 2); __PYX_ERR(0, 46, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "hard_gw") < 0)) __PYX_ERR(0, 46, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
    }
    __pyx_v_mtot = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_mtot == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 46, __pyx_L3_error)
    __pyx_v_mrat = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_mrat == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 46, __pyx_L3_error)
    __pyx_v_sepa = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_sepa == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 46, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("hard_gw", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 46, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.hard_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_hard_gw(__pyx_self, __pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_hard_gw(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_mtot, double __pyx_v_mrat, double __pyx_v_sepa) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("hard_gw", 0);
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = PyFloat_FromDouble(__pyx_f_8holodeck_4sams_11sam_cyutils_hard_gw(__pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 46, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.hard_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 047: # cdef double hard_gw(double mtot, double mrat, double sepa):
+048:     cdef double dadt = GW_DADT_SEP_CONST * pow(mtot, 3) * mrat / pow(sepa, 3) / pow(1 + mrat, 2)
  __pyx_v_dadt = ((((__pyx_v_8holodeck_4sams_11sam_cyutils_GW_DADT_SEP_CONST * pow(__pyx_v_mtot, 3.0)) * __pyx_v_mrat) / pow(__pyx_v_sepa, 3.0)) / pow((1.0 + __pyx_v_mrat), 2.0));
+049:     return dadt
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 050: 
 051: 
 052: @cython.cdivision(True)
+053: cdef double kepler_freq_from_sepa(double mtot, double sepa):
static double __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_freq_from_sepa(double __pyx_v_mtot, double __pyx_v_sepa) {
  double __pyx_v_freq;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("kepler_freq_from_sepa", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+054:     cdef double freq = KEPLER_CONST_FREQ * sqrt(mtot) / pow(sepa, 1.5)
  __pyx_v_freq = ((__pyx_v_8holodeck_4sams_11sam_cyutils_KEPLER_CONST_FREQ * sqrt(__pyx_v_mtot)) / pow(__pyx_v_sepa, 1.5));
+055:     return freq
  __pyx_r = __pyx_v_freq;
  goto __pyx_L0;
 056: 
 057: 
 058: @cython.cdivision(True)
+059: cdef double kepler_sepa_from_freq(double mtot, double freq):
static double __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_sepa_from_freq(double __pyx_v_mtot, double __pyx_v_freq) {
  double __pyx_v_sepa;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("kepler_sepa_from_freq", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+060:     cdef double sepa = KEPLER_CONST_SEPA * pow(mtot, 1.0/3.0) / pow(freq, 2.0/3.0)
  __pyx_v_sepa = ((__pyx_v_8holodeck_4sams_11sam_cyutils_KEPLER_CONST_SEPA * pow(__pyx_v_mtot, (1.0 / 3.0))) / pow(__pyx_v_freq, (2.0 / 3.0)));
+061:     return sepa
  __pyx_r = __pyx_v_sepa;
  goto __pyx_L0;
 062: 
 063: 
 064: @cython.boundscheck(False)
 065: @cython.wraparound(False)
+066: cdef int while_while_increasing(int start, int size, double val, double[:] edges):
static int __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_increasing(int __pyx_v_start, int __pyx_v_size, double __pyx_v_val, __Pyx_memviewslice __pyx_v_edges) {
  int __pyx_v_index;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("while_while_increasing", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 067:     """Step through an INCREASING array of `edges`, first forward, then backward, to find edges bounding `val`.
 068: 
 069:     Use this function when `start` is already a close guess, and we just need to update a bit.
 070: 
 071:     """
 072: 
+073:     cdef int index = start    #: index corresponding to the LEFT side of the edges bounding `val`
  __pyx_v_index = __pyx_v_start;
 074: 
 075:     # `index < size-2` so that the result is always within the edges array
 076:     # `edges[index+1] < val` to get the RIGHT-edge to be MORE than `val`
+077:     while (index < size - 2) and (edges[index+1] < val):
  while (1) {
    __pyx_t_2 = ((__pyx_v_index < (__pyx_v_size - 2)) != 0);
    if (__pyx_t_2) {
    } else {
      __pyx_t_1 = __pyx_t_2;
      goto __pyx_L5_bool_binop_done;
    }
    __pyx_t_3 = (__pyx_v_index + 1);
    __pyx_t_2 = (((*((double *) ( /* dim=0 */ (__pyx_v_edges.data + __pyx_t_3 * __pyx_v_edges.strides[0]) ))) < __pyx_v_val) != 0);
    __pyx_t_1 = __pyx_t_2;
    __pyx_L5_bool_binop_done:;
    if (!__pyx_t_1) break;
+078:         index += 1
    __pyx_v_index = (__pyx_v_index + 1);
  }
 079: 
 080:     # `edges[index] > val` to get the LEFT-edge to be LESS than `val`
+081:     while (index > 0) and (edges[index] > val):
  while (1) {
    __pyx_t_2 = ((__pyx_v_index > 0) != 0);
    if (__pyx_t_2) {
    } else {
      __pyx_t_1 = __pyx_t_2;
      goto __pyx_L9_bool_binop_done;
    }
    __pyx_t_3 = __pyx_v_index;
    __pyx_t_2 = (((*((double *) ( /* dim=0 */ (__pyx_v_edges.data + __pyx_t_3 * __pyx_v_edges.strides[0]) ))) > __pyx_v_val) != 0);
    __pyx_t_1 = __pyx_t_2;
    __pyx_L9_bool_binop_done:;
    if (!__pyx_t_1) break;
+082:         index -= 1
    __pyx_v_index = (__pyx_v_index - 1);
  }
 083: 
+084:     return index
  __pyx_r = __pyx_v_index;
  goto __pyx_L0;
 085: 
 086: 
 087: @cython.boundscheck(False)
 088: @cython.wraparound(False)
+089: cdef int while_while_decreasing(int start, int size, double val, double[:] edges):
static int __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_decreasing(int __pyx_v_start, int __pyx_v_size, double __pyx_v_val, __Pyx_memviewslice __pyx_v_edges) {
  int __pyx_v_index;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("while_while_decreasing", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 090:     """Step through a DECREASING array of `edges`, first forward, then backward, to find edges bounding `val`.
 091: 
 092:     Use this function when `start` is already a close guess, and we just need to update a bit.
 093: 
 094:     """
 095: 
+096:     cdef int index = start    #: index corresponding to the LEFT side of the edges bounding `val`
  __pyx_v_index = __pyx_v_start;
 097: 
 098:     # `index < size-1` so that the result is always within the edges array
 099:     # `edges[index+1] > val` to get the RIGHT-edge to be LESS than `val`
+100:     while (index < size - 1) and (edges[index+1] > val):
  while (1) {
    __pyx_t_2 = ((__pyx_v_index < (__pyx_v_size - 1)) != 0);
    if (__pyx_t_2) {
    } else {
      __pyx_t_1 = __pyx_t_2;
      goto __pyx_L5_bool_binop_done;
    }
    __pyx_t_3 = (__pyx_v_index + 1);
    __pyx_t_2 = (((*((double *) ( /* dim=0 */ (__pyx_v_edges.data + __pyx_t_3 * __pyx_v_edges.strides[0]) ))) > __pyx_v_val) != 0);
    __pyx_t_1 = __pyx_t_2;
    __pyx_L5_bool_binop_done:;
    if (!__pyx_t_1) break;
+101:         index += 1
    __pyx_v_index = (__pyx_v_index + 1);
  }
 102: 
 103:     # `edges[index-1] < val` to get the LEFT-edge to be MORE than `val`
+104:     while (index > 0) and (edges[index-1] < val):
  while (1) {
    __pyx_t_2 = ((__pyx_v_index > 0) != 0);
    if (__pyx_t_2) {
    } else {
      __pyx_t_1 = __pyx_t_2;
      goto __pyx_L9_bool_binop_done;
    }
    __pyx_t_3 = (__pyx_v_index - 1);
    __pyx_t_2 = (((*((double *) ( /* dim=0 */ (__pyx_v_edges.data + __pyx_t_3 * __pyx_v_edges.strides[0]) ))) < __pyx_v_val) != 0);
    __pyx_t_1 = __pyx_t_2;
    __pyx_L9_bool_binop_done:;
    if (!__pyx_t_1) break;
+105:         index -= 1
    __pyx_v_index = (__pyx_v_index - 1);
  }
 106: 
+107:     return index
  __pyx_r = __pyx_v_index;
  goto __pyx_L0;
 108: 
 109: 
 110: # ==================================================================================================
 111: # ====    Integrate Bins from differential-parameter-volume to total numbers   ====
 112: # ==================================================================================================
 113: 
 114: 
+115: def integrate_differential_number_3dx1d(edges, dnum):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_3integrate_differential_number_3dx1d(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_11sam_cyutils_2integrate_differential_number_3dx1d[] = "Integrate the differential number of binaries over each grid bin into total numbers of binaries.\n\n    Trapezoid used over first 3 dims (mtot, mrat, redz), and Riemann over 4th (freq).\n    (Riemann seemed empirically to be more accurate for freq, but this should be revisited.)\n    mtot is integrated over `log10(mtot)` and frequency is integrated over `ln(f)`.\n\n    Note on array shapes:\n\n    * input  `dnum` is shaped (M, Q, Z, F)\n    * input  `edges` must be (4,) of array_like of lengths:  M, Q, Z, F+1\n    * output `numb` is shaped (M-1, Q-1, Z-1, F)\n\n    Arguments\n    ---------\n    edges : (4,) array_like  w/ lengths M, Q, Z, F+1\n        Grid edges of `mtot`, `mrat`, `redz`, and `freq`.  NOTE:\n\n        * `mtot` should be passed as regular `mtot`, NOT log10(mtot)\n        * `freq` should be passed as regular `freq`, NOT    ln(freq)\n\n    dnum : (M, Q, Z, F)\n        Differential number of binaries, dN/[dlog10M dq qz dlnf] where 'N' is in units of dimensionless number.\n\n    Returns\n    -------\n    numb : (M-1, Q-1, Z-1, F)\n\n    ";
static PyMethodDef __pyx_mdef_8holodeck_4sams_11sam_cyutils_3integrate_differential_number_3dx1d = {"integrate_differential_number_3dx1d", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_11sam_cyutils_3integrate_differential_number_3dx1d, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_11sam_cyutils_2integrate_differential_number_3dx1d};
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_3integrate_differential_number_3dx1d(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_edges = 0;
  PyObject *__pyx_v_dnum = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("integrate_differential_number_3dx1d (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_edges,&__pyx_n_s_dnum,0};
    PyObject* values[2] = {0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_edges)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_dnum)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_differential_number_3dx1d", 1, 2, 2, 1); __PYX_ERR(0, 115, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "integrate_differential_number_3dx1d") < 0)) __PYX_ERR(0, 115, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
    }
    __pyx_v_edges = values[0];
    __pyx_v_dnum = values[1];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("integrate_differential_number_3dx1d", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 115, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.integrate_differential_number_3dx1d", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_2integrate_differential_number_3dx1d(__pyx_self, __pyx_v_edges, __pyx_v_dnum);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_2integrate_differential_number_3dx1d(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_edges, PyObject *__pyx_v_dnum) {
  PyObject *__pyx_v_shape = NULL;
  PyObject *__pyx_v_new_shape = NULL;
  PyArrayObject *__pyx_v_numb = 0;
  PyObject *__pyx_v_ee = NULL;
  PyObject *__pyx_7genexpr__pyx_v_ee = NULL;
  PyObject *__pyx_8genexpr1__pyx_v_sh = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_numb;
  __Pyx_Buffer __pyx_pybuffer_numb;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("integrate_differential_number_3dx1d", 0);
  __pyx_pybuffer_numb.pybuffer.buf = NULL;
  __pyx_pybuffer_numb.refcount = 0;
  __pyx_pybuffernd_numb.data = NULL;
  __pyx_pybuffernd_numb.rcbuffer = &__pyx_pybuffer_numb;
/* … */
  /* 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_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_XDECREF(__pyx_t_11);
  __Pyx_XDECREF(__pyx_t_12);
  __Pyx_XDECREF(__pyx_t_13);
  __Pyx_XDECREF(__pyx_t_14);
  __PYX_XDEC_MEMVIEW(&__pyx_t_15, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_19, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_20, 1);
  { 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_numb.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.integrate_differential_number_3dx1d", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_numb.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF(__pyx_v_shape);
  __Pyx_XDECREF(__pyx_v_new_shape);
  __Pyx_XDECREF((PyObject *)__pyx_v_numb);
  __Pyx_XDECREF(__pyx_v_ee);
  __Pyx_XDECREF(__pyx_7genexpr__pyx_v_ee);
  __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_sh);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__23 = PyTuple_Pack(8, __pyx_n_s_edges, __pyx_n_s_dnum, __pyx_n_s_shape, __pyx_n_s_new_shape, __pyx_n_s_numb, __pyx_n_s_ee, __pyx_n_s_ee, __pyx_n_s_sh); if (unlikely(!__pyx_tuple__23)) __PYX_ERR(0, 115, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__23);
  __Pyx_GIVEREF(__pyx_tuple__23);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_11sam_cyutils_3integrate_differential_number_3dx1d, NULL, __pyx_n_s_holodeck_sams_sam_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 115, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_integrate_differential_number_3d, __pyx_t_1) < 0) __PYX_ERR(0, 115, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__24 = (PyObject*)__Pyx_PyCode_New(2, 0, 8, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__23, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_sam_cyutils_pyx, __pyx_n_s_integrate_differential_number_3d, 115, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__24)) __PYX_ERR(0, 115, __pyx_L1_error)
 116:     """Integrate the differential number of binaries over each grid bin into total numbers of binaries.
 117: 
 118:     Trapezoid used over first 3 dims (mtot, mrat, redz), and Riemann over 4th (freq).
 119:     (Riemann seemed empirically to be more accurate for freq, but this should be revisited.)
 120:     mtot is integrated over `log10(mtot)` and frequency is integrated over `ln(f)`.
 121: 
 122:     Note on array shapes:
 123: 
 124:     * input  `dnum` is shaped (M, Q, Z, F)
 125:     * input  `edges` must be (4,) of array_like of lengths:  M, Q, Z, F+1
 126:     * output `numb` is shaped (M-1, Q-1, Z-1, F)
 127: 
 128:     Arguments
 129:     ---------
 130:     edges : (4,) array_like  w/ lengths M, Q, Z, F+1
 131:         Grid edges of `mtot`, `mrat`, `redz`, and `freq`.  NOTE:
 132: 
 133:         * `mtot` should be passed as regular `mtot`, NOT log10(mtot)
 134:         * `freq` should be passed as regular `freq`, NOT    ln(freq)
 135: 
 136:     dnum : (M, Q, Z, F)
 137:         Differential number of binaries, dN/[dlog10M dq qz dlnf] where 'N' is in units of dimensionless number.
 138: 
 139:     Returns
 140:     -------
 141:     numb : (M-1, Q-1, Z-1, F)
 142: 
 143:     """
 144: 
 145:     # each edge should have the same length as the corresponding dimension of `dnum`
+146:     shape = [len(ee) for ee in edges]
  { /* enter inner scope */
    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 146, __pyx_L5_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (likely(PyList_CheckExact(__pyx_v_edges)) || PyTuple_CheckExact(__pyx_v_edges)) {
      __pyx_t_2 = __pyx_v_edges; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
      __pyx_t_4 = NULL;
    } else {
      __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_edges); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 146, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 146, __pyx_L5_error)
    }
    for (;;) {
      if (likely(!__pyx_t_4)) {
        if (likely(PyList_CheckExact(__pyx_t_2))) {
          if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 146, __pyx_L5_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 146, __pyx_L5_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        } else {
          if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 146, __pyx_L5_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 146, __pyx_L5_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        }
      } else {
        __pyx_t_5 = __pyx_t_4(__pyx_t_2);
        if (unlikely(!__pyx_t_5)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 146, __pyx_L5_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_5);
      }
      __Pyx_XDECREF_SET(__pyx_7genexpr__pyx_v_ee, __pyx_t_5);
      __pyx_t_5 = 0;
      __pyx_t_6 = PyObject_Length(__pyx_7genexpr__pyx_v_ee); if (unlikely(__pyx_t_6 == ((Py_ssize_t)-1))) __PYX_ERR(0, 146, __pyx_L5_error)
      __pyx_t_5 = PyInt_FromSsize_t(__pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 146, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(0, 146, __pyx_L5_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_ee); __pyx_7genexpr__pyx_v_ee = 0;
    goto __pyx_L8_exit_scope;
    __pyx_L5_error:;
    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_ee); __pyx_7genexpr__pyx_v_ee = 0;
    goto __pyx_L1_error;
    __pyx_L8_exit_scope:;
  } /* exit inner scope */
  __pyx_v_shape = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
 147:     # except the last edge (freq), where `dnum` should be 1-shorter
+148:     shape[-1] -= 1
  __pyx_t_3 = -1L;
  __pyx_t_1 = __Pyx_GetItemInt_List(__pyx_v_shape, __pyx_t_3, Py_ssize_t, 1, PyInt_FromSsize_t, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyInt_SubtractObjC(__pyx_t_1, __pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 148, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(__Pyx_SetItemInt(__pyx_v_shape, __pyx_t_3, __pyx_t_2, Py_ssize_t, 1, PyInt_FromSsize_t, 1, 1, 1) < 0)) __PYX_ERR(0, 148, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+149:     assert np.shape(dnum) == tuple(shape)
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(__pyx_assertions_enabled())) {
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_shape); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_1)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_1, __pyx_v_dnum) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_dnum);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_5 = PyList_AsTuple(__pyx_v_shape); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_t_5, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 149, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_7)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 149, __pyx_L1_error)
    }
  }
  #endif
 150:     # the number will be shaped as one-less the size of each dimension of `dnum`
+151:     new_shape = [sh-1 for sh in dnum.shape]
  { /* enter inner scope */
    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L11_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_dnum, __pyx_n_s_shape); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 151, __pyx_L11_error)
    __Pyx_GOTREF(__pyx_t_5);
    if (likely(PyList_CheckExact(__pyx_t_5)) || PyTuple_CheckExact(__pyx_t_5)) {
      __pyx_t_2 = __pyx_t_5; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
      __pyx_t_4 = NULL;
    } else {
      __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 151, __pyx_L11_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 151, __pyx_L11_error)
    }
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    for (;;) {
      if (likely(!__pyx_t_4)) {
        if (likely(PyList_CheckExact(__pyx_t_2))) {
          if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 151, __pyx_L11_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 151, __pyx_L11_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        } else {
          if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 151, __pyx_L11_error)
          #else
          __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 151, __pyx_L11_error)
          __Pyx_GOTREF(__pyx_t_5);
          #endif
        }
      } else {
        __pyx_t_5 = __pyx_t_4(__pyx_t_2);
        if (unlikely(!__pyx_t_5)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 151, __pyx_L11_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_5);
      }
      __Pyx_XDECREF_SET(__pyx_8genexpr1__pyx_v_sh, __pyx_t_5);
      __pyx_t_5 = 0;
      __pyx_t_5 = __Pyx_PyInt_SubtractObjC(__pyx_8genexpr1__pyx_v_sh, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 151, __pyx_L11_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(0, 151, __pyx_L11_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    }
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_sh); __pyx_8genexpr1__pyx_v_sh = 0;
    goto __pyx_L14_exit_scope;
    __pyx_L11_error:;
    __Pyx_XDECREF(__pyx_8genexpr1__pyx_v_sh); __pyx_8genexpr1__pyx_v_sh = 0;
    goto __pyx_L1_error;
    __pyx_L14_exit_scope:;
  } /* exit inner scope */
  __pyx_v_new_shape = ((PyObject*)__pyx_t_1);
  __pyx_t_1 = 0;
 152:     # except for the last dimension (freq) which is the same shape
+153:     new_shape[-1] = dnum.shape[-1]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_dnum, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 153, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, -1L, long, 1, __Pyx_PyInt_From_long, 0, 1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 153, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(__Pyx_SetItemInt(__pyx_v_new_shape, -1L, __pyx_t_2, long, 1, __Pyx_PyInt_From_long, 1, 1, 1) < 0)) __PYX_ERR(0, 153, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 154: 
 155:     # prepare output array
+156:     cdef np.ndarray[np.double_t, ndim=4] numb = np.zeros(new_shape)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_5);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_5, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_1, __pyx_v_new_shape) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_new_shape);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 156, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 156, __pyx_L1_error)
  __pyx_t_8 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_numb.rcbuffer->pybuffer, (PyObject*)__pyx_t_8, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 4, 0, __pyx_stack) == -1)) {
      __pyx_v_numb = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_numb.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 156, __pyx_L1_error)
    } else {__pyx_pybuffernd_numb.diminfo[0].strides = __pyx_pybuffernd_numb.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_numb.diminfo[0].shape = __pyx_pybuffernd_numb.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_numb.diminfo[1].strides = __pyx_pybuffernd_numb.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_numb.diminfo[1].shape = __pyx_pybuffernd_numb.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_numb.diminfo[2].strides = __pyx_pybuffernd_numb.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_numb.diminfo[2].shape = __pyx_pybuffernd_numb.rcbuffer->pybuffer.shape[2]; __pyx_pybuffernd_numb.diminfo[3].strides = __pyx_pybuffernd_numb.rcbuffer->pybuffer.strides[3]; __pyx_pybuffernd_numb.diminfo[3].shape = __pyx_pybuffernd_numb.rcbuffer->pybuffer.shape[3];
    }
  }
  __pyx_t_8 = 0;
  __pyx_v_numb = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
 157:     # Convert from  mtot => log10(mtot)  and  freq ==> ln(freq)
+158:     ee = [np.log10(edges[0]), edges[1], edges[2], np.diff(np.log(edges[3]))]
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_log10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_edges, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __pyx_t_9 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_9)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_2 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_9, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_5);
  __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_edges, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_edges, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_n_s_np); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_diff); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_n_s_np); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_n_s_log); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_13);
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  __pyx_t_12 = __Pyx_GetItemInt(__pyx_v_edges, 3, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_12);
  __pyx_t_14 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_13))) {
    __pyx_t_14 = PyMethod_GET_SELF(__pyx_t_13);
    if (likely(__pyx_t_14)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_13);
      __Pyx_INCREF(__pyx_t_14);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_13, function);
    }
  }
  __pyx_t_10 = (__pyx_t_14) ? __Pyx_PyObject_Call2Args(__pyx_t_13, __pyx_t_14, __pyx_t_12) : __Pyx_PyObject_CallOneArg(__pyx_t_13, __pyx_t_12);
  __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
  if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
  __pyx_t_13 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_11))) {
    __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_11);
    if (likely(__pyx_t_13)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_11);
      __Pyx_INCREF(__pyx_t_13);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_11, function);
    }
  }
  __pyx_t_9 = (__pyx_t_13) ? __Pyx_PyObject_Call2Args(__pyx_t_11, __pyx_t_13, __pyx_t_10) : __Pyx_PyObject_CallOneArg(__pyx_t_11, __pyx_t_10);
  __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = PyList_New(4); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 158, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __Pyx_GIVEREF(__pyx_t_2);
  PyList_SET_ITEM(__pyx_t_11, 0, __pyx_t_2);
  __Pyx_GIVEREF(__pyx_t_1);
  PyList_SET_ITEM(__pyx_t_11, 1, __pyx_t_1);
  __Pyx_GIVEREF(__pyx_t_5);
  PyList_SET_ITEM(__pyx_t_11, 2, __pyx_t_5);
  __Pyx_GIVEREF(__pyx_t_9);
  PyList_SET_ITEM(__pyx_t_11, 3, __pyx_t_9);
  __pyx_t_2 = 0;
  __pyx_t_1 = 0;
  __pyx_t_5 = 0;
  __pyx_t_9 = 0;
  __pyx_v_ee = ((PyObject*)__pyx_t_11);
  __pyx_t_11 = 0;
 159:     # integrate
+160:     _integrate_differential_number_3dx1d(ee[0], ee[1], ee[2], ee[3], dnum, numb)
  __pyx_t_11 = __Pyx_GetItemInt_List(__pyx_v_ee, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_15 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_11, PyBUF_WRITABLE); if (unlikely(!__pyx_t_15.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_GetItemInt_List(__pyx_v_ee, 1, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_16 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_11, PyBUF_WRITABLE); if (unlikely(!__pyx_t_16.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_GetItemInt_List(__pyx_v_ee, 2, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_17 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_11, PyBUF_WRITABLE); if (unlikely(!__pyx_t_17.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_11 = __Pyx_GetItemInt_List(__pyx_v_ee, 3, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_11);
  __pyx_t_18 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_11, PyBUF_WRITABLE); if (unlikely(!__pyx_t_18.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
  __pyx_t_19 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(__pyx_v_dnum, PyBUF_WRITABLE); if (unlikely(!__pyx_t_19.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __pyx_t_20 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_numb), PyBUF_WRITABLE); if (unlikely(!__pyx_t_20.memview)) __PYX_ERR(0, 160, __pyx_L1_error)
  __pyx_f_8holodeck_4sams_11sam_cyutils__integrate_differential_number_3dx1d(__pyx_t_15, __pyx_t_16, __pyx_t_17, __pyx_t_18, __pyx_t_19, __pyx_t_20);
  __PYX_XDEC_MEMVIEW(&__pyx_t_15, 1);
  __pyx_t_15.memview = NULL;
  __pyx_t_15.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
  __pyx_t_16.memview = NULL;
  __pyx_t_16.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
  __pyx_t_17.memview = NULL;
  __pyx_t_17.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
  __pyx_t_18.memview = NULL;
  __pyx_t_18.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_19, 1);
  __pyx_t_19.memview = NULL;
  __pyx_t_19.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_20, 1);
  __pyx_t_20.memview = NULL;
  __pyx_t_20.data = NULL;
 161: 
+162:     return numb
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_numb));
  __pyx_r = ((PyObject *)__pyx_v_numb);
  goto __pyx_L0;
 163: 
 164: 
 165: @cython.boundscheck(False)
 166: @cython.wraparound(False)
 167: @cython.nonecheck(False)
 168: @cython.cdivision(True)
+169: cdef void _integrate_differential_number_3dx1d(
static void __pyx_f_8holodeck_4sams_11sam_cyutils__integrate_differential_number_3dx1d(__Pyx_memviewslice __pyx_v_log10_mtot, __Pyx_memviewslice __pyx_v_mrat, __Pyx_memviewslice __pyx_v_redz, __Pyx_memviewslice __pyx_v_dln_freq, __Pyx_memviewslice __pyx_v_dnum, __Pyx_memviewslice __pyx_v_numb) {
  int __pyx_v_n_mtot;
  int __pyx_v_n_mrat;
  int __pyx_v_n_redz;
  int __pyx_v_n_freq;
  int __pyx_v_mm;
  int __pyx_v_qq;
  int __pyx_v_zz;
  int __pyx_v_ff;
  int __pyx_v_ii;
  int __pyx_v_jj;
  int __pyx_v_kk;
  double __pyx_v_dm;
  double __pyx_v_dmdq;
  double __pyx_v_dmdqdz;
  PyObject *__pyx_v_temp = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_integrate_differential_number_3dx1d", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_22);
  __Pyx_WriteUnraisable("holodeck.sams.sam_cyutils._integrate_differential_number_3dx1d", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_temp);
  __Pyx_RefNannyFinishContext();
}
 170:     double[:] log10_mtot,
 171:     double[:] mrat,
 172:     double[:] redz,
 173:     double[:] dln_freq,    # actually ln(freq)
 174:     double[:, :, :, :] dnum,
 175:     # output
 176:     double[:, :, :, :] numb
 177: ):
 178:     """Integrate the differential number of binaries over each grid bin into total numbers of binaries.
 179: 
 180:     Trapezoid used over first 3 dims (mtot, mrat, redz), and Riemann over 4th (freq).
 181:     See docstrings in `integrate_differential_number_3dx1d`
 182: 
 183:     """
 184: 
+185:     cdef int n_mtot = log10_mtot.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_log10_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 185, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 185, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+186:     cdef int n_mrat = mrat.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_mrat, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 186, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 186, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 186, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+187:     cdef int n_redz = redz.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_redz, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 187, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 187, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 187, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+188:     cdef int n_freq = dln_freq.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_dln_freq, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 188, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 188, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
 189: 
 190:     cdef int mm, qq, zz, ff, ii, jj, kk
 191:     cdef double dm, dmdq, dmdqdz
 192: 
+193:     for mm in range(n_mtot-1):                              # iterate over output-shape of mass-grid
  __pyx_t_4 = (__pyx_v_n_mtot - 1);
  __pyx_t_5 = __pyx_t_4;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_5; __pyx_t_3+=1) {
    __pyx_v_mm = __pyx_t_3;
+194:         dm = log10_mtot[mm+1] - log10_mtot[mm]              # get the bin-length
    __pyx_t_6 = (__pyx_v_mm + 1);
    __pyx_t_7 = __pyx_v_mm;
    __pyx_v_dm = ((*((double *) ( /* dim=0 */ (__pyx_v_log10_mtot.data + __pyx_t_6 * __pyx_v_log10_mtot.strides[0]) ))) - (*((double *) ( /* dim=0 */ (__pyx_v_log10_mtot.data + __pyx_t_7 * __pyx_v_log10_mtot.strides[0]) ))));
 195: 
+196:         for qq in range(n_mrat-1):                          # iterate over output-shape of mass-ratio-grid
    __pyx_t_8 = (__pyx_v_n_mrat - 1);
    __pyx_t_9 = __pyx_t_8;
    for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
      __pyx_v_qq = __pyx_t_10;
+197:             dmdq = dm * (mrat[qq+1] - mrat[qq])             # get the bin-area
      __pyx_t_7 = (__pyx_v_qq + 1);
      __pyx_t_6 = __pyx_v_qq;
      __pyx_v_dmdq = (__pyx_v_dm * ((*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_7 * __pyx_v_mrat.strides[0]) ))) - (*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_6 * __pyx_v_mrat.strides[0]) )))));
 198: 
+199:             for zz in range(n_redz-1):                      # iterate over output-shape of redsz-grid
      __pyx_t_11 = (__pyx_v_n_redz - 1);
      __pyx_t_12 = __pyx_t_11;
      for (__pyx_t_13 = 0; __pyx_t_13 < __pyx_t_12; __pyx_t_13+=1) {
        __pyx_v_zz = __pyx_t_13;
+200:                 dmdqdz = dmdq * (redz[zz+1] - redz[zz])     # get the bin-volume
        __pyx_t_6 = (__pyx_v_zz + 1);
        __pyx_t_7 = __pyx_v_zz;
        __pyx_v_dmdqdz = (__pyx_v_dmdq * ((*((double *) ( /* dim=0 */ (__pyx_v_redz.data + __pyx_t_6 * __pyx_v_redz.strides[0]) ))) - (*((double *) ( /* dim=0 */ (__pyx_v_redz.data + __pyx_t_7 * __pyx_v_redz.strides[0]) )))));
 201: 
 202:                 # iterate over output-shape of frequency
 203:                 # note that this is a Riemann sum, so input and output dimensions are the same size
+204:                 for ff in range(n_freq):
        __pyx_t_14 = __pyx_v_n_freq;
        __pyx_t_15 = __pyx_t_14;
        for (__pyx_t_16 = 0; __pyx_t_16 < __pyx_t_15; __pyx_t_16+=1) {
          __pyx_v_ff = __pyx_t_16;
+205:                     temp = 0.0
          __Pyx_INCREF(__pyx_float_0_0);
          __Pyx_XDECREF_SET(__pyx_v_temp, __pyx_float_0_0);
 206: 
 207:                     # iterate over each vertex of this cube, averaging the contributions
+208:                     for ii in range(2):                     # mass vertices
          for (__pyx_t_17 = 0; __pyx_t_17 < 2; __pyx_t_17+=1) {
            __pyx_v_ii = __pyx_t_17;
+209:                         for jj in range(2):                 # mass-ratio vertices
            for (__pyx_t_18 = 0; __pyx_t_18 < 2; __pyx_t_18+=1) {
              __pyx_v_jj = __pyx_t_18;
+210:                             for kk in range(2):             # redshift vertices
              for (__pyx_t_19 = 0; __pyx_t_19 < 2; __pyx_t_19+=1) {
                __pyx_v_kk = __pyx_t_19;
+211:                                 temp += dnum[mm+ii, qq+jj, zz+kk, ff]
                __pyx_t_7 = (__pyx_v_mm + __pyx_v_ii);
                __pyx_t_6 = (__pyx_v_qq + __pyx_v_jj);
                __pyx_t_20 = (__pyx_v_zz + __pyx_v_kk);
                __pyx_t_21 = __pyx_v_ff;
                __pyx_t_1 = PyFloat_FromDouble((*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_dnum.data + __pyx_t_7 * __pyx_v_dnum.strides[0]) ) + __pyx_t_6 * __pyx_v_dnum.strides[1]) ) + __pyx_t_20 * __pyx_v_dnum.strides[2]) ) + __pyx_t_21 * __pyx_v_dnum.strides[3]) )))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 211, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_1);
                __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_temp, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 211, __pyx_L1_error)
                __Pyx_GOTREF(__pyx_t_2);
                __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
                __Pyx_DECREF_SET(__pyx_v_temp, __pyx_t_2);
                __pyx_t_2 = 0;
              }
            }
          }
 212: 
+213:                     numb[mm, qq, zz, ff] = temp * dmdqdz * dln_freq[ff] / 8.0
          __pyx_t_2 = PyFloat_FromDouble(__pyx_v_dmdqdz); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __pyx_t_1 = PyNumber_Multiply(__pyx_v_temp, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_1);
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __pyx_t_21 = __pyx_v_ff;
          __pyx_t_2 = PyFloat_FromDouble((*((double *) ( /* dim=0 */ (__pyx_v_dln_freq.data + __pyx_t_21 * __pyx_v_dln_freq.strides[0]) )))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __pyx_t_22 = PyNumber_Multiply(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_22)) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_22);
          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __pyx_t_2 = __Pyx_PyFloat_TrueDivideObjC(__pyx_t_22, __pyx_float_8_0, 8.0, 0, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_GOTREF(__pyx_t_2);
          __Pyx_DECREF(__pyx_t_22); __pyx_t_22 = 0;
          __pyx_t_23 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_23 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 213, __pyx_L1_error)
          __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
          __pyx_t_21 = __pyx_v_mm;
          __pyx_t_20 = __pyx_v_qq;
          __pyx_t_6 = __pyx_v_zz;
          __pyx_t_7 = __pyx_v_ff;
          *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_numb.data + __pyx_t_21 * __pyx_v_numb.strides[0]) ) + __pyx_t_20 * __pyx_v_numb.strides[1]) ) + __pyx_t_6 * __pyx_v_numb.strides[2]) ) + __pyx_t_7 * __pyx_v_numb.strides[3]) )) = __pyx_t_23;
        }
      }
    }
  }
 214: 
+215:     return
  goto __pyx_L0;
 216: 
 217: 
 218: # ==================================================================================================
 219: # ====    Fixed_Time_2pwl_SAM - Hardening Model    ====
 220: # ==================================================================================================
 221: 
 222: 
 223: # @cython.cdivision(True)
 224: # cpdef double _hard_func_2pwl(double norm, double xx, double gamma_inner, double gamma_outer):
 225: #     cdef double dadt = - norm * pow(1.0 + xx, -gamma_outer+gamma_inner) / pow(xx, gamma_inner-1)
 226: #     return dadt
 227: 
 228: 
 229: # @cython.cdivision(True)
 230: # cpdef double hard_func_2pwl_gw(
 231: #     double mtot, double mrat, double sepa,
 232: #     double norm, double rchar, double gamma_inner, double gamma_outer
 233: # ):
 234: #     cdef double dadt = _hard_func_2pwl(norm, sepa/rchar, gamma_inner, gamma_outer)
 235: #     dadt += hard_gw(mtot, mrat, sepa)
 236: #     return dadt
 237: 
 238: 
 239: @cython.cdivision(True)
+240: cdef double _hard_func_2pwl(double norm, double xx, double gamma_inner, double gamma_outer):
static double __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl(double __pyx_v_norm, double __pyx_v_xx, double __pyx_v_gamma_inner, double __pyx_v_gamma_outer) {
  double __pyx_v_dadt;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_hard_func_2pwl", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+241:     cdef double dadt = - norm * pow(1.0 + xx, -gamma_outer+gamma_inner) / pow(xx, gamma_inner-1)
  __pyx_v_dadt = (((-__pyx_v_norm) * pow((1.0 + __pyx_v_xx), ((-__pyx_v_gamma_outer) + __pyx_v_gamma_inner))) / pow(__pyx_v_xx, (__pyx_v_gamma_inner - 1.0)));
+242:     return dadt
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 243: 
 244: 
 245: @cython.cdivision(True)
+246: cdef double _hard_func_2pwl_gw(
static double __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(double __pyx_v_mtot, double __pyx_v_mrat, double __pyx_v_sepa, double __pyx_v_norm, double __pyx_v_rchar, double __pyx_v_gamma_inner, double __pyx_v_gamma_outer) {
  double __pyx_v_dadt;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_hard_func_2pwl_gw", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 247:     double mtot, double mrat, double sepa,
 248:     double norm, double rchar, double gamma_inner, double gamma_outer
 249: ):
+250:     cdef double dadt = _hard_func_2pwl(norm, sepa/rchar, gamma_inner, gamma_outer)
  __pyx_v_dadt = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl(__pyx_v_norm, (__pyx_v_sepa / __pyx_v_rchar), __pyx_v_gamma_inner, __pyx_v_gamma_outer);
+251:     dadt += hard_gw(mtot, mrat, sepa)
  __pyx_v_dadt = (__pyx_v_dadt + __pyx_f_8holodeck_4sams_11sam_cyutils_hard_gw(__pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa, 0));
+252:     return dadt
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 253: 
 254: 
 255: @cython.cdivision(True)
+256: cdef double[:] _hard_func_2pwl_gw_1darray(
static __Pyx_memviewslice __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw_1darray(__Pyx_memviewslice __pyx_v_mtot, __Pyx_memviewslice __pyx_v_mrat, __Pyx_memviewslice __pyx_v_sepa, __Pyx_memviewslice __pyx_v_norm, __Pyx_memviewslice __pyx_v_rchar, __Pyx_memviewslice __pyx_v_gamma_inner, __Pyx_memviewslice __pyx_v_gamma_outer) {
  int __pyx_v_ii;
  int __pyx_v_size;
  PyArrayObject *__pyx_v_dadt = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_dadt;
  __Pyx_Buffer __pyx_pybuffer_dadt;
  __Pyx_memviewslice __pyx_r = { 0, 0, { 0 }, { 0 }, { 0 } };
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_hard_func_2pwl_gw_1darray", 0);
  __pyx_pybuffer_dadt.pybuffer.buf = NULL;
  __pyx_pybuffer_dadt.refcount = 0;
  __pyx_pybuffernd_dadt.data = NULL;
  __pyx_pybuffernd_dadt.rcbuffer = &__pyx_pybuffer_dadt;
/* … */
  /* 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_XDEC_MEMVIEW(&__pyx_t_16, 1);
  { 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_dadt.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __pyx_r.data = NULL;
  __pyx_r.memview = NULL;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils._hard_func_2pwl_gw_1darray", __pyx_clineno, __pyx_lineno, __pyx_filename);
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_dadt.rcbuffer->pybuffer);
  if (unlikely(!__pyx_r.memview)) {
    PyErr_SetString(PyExc_TypeError, "Memoryview return value is not initialized");
  }
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_dadt);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 257:     double[:] mtot, double[:] mrat, double[:] sepa,
 258:     double[:] norm, double[:] rchar, double[:] gamma_inner, double[:] gamma_outer
 259: ):
 260:     cdef int ii
+261:     cdef int size = mtot.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 261, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 261, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 261, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_size = __pyx_t_3;
+262:     cdef np.ndarray[np.double_t, ndim=1] dadt = np.zeros(size)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 262, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_5 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_5)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_5);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_1);
  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 262, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 262, __pyx_L1_error)
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_dadt.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_dadt = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_dadt.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 262, __pyx_L1_error)
    } else {__pyx_pybuffernd_dadt.diminfo[0].strides = __pyx_pybuffernd_dadt.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_dadt.diminfo[0].shape = __pyx_pybuffernd_dadt.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_6 = 0;
  __pyx_v_dadt = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+263:     for ii in range(size):
  __pyx_t_3 = __pyx_v_size;
  __pyx_t_7 = __pyx_t_3;
  for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {
    __pyx_v_ii = __pyx_t_8;
+264:         dadt[ii] = _hard_func_2pwl(norm[ii], sepa[ii]/rchar[ii], gamma_inner[ii], gamma_outer[ii])
    __pyx_t_9 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_9 < 0) {
      __pyx_t_9 += __pyx_v_norm.shape[0];
      if (unlikely(__pyx_t_9 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_9 >= __pyx_v_norm.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    __pyx_t_11 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_11 < 0) {
      __pyx_t_11 += __pyx_v_sepa.shape[0];
      if (unlikely(__pyx_t_11 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_11 >= __pyx_v_sepa.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    __pyx_t_12 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_12 < 0) {
      __pyx_t_12 += __pyx_v_rchar.shape[0];
      if (unlikely(__pyx_t_12 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_12 >= __pyx_v_rchar.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    __pyx_t_13 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_13 < 0) {
      __pyx_t_13 += __pyx_v_gamma_inner.shape[0];
      if (unlikely(__pyx_t_13 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_13 >= __pyx_v_gamma_inner.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    __pyx_t_14 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_14 < 0) {
      __pyx_t_14 += __pyx_v_gamma_outer.shape[0];
      if (unlikely(__pyx_t_14 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_14 >= __pyx_v_gamma_outer.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    __pyx_t_15 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_15 < 0) {
      __pyx_t_15 += __pyx_pybuffernd_dadt.diminfo[0].shape;
      if (unlikely(__pyx_t_15 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_15 >= __pyx_pybuffernd_dadt.diminfo[0].shape)) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 264, __pyx_L1_error)
    }
    *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_dadt.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_dadt.diminfo[0].strides) = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl((*((double *) ( /* dim=0 */ (__pyx_v_norm.data + __pyx_t_9 * __pyx_v_norm.strides[0]) ))), ((*((double *) ( /* dim=0 */ (__pyx_v_sepa.data + __pyx_t_11 * __pyx_v_sepa.strides[0]) ))) / (*((double *) ( /* dim=0 */ (__pyx_v_rchar.data + __pyx_t_12 * __pyx_v_rchar.strides[0]) )))), (*((double *) ( /* dim=0 */ (__pyx_v_gamma_inner.data + __pyx_t_13 * __pyx_v_gamma_inner.strides[0]) ))), (*((double *) ( /* dim=0 */ (__pyx_v_gamma_outer.data + __pyx_t_14 * __pyx_v_gamma_outer.strides[0]) ))));
+265:         dadt[ii] += hard_gw(mtot[ii], mrat[ii], sepa[ii])
    __pyx_t_14 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_14 < 0) {
      __pyx_t_14 += __pyx_v_mtot.shape[0];
      if (unlikely(__pyx_t_14 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_14 >= __pyx_v_mtot.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 265, __pyx_L1_error)
    }
    __pyx_t_13 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_13 < 0) {
      __pyx_t_13 += __pyx_v_mrat.shape[0];
      if (unlikely(__pyx_t_13 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_13 >= __pyx_v_mrat.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 265, __pyx_L1_error)
    }
    __pyx_t_12 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_12 < 0) {
      __pyx_t_12 += __pyx_v_sepa.shape[0];
      if (unlikely(__pyx_t_12 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_12 >= __pyx_v_sepa.shape[0])) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 265, __pyx_L1_error)
    }
    __pyx_t_11 = __pyx_v_ii;
    __pyx_t_10 = -1;
    if (__pyx_t_11 < 0) {
      __pyx_t_11 += __pyx_pybuffernd_dadt.diminfo[0].shape;
      if (unlikely(__pyx_t_11 < 0)) __pyx_t_10 = 0;
    } else if (unlikely(__pyx_t_11 >= __pyx_pybuffernd_dadt.diminfo[0].shape)) __pyx_t_10 = 0;
    if (unlikely(__pyx_t_10 != -1)) {
      __Pyx_RaiseBufferIndexError(__pyx_t_10);
      __PYX_ERR(0, 265, __pyx_L1_error)
    }
    *__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_pybuffernd_dadt.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_dadt.diminfo[0].strides) += __pyx_f_8holodeck_4sams_11sam_cyutils_hard_gw((*((double *) ( /* dim=0 */ (__pyx_v_mtot.data + __pyx_t_14 * __pyx_v_mtot.strides[0]) ))), (*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_13 * __pyx_v_mrat.strides[0]) ))), (*((double *) ( /* dim=0 */ (__pyx_v_sepa.data + __pyx_t_12 * __pyx_v_sepa.strides[0]) ))), 0);
  }
 266: 
+267:     return dadt
  __pyx_t_16 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_dadt), PyBUF_WRITABLE); if (unlikely(!__pyx_t_16.memview)) __PYX_ERR(0, 267, __pyx_L1_error)
  __pyx_r = __pyx_t_16;
  __pyx_t_16.memview = NULL;
  __pyx_t_16.data = NULL;
  goto __pyx_L0;
 268: 
 269: 
+270: def hard_func_2pwl_gw(
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_5hard_func_2pwl_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_11sam_cyutils_4hard_func_2pwl_gw[] = "\n\n    NOTE: this function will be somewhat slow, because of the explicit broadcasting!\n\n    ";
static PyMethodDef __pyx_mdef_8holodeck_4sams_11sam_cyutils_5hard_func_2pwl_gw = {"hard_func_2pwl_gw", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_11sam_cyutils_5hard_func_2pwl_gw, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_11sam_cyutils_4hard_func_2pwl_gw};
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_5hard_func_2pwl_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_mtot = 0;
  PyObject *__pyx_v_mrat = 0;
  PyObject *__pyx_v_sepa = 0;
  PyObject *__pyx_v_norm = 0;
  PyObject *__pyx_v_rchar = 0;
  PyObject *__pyx_v_gamma_inner = 0;
  PyObject *__pyx_v_gamma_outer = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("hard_func_2pwl_gw (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_mtot,&__pyx_n_s_mrat,&__pyx_n_s_sepa,&__pyx_n_s_norm,&__pyx_n_s_rchar,&__pyx_n_s_gamma_inner,&__pyx_n_s_gamma_outer,0};
    PyObject* values[7] = {0,0,0,0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mtot)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mrat)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 1); __PYX_ERR(0, 270, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sepa)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 2); __PYX_ERR(0, 270, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_norm)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 3); __PYX_ERR(0, 270, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rchar)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 4); __PYX_ERR(0, 270, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_inner)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 5); __PYX_ERR(0, 270, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_outer)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, 6); __PYX_ERR(0, 270, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "hard_func_2pwl_gw") < 0)) __PYX_ERR(0, 270, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 7) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
      values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
    }
    __pyx_v_mtot = values[0];
    __pyx_v_mrat = values[1];
    __pyx_v_sepa = values[2];
    __pyx_v_norm = values[3];
    __pyx_v_rchar = values[4];
    __pyx_v_gamma_inner = values[5];
    __pyx_v_gamma_outer = values[6];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("hard_func_2pwl_gw", 1, 7, 7, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 270, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.hard_func_2pwl_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_4hard_func_2pwl_gw(__pyx_self, __pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa, __pyx_v_norm, __pyx_v_rchar, __pyx_v_gamma_inner, __pyx_v_gamma_outer);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_4hard_func_2pwl_gw(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_mtot, PyObject *__pyx_v_mrat, PyObject *__pyx_v_sepa, PyObject *__pyx_v_norm, PyObject *__pyx_v_rchar, PyObject *__pyx_v_gamma_inner, PyObject *__pyx_v_gamma_outer) {
  PyObject *__pyx_v_args = NULL;
  PyObject *__pyx_v_shape = NULL;
  PyObject *__pyx_v_dadt = NULL;
  PyObject *__pyx_8genexpr2__pyx_v_aa = NULL;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("hard_func_2pwl_gw", 0);
  __Pyx_INCREF(__pyx_v_mtot);
  __Pyx_INCREF(__pyx_v_mrat);
  __Pyx_INCREF(__pyx_v_sepa);
  __Pyx_INCREF(__pyx_v_norm);
  __Pyx_INCREF(__pyx_v_rchar);
  __Pyx_INCREF(__pyx_v_gamma_inner);
  __Pyx_INCREF(__pyx_v_gamma_outer);
/* … */
  /* 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_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_12, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_13, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_14, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_15, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.hard_func_2pwl_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_args);
  __Pyx_XDECREF(__pyx_v_shape);
  __Pyx_XDECREF(__pyx_v_dadt);
  __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_aa);
  __Pyx_XDECREF(__pyx_v_mtot);
  __Pyx_XDECREF(__pyx_v_mrat);
  __Pyx_XDECREF(__pyx_v_sepa);
  __Pyx_XDECREF(__pyx_v_norm);
  __Pyx_XDECREF(__pyx_v_rchar);
  __Pyx_XDECREF(__pyx_v_gamma_inner);
  __Pyx_XDECREF(__pyx_v_gamma_outer);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__25 = PyTuple_Pack(11, __pyx_n_s_mtot, __pyx_n_s_mrat, __pyx_n_s_sepa, __pyx_n_s_norm, __pyx_n_s_rchar, __pyx_n_s_gamma_inner, __pyx_n_s_gamma_outer, __pyx_n_s_args, __pyx_n_s_shape, __pyx_n_s_dadt, __pyx_n_s_aa); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 270, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__25);
  __Pyx_GIVEREF(__pyx_tuple__25);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_11sam_cyutils_5hard_func_2pwl_gw, NULL, __pyx_n_s_holodeck_sams_sam_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_hard_func_2pwl_gw, __pyx_t_1) < 0) __PYX_ERR(0, 270, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__26 = (PyObject*)__Pyx_PyCode_New(7, 0, 11, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__25, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_sam_cyutils_pyx, __pyx_n_s_hard_func_2pwl_gw, 270, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__26)) __PYX_ERR(0, 270, __pyx_L1_error)
 271:     mtot, mrat, sepa,
 272:     norm, rchar, gamma_inner, gamma_outer
 273: ):
 274:     """
 275: 
 276:     NOTE: this function will be somewhat slow, because of the explicit broadcasting!
 277: 
 278:     """
+279:     args = mtot, mrat, sepa, norm, rchar, gamma_inner, gamma_outer
  __pyx_t_1 = PyTuple_New(7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 279, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_INCREF(__pyx_v_mtot);
  __Pyx_GIVEREF(__pyx_v_mtot);
  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_mtot);
  __Pyx_INCREF(__pyx_v_mrat);
  __Pyx_GIVEREF(__pyx_v_mrat);
  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_mrat);
  __Pyx_INCREF(__pyx_v_sepa);
  __Pyx_GIVEREF(__pyx_v_sepa);
  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_sepa);
  __Pyx_INCREF(__pyx_v_norm);
  __Pyx_GIVEREF(__pyx_v_norm);
  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_norm);
  __Pyx_INCREF(__pyx_v_rchar);
  __Pyx_GIVEREF(__pyx_v_rchar);
  PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_rchar);
  __Pyx_INCREF(__pyx_v_gamma_inner);
  __Pyx_GIVEREF(__pyx_v_gamma_inner);
  PyTuple_SET_ITEM(__pyx_t_1, 5, __pyx_v_gamma_inner);
  __Pyx_INCREF(__pyx_v_gamma_outer);
  __Pyx_GIVEREF(__pyx_v_gamma_outer);
  PyTuple_SET_ITEM(__pyx_t_1, 6, __pyx_v_gamma_outer);
  __pyx_v_args = __pyx_t_1;
  __pyx_t_1 = 0;
+280:     args = np.broadcast_arrays(*args)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 280, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_broadcast_arrays); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PySequence_Tuple(__pyx_v_args); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 280, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_1, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 280, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF_SET(__pyx_v_args, __pyx_t_3);
  __pyx_t_3 = 0;
+281:     shape = args[0].shape
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_v_args, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 281, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 281, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_shape = __pyx_t_1;
  __pyx_t_1 = 0;
+282:     mtot, mrat, sepa, norm, rchar, gamma_inner, gamma_outer = [aa.flatten() for aa in args]
  { /* enter inner scope */
    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 282, __pyx_L5_error)
    __Pyx_GOTREF(__pyx_t_1);
    if (likely(PyList_CheckExact(__pyx_v_args)) || PyTuple_CheckExact(__pyx_v_args)) {
      __pyx_t_3 = __pyx_v_args; __Pyx_INCREF(__pyx_t_3); __pyx_t_4 = 0;
      __pyx_t_5 = NULL;
    } else {
      __pyx_t_4 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_v_args); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 282, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_5 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 282, __pyx_L5_error)
    }
    for (;;) {
      if (likely(!__pyx_t_5)) {
        if (likely(PyList_CheckExact(__pyx_t_3))) {
          if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_3)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_2 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_2); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 282, __pyx_L5_error)
          #else
          __pyx_t_2 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 282, __pyx_L5_error)
          __Pyx_GOTREF(__pyx_t_2);
          #endif
        } else {
          if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
          __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_4); __Pyx_INCREF(__pyx_t_2); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 282, __pyx_L5_error)
          #else
          __pyx_t_2 = PySequence_ITEM(__pyx_t_3, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 282, __pyx_L5_error)
          __Pyx_GOTREF(__pyx_t_2);
          #endif
        }
      } else {
        __pyx_t_2 = __pyx_t_5(__pyx_t_3);
        if (unlikely(!__pyx_t_2)) {
          PyObject* exc_type = PyErr_Occurred();
          if (exc_type) {
            if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
            else __PYX_ERR(0, 282, __pyx_L5_error)
          }
          break;
        }
        __Pyx_GOTREF(__pyx_t_2);
      }
      __Pyx_XDECREF_SET(__pyx_8genexpr2__pyx_v_aa, __pyx_t_2);
      __pyx_t_2 = 0;
      __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_8genexpr2__pyx_v_aa, __pyx_n_s_flatten); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 282, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_6);
      __pyx_t_7 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_6))) {
        __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_6);
        if (likely(__pyx_t_7)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
          __Pyx_INCREF(__pyx_t_7);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_6, function);
        }
      }
      __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_6);
      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 282, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_2))) __PYX_ERR(0, 282, __pyx_L5_error)
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    }
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_aa); __pyx_8genexpr2__pyx_v_aa = 0;
    goto __pyx_L8_exit_scope;
    __pyx_L5_error:;
    __Pyx_XDECREF(__pyx_8genexpr2__pyx_v_aa); __pyx_8genexpr2__pyx_v_aa = 0;
    goto __pyx_L1_error;
    __pyx_L8_exit_scope:;
  } /* exit inner scope */
  if (1) {
    PyObject* sequence = __pyx_t_1;
    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
    if (unlikely(size != 7)) {
      if (size > 7) __Pyx_RaiseTooManyValuesError(7);
      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
      __PYX_ERR(0, 282, __pyx_L1_error)
    }
    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
    __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
    __pyx_t_2 = PyList_GET_ITEM(sequence, 1); 
    __pyx_t_6 = PyList_GET_ITEM(sequence, 2); 
    __pyx_t_7 = PyList_GET_ITEM(sequence, 3); 
    __pyx_t_8 = PyList_GET_ITEM(sequence, 4); 
    __pyx_t_9 = PyList_GET_ITEM(sequence, 5); 
    __pyx_t_10 = PyList_GET_ITEM(sequence, 6); 
    __Pyx_INCREF(__pyx_t_3);
    __Pyx_INCREF(__pyx_t_2);
    __Pyx_INCREF(__pyx_t_6);
    __Pyx_INCREF(__pyx_t_7);
    __Pyx_INCREF(__pyx_t_8);
    __Pyx_INCREF(__pyx_t_9);
    __Pyx_INCREF(__pyx_t_10);
    #else
    {
      Py_ssize_t i;
      PyObject** temps[7] = {&__pyx_t_3,&__pyx_t_2,&__pyx_t_6,&__pyx_t_7,&__pyx_t_8,&__pyx_t_9,&__pyx_t_10};
      for (i=0; i < 7; i++) {
        PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 282, __pyx_L1_error)
        __Pyx_GOTREF(item);
        *(temps[i]) = item;
      }
    }
    #endif
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  }
  __Pyx_DECREF_SET(__pyx_v_mtot, __pyx_t_3);
  __pyx_t_3 = 0;
  __Pyx_DECREF_SET(__pyx_v_mrat, __pyx_t_2);
  __pyx_t_2 = 0;
  __Pyx_DECREF_SET(__pyx_v_sepa, __pyx_t_6);
  __pyx_t_6 = 0;
  __Pyx_DECREF_SET(__pyx_v_norm, __pyx_t_7);
  __pyx_t_7 = 0;
  __Pyx_DECREF_SET(__pyx_v_rchar, __pyx_t_8);
  __pyx_t_8 = 0;
  __Pyx_DECREF_SET(__pyx_v_gamma_inner, __pyx_t_9);
  __pyx_t_9 = 0;
  __Pyx_DECREF_SET(__pyx_v_gamma_outer, __pyx_t_10);
  __pyx_t_10 = 0;
+283:     dadt = _hard_func_2pwl_gw_1darray(mtot, mrat, sepa, norm, rchar, gamma_inner, gamma_outer)
  __pyx_t_11 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_mtot, PyBUF_WRITABLE); if (unlikely(!__pyx_t_11.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_12 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_mrat, PyBUF_WRITABLE); if (unlikely(!__pyx_t_12.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_13 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_sepa, PyBUF_WRITABLE); if (unlikely(!__pyx_t_13.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_14 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_norm, PyBUF_WRITABLE); if (unlikely(!__pyx_t_14.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_15 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_rchar, PyBUF_WRITABLE); if (unlikely(!__pyx_t_15.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_16 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_gamma_inner, PyBUF_WRITABLE); if (unlikely(!__pyx_t_16.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_17 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_gamma_outer, PyBUF_WRITABLE); if (unlikely(!__pyx_t_17.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __pyx_t_18 = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw_1darray(__pyx_t_11, __pyx_t_12, __pyx_t_13, __pyx_t_14, __pyx_t_15, __pyx_t_16, __pyx_t_17); if (unlikely(!__pyx_t_18.memview)) __PYX_ERR(0, 283, __pyx_L1_error)
  __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);
  __pyx_t_11.memview = NULL;
  __pyx_t_11.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_12, 1);
  __pyx_t_12.memview = NULL;
  __pyx_t_12.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_13, 1);
  __pyx_t_13.memview = NULL;
  __pyx_t_13.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_14, 1);
  __pyx_t_14.memview = NULL;
  __pyx_t_14.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_15, 1);
  __pyx_t_15.memview = NULL;
  __pyx_t_15.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
  __pyx_t_16.memview = NULL;
  __pyx_t_16.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
  __pyx_t_17.memview = NULL;
  __pyx_t_17.data = NULL;
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_t_18, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 283, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
  __pyx_t_18.memview = NULL;
  __pyx_t_18.data = NULL;
  __pyx_v_dadt = __pyx_t_1;
  __pyx_t_1 = 0;
+284:     dadt = np.array(dadt).reshape(shape)
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_array); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  __pyx_t_9 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_9)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_9);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
    }
  }
  __pyx_t_10 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_9, __pyx_v_dadt) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_dadt);
  __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
  if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_reshape); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = NULL;
  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_8))) {
    __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_8);
    if (likely(__pyx_t_10)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
      __Pyx_INCREF(__pyx_t_10);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_8, function);
    }
  }
  __pyx_t_1 = (__pyx_t_10) ? __Pyx_PyObject_Call2Args(__pyx_t_8, __pyx_t_10, __pyx_v_shape) : __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_shape);
  __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 284, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  __Pyx_DECREF_SET(__pyx_v_dadt, __pyx_t_1);
  __pyx_t_1 = 0;
+285:     return dadt
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_dadt);
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 286: 
 287: 
+288: def find_2pwl_hardening_norm(time, mtot, mrat, sepa_init, rchar, gamma_inner, gamma_outer, nsteps):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_7find_2pwl_hardening_norm(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_11sam_cyutils_7find_2pwl_hardening_norm = {"find_2pwl_hardening_norm", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_11sam_cyutils_7find_2pwl_hardening_norm, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_7find_2pwl_hardening_norm(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_time = 0;
  PyObject *__pyx_v_mtot = 0;
  PyObject *__pyx_v_mrat = 0;
  PyObject *__pyx_v_sepa_init = 0;
  PyObject *__pyx_v_rchar = 0;
  PyObject *__pyx_v_gamma_inner = 0;
  PyObject *__pyx_v_gamma_outer = 0;
  PyObject *__pyx_v_nsteps = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("find_2pwl_hardening_norm (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_time,&__pyx_n_s_mtot,&__pyx_n_s_mrat,&__pyx_n_s_sepa_init,&__pyx_n_s_rchar,&__pyx_n_s_gamma_inner,&__pyx_n_s_gamma_outer,&__pyx_n_s_nsteps,0};
    PyObject* values[8] = {0,0,0,0,0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_time)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mtot)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 1); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mrat)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 2); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sepa_init)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 3); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rchar)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 4); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_inner)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 5); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_outer)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 6); __PYX_ERR(0, 288, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nsteps)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, 7); __PYX_ERR(0, 288, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "find_2pwl_hardening_norm") < 0)) __PYX_ERR(0, 288, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 8) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
      values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
      values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
    }
    __pyx_v_time = values[0];
    __pyx_v_mtot = values[1];
    __pyx_v_mrat = values[2];
    __pyx_v_sepa_init = values[3];
    __pyx_v_rchar = values[4];
    __pyx_v_gamma_inner = values[5];
    __pyx_v_gamma_outer = values[6];
    __pyx_v_nsteps = values[7];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("find_2pwl_hardening_norm", 1, 8, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 288, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.find_2pwl_hardening_norm", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_6find_2pwl_hardening_norm(__pyx_self, __pyx_v_time, __pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa_init, __pyx_v_rchar, __pyx_v_gamma_inner, __pyx_v_gamma_outer, __pyx_v_nsteps);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_6find_2pwl_hardening_norm(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_time, PyObject *__pyx_v_mtot, PyObject *__pyx_v_mrat, PyObject *__pyx_v_sepa_init, PyObject *__pyx_v_rchar, PyObject *__pyx_v_gamma_inner, PyObject *__pyx_v_gamma_outer, PyObject *__pyx_v_nsteps) {
  PyArrayObject *__pyx_v_norm_log10 = 0;
  __pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params __pyx_v_args;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_norm_log10;
  __Pyx_Buffer __pyx_pybuffer_norm_log10;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("find_2pwl_hardening_norm", 0);
  __pyx_pybuffer_norm_log10.pybuffer.buf = NULL;
  __pyx_pybuffer_norm_log10.refcount = 0;
  __pyx_pybuffernd_norm_log10.data = NULL;
  __pyx_pybuffernd_norm_log10.rcbuffer = &__pyx_pybuffer_norm_log10;
/* … */
  /* 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_5);
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_10, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);
  { 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_norm_log10.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.find_2pwl_hardening_norm", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_norm_log10.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_norm_log10);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__27 = PyTuple_Pack(10, __pyx_n_s_time, __pyx_n_s_mtot, __pyx_n_s_mrat, __pyx_n_s_sepa_init, __pyx_n_s_rchar, __pyx_n_s_gamma_inner, __pyx_n_s_gamma_outer, __pyx_n_s_nsteps, __pyx_n_s_norm_log10, __pyx_n_s_args); if (unlikely(!__pyx_tuple__27)) __PYX_ERR(0, 288, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__27);
  __Pyx_GIVEREF(__pyx_tuple__27);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_11sam_cyutils_7find_2pwl_hardening_norm, NULL, __pyx_n_s_holodeck_sams_sam_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 288, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_find_2pwl_hardening_norm, __pyx_t_1) < 0) __PYX_ERR(0, 288, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__28 = (PyObject*)__Pyx_PyCode_New(8, 0, 10, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__27, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_sam_cyutils_pyx, __pyx_n_s_find_2pwl_hardening_norm, 288, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__28)) __PYX_ERR(0, 288, __pyx_L1_error)
+289:     assert np.ndim(time) == 0
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(__pyx_assertions_enabled())) {
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 289, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_ndim); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 289, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
      __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
      if (likely(__pyx_t_2)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
        __Pyx_INCREF(__pyx_t_2);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_3, function);
      }
    }
    __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_2, __pyx_v_time) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_time);
    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 289, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyInt_EqObjC(__pyx_t_1, __pyx_int_0, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 289, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 289, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 289, __pyx_L1_error)
    }
  }
  #endif
+290:     assert np.ndim(mtot) == 1
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(__pyx_assertions_enabled())) {
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 290, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ndim); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 290, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_1 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
      __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_2);
      if (likely(__pyx_t_1)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
        __Pyx_INCREF(__pyx_t_1);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_2, function);
      }
    }
    __pyx_t_3 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_1, __pyx_v_mtot) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_mtot);
    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 290, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyInt_EqObjC(__pyx_t_3, __pyx_int_1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 290, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 290, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 290, __pyx_L1_error)
    }
  }
  #endif
+291:     assert np.shape(mtot) == np.shape(mrat)
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(__pyx_assertions_enabled())) {
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_1, function);
      }
    }
    __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_v_mtot) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_mtot);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_shape); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = NULL;
    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_5);
      if (likely(__pyx_t_3)) {
        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
        __Pyx_INCREF(__pyx_t_3);
        __Pyx_INCREF(function);
        __Pyx_DECREF_SET(__pyx_t_5, function);
      }
    }
    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_3, __pyx_v_mrat) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_mrat);
    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_t_5 = PyObject_RichCompare(__pyx_t_2, __pyx_t_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 291, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 291, __pyx_L1_error)
    }
  }
  #endif
 292: 
+293:     cdef np.ndarray[np.double_t, ndim=1] norm_log10 = np.zeros(mtot.size)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 293, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_mtot, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_2, function);
    }
  }
  __pyx_t_5 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_1);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 293, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_5);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 293, __pyx_L1_error)
  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_norm_log10.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_norm_log10 = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_norm_log10.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 293, __pyx_L1_error)
    } else {__pyx_pybuffernd_norm_log10.diminfo[0].strides = __pyx_pybuffernd_norm_log10.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_norm_log10.diminfo[0].shape = __pyx_pybuffernd_norm_log10.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_6 = 0;
  __pyx_v_norm_log10 = ((PyArrayObject *)__pyx_t_5);
  __pyx_t_5 = 0;
 294: 
 295:     cdef lifetime_2pwl_params args
+296:     args.target_time = time
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_time); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 296, __pyx_L1_error)
  __pyx_v_args.target_time = __pyx_t_7;
+297:     args.sepa_init = sepa_init
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_sepa_init); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 297, __pyx_L1_error)
  __pyx_v_args.sepa_init = __pyx_t_7;
+298:     args.rchar = rchar
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_rchar); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 298, __pyx_L1_error)
  __pyx_v_args.rchar = __pyx_t_7;
+299:     args.gamma_inner = gamma_inner
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_gamma_inner); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 299, __pyx_L1_error)
  __pyx_v_args.gamma_inner = __pyx_t_7;
+300:     args.gamma_outer = gamma_outer
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_gamma_outer); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 300, __pyx_L1_error)
  __pyx_v_args.gamma_outer = __pyx_t_7;
+301:     args.nsteps = nsteps
  __pyx_t_8 = __Pyx_PyInt_As_int(__pyx_v_nsteps); if (unlikely((__pyx_t_8 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 301, __pyx_L1_error)
  __pyx_v_args.nsteps = __pyx_t_8;
 302: 
+303:     _get_hardening_norm_2pwl(mtot, mrat, args, norm_log10)
  __pyx_t_9 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_mtot, PyBUF_WRITABLE); if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 303, __pyx_L1_error)
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_mrat, PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 303, __pyx_L1_error)
  __pyx_t_11 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_norm_log10), PyBUF_WRITABLE); if (unlikely(!__pyx_t_11.memview)) __PYX_ERR(0, 303, __pyx_L1_error)
  __pyx_f_8holodeck_4sams_11sam_cyutils__get_hardening_norm_2pwl(__pyx_t_9, __pyx_t_10, __pyx_v_args, __pyx_t_11);
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __pyx_t_9.memview = NULL;
  __pyx_t_9.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_10, 1);
  __pyx_t_10.memview = NULL;
  __pyx_t_10.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);
  __pyx_t_11.memview = NULL;
  __pyx_t_11.data = NULL;
 304: 
+305:     return norm_log10
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_norm_log10));
  __pyx_r = ((PyObject *)__pyx_v_norm_log10);
  goto __pyx_L0;
 306: 
 307: 
+308: ctypedef struct lifetime_2pwl_params:
struct __pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params {
  double target_time;
  double mt;
  double mr;
  double sepa_init;
  double rchar;
  double gamma_inner;
  double gamma_outer;
  int nsteps;
};
 309:     double target_time
 310:     double mt
 311:     double mr
 312:     double sepa_init
 313:     double rchar
 314:     double gamma_inner
 315:     double gamma_outer
 316:     int nsteps
 317: 
 318: 
 319: @cython.boundscheck(False)
 320: @cython.wraparound(False)
 321: @cython.nonecheck(False)
 322: @cython.cdivision(True)
+323: cdef void _get_hardening_norm_2pwl(
static void __pyx_f_8holodeck_4sams_11sam_cyutils__get_hardening_norm_2pwl(__Pyx_memviewslice __pyx_v_mtot, __Pyx_memviewslice __pyx_v_mrat, __pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params __pyx_v_args, __Pyx_memviewslice __pyx_v_norm_log10) {
  double __pyx_v_XTOL;
  double __pyx_v_RTOL;
  int __pyx_v_MITR;
  double __pyx_v_NORM_LOG10_LO;
  double __pyx_v_NORM_LOG10_HI;
  int __pyx_v_num;
  int __pyx_v_ii;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_get_hardening_norm_2pwl", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4);
  __Pyx_WriteUnraisable("holodeck.sams.sam_cyutils._get_hardening_norm_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
}
 324:     double[:] mtot,
 325:     double[:] mrat,
 326:     lifetime_2pwl_params args,
 327:     # output
 328:     double[:] norm_log10,
 329: ):
 330: 
+331:     cdef double XTOL = 1e-3
  __pyx_v_XTOL = 1e-3;
+332:     cdef double RTOL = 1e-5
  __pyx_v_RTOL = 1e-5;
+333:     cdef int MITR = 100    # note: the function doesn't return an error on failure, it still returns last try
  __pyx_v_MITR = 0x64;
+334:     cdef double NORM_LOG10_LO = -20.0
  __pyx_v_NORM_LOG10_LO = -20.0;
+335:     cdef double NORM_LOG10_HI = +20.0
  __pyx_v_NORM_LOG10_HI = 20.0;
 336: 
+337:     cdef int num = mtot.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 337, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 337, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 337, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_num = __pyx_t_3;
+338:     assert mtot.size == mrat.size
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(__pyx_assertions_enabled())) {
    __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_mrat, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_4);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = PyObject_RichCompare(__pyx_t_1, __pyx_t_4, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 338, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_5)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 338, __pyx_L1_error)
    }
  }
  #endif
 339:     cdef double time
 340: 
 341:     cdef int ii
+342:     for ii in range(num):
  __pyx_t_3 = __pyx_v_num;
  __pyx_t_6 = __pyx_t_3;
  for (__pyx_t_7 = 0; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) {
    __pyx_v_ii = __pyx_t_7;
+343:         args.mt = mtot[ii]
    __pyx_t_8 = __pyx_v_ii;
    __pyx_v_args.mt = (*((double *) ( /* dim=0 */ (__pyx_v_mtot.data + __pyx_t_8 * __pyx_v_mtot.strides[0]) )));
+344:         args.mr = mrat[ii]
    __pyx_t_8 = __pyx_v_ii;
    __pyx_v_args.mr = (*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_8 * __pyx_v_mrat.strides[0]) )));
+345:         norm_log10[ii] = brentq(
    __pyx_t_8 = __pyx_v_ii;
    *((double *) ( /* dim=0 */ (__pyx_v_norm_log10.data + __pyx_t_8 * __pyx_v_norm_log10.strides[0]) )) = __pyx_f_5scipy_8optimize_15cython_optimize_6_zeros_brentq(__pyx_f_8holodeck_4sams_11sam_cyutils_get_binary_lifetime_2pwl, __pyx_v_NORM_LOG10_LO, __pyx_v_NORM_LOG10_HI, ((__pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params *)(&__pyx_v_args)), __pyx_v_XTOL, __pyx_v_RTOL, __pyx_v_MITR, NULL);
  }
 346:             get_binary_lifetime_2pwl, NORM_LOG10_LO, NORM_LOG10_HI,
 347:             <lifetime_2pwl_params *> &args, XTOL, RTOL, MITR, NULL
 348:         )
 349:         # time = get_binary_lifetime_2pwl(norm_log10[ii], <lifetime_2pwl_params *> &args)
 350:         # total_time[ii] = time + args.target_time
 351: 
+352:     return
  goto __pyx_L0;
 353: 
 354: 
 355: @cython.boundscheck(False)
 356: @cython.wraparound(False)
 357: @cython.nonecheck(False)
 358: @cython.cdivision(True)
+359: cdef double get_binary_lifetime_2pwl(double norm_log10, void *args) noexcept:
static double __pyx_f_8holodeck_4sams_11sam_cyutils_get_binary_lifetime_2pwl(double __pyx_v_norm_log10, void *__pyx_v_args) {
  __pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params *__pyx_v_pars;
  double __pyx_v_risco_log10;
  double __pyx_v_sepa_log10;
  double __pyx_v_norm;
  double __pyx_v_dx;
  double __pyx_v_time;
  CYTHON_UNUSED int __pyx_v_ii;
  double __pyx_v_sepa_right;
  double __pyx_v_dadt_right;
  double __pyx_v_dt;
  double __pyx_v_sepa_left;
  double __pyx_v_dadt_left;
  double __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("get_binary_lifetime_2pwl", 0);
/* … */
  /* function exit code */
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+360:     cdef lifetime_2pwl_params *pars = <lifetime_2pwl_params *> args
  __pyx_v_pars = ((__pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params *)__pyx_v_args);
 361: 
+362:     cdef double risco_log10 = log10(3.0 * MY_SCHW * pars.mt)
  __pyx_v_risco_log10 = log10(((3.0 * __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SCHW) * __pyx_v_pars->mt));
+363:     cdef double sepa_log10 = log10(pars.sepa_init)
  __pyx_v_sepa_log10 = log10(__pyx_v_pars->sepa_init);
+364:     cdef double norm = pow(10.0, norm_log10)
  __pyx_v_norm = pow(10.0, __pyx_v_norm_log10);
 365: 
 366:     # step-size, in log10-space, to go from sepa_init to ISCO
+367:     cdef double dx = (sepa_log10 - risco_log10) / pars.nsteps
  __pyx_v_dx = ((__pyx_v_sepa_log10 - __pyx_v_risco_log10) / ((double)__pyx_v_pars->nsteps));
+368:     cdef double time = 0.0
  __pyx_v_time = 0.0;
 369: 
 370:     cdef int ii
 371:     cdef double sepa_right, dadt_right, dt
 372: 
+373:     cdef double sepa_left = pow(10.0, sepa_log10)
  __pyx_v_sepa_left = pow(10.0, __pyx_v_sepa_log10);
+374:     cdef double dadt_left = _hard_func_2pwl_gw(
  __pyx_v_dadt_left = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(__pyx_v_pars->mt, __pyx_v_pars->mr, __pyx_v_sepa_left, __pyx_v_norm, __pyx_v_pars->rchar, __pyx_v_pars->gamma_inner, __pyx_v_pars->gamma_outer);
 375:         pars.mt, pars.mr, sepa_left,
 376:         norm, pars.rchar, pars.gamma_inner, pars.gamma_outer
 377:     )
 378: 
+379:     for ii in range(pars.nsteps):
  __pyx_t_1 = __pyx_v_pars->nsteps;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_ii = __pyx_t_3;
+380:         sepa_log10 -= dx
    __pyx_v_sepa_log10 = (__pyx_v_sepa_log10 - __pyx_v_dx);
+381:         sepa_right = pow(10.0, sepa_log10)
    __pyx_v_sepa_right = pow(10.0, __pyx_v_sepa_log10);
 382: 
 383:         # Get total hardening rate at k+1 edge
+384:         dadt_right = _hard_func_2pwl_gw(
    __pyx_v_dadt_right = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(__pyx_v_pars->mt, __pyx_v_pars->mr, __pyx_v_sepa_right, __pyx_v_norm, __pyx_v_pars->rchar, __pyx_v_pars->gamma_inner, __pyx_v_pars->gamma_outer);
 385:             pars.mt, pars.mr, sepa_right,
 386:             norm, pars.rchar, pars.gamma_inner, pars.gamma_outer
 387:         )
 388: 
 389:         # Find time to move from left to right
+390:         dt = 2.0 * (sepa_right - sepa_left) / (dadt_left + dadt_right)
    __pyx_v_dt = ((2.0 * (__pyx_v_sepa_right - __pyx_v_sepa_left)) / (__pyx_v_dadt_left + __pyx_v_dadt_right));
+391:         time += dt
    __pyx_v_time = (__pyx_v_time + __pyx_v_dt);
 392: 
+393:         sepa_left = sepa_right
    __pyx_v_sepa_left = __pyx_v_sepa_right;
+394:         dadt_left = dadt_right
    __pyx_v_dadt_left = __pyx_v_dadt_right;
  }
 395: 
+396:     time = time - pars.target_time
  __pyx_v_time = (__pyx_v_time - __pyx_v_pars->target_time);
+397:     return time
  __pyx_r = __pyx_v_time;
  goto __pyx_L0;
 398: 
 399: 
+400: def integrate_binary_evolution_2pwl(norm_log10, mtot, mrat, sepa_init, rchar, gamma_inner, gamma_outer, nsteps):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_9integrate_binary_evolution_2pwl(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_11sam_cyutils_9integrate_binary_evolution_2pwl = {"integrate_binary_evolution_2pwl", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_11sam_cyutils_9integrate_binary_evolution_2pwl, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_9integrate_binary_evolution_2pwl(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_norm_log10 = 0;
  PyObject *__pyx_v_mtot = 0;
  PyObject *__pyx_v_mrat = 0;
  PyObject *__pyx_v_sepa_init = 0;
  PyObject *__pyx_v_rchar = 0;
  PyObject *__pyx_v_gamma_inner = 0;
  PyObject *__pyx_v_gamma_outer = 0;
  PyObject *__pyx_v_nsteps = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("integrate_binary_evolution_2pwl (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_norm_log10,&__pyx_n_s_mtot,&__pyx_n_s_mrat,&__pyx_n_s_sepa_init,&__pyx_n_s_rchar,&__pyx_n_s_gamma_inner,&__pyx_n_s_gamma_outer,&__pyx_n_s_nsteps,0};
    PyObject* values[8] = {0,0,0,0,0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
        CYTHON_FALLTHROUGH;
        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
        CYTHON_FALLTHROUGH;
        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
        CYTHON_FALLTHROUGH;
        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
        CYTHON_FALLTHROUGH;
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_norm_log10)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mtot)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 1); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mrat)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 2); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sepa_init)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 3); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rchar)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 4); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_inner)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 5); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_outer)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 6); __PYX_ERR(0, 400, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_nsteps)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, 7); __PYX_ERR(0, 400, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "integrate_binary_evolution_2pwl") < 0)) __PYX_ERR(0, 400, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 8) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
      values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
      values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
    }
    __pyx_v_norm_log10 = values[0];
    __pyx_v_mtot = values[1];
    __pyx_v_mrat = values[2];
    __pyx_v_sepa_init = values[3];
    __pyx_v_rchar = values[4];
    __pyx_v_gamma_inner = values[5];
    __pyx_v_gamma_outer = values[6];
    __pyx_v_nsteps = values[7];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("integrate_binary_evolution_2pwl", 1, 8, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 400, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.integrate_binary_evolution_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_8integrate_binary_evolution_2pwl(__pyx_self, __pyx_v_norm_log10, __pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa_init, __pyx_v_rchar, __pyx_v_gamma_inner, __pyx_v_gamma_outer, __pyx_v_nsteps);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_8integrate_binary_evolution_2pwl(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_norm_log10, PyObject *__pyx_v_mtot, PyObject *__pyx_v_mrat, PyObject *__pyx_v_sepa_init, PyObject *__pyx_v_rchar, PyObject *__pyx_v_gamma_inner, PyObject *__pyx_v_gamma_outer, PyObject *__pyx_v_nsteps) {
  __pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params __pyx_v_args;
  double __pyx_v_time;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("integrate_binary_evolution_2pwl", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.integrate_binary_evolution_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__29 = PyTuple_Pack(10, __pyx_n_s_norm_log10, __pyx_n_s_mtot, __pyx_n_s_mrat, __pyx_n_s_sepa_init, __pyx_n_s_rchar, __pyx_n_s_gamma_inner, __pyx_n_s_gamma_outer, __pyx_n_s_nsteps, __pyx_n_s_args, __pyx_n_s_time); if (unlikely(!__pyx_tuple__29)) __PYX_ERR(0, 400, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__29);
  __Pyx_GIVEREF(__pyx_tuple__29);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_11sam_cyutils_9integrate_binary_evolution_2pwl, NULL, __pyx_n_s_holodeck_sams_sam_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 400, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_integrate_binary_evolution_2pwl, __pyx_t_1) < 0) __PYX_ERR(0, 400, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__30 = (PyObject*)__Pyx_PyCode_New(8, 0, 10, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__29, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_sam_cyutils_pyx, __pyx_n_s_integrate_binary_evolution_2pwl, 400, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__30)) __PYX_ERR(0, 400, __pyx_L1_error)
 401:     cdef lifetime_2pwl_params args
+402:     args.mt = mtot
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_mtot); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 402, __pyx_L1_error)
  __pyx_v_args.mt = __pyx_t_1;
+403:     args.mr = mrat
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_mrat); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 403, __pyx_L1_error)
  __pyx_v_args.mr = __pyx_t_1;
+404:     args.target_time = 0.0
  __pyx_v_args.target_time = 0.0;
+405:     args.sepa_init = sepa_init
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_sepa_init); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 405, __pyx_L1_error)
  __pyx_v_args.sepa_init = __pyx_t_1;
+406:     args.rchar = rchar
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_rchar); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 406, __pyx_L1_error)
  __pyx_v_args.rchar = __pyx_t_1;
+407:     args.gamma_inner = gamma_inner
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_gamma_inner); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 407, __pyx_L1_error)
  __pyx_v_args.gamma_inner = __pyx_t_1;
+408:     args.gamma_outer = gamma_outer
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_gamma_outer); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 408, __pyx_L1_error)
  __pyx_v_args.gamma_outer = __pyx_t_1;
+409:     args.nsteps = nsteps
  __pyx_t_2 = __Pyx_PyInt_As_int(__pyx_v_nsteps); if (unlikely((__pyx_t_2 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 409, __pyx_L1_error)
  __pyx_v_args.nsteps = __pyx_t_2;
 410: 
+411:     time = get_binary_lifetime_2pwl(norm_log10, <lifetime_2pwl_params *> &args)
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_norm_log10); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 411, __pyx_L1_error)
  __pyx_v_time = __pyx_f_8holodeck_4sams_11sam_cyutils_get_binary_lifetime_2pwl(__pyx_t_1, ((__pyx_t_8holodeck_4sams_11sam_cyutils_lifetime_2pwl_params *)(&__pyx_v_args)));
+412:     return time
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_time); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 412, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;
 413: 
 414: 
 415: # ==================================================================================================
 416: # ====    Dynamic Binary Number - calculate number of binaries at each frequency    ====
 417: # ==================================================================================================
 418: 
 419: 
+420: def dynamic_binary_number_at_fobs(fobs_orb, sam, hard, cosmo):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_11dynamic_binary_number_at_fobs(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_11sam_cyutils_11dynamic_binary_number_at_fobs = {"dynamic_binary_number_at_fobs", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_11sam_cyutils_11dynamic_binary_number_at_fobs, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_11sam_cyutils_11dynamic_binary_number_at_fobs(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_fobs_orb = 0;
  PyObject *__pyx_v_sam = 0;
  PyObject *__pyx_v_hard = 0;
  PyObject *__pyx_v_cosmo = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("dynamic_binary_number_at_fobs (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fobs_orb,&__pyx_n_s_sam,&__pyx_n_s_hard,&__pyx_n_s_cosmo,0};
    PyObject* values[4] = {0,0,0,0};
    if (unlikely(__pyx_kwds)) {
      Py_ssize_t kw_args;
      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
      switch (pos_args) {
        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
        CYTHON_FALLTHROUGH;
        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
        CYTHON_FALLTHROUGH;
        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
        CYTHON_FALLTHROUGH;
        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
        CYTHON_FALLTHROUGH;
        case  0: break;
        default: goto __pyx_L5_argtuple_error;
      }
      kw_args = PyDict_Size(__pyx_kwds);
      switch (pos_args) {
        case  0:
        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fobs_orb)) != 0)) kw_args--;
        else goto __pyx_L5_argtuple_error;
        CYTHON_FALLTHROUGH;
        case  1:
        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_sam)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("dynamic_binary_number_at_fobs", 1, 4, 4, 1); __PYX_ERR(0, 420, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_hard)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("dynamic_binary_number_at_fobs", 1, 4, 4, 2); __PYX_ERR(0, 420, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_cosmo)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("dynamic_binary_number_at_fobs", 1, 4, 4, 3); __PYX_ERR(0, 420, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "dynamic_binary_number_at_fobs") < 0)) __PYX_ERR(0, 420, __pyx_L3_error)
      }
    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
      goto __pyx_L5_argtuple_error;
    } else {
      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
    }
    __pyx_v_fobs_orb = values[0];
    __pyx_v_sam = values[1];
    __pyx_v_hard = values[2];
    __pyx_v_cosmo = values[3];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("dynamic_binary_number_at_fobs", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 420, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.dynamic_binary_number_at_fobs", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_11sam_cyutils_10dynamic_binary_number_at_fobs(__pyx_self, __pyx_v_fobs_orb, __pyx_v_sam, __pyx_v_hard, __pyx_v_cosmo);
  int __pyx_lineno = 0;
  const char *__pyx_filename = NULL;
  int __pyx_clineno = 0;

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

static PyObject *__pyx_pf_8holodeck_4sams_11sam_cyutils_10dynamic_binary_number_at_fobs(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fobs_orb, PyObject *__pyx_v_sam, PyObject *__pyx_v_hard, PyObject *__pyx_v_cosmo) {
  PyObject *__pyx_v_dens = NULL;
  PyObject *__pyx_v_shape = NULL;
  PyArrayObject *__pyx_v_diff_num = 0;
  PyArrayObject *__pyx_v_redz_final = 0;
  PyObject *__pyx_v_gmt_time = NULL;
  PyObject *__pyx_v_redz_prime = NULL;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_diff_num;
  __Pyx_Buffer __pyx_pybuffer_diff_num;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_redz_final;
  __Pyx_Buffer __pyx_pybuffer_redz_final;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("dynamic_binary_number_at_fobs", 0);
  __pyx_pybuffer_diff_num.pybuffer.buf = NULL;
  __pyx_pybuffer_diff_num.refcount = 0;
  __pyx_pybuffernd_diff_num.data = NULL;
  __pyx_pybuffernd_diff_num.rcbuffer = &__pyx_pybuffer_diff_num;
  __pyx_pybuffer_redz_final.pybuffer.buf = NULL;
  __pyx_pybuffer_redz_final.refcount = 0;
  __pyx_pybuffernd_redz_final.data = NULL;
  __pyx_pybuffernd_redz_final.rcbuffer = &__pyx_pybuffer_redz_final;
/* … */
  /* 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_8);
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_12, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_19, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_20, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_21, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_22, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_23, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_24, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_25, 1);
  __Pyx_XDECREF(__pyx_t_28);
  { 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_diff_num.rcbuffer->pybuffer);
    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_redz_final.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils.dynamic_binary_number_at_fobs", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_diff_num.rcbuffer->pybuffer);
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_redz_final.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF(__pyx_v_dens);
  __Pyx_XDECREF(__pyx_v_shape);
  __Pyx_XDECREF((PyObject *)__pyx_v_diff_num);
  __Pyx_XDECREF((PyObject *)__pyx_v_redz_final);
  __Pyx_XDECREF(__pyx_v_gmt_time);
  __Pyx_XDECREF(__pyx_v_redz_prime);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__31 = PyTuple_Pack(10, __pyx_n_s_fobs_orb, __pyx_n_s_sam, __pyx_n_s_hard, __pyx_n_s_cosmo, __pyx_n_s_dens, __pyx_n_s_shape, __pyx_n_s_diff_num, __pyx_n_s_redz_final, __pyx_n_s_gmt_time_2, __pyx_n_s_redz_prime_2); if (unlikely(!__pyx_tuple__31)) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__31);
  __Pyx_GIVEREF(__pyx_tuple__31);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_11sam_cyutils_11dynamic_binary_number_at_fobs, NULL, __pyx_n_s_holodeck_sams_sam_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_dynamic_binary_number_at_fobs, __pyx_t_1) < 0) __PYX_ERR(0, 420, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__32 = (PyObject*)__Pyx_PyCode_New(4, 0, 10, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__31, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_sam_cyutils_pyx, __pyx_n_s_dynamic_binary_number_at_fobs, 420, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__32)) __PYX_ERR(0, 420, __pyx_L1_error)
 421: 
+422:     dens = sam.static_binary_density
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_static_binary_density); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 422, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_dens = __pyx_t_1;
  __pyx_t_1 = 0;
 423: 
+424:     shape = sam.shape + (fobs_orb.size,)
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_fobs_orb, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_GIVEREF(__pyx_t_2);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);
  __pyx_t_2 = 0;
  __pyx_t_2 = PyNumber_Add(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 424, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_v_shape = __pyx_t_2;
  __pyx_t_2 = 0;
+425:     cdef np.ndarray[np.double_t, ndim=4] diff_num = np.zeros(shape)
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 425, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_zeros); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 425, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_1);
    if (likely(__pyx_t_3)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
      __Pyx_INCREF(__pyx_t_3);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_1, function);
    }
  }
  __pyx_t_2 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_3, __pyx_v_shape) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_shape);
  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 425, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (!(likely(((__pyx_t_2) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_2, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 425, __pyx_L1_error)
  __pyx_t_4 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_diff_num.rcbuffer->pybuffer, (PyObject*)__pyx_t_4, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 4, 0, __pyx_stack) == -1)) {
      __pyx_v_diff_num = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 425, __pyx_L1_error)
    } else {__pyx_pybuffernd_diff_num.diminfo[0].strides = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_diff_num.diminfo[0].shape = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_diff_num.diminfo[1].strides = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_diff_num.diminfo[1].shape = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_diff_num.diminfo[2].strides = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_diff_num.diminfo[2].shape = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.shape[2]; __pyx_pybuffernd_diff_num.diminfo[3].strides = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.strides[3]; __pyx_pybuffernd_diff_num.diminfo[3].shape = __pyx_pybuffernd_diff_num.rcbuffer->pybuffer.shape[3];
    }
  }
  __pyx_t_4 = 0;
  __pyx_v_diff_num = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+426:     cdef np.ndarray[np.double_t, ndim=4] redz_final = -1.0 * np.ones(shape)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_ones); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_1, __pyx_v_shape) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_shape);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyNumber_Multiply(__pyx_float_neg_1_0, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 426, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (!(likely(((__pyx_t_3) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_3, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 426, __pyx_L1_error)
  __pyx_t_5 = ((PyArrayObject *)__pyx_t_3);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_redz_final.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 4, 0, __pyx_stack) == -1)) {
      __pyx_v_redz_final = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 426, __pyx_L1_error)
    } else {__pyx_pybuffernd_redz_final.diminfo[0].strides = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_redz_final.diminfo[0].shape = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_redz_final.diminfo[1].strides = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_redz_final.diminfo[1].shape = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_redz_final.diminfo[2].strides = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_redz_final.diminfo[2].shape = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.shape[2]; __pyx_pybuffernd_redz_final.diminfo[3].strides = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.strides[3]; __pyx_pybuffernd_redz_final.diminfo[3].shape = __pyx_pybuffernd_redz_final.rcbuffer->pybuffer.shape[3];
    }
  }
  __pyx_t_5 = 0;
  __pyx_v_redz_final = ((PyArrayObject *)__pyx_t_3);
  __pyx_t_3 = 0;
 427: 
 428:     # ---- Fixed_Time_2pwl_SAM
 429: 
+430:     if isinstance(hard, holo.hardening.Fixed_Time_2PL_SAM):
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_holo); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_hardening); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_Fixed_Time_2PL_SAM); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_6 = PyObject_IsInstance(__pyx_v_hard, __pyx_t_3); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(0, 430, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_7 = (__pyx_t_6 != 0);
  if (__pyx_t_7) {
/* … */
    goto __pyx_L3;
  }
+431:         gmt_time = sam._gmt_time
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_gmt_time); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 431, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_v_gmt_time = __pyx_t_3;
    __pyx_t_3 = 0;
 432:         # if `sam` is using galaxy merger rate (GMR), then `gmt_time` will be `None`
+433:         if gmt_time is None:
    __pyx_t_7 = (__pyx_v_gmt_time == Py_None);
    __pyx_t_6 = (__pyx_t_7 != 0);
    if (__pyx_t_6) {
/* … */
    }
+434:             sam._log.info("`gmt_time` not calculated in SAM.  Setting to zeros.")
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_log_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 434, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 434, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
        if (likely(__pyx_t_2)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_2);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_1, function);
        }
      }
      __pyx_t_3 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_2, __pyx_kp_u_gmt_time_not_calculated_in_SAM) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_kp_u_gmt_time_not_calculated_in_SAM);
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 434, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+435:             gmt_time = np.zeros(sam.shape)
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 435, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 435, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 435, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_8 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_2);
        if (likely(__pyx_t_8)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
          __Pyx_INCREF(__pyx_t_8);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_2, function);
        }
      }
      __pyx_t_3 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_8, __pyx_t_1) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_1);
      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 435, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __Pyx_DECREF_SET(__pyx_v_gmt_time, __pyx_t_3);
      __pyx_t_3 = 0;
 436: 
+437:         _dynamic_binary_number_at_fobs_2pwl(
    __pyx_t_26 = __pyx_f_8holodeck_4sams_11sam_cyutils__dynamic_binary_number_at_fobs_2pwl(__pyx_t_9, __pyx_t_10, __pyx_t_11, __pyx_t_12, __pyx_t_13, __pyx_t_14, __pyx_t_15, __pyx_t_16, __pyx_t_17, __pyx_t_18, __pyx_t_19, __pyx_t_20, __pyx_t_21, __pyx_t_22, __pyx_t_23, __pyx_t_24, __pyx_t_25); if (unlikely(__pyx_t_26 == ((int)-1))) __PYX_ERR(0, 437, __pyx_L1_error)
    __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
    __pyx_t_9.memview = NULL;
    __pyx_t_9.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_12, 1);
    __pyx_t_12.memview = NULL;
    __pyx_t_12.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
    __pyx_t_16.memview = NULL;
    __pyx_t_16.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
    __pyx_t_17.memview = NULL;
    __pyx_t_17.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
    __pyx_t_18.memview = NULL;
    __pyx_t_18.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_19, 1);
    __pyx_t_19.memview = NULL;
    __pyx_t_19.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_20, 1);
    __pyx_t_20.memview = NULL;
    __pyx_t_20.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_21, 1);
    __pyx_t_21.memview = NULL;
    __pyx_t_21.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_22, 1);
    __pyx_t_22.memview = NULL;
    __pyx_t_22.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_23, 1);
    __pyx_t_23.memview = NULL;
    __pyx_t_23.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_24, 1);
    __pyx_t_24.memview = NULL;
    __pyx_t_24.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_25, 1);
    __pyx_t_25.memview = NULL;
    __pyx_t_25.data = NULL;
+438:             fobs_orb, hard._sepa_init, hard._num_steps,
    __pyx_t_9 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_fobs_orb, PyBUF_WRITABLE); if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 438, __pyx_L1_error)
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_sepa_init_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 438, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 438, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_num_steps); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 438, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_11 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_11 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 438, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+439:             hard._norm, hard._rchar, hard._gamma_inner, hard._gamma_outer,
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_norm_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_12 = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_12.memview)) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_rchar_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_13 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_13 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_gamma_inner_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_14 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_14 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_hard, __pyx_n_s_gamma_outer_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_15 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_15 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 439, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+440:             dens, sam.mtot, sam.mrat, sam.redz, gmt_time,
    __pyx_t_16 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_dens, PyBUF_WRITABLE); if (unlikely(!__pyx_t_16.memview)) __PYX_ERR(0, 440, __pyx_L1_error)
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mtot); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_17 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_17.memview)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mrat); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_18 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_18.memview)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_redz); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_19 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_19.memview)) __PYX_ERR(0, 440, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_20 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_gmt_time, PyBUF_WRITABLE); if (unlikely(!__pyx_t_20.memview)) __PYX_ERR(0, 440, __pyx_L1_error)
+441:             cosmo._grid_z, cosmo._grid_dcom, cosmo._grid_age,
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cosmo, __pyx_n_s_grid_z); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_21 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_21.memview)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cosmo, __pyx_n_s_grid_dcom); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_22 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_22.memview)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_cosmo, __pyx_n_s_grid_age); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_t_23 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_3, PyBUF_WRITABLE); if (unlikely(!__pyx_t_23.memview)) __PYX_ERR(0, 441, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 442:             # output:
+443:             redz_final, diff_num
    __pyx_t_24 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_redz_final), PyBUF_WRITABLE); if (unlikely(!__pyx_t_24.memview)) __PYX_ERR(0, 443, __pyx_L1_error)
    __pyx_t_25 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_diff_num), PyBUF_WRITABLE); if (unlikely(!__pyx_t_25.memview)) __PYX_ERR(0, 443, __pyx_L1_error)
 444:         )
 445: 
 446:     # ---- Hard_GW
 447: 
+448:     elif isinstance(hard, holo.hardening.Hard_GW) or issubclass(hard, holo.hardening.Hard_GW):
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_holo); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_hardening); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_Hard_GW); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_7 = PyObject_IsInstance(__pyx_v_hard, __pyx_t_3); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_27 = (__pyx_t_7 != 0);
  if (!__pyx_t_27) {
  } else {
    __pyx_t_6 = __pyx_t_27;
    goto __pyx_L5_bool_binop_done;
  }
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_holo); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_hardening); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_Hard_GW); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_27 = PyObject_IsSubclass(__pyx_v_hard, __pyx_t_3); if (unlikely(__pyx_t_27 == ((int)-1))) __PYX_ERR(0, 448, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_7 = (__pyx_t_27 != 0);
  __pyx_t_6 = __pyx_t_7;
  __pyx_L5_bool_binop_done:;
  if (likely(__pyx_t_6)) {
/* … */
    goto __pyx_L3;
  }
+449:         redz_prime = sam._redz_prime
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_redz_prime); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 449, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_v_redz_prime = __pyx_t_3;
    __pyx_t_3 = 0;
 450:         # if `sam` is using galaxy merger rate (GMR), then `redz_prime` will be `None`
+451:         if redz_prime is None:
    __pyx_t_6 = (__pyx_v_redz_prime == Py_None);
    __pyx_t_7 = (__pyx_t_6 != 0);
    if (__pyx_t_7) {
/* … */
    }
+452:             sam._log.info("`redz_prime` not calculated in SAM.  Setting to `redz` (initial) values.")
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_log_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_info); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = NULL;
      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_1))) {
        __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_1);
        if (likely(__pyx_t_2)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
          __Pyx_INCREF(__pyx_t_2);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_1, function);
        }
      }
      __pyx_t_3 = (__pyx_t_2) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_2, __pyx_kp_u_redz_prime_not_calculated_in_SA) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_kp_u_redz_prime_not_calculated_in_SA);
      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 452, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+453:             redz_prime = sam.redz[np.newaxis, np.newaxis, :] * np.ones(sam.shape)
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_redz); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_newaxis); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_newaxis); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_GIVEREF(__pyx_t_2);
      PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
      __Pyx_GIVEREF(__pyx_t_8);
      PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_8);
      __Pyx_INCREF(__pyx_slice_);
      __Pyx_GIVEREF(__pyx_slice_);
      PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_slice_);
      __pyx_t_2 = 0;
      __pyx_t_8 = 0;
      __pyx_t_8 = __Pyx_PyObject_GetItem(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_8);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_ones); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_shape); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_3);
      __pyx_t_28 = NULL;
      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
        __pyx_t_28 = PyMethod_GET_SELF(__pyx_t_2);
        if (likely(__pyx_t_28)) {
          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
          __Pyx_INCREF(__pyx_t_28);
          __Pyx_INCREF(function);
          __Pyx_DECREF_SET(__pyx_t_2, function);
        }
      }
      __pyx_t_1 = (__pyx_t_28) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_28, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
      __Pyx_XDECREF(__pyx_t_28); __pyx_t_28 = 0;
      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_1);
      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
      __pyx_t_2 = PyNumber_Multiply(__pyx_t_8, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 453, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_2);
      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      __Pyx_DECREF_SET(__pyx_v_redz_prime, __pyx_t_2);
      __pyx_t_2 = 0;
/* … */
  __pyx_slice_ = PySlice_New(Py_None, Py_None, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 453, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_slice_);
  __Pyx_GIVEREF(__pyx_slice_);
 454: 
+455:         _dynamic_binary_number_at_fobs_gw(
    __pyx_t_26 = __pyx_f_8holodeck_4sams_11sam_cyutils__dynamic_binary_number_at_fobs_gw(__pyx_t_23, __pyx_t_20, __pyx_t_22, __pyx_t_21, __pyx_t_19, __pyx_t_16, __pyx_t_18, __pyx_t_17, __pyx_t_25, __pyx_t_24); if (unlikely(__pyx_t_26 == ((int)-1))) __PYX_ERR(0, 455, __pyx_L1_error)
    __PYX_XDEC_MEMVIEW(&__pyx_t_23, 1);
    __pyx_t_23.memview = NULL;
    __pyx_t_23.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_20, 1);
    __pyx_t_20.memview = NULL;
    __pyx_t_20.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_22, 1);
    __pyx_t_22.memview = NULL;
    __pyx_t_22.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_21, 1);
    __pyx_t_21.memview = NULL;
    __pyx_t_21.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_19, 1);
    __pyx_t_19.memview = NULL;
    __pyx_t_19.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_16, 1);
    __pyx_t_16.memview = NULL;
    __pyx_t_16.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_18, 1);
    __pyx_t_18.memview = NULL;
    __pyx_t_18.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_17, 1);
    __pyx_t_17.memview = NULL;
    __pyx_t_17.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_25, 1);
    __pyx_t_25.memview = NULL;
    __pyx_t_25.data = NULL;
    __PYX_XDEC_MEMVIEW(&__pyx_t_24, 1);
    __pyx_t_24.memview = NULL;
    __pyx_t_24.data = NULL;
+456:             fobs_orb,
    __pyx_t_23 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_fobs_orb, PyBUF_WRITABLE); if (unlikely(!__pyx_t_23.memview)) __PYX_ERR(0, 456, __pyx_L1_error)
+457:             dens, sam.mtot, sam.mrat, sam.redz, redz_prime,
    __pyx_t_20 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_dens, PyBUF_WRITABLE); if (unlikely(!__pyx_t_20.memview)) __PYX_ERR(0, 457, __pyx_L1_error)
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mtot); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_22 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_22.memview)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mrat); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_21 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_21.memview)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_redz); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_19 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_19.memview)) __PYX_ERR(0, 457, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_16 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_redz_prime, PyBUF_WRITABLE); if (unlikely(!__pyx_t_16.memview)) __PYX_ERR(0, 457, __pyx_L1_error)
+458:             cosmo._grid_z, cosmo._grid_dcom,
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_cosmo, __pyx_n_s_grid_z); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_18 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_18.memview)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_cosmo, __pyx_n_s_grid_dcom); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_17 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_2, PyBUF_WRITABLE); if (unlikely(!__pyx_t_17.memview)) __PYX_ERR(0, 458, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 459:             # output:
+460:             redz_final, diff_num
    __pyx_t_25 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_redz_final), PyBUF_WRITABLE); if (unlikely(!__pyx_t_25.memview)) __PYX_ERR(0, 460, __pyx_L1_error)
    __pyx_t_24 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_diff_num), PyBUF_WRITABLE); if (unlikely(!__pyx_t_24.memview)) __PYX_ERR(0, 460, __pyx_L1_error)
 461:         )
 462: 
 463:     # ---- OTHER
 464: 
 465:     else:
+466:         raise ValueError(f"Unexpected `hard` value {hard}!")
  /*else*/ {
    __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_29 = 0;
    __pyx_t_30 = 127;
    __Pyx_INCREF(__pyx_kp_u_Unexpected_hard_value);
    __pyx_t_29 += 24;
    __Pyx_GIVEREF(__pyx_kp_u_Unexpected_hard_value);
    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_kp_u_Unexpected_hard_value);
    __pyx_t_1 = __Pyx_PyObject_FormatSimple(__pyx_v_hard, __pyx_empty_unicode); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_30 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_1) > __pyx_t_30) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_1) : __pyx_t_30;
    __pyx_t_29 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_1);
    __Pyx_GIVEREF(__pyx_t_1);
    PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_1);
    __pyx_t_1 = 0;
    __Pyx_INCREF(__pyx_kp_u__2);
    __pyx_t_29 += 1;
    __Pyx_GIVEREF(__pyx_kp_u__2);
    PyTuple_SET_ITEM(__pyx_t_2, 2, __pyx_kp_u__2);
    __pyx_t_1 = __Pyx_PyUnicode_Join(__pyx_t_2, 3, __pyx_t_29, __pyx_t_30); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_ValueError, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 466, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __PYX_ERR(0, 466, __pyx_L1_error)
  }
  __pyx_L3:;
 467: 
+468:     return redz_final, diff_num
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 468, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_INCREF(((PyObject *)__pyx_v_redz_final));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_redz_final));
  PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_redz_final));
  __Pyx_INCREF(((PyObject *)__pyx_v_diff_num));
  __Pyx_GIVEREF(((PyObject *)__pyx_v_diff_num));
  PyTuple_SET_ITEM(__pyx_t_2, 1, ((PyObject *)__pyx_v_diff_num));
  __pyx_r = __pyx_t_2;
  __pyx_t_2 = 0;
  goto __pyx_L0;
 469: 
 470: @cython.boundscheck(False)
 471: @cython.wraparound(False)
 472: @cython.nonecheck(False)
 473: @cython.cdivision(True)
+474: cdef int _dynamic_binary_number_at_fobs_2pwl(
static int __pyx_f_8holodeck_4sams_11sam_cyutils__dynamic_binary_number_at_fobs_2pwl(__Pyx_memviewslice __pyx_v_target_fobs_orb, double __pyx_v_sepa_init, int __pyx_v_num_steps, __Pyx_memviewslice __pyx_v_hard_norm, double __pyx_v_hard_rchar, double __pyx_v_hard_gamma_inner, double __pyx_v_hard_gamma_outer, __Pyx_memviewslice __pyx_v_dens, __Pyx_memviewslice __pyx_v_mtot, __Pyx_memviewslice __pyx_v_mrat, __Pyx_memviewslice __pyx_v_redz, __Pyx_memviewslice __pyx_v_gmt_time, __Pyx_memviewslice __pyx_v_redz_interp_grid, __Pyx_memviewslice __pyx_v_dcom_interp_grid, __Pyx_memviewslice __pyx_v_tage_interp_grid, __Pyx_memviewslice __pyx_v_redz_final, __Pyx_memviewslice __pyx_v_diff_num) {
  int __pyx_v_n_mtot;
  int __pyx_v_n_mrat;
  int __pyx_v_n_redz;
  int __pyx_v_n_freq;
  int __pyx_v_n_interp;
  double __pyx_v_age_universe;
  double __pyx_v_sepa_init_log10;
  int __pyx_v_ii;
  int __pyx_v_jj;
  int __pyx_v_kk;
  int __pyx_v_ff;
  CYTHON_UNUSED int __pyx_v_step;
  int __pyx_v_interp_left_idx;
  int __pyx_v_interp_right_idx;
  int __pyx_v_new_interp_idx;
  double __pyx_v_mt;
  double __pyx_v_mr;
  double __pyx_v_norm;
  double __pyx_v_risco;
  double __pyx_v_dx;
  double __pyx_v_new_redz;
  double __pyx_v_gmt;
  double __pyx_v_ftarget;
  double __pyx_v_target_frst_orb;
  double __pyx_v_sepa_log10;
  double __pyx_v_sepa;
  double __pyx_v_sepa_left;
  double __pyx_v_sepa_right;
  double __pyx_v_dadt_left;
  double __pyx_v_dadt_right;
  double __pyx_v_time_evo;
  double __pyx_v_redz_left;
  double __pyx_v_redz_right;
  double __pyx_v_time_left;
  double __pyx_v_time_right;
  double __pyx_v_new_time;
  double __pyx_v_frst_orb_left;
  double __pyx_v_fobs_orb_left;
  double __pyx_v_frst_orb_right;
  double __pyx_v_fobs_orb_right;
  double *__pyx_v_redz_age;
  int __pyx_v_rev;
  double __pyx_v_dt;
  double __pyx_v_dcom;
  double __pyx_v_dadt;
  double __pyx_v_tres;
  double __pyx_v_cosmo_fact;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_dynamic_binary_number_at_fobs_2pwl", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils._dynamic_binary_number_at_fobs_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 475:     double[:] target_fobs_orb,
 476:     double sepa_init,
 477:     int num_steps,
 478: 
 479:     double[:, :] hard_norm,
 480:     double hard_rchar,
 481:     double hard_gamma_inner,
 482:     double hard_gamma_outer,
 483: 
 484:     double[:, :, :] dens,
 485:     double[:] mtot,
 486:     double[:] mrat,
 487:     double[:] redz,
 488:     double[:, :, :] gmt_time,
 489: 
 490:     double[:] redz_interp_grid,
 491:     double[:] dcom_interp_grid,
 492:     double[:] tage_interp_grid,
 493: 
 494:     # output
 495:     double[:, :, :, :] redz_final,
 496:     double[:, :, :, :] diff_num,
 497: ) except -1:
 498:     """Convert from binary volume-density (all separations) to binary number at particular frequencies.
 499:     """
 500: 
+501:     cdef int n_mtot = mtot.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 501, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+502:     cdef int n_mrat = mrat.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_mrat, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 502, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 502, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 502, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+503:     cdef int n_redz = redz.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_redz, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 503, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 503, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 503, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+504:     cdef int n_freq = target_fobs_orb.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_target_fobs_orb, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 504, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 504, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 504, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
+505:     cdef int n_interp = redz_interp_grid.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_redz_interp_grid, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 505, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 505, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 505, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_interp = __pyx_t_3;
+506:     cdef double age_universe = tage_interp_grid[n_interp - 1]
  __pyx_t_4 = (__pyx_v_n_interp - 1);
  __pyx_v_age_universe = (*((double *) ( /* dim=0 */ (__pyx_v_tage_interp_grid.data + __pyx_t_4 * __pyx_v_tage_interp_grid.strides[0]) )));
+507:     cdef double sepa_init_log10 = log10(sepa_init)
  __pyx_v_sepa_init_log10 = log10(__pyx_v_sepa_init);
 508: 
 509:     cdef int ii, jj, kk, ff, step, interp_left_idx, interp_right_idx, new_interp_idx
 510:     cdef double mt, mr, norm, risco, dx, new_redz, gmt, ftarget, target_frst_orb
 511:     cdef double sepa_log10, sepa, sepa_left, sepa_right, dadt_left, dadt_right
 512:     cdef double time_evo, redz_left, redz_right, time_left, time_right, new_time
 513:     cdef double frst_orb_left, fobs_orb_left, frst_orb_right, fobs_orb_right
 514: 
 515:     # ---- Calculate ages corresponding to SAM `redz` grid
 516: 
+517:     cdef double *redz_age = <double *>malloc(n_redz * sizeof(double))     # (Z,) age of the universe in [sec]
  __pyx_v_redz_age = ((double *)malloc((__pyx_v_n_redz * (sizeof(double)))));
+518:     ii = 0
  __pyx_v_ii = 0;
 519:     cdef int rev
+520:     for kk in range(n_redz):
  __pyx_t_3 = __pyx_v_n_redz;
  __pyx_t_5 = __pyx_t_3;
  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_kk = __pyx_t_6;
 521:         # iterate in reverse order to match with `redz_interp_grid` which is decreasing
+522:         rev = n_redz - 1 - kk
    __pyx_v_rev = ((__pyx_v_n_redz - 1) - __pyx_v_kk);
 523:         # get to the right index of the interpolation-grid
+524:         while (redz_interp_grid[ii+1] > redz[rev]) and (ii < n_interp - 1):
    while (1) {
      __pyx_t_4 = (__pyx_v_ii + 1);
      __pyx_t_8 = __pyx_v_rev;
      __pyx_t_9 = (((*((double *) ( /* dim=0 */ (__pyx_v_redz_interp_grid.data + __pyx_t_4 * __pyx_v_redz_interp_grid.strides[0]) ))) > (*((double *) ( /* dim=0 */ (__pyx_v_redz.data + __pyx_t_8 * __pyx_v_redz.strides[0]) )))) != 0);
      if (__pyx_t_9) {
      } else {
        __pyx_t_7 = __pyx_t_9;
        goto __pyx_L7_bool_binop_done;
      }
      __pyx_t_9 = ((__pyx_v_ii < (__pyx_v_n_interp - 1)) != 0);
      __pyx_t_7 = __pyx_t_9;
      __pyx_L7_bool_binop_done:;
      if (!__pyx_t_7) break;
+525:             ii += 1
      __pyx_v_ii = (__pyx_v_ii + 1);
    }
 526: 
 527:         # interpolate
+528:         redz_age[rev] = interp_at_index(ii, redz[rev], redz_interp_grid, tage_interp_grid)
    __pyx_t_8 = __pyx_v_rev;
    (__pyx_v_redz_age[__pyx_v_rev]) = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_ii, (*((double *) ( /* dim=0 */ (__pyx_v_redz.data + __pyx_t_8 * __pyx_v_redz.strides[0]) ))), __pyx_v_redz_interp_grid, __pyx_v_tage_interp_grid);
  }
 529: 
 530:     # ---- calculate dynamic binary numbers for all SAM grid bins
 531: 
+532:     for ii in range(n_mtot):
  __pyx_t_3 = __pyx_v_n_mtot;
  __pyx_t_5 = __pyx_t_3;
  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
    __pyx_v_ii = __pyx_t_6;
+533:         mt = mtot[ii]
    __pyx_t_8 = __pyx_v_ii;
    __pyx_v_mt = (*((double *) ( /* dim=0 */ (__pyx_v_mtot.data + __pyx_t_8 * __pyx_v_mtot.strides[0]) )));
 534: 
 535:         # Determine separation step-size, in log10-space, to integrate from sepa_init to ISCO
+536:         risco = 3.0 * MY_SCHW * mt     # ISCO is 3x combined schwarzschild radius
    __pyx_v_risco = ((3.0 * __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SCHW) * __pyx_v_mt);
+537:         dx = (sepa_init_log10 - log10(risco)) / num_steps
    __pyx_v_dx = ((__pyx_v_sepa_init_log10 - log10(__pyx_v_risco)) / ((double)__pyx_v_num_steps));
 538: 
+539:         for jj in range(n_mrat):
    __pyx_t_10 = __pyx_v_n_mrat;
    __pyx_t_11 = __pyx_t_10;
    for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_11; __pyx_t_12+=1) {
      __pyx_v_jj = __pyx_t_12;
+540:             mr = mrat[jj]
      __pyx_t_8 = __pyx_v_jj;
      __pyx_v_mr = (*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_8 * __pyx_v_mrat.strides[0]) )));
 541: 
 542:             # Binary evolution is determined by M and q only
 543:             # so integration is started for each of these bins
+544:             sepa_log10 = sepa_init_log10                # set initial separation to initial value
      __pyx_v_sepa_log10 = __pyx_v_sepa_init_log10;
+545:             norm = hard_norm[ii, jj]                    # get hardening-rate normalization for this bin
      __pyx_t_8 = __pyx_v_ii;
      __pyx_t_4 = __pyx_v_jj;
      __pyx_v_norm = (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_hard_norm.data + __pyx_t_8 * __pyx_v_hard_norm.strides[0]) ) + __pyx_t_4 * __pyx_v_hard_norm.strides[1]) )));
 546: 
 547:             # Get total hardening rate at left-most edge
+548:             sepa_left = pow(10.0, sepa_log10)
      __pyx_v_sepa_left = pow(10.0, __pyx_v_sepa_log10);
+549:             dadt_left = _hard_func_2pwl_gw(
      __pyx_v_dadt_left = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(__pyx_v_mt, __pyx_v_mr, __pyx_v_sepa_left, __pyx_v_norm, __pyx_v_hard_rchar, __pyx_v_hard_gamma_inner, __pyx_v_hard_gamma_outer);
 550:                 mt, mr, sepa_left,
 551:                 norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 552:             )
 553: 
 554:             # get rest-frame orbital frequency of binary at left edge
+555:             frst_orb_left = kepler_freq_from_sepa(mt, sepa_left)
      __pyx_v_frst_orb_left = __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_sepa_left);
 556: 
 557:             # ---- Integrate of `num_steps` discrete intervals in binary separation from large to small
 558: 
+559:             time_evo = 0.0                  # track total binary evolution time
      __pyx_v_time_evo = 0.0;
+560:             interp_left_idx = 0                 # interpolation index, will be updated in each step
      __pyx_v_interp_left_idx = 0;
+561:             for step in range(num_steps):
      __pyx_t_13 = __pyx_v_num_steps;
      __pyx_t_14 = __pyx_t_13;
      for (__pyx_t_15 = 0; __pyx_t_15 < __pyx_t_14; __pyx_t_15+=1) {
        __pyx_v_step = __pyx_t_15;
 562:                 # Increment the current separation
+563:                 sepa_log10 -= dx
        __pyx_v_sepa_log10 = (__pyx_v_sepa_log10 - __pyx_v_dx);
+564:                 sepa_right = pow(10.0, sepa_log10)
        __pyx_v_sepa_right = pow(10.0, __pyx_v_sepa_log10);
+565:                 frst_orb_right = kepler_freq_from_sepa(mt, sepa_right)
        __pyx_v_frst_orb_right = __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_sepa_right);
 566: 
 567:                 # Get total hardening rate at the right-edge of this step (left-edge already obtained)
+568:                 dadt_right = _hard_func_2pwl_gw(
        __pyx_v_dadt_right = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(__pyx_v_mt, __pyx_v_mr, __pyx_v_sepa_right, __pyx_v_norm, __pyx_v_hard_rchar, __pyx_v_hard_gamma_inner, __pyx_v_hard_gamma_outer);
 569:                     mt, mr, sepa_right,
 570:                     norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 571:                 )
 572: 
 573:                 # Find time to move from left- to right- edges:  dt = da / (da/dt)
+574:                 dt = 2.0 * (sepa_right - sepa_left) / (dadt_left + dadt_right)
        __pyx_v_dt = ((2.0 * (__pyx_v_sepa_right - __pyx_v_sepa_left)) / (__pyx_v_dadt_left + __pyx_v_dadt_right));
+575:                 time_evo += dt
        __pyx_v_time_evo = (__pyx_v_time_evo + __pyx_v_dt);
 576: 
 577:                 # ---- Iterate over starting redshift bins
 578: 
+579:                 for kk in range(n_redz-1, -1, -1):
        for (__pyx_t_16 = (__pyx_v_n_redz - 1); __pyx_t_16 > -1; __pyx_t_16-=1) {
          __pyx_v_kk = __pyx_t_16;
 580:                     # get the total time from each starting redshift, plus GMT time, plus evolution time to this step
+581:                     gmt = gmt_time[ii, jj, kk]
          __pyx_t_4 = __pyx_v_ii;
          __pyx_t_8 = __pyx_v_jj;
          __pyx_t_17 = __pyx_v_kk;
          __pyx_v_gmt = (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_gmt_time.data + __pyx_t_4 * __pyx_v_gmt_time.strides[0]) ) + __pyx_t_8 * __pyx_v_gmt_time.strides[1]) ) + __pyx_t_17 * __pyx_v_gmt_time.strides[2]) )));
+582:                     time_right = time_evo + gmt + redz_age[kk]
          __pyx_v_time_right = ((__pyx_v_time_evo + __pyx_v_gmt) + (__pyx_v_redz_age[__pyx_v_kk]));
 583:                     # also get the evolution-time to the left edge
+584:                     time_left = time_right - dt
          __pyx_v_time_left = (__pyx_v_time_right - __pyx_v_dt);
 585: 
 586:                     # if we pass the age of the universe, this binary has stalled, no further redshifts will work
 587:                     # NOTE: if `gmt_time` decreases faster than redshift bins increase the universe age,
 588:                     #       then systems in later `redz` bins may no longer stall, so we still need to calculate them
 589:                     #       i.e. we can NOT use a `break` statement here
+590:                     if time_left > age_universe:
          __pyx_t_7 = ((__pyx_v_time_left > __pyx_v_age_universe) != 0);
          if (__pyx_t_7) {
/* … */
          }
+591:                         continue
            goto __pyx_L15_continue;
 592: 
 593:                     # find the redshift bins corresponding to left- and right- side of step
 594:                     # left edge
+595:                     interp_left_idx = while_while_increasing(interp_left_idx, n_interp, time_left, tage_interp_grid)
          __pyx_v_interp_left_idx = __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_increasing(__pyx_v_interp_left_idx, __pyx_v_n_interp, __pyx_v_time_left, __pyx_v_tage_interp_grid);
 596: 
+597:                     redz_left = interp_at_index(interp_left_idx, time_left, tage_interp_grid, redz_interp_grid)
          __pyx_v_redz_left = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_interp_left_idx, __pyx_v_time_left, __pyx_v_tage_interp_grid, __pyx_v_redz_interp_grid);
 598: 
 599:                     # double check that left-edge is within age of Universe (should rarely if ever be a problem
 600:                     # but possible due to rounding/interpolation errors
+601:                     if redz_left < 0.0:
          __pyx_t_7 = ((__pyx_v_redz_left < 0.0) != 0);
          if (__pyx_t_7) {
/* … */
          }
+602:                         continue
            goto __pyx_L15_continue;
 603: 
 604:                     # find right-edge starting from left edge, i.e. `interp_left_idx` (`interp_left_idx` is not a typo!)
+605:                     interp_right_idx = while_while_increasing(interp_left_idx, n_interp, time_right, tage_interp_grid)
          __pyx_v_interp_right_idx = __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_increasing(__pyx_v_interp_left_idx, __pyx_v_n_interp, __pyx_v_time_right, __pyx_v_tage_interp_grid);
 606:                     # NOTE: because `time_right` can be larger than age of universe, it can exceed `tage_interp_grid`
 607:                     #       in this case `interp_right_idx=n_interp-2`, and the `interp_at_index` function can still
 608:                     #       be used to extrapolate to further out values, which will likely be negative
 609: 
+610:                     redz_right = interp_at_index(interp_right_idx, time_right, tage_interp_grid, redz_interp_grid)
          __pyx_v_redz_right = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_interp_right_idx, __pyx_v_time_right, __pyx_v_tage_interp_grid, __pyx_v_redz_interp_grid);
 611:                     # NOTE: at this point `redz_right` could be negative, even though `redz_left` is definitely not
+612:                     if redz_right < 0.0:
          __pyx_t_7 = ((__pyx_v_redz_right < 0.0) != 0);
          if (__pyx_t_7) {
/* … */
          }
+613:                         redz_right = 0.0
            __pyx_v_redz_right = 0.0;
 614: 
 615:                     # convert to frequencies
+616:                     fobs_orb_left = frst_orb_left / (1.0 + redz_left)
          __pyx_v_fobs_orb_left = (__pyx_v_frst_orb_left / (1.0 + __pyx_v_redz_left));
+617:                     fobs_orb_right = frst_orb_right / (1.0 + redz_right)
          __pyx_v_fobs_orb_right = (__pyx_v_frst_orb_right / (1.0 + __pyx_v_redz_right));
 618: 
 619:                     # ---- Iterate over all target frequencies
 620: 
 621:                     # NOTE: there should be a more efficient way to do this.
 622:                     #       Tried a different implementation in `_dynamic_binary_number_at_fobs_1`, but not working
 623:                     #       some of the frequency bins seem to be getting skipped in that version.
 624: 
+625:                     for ff in range(n_freq):
          __pyx_t_18 = __pyx_v_n_freq;
          __pyx_t_19 = __pyx_t_18;
          for (__pyx_t_20 = 0; __pyx_t_20 < __pyx_t_19; __pyx_t_20+=1) {
            __pyx_v_ff = __pyx_t_20;
+626:                         ftarget = target_fobs_orb[ff]
            __pyx_t_17 = __pyx_v_ff;
            __pyx_v_ftarget = (*((double *) ( /* dim=0 */ (__pyx_v_target_fobs_orb.data + __pyx_t_17 * __pyx_v_target_fobs_orb.strides[0]) )));
 627: 
 628:                         # If the integration-step does NOT bracket the target frequency, continue to next frequency
+629:                         if (ftarget < fobs_orb_left) or (fobs_orb_right < ftarget):
            __pyx_t_9 = ((__pyx_v_ftarget < __pyx_v_fobs_orb_left) != 0);
            if (!__pyx_t_9) {
            } else {
              __pyx_t_7 = __pyx_t_9;
              goto __pyx_L23_bool_binop_done;
            }
            __pyx_t_9 = ((__pyx_v_fobs_orb_right < __pyx_v_ftarget) != 0);
            __pyx_t_7 = __pyx_t_9;
            __pyx_L23_bool_binop_done:;
            if (__pyx_t_7) {
/* … */
            }
+630:                             continue
              goto __pyx_L20_continue;
 631: 
 632:                         # ------------------------------------------------------
 633:                         # ---- TARGET FOUND ----
 634: 
 635:                         # At this point in the code, this target frequency is inbetween the left- and right- edges
 636:                         # of the integration step, so we can interpolate the evolution to exactly this frequency,
 637:                         # and perform the actual dynamic_binary_number calculation
 638: 
+639:                         new_time = _interp_between_vals(ftarget, fobs_orb_left, fobs_orb_right, time_left, time_right)
            __pyx_v_new_time = __pyx_f_8holodeck_7cyutils__interp_between_vals(__pyx_v_ftarget, __pyx_v_fobs_orb_left, __pyx_v_fobs_orb_right, __pyx_v_time_left, __pyx_v_time_right);
 640: 
 641:                         # `time_right` can be after age of Universe, make sure interpolated value is not
 642:                         #    if it is, then all higher-frequencies will also, so break out of target-frequency loop
+643:                         if new_time > tage_interp_grid[n_interp - 1]:
            __pyx_t_17 = (__pyx_v_n_interp - 1);
            __pyx_t_7 = ((__pyx_v_new_time > (*((double *) ( /* dim=0 */ (__pyx_v_tage_interp_grid.data + __pyx_t_17 * __pyx_v_tage_interp_grid.strides[0]) )))) != 0);
            if (__pyx_t_7) {
/* … */
            }
+644:                             break
              goto __pyx_L21_break;
 645: 
 646:                         # find index in interpolation grid for this exact time
+647:                         new_interp_idx = interp_left_idx      # start from left-step edge
            __pyx_v_new_interp_idx = __pyx_v_interp_left_idx;
+648:                         new_interp_idx = while_while_increasing(new_interp_idx, n_interp, new_time, tage_interp_grid)
            __pyx_v_new_interp_idx = __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_increasing(__pyx_v_new_interp_idx, __pyx_v_n_interp, __pyx_v_new_time, __pyx_v_tage_interp_grid);
 649: 
 650:                         # get redshift
+651:                         new_redz = interp_at_index(new_interp_idx, new_time, tage_interp_grid, redz_interp_grid)
            __pyx_v_new_redz = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_new_interp_idx, __pyx_v_new_time, __pyx_v_tage_interp_grid, __pyx_v_redz_interp_grid);
 652:                         # get comoving distance
+653:                         dcom = interp_at_index(new_interp_idx, new_time, tage_interp_grid, dcom_interp_grid)
            __pyx_v_dcom = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_new_interp_idx, __pyx_v_new_time, __pyx_v_tage_interp_grid, __pyx_v_dcom_interp_grid);
 654: 
 655:                         # Store redshift
+656:                         redz_final[ii, jj, kk, ff] = new_redz
            __pyx_t_17 = __pyx_v_ii;
            __pyx_t_8 = __pyx_v_jj;
            __pyx_t_4 = __pyx_v_kk;
            __pyx_t_21 = __pyx_v_ff;
            *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_redz_final.data + __pyx_t_17 * __pyx_v_redz_final.strides[0]) ) + __pyx_t_8 * __pyx_v_redz_final.strides[1]) ) + __pyx_t_4 * __pyx_v_redz_final.strides[2]) ) + __pyx_t_21 * __pyx_v_redz_final.strides[3]) )) = __pyx_v_new_redz;
 657: 
 658:                         # find rest-frame orbital frequency and binary separation
+659:                         target_frst_orb = ftarget * (1.0 + new_redz)
            __pyx_v_target_frst_orb = (__pyx_v_ftarget * (1.0 + __pyx_v_new_redz));
+660:                         sepa = kepler_sepa_from_freq(mt, target_frst_orb)
            __pyx_v_sepa = __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_sepa_from_freq(__pyx_v_mt, __pyx_v_target_frst_orb);
 661: 
 662:                         # calculate total hardening rate at this exact separation
+663:                         dadt = _hard_func_2pwl_gw(
            __pyx_v_dadt = __pyx_f_8holodeck_4sams_11sam_cyutils__hard_func_2pwl_gw(__pyx_v_mt, __pyx_v_mr, __pyx_v_sepa, __pyx_v_norm, __pyx_v_hard_rchar, __pyx_v_hard_gamma_inner, __pyx_v_hard_gamma_outer);
 664:                             mt, mr, sepa,
 665:                             norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 666:                         )
 667: 
 668:                         # calculate residence/hardening time = f/[df/dt] = -(2/3) a/[da/dt]
+669:                         tres = - (2.0/3.0) * sepa / dadt
            __pyx_v_tres = (((-(2.0 / 3.0)) * __pyx_v_sepa) / __pyx_v_dadt);
 670: 
 671:                         # calculate number of binaries
+672:                         cosmo_fact = FOUR_PI_SPLC_OVER_MPC * (1.0 + new_redz) * pow(dcom / MY_MPC, 2)
            __pyx_v_cosmo_fact = ((__pyx_v_8holodeck_4sams_11sam_cyutils_FOUR_PI_SPLC_OVER_MPC * (1.0 + __pyx_v_new_redz)) * pow((__pyx_v_dcom / __pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC), 2.0));
+673:                         diff_num[ii, jj, kk, ff] = dens[ii, jj, kk] * tres * cosmo_fact
            __pyx_t_21 = __pyx_v_ii;
            __pyx_t_4 = __pyx_v_jj;
            __pyx_t_8 = __pyx_v_kk;
            __pyx_t_17 = __pyx_v_ii;
            __pyx_t_22 = __pyx_v_jj;
            __pyx_t_23 = __pyx_v_kk;
            __pyx_t_24 = __pyx_v_ff;
            *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_diff_num.data + __pyx_t_17 * __pyx_v_diff_num.strides[0]) ) + __pyx_t_22 * __pyx_v_diff_num.strides[1]) ) + __pyx_t_23 * __pyx_v_diff_num.strides[2]) ) + __pyx_t_24 * __pyx_v_diff_num.strides[3]) )) = (((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_dens.data + __pyx_t_21 * __pyx_v_dens.strides[0]) ) + __pyx_t_4 * __pyx_v_dens.strides[1]) ) + __pyx_t_8 * __pyx_v_dens.strides[2]) ))) * __pyx_v_tres) * __pyx_v_cosmo_fact);
            __pyx_L20_continue:;
          }
          __pyx_L21_break:;
          __pyx_L15_continue:;
        }
 674: 
 675:                         # ----------------------
 676:                         # ------------------------------------------------------
 677: 
 678:                 # update new left edge
+679:                 dadt_left = dadt_right
        __pyx_v_dadt_left = __pyx_v_dadt_right;
+680:                 sepa_left = sepa_right
        __pyx_v_sepa_left = __pyx_v_sepa_right;
+681:                 frst_orb_left = frst_orb_right
        __pyx_v_frst_orb_left = __pyx_v_frst_orb_right;
      }
    }
  }
 682:                 # note that we _cannot_ do this for redz or freqs because the redshift _bin_ is changing
 683: 
+684:     free(redz_age)
  free(__pyx_v_redz_age);
 685: 
+686:     return 0
  __pyx_r = 0;
  goto __pyx_L0;
 687: 
 688: 
 689: @cython.boundscheck(False)
 690: @cython.wraparound(False)
 691: @cython.nonecheck(False)
 692: @cython.cdivision(True)
+693: cdef int _dynamic_binary_number_at_fobs_gw(
static int __pyx_f_8holodeck_4sams_11sam_cyutils__dynamic_binary_number_at_fobs_gw(__Pyx_memviewslice __pyx_v_target_fobs_orb, __Pyx_memviewslice __pyx_v_dens, __Pyx_memviewslice __pyx_v_mtot, __Pyx_memviewslice __pyx_v_mrat, __Pyx_memviewslice __pyx_v_redz, __Pyx_memviewslice __pyx_v_redz_prime, __Pyx_memviewslice __pyx_v_redz_interp_grid, __Pyx_memviewslice __pyx_v_dcom_interp_grid, __Pyx_memviewslice __pyx_v_redz_final, __Pyx_memviewslice __pyx_v_diff_num) {
  int __pyx_v_n_mtot;
  int __pyx_v_n_mrat;
  int __pyx_v_n_redz;
  int __pyx_v_n_freq;
  int __pyx_v_n_interp;
  int __pyx_v_ii;
  int __pyx_v_jj;
  int __pyx_v_kk;
  int __pyx_v_ff;
  int __pyx_v_interp_idx;
  int __pyx_v__kk;
  double __pyx_v_mt;
  double __pyx_v_mr;
  double __pyx_v_ftarget;
  double __pyx_v_target_frst_orb;
  double __pyx_v_sepa;
  double __pyx_v_rad_isco;
  double __pyx_v_frst_orb_isco;
  double __pyx_v_rzp;
  double __pyx_v_dcom;
  double __pyx_v_dadt;
  double __pyx_v_tres;
  double __pyx_v_cosmo_fact;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_dynamic_binary_number_at_fobs_gw", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("holodeck.sams.sam_cyutils._dynamic_binary_number_at_fobs_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 694:     double[:] target_fobs_orb,
 695: 
 696:     double[:, :, :] dens,
 697:     double[:] mtot,
 698:     double[:] mrat,
 699:     double[:] redz,
 700:     double[:, :, :] redz_prime,
 701: 
 702:     double[:] redz_interp_grid,
 703:     double[:] dcom_interp_grid,
 704: 
 705:     # output
 706:     double[:, :, :, :] redz_final,
 707:     double[:, :, :, :] diff_num,
 708: ) except -1:
 709:     """Convert from binary volume-density (all separations) to binary number at particular frequencies.
 710:     """
 711: 
+712:     cdef int n_mtot = mtot.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_mtot, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 712, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 712, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 712, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+713:     cdef int n_mrat = mrat.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_mrat, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 713, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 713, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 713, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+714:     cdef int n_redz = redz.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_redz, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 714, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 714, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 714, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+715:     cdef int n_freq = target_fobs_orb.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_target_fobs_orb, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 715, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_size); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 715, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_1); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 715, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
+716:     cdef int n_interp = redz_interp_grid.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_redz_interp_grid, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 716, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_size); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 716, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 716, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_interp = __pyx_t_3;
 717: 
 718:     cdef int ii, jj, kk, ff, interp_idx, _kk
 719:     cdef double mt, mr, ftarget, target_frst_orb, sepa, rad_isco, frst_orb_isco, rzp
 720: 
 721: 
 722:     # ---- calculate dynamic binary numbers for all SAM grid bins
 723: 
+724:     for ii in range(n_mtot):
  __pyx_t_3 = __pyx_v_n_mtot;
  __pyx_t_4 = __pyx_t_3;
  for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
    __pyx_v_ii = __pyx_t_5;
+725:         mt = mtot[ii]
    __pyx_t_6 = __pyx_v_ii;
    __pyx_v_mt = (*((double *) ( /* dim=0 */ (__pyx_v_mtot.data + __pyx_t_6 * __pyx_v_mtot.strides[0]) )));
+726:         rad_isco = 3.0 * MY_SCHW * mt
    __pyx_v_rad_isco = ((3.0 * __pyx_v_8holodeck_4sams_11sam_cyutils_MY_SCHW) * __pyx_v_mt);
+727:         frst_orb_isco = kepler_freq_from_sepa(mt, rad_isco)
    __pyx_v_frst_orb_isco = __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_rad_isco);
 728: 
+729:         for jj in range(n_mrat):
    __pyx_t_7 = __pyx_v_n_mrat;
    __pyx_t_8 = __pyx_t_7;
    for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
      __pyx_v_jj = __pyx_t_9;
+730:             mr = mrat[jj]
      __pyx_t_6 = __pyx_v_jj;
      __pyx_v_mr = (*((double *) ( /* dim=0 */ (__pyx_v_mrat.data + __pyx_t_6 * __pyx_v_mrat.strides[0]) )));
 731: 
+732:             interp_idx = 0
      __pyx_v_interp_idx = 0;
+733:             for _kk in range(n_redz):
      __pyx_t_10 = __pyx_v_n_redz;
      __pyx_t_11 = __pyx_t_10;
      for (__pyx_t_12 = 0; __pyx_t_12 < __pyx_t_11; __pyx_t_12+=1) {
        __pyx_v__kk = __pyx_t_12;
+734:                 kk = n_redz - 1 - _kk
        __pyx_v_kk = ((__pyx_v_n_redz - 1) - __pyx_v__kk);
 735: 
 736:                 # redz_prime is -1 for systems past age of Universe
+737:                 rzp = <double>redz_prime[ii, jj, kk]
        __pyx_t_6 = __pyx_v_ii;
        __pyx_t_13 = __pyx_v_jj;
        __pyx_t_14 = __pyx_v_kk;
        __pyx_v_rzp = ((double)(*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_redz_prime.data + __pyx_t_6 * __pyx_v_redz_prime.strides[0]) ) + __pyx_t_13 * __pyx_v_redz_prime.strides[1]) ) + __pyx_t_14 * __pyx_v_redz_prime.strides[2]) ))));
+738:                 if rzp <= 0.0:
        __pyx_t_15 = ((__pyx_v_rzp <= 0.0) != 0);
        if (__pyx_t_15) {
/* … */
        }
+739:                     continue
          goto __pyx_L7_continue;
 740: 
+741:                 for ff in range(n_freq):
        __pyx_t_16 = __pyx_v_n_freq;
        __pyx_t_17 = __pyx_t_16;
        for (__pyx_t_18 = 0; __pyx_t_18 < __pyx_t_17; __pyx_t_18+=1) {
          __pyx_v_ff = __pyx_t_18;
+742:                     redz_final[ii, jj, kk, ff] = rzp
          __pyx_t_14 = __pyx_v_ii;
          __pyx_t_13 = __pyx_v_jj;
          __pyx_t_6 = __pyx_v_kk;
          __pyx_t_19 = __pyx_v_ff;
          *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_redz_final.data + __pyx_t_14 * __pyx_v_redz_final.strides[0]) ) + __pyx_t_13 * __pyx_v_redz_final.strides[1]) ) + __pyx_t_6 * __pyx_v_redz_final.strides[2]) ) + __pyx_t_19 * __pyx_v_redz_final.strides[3]) )) = __pyx_v_rzp;
 743: 
+744:                     ftarget = target_fobs_orb[ff]
          __pyx_t_19 = __pyx_v_ff;
          __pyx_v_ftarget = (*((double *) ( /* dim=0 */ (__pyx_v_target_fobs_orb.data + __pyx_t_19 * __pyx_v_target_fobs_orb.strides[0]) )));
 745:                     # find rest-frame orbital frequency and binary separation
+746:                     target_frst_orb = ftarget * (1.0 + rzp)
          __pyx_v_target_frst_orb = (__pyx_v_ftarget * (1.0 + __pyx_v_rzp));
 747:                     # if target frequency is above ISCO freq, then all future ones will be also, so: break
+748:                     if target_frst_orb > frst_orb_isco:
          __pyx_t_15 = ((__pyx_v_target_frst_orb > __pyx_v_frst_orb_isco) != 0);
          if (__pyx_t_15) {
/* … */
          }
+749:                         break
            goto __pyx_L11_break;
 750: 
 751:                     # get comoving distance
+752:                     interp_idx = while_while_decreasing(interp_idx, n_interp, rzp, redz_interp_grid)
          __pyx_v_interp_idx = __pyx_f_8holodeck_4sams_11sam_cyutils_while_while_decreasing(__pyx_v_interp_idx, __pyx_v_n_interp, __pyx_v_rzp, __pyx_v_redz_interp_grid);
+753:                     dcom = interp_at_index(interp_idx, rzp, redz_interp_grid, dcom_interp_grid)
          __pyx_v_dcom = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_interp_idx, __pyx_v_rzp, __pyx_v_redz_interp_grid, __pyx_v_dcom_interp_grid);
 754: 
 755:                     # calculate total hardening rate at this exact separation
+756:                     sepa = kepler_sepa_from_freq(mt, target_frst_orb)
          __pyx_v_sepa = __pyx_f_8holodeck_4sams_11sam_cyutils_kepler_sepa_from_freq(__pyx_v_mt, __pyx_v_target_frst_orb);
+757:                     dadt = hard_gw(mt, mr, sepa)
          __pyx_v_dadt = __pyx_f_8holodeck_4sams_11sam_cyutils_hard_gw(__pyx_v_mt, __pyx_v_mr, __pyx_v_sepa, 0);
 758: 
 759:                     # calculate residence/hardening time = f/[df/dt] = -(2/3) a/[da/dt]
+760:                     tres = - (2.0/3.0) * sepa / dadt
          __pyx_v_tres = (((-(2.0 / 3.0)) * __pyx_v_sepa) / __pyx_v_dadt);
 761: 
 762:                     # calculate number of binaries
+763:                     cosmo_fact = FOUR_PI_SPLC_OVER_MPC * (1.0 + rzp) * pow(dcom / MY_MPC, 2)
          __pyx_v_cosmo_fact = ((__pyx_v_8holodeck_4sams_11sam_cyutils_FOUR_PI_SPLC_OVER_MPC * (1.0 + __pyx_v_rzp)) * pow((__pyx_v_dcom / __pyx_v_8holodeck_4sams_11sam_cyutils_MY_MPC), 2.0));
+764:                     diff_num[ii, jj, kk, ff] = dens[ii, jj, kk] * tres * cosmo_fact
          __pyx_t_19 = __pyx_v_ii;
          __pyx_t_6 = __pyx_v_jj;
          __pyx_t_13 = __pyx_v_kk;
          __pyx_t_14 = __pyx_v_ii;
          __pyx_t_20 = __pyx_v_jj;
          __pyx_t_21 = __pyx_v_kk;
          __pyx_t_22 = __pyx_v_ff;
          *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_diff_num.data + __pyx_t_14 * __pyx_v_diff_num.strides[0]) ) + __pyx_t_20 * __pyx_v_diff_num.strides[1]) ) + __pyx_t_21 * __pyx_v_diff_num.strides[2]) ) + __pyx_t_22 * __pyx_v_diff_num.strides[3]) )) = (((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_dens.data + __pyx_t_19 * __pyx_v_dens.strides[0]) ) + __pyx_t_6 * __pyx_v_dens.strides[1]) ) + __pyx_t_13 * __pyx_v_dens.strides[2]) ))) * __pyx_v_tres) * __pyx_v_cosmo_fact);
        }
        __pyx_L11_break:;
        __pyx_L7_continue:;
      }
    }
  }
 765: 
+766:     return 0
  __pyx_r = 0;
  goto __pyx_L0;
 767: