Generated by Cython 0.29.35

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: 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_7cyutils_MY_NWTG = 6.6742999e-08;
+031: cdef double MY_SPLC = 29979245800.0
  __pyx_v_8holodeck_4sams_7cyutils_MY_SPLC = 29979245800.0;
+032: cdef double MY_MPC = 3.08567758e+24
  __pyx_v_8holodeck_4sams_7cyutils_MY_MPC = 3.08567758e+24;
+033: cdef double MY_MSOL = 1.988409870698051e+33
  __pyx_v_8holodeck_4sams_7cyutils_MY_MSOL = 1.988409870698051e+33;
+034: cdef double MY_YR = 31557600.0
  __pyx_v_8holodeck_4sams_7cyutils_MY_YR = 31557600.0;
+035: cdef double MY_SCHW = 1.4852320538237328e-28     #: Schwarzschild Constant  2*G/c^2  [cm]
  __pyx_v_8holodeck_4sams_7cyutils_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_7cyutils_MY_NWTG, 3.0)) / 5.0);
  __pyx_t_4 = pow(__pyx_v_8holodeck_4sams_7cyutils_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_7cyutils_GW_DADT_SEP_CONST = (__pyx_t_3 / __pyx_t_4);
 037: 
+038: cdef double MY_PC = MY_MPC / 1.0e6
  __pyx_v_8holodeck_4sams_7cyutils_MY_PC = (__pyx_v_8holodeck_4sams_7cyutils_MY_MPC / 1.0e6);
+039: cdef double MY_GYR = MY_YR * 1.0e9
  __pyx_v_8holodeck_4sams_7cyutils_MY_GYR = (__pyx_v_8holodeck_4sams_7cyutils_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_7cyutils_KEPLER_CONST_FREQ = ((1.0 / __pyx_t_4) * sqrt(__pyx_v_8holodeck_4sams_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_MY_SPLC);
  if (unlikely(__pyx_v_8holodeck_4sams_7cyutils_MY_MPC == 0)) {
    PyErr_SetString(PyExc_ZeroDivisionError, "float division");
    __PYX_ERR(0, 42, __pyx_L1_error)
  }
  __pyx_v_8holodeck_4sams_7cyutils_FOUR_PI_SPLC_OVER_MPC = (__pyx_t_3 / __pyx_v_8holodeck_4sams_7cyutils_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_7cyutils_1hard_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static double __pyx_f_8holodeck_4sams_7cyutils_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_7cyutils_1hard_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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.cyutils.hard_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_7cyutils_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_7cyutils_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_7cyutils_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.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_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_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_7cyutils_3integrate_differential_number_3dx1d(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_7cyutils_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    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`\n        NOTE: `mtot` should be passed as regular `mtot`, NOT log10(mtot)\n              `freq` should be passed as regular `freq`, NOT    ln(freq)\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_7cyutils_3integrate_differential_number_3dx1d = {"integrate_differential_number_3dx1d", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_3integrate_differential_number_3dx1d, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_7cyutils_2integrate_differential_number_3dx1d};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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.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_7cyutils_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_7cyutils_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.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_7cyutils_3integrate_differential_number_3dx1d, NULL, __pyx_n_s_holodeck_sams_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_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:     input  `dnum` is shaped (M, Q, Z, F)
 124:     input  `edges` must be (4,) of array_like of lengths:  M, Q, Z, F+1
 125:     output `numb` is shaped (M-1, Q-1, Z-1, F)
 126: 
 127:     Arguments
 128:     ---------
 129:     edges : (4,) array_like  w/ lengths M, Q, Z, F+1
 130:         Grid edges of `mtot`, `mrat`, `redz`, and `freq`
 131:         NOTE: `mtot` should be passed as regular `mtot`, NOT log10(mtot)
 132:               `freq` should be passed as regular `freq`, NOT    ln(freq)
 133:     dnum : (M, Q, Z, F)
 134:         Differential number of binaries, dN/[dlog10M dq qz dlnf] where 'N' is in units of dimensionless number.
 135: 
 136:     Returns
 137:     -------
 138:     numb : (M-1, Q-1, Z-1, F)
 139: 
 140:     """
 141: 
 142:     # each edge should have the same length as the corresponding dimension of `dnum`
+143:     shape = [len(ee) for ee in edges]
  { /* enter inner scope */
    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __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, 143, __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, 143, __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, 143, __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, 143, __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, 143, __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, 143, __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, 143, __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, 143, __pyx_L5_error)
      __pyx_t_5 = PyInt_FromSsize_t(__pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 143, __pyx_L5_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(0, 143, __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;
 144:     # except the last edge (freq), where `dnum` should be 1-shorter
+145:     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, 145, __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, 145, __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, 145, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+146:     assert np.shape(dnum) == tuple(shape)
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 146, __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, 146, __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, 146, __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, 146, __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, 146, __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, 146, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
    if (unlikely(!__pyx_t_7)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 146, __pyx_L1_error)
    }
  }
  #endif
 147:     # the number will be shaped as one-less the size of each dimension of `dnum`
+148:     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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __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, 148, __pyx_L11_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(0, 148, __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;
 149:     # except for the last dimension (freq) which is the same shape
+150:     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, 150, __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, 150, __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, 150, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 151: 
 152:     # prepare output array
+153:     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, 153, __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, 153, __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, 153, __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, 153, __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, 153, __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;
 154:     # Convert from  mtot => log10(mtot)  and  freq ==> ln(freq)
+155:     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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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, 155, __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;
 156:     # integrate
+157:     _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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __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, 157, __pyx_L1_error)
  __pyx_f_8holodeck_4sams_7cyutils__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;
 158: 
+159:     return numb
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_numb));
  __pyx_r = ((PyObject *)__pyx_v_numb);
  goto __pyx_L0;
 160: 
 161: 
 162: @cython.boundscheck(False)
 163: @cython.wraparound(False)
 164: @cython.nonecheck(False)
 165: @cython.cdivision(True)
+166: cdef void _integrate_differential_number_3dx1d(
static void __pyx_f_8holodeck_4sams_7cyutils__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.cyutils._integrate_differential_number_3dx1d", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_temp);
  __Pyx_RefNannyFinishContext();
}
 167:     double[:] log10_mtot,
 168:     double[:] mrat,
 169:     double[:] redz,
 170:     double[:] dln_freq,    # actually ln(freq)
 171:     double[:, :, :, :] dnum,
 172:     # output
 173:     double[:, :, :, :] numb
 174: ):
 175:     """Integrate the differential number of binaries over each grid bin into total numbers of binaries.
 176: 
 177:     Trapezoid used over first 3 dims (mtot, mrat, redz), and Riemann over 4th (freq).
 178:     See docstrings in `integrate_differential_number_3dx1d`
 179: 
 180:     """
 181: 
+182:     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, 182, __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, 182, __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, 182, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+183:     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, 183, __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, 183, __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, 183, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+184:     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, 184, __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, 184, __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, 184, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+185:     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, 185, __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, 185, __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, 185, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
 186: 
 187:     cdef int mm, qq, zz, ff, ii, jj, kk
 188:     cdef double dm, dmdq, dmdqdz
 189: 
+190:     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;
+191:         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]) ))));
 192: 
+193:         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;
+194:             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]) )))));
 195: 
+196:             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;
+197:                 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]) )))));
 198: 
 199:                 # iterate over output-shape of frequency
 200:                 # note that this is a Riemann sum, so input and output dimensions are the same size
+201:                 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;
+202:                     temp = 0.0
          __Pyx_INCREF(__pyx_float_0_0);
          __Pyx_XDECREF_SET(__pyx_v_temp, __pyx_float_0_0);
 203: 
 204:                     # iterate over each vertex of this cube, averaging the contributions
+205:                     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;
+206:                         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;
+207:                             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;
+208:                                 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, 208, __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, 208, __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;
              }
            }
          }
 209: 
+210:                     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, 210, __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, 210, __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, 210, __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, 210, __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, 210, __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, 210, __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;
        }
      }
    }
  }
 211: 
+212:     return
  goto __pyx_L0;
 213: 
 214: 
 215: # ==================================================================================================
 216: # ====    Fixed_Time_2pwl_SAM - Hardening Model    ====
 217: # ==================================================================================================
 218: 
 219: 
 220: # @cython.cdivision(True)
 221: # cpdef double _hard_func_2pwl(double norm, double xx, double gamma_inner, double gamma_outer):
 222: #     cdef double dadt = - norm * pow(1.0 + xx, -gamma_outer+gamma_inner) / pow(xx, gamma_inner-1)
 223: #     return dadt
 224: 
 225: 
 226: # @cython.cdivision(True)
 227: # cpdef double hard_func_2pwl_gw(
 228: #     double mtot, double mrat, double sepa,
 229: #     double norm, double rchar, double gamma_inner, double gamma_outer
 230: # ):
 231: #     cdef double dadt = _hard_func_2pwl(norm, sepa/rchar, gamma_inner, gamma_outer)
 232: #     dadt += hard_gw(mtot, mrat, sepa)
 233: #     return dadt
 234: 
 235: 
 236: @cython.cdivision(True)
+237: cdef double _hard_func_2pwl(double norm, double xx, double gamma_inner, double gamma_outer):
static double __pyx_f_8holodeck_4sams_7cyutils__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;
}
+238:     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)));
+239:     return dadt
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 240: 
 241: 
 242: @cython.cdivision(True)
+243: cdef double _hard_func_2pwl_gw(
static double __pyx_f_8holodeck_4sams_7cyutils__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;
}
 244:     double mtot, double mrat, double sepa,
 245:     double norm, double rchar, double gamma_inner, double gamma_outer
 246: ):
+247:     cdef double dadt = _hard_func_2pwl(norm, sepa/rchar, gamma_inner, gamma_outer)
  __pyx_v_dadt = __pyx_f_8holodeck_4sams_7cyutils__hard_func_2pwl(__pyx_v_norm, (__pyx_v_sepa / __pyx_v_rchar), __pyx_v_gamma_inner, __pyx_v_gamma_outer);
+248:     dadt += hard_gw(mtot, mrat, sepa)
  __pyx_v_dadt = (__pyx_v_dadt + __pyx_f_8holodeck_4sams_7cyutils_hard_gw(__pyx_v_mtot, __pyx_v_mrat, __pyx_v_sepa, 0));
+249:     return dadt
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 250: 
 251: 
 252: @cython.cdivision(True)
+253: cdef double[:] _hard_func_2pwl_gw_1darray(
static __Pyx_memviewslice __pyx_f_8holodeck_4sams_7cyutils__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.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;
}
 254:     double[:] mtot, double[:] mrat, double[:] sepa,
 255:     double[:] norm, double[:] rchar, double[:] gamma_inner, double[:] gamma_outer
 256: ):
 257:     cdef int ii
+258:     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, 258, __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, 258, __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, 258, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_size = __pyx_t_3;
+259:     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, 259, __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, 259, __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, 259, __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, 259, __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, 259, __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, 259, __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;
+260:     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;
+261:         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, 261, __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, 261, __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, 261, __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, 261, __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, 261, __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, 261, __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_7cyutils__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]) ))));
+262:         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, 262, __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, 262, __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, 262, __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, 262, __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_7cyutils_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);
  }
 263: 
+264:     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, 264, __pyx_L1_error)
  __pyx_r = __pyx_t_16;
  __pyx_t_16.memview = NULL;
  __pyx_t_16.data = NULL;
  goto __pyx_L0;
 265: 
 266: 
+267: def hard_func_2pwl_gw(
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_5hard_func_2pwl_gw(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_7cyutils_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_7cyutils_5hard_func_2pwl_gw = {"hard_func_2pwl_gw", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_5hard_func_2pwl_gw, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_7cyutils_4hard_func_2pwl_gw};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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, 267, __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, 267, __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, 267, __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, 267, __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, 267, __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, 267, __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, 267, __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, 267, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.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_7cyutils_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_7cyutils_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.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, 267, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__25);
  __Pyx_GIVEREF(__pyx_tuple__25);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_5hard_func_2pwl_gw, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __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, 267, __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_cyutils_pyx, __pyx_n_s_hard_func_2pwl_gw, 267, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__26)) __PYX_ERR(0, 267, __pyx_L1_error)
 268:     mtot, mrat, sepa,
 269:     norm, rchar, gamma_inner, gamma_outer
 270: ):
 271:     """
 272: 
 273:     NOTE: this function will be somewhat slow, because of the explicit broadcasting!
 274: 
 275:     """
+276:     args = mtot, mrat, sepa, norm, rchar, gamma_inner, gamma_outer
  __pyx_t_1 = PyTuple_New(7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __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;
+277:     args = np.broadcast_arrays(*args)
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __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, 277, __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, 277, __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, 277, __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;
+278:     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, 278, __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, 278, __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;
+279:     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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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, 279, __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;
+280:     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, 280, __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, 280, __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, 280, __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, 280, __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, 280, __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, 280, __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, 280, __pyx_L1_error)
  __pyx_t_18 = __pyx_f_8holodeck_4sams_7cyutils__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, 280, __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, 280, __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;
+281:     dadt = np.array(dadt).reshape(shape)
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_np); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 281, __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, 281, __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, 281, __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, 281, __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, 281, __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;
+282:     return dadt
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(__pyx_v_dadt);
  __pyx_r = __pyx_v_dadt;
  goto __pyx_L0;
 283: 
 284: 
+285: def find_2pwl_hardening_norm(time, mtot, mrat, sepa_init, rchar, gamma_inner, gamma_outer, nsteps):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_7find_2pwl_hardening_norm(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_7cyutils_7find_2pwl_hardening_norm = {"find_2pwl_hardening_norm", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_7find_2pwl_hardening_norm, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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, 285, __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, 285, __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, 285, __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, 285, __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, 285, __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, 285, __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, 285, __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, 285, __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, 285, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.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_7cyutils_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_7cyutils_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_7cyutils_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.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, 285, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__27);
  __Pyx_GIVEREF(__pyx_tuple__27);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_7find_2pwl_hardening_norm, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 285, __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, 285, __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_cyutils_pyx, __pyx_n_s_find_2pwl_hardening_norm, 285, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__28)) __PYX_ERR(0, 285, __pyx_L1_error)
+286:     assert np.ndim(time) == 0
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 286, __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, 286, __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, 286, __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, 286, __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, 286, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 286, __pyx_L1_error)
    }
  }
  #endif
+287:     assert np.ndim(mtot) == 1
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 287, __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, 287, __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, 287, __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, 287, __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, 287, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 287, __pyx_L1_error)
    }
  }
  #endif
+288:     assert np.shape(mtot) == np.shape(mrat)
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 288, __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, 288, __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, 288, __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, 288, __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, 288, __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, 288, __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, 288, __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, 288, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    if (unlikely(!__pyx_t_4)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 288, __pyx_L1_error)
    }
  }
  #endif
 289: 
+290:     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, 290, __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, 290, __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, 290, __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, 290, __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, 290, __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, 290, __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;
 291: 
 292:     cdef lifetime_2pwl_params args
+293:     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, 293, __pyx_L1_error)
  __pyx_v_args.target_time = __pyx_t_7;
+294:     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, 294, __pyx_L1_error)
  __pyx_v_args.sepa_init = __pyx_t_7;
+295:     args.rchar = rchar
  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_v_rchar); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 295, __pyx_L1_error)
  __pyx_v_args.rchar = __pyx_t_7;
+296:     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, 296, __pyx_L1_error)
  __pyx_v_args.gamma_inner = __pyx_t_7;
+297:     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, 297, __pyx_L1_error)
  __pyx_v_args.gamma_outer = __pyx_t_7;
+298:     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, 298, __pyx_L1_error)
  __pyx_v_args.nsteps = __pyx_t_8;
 299: 
+300:     _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, 300, __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, 300, __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, 300, __pyx_L1_error)
  __pyx_f_8holodeck_4sams_7cyutils__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;
 301: 
+302:     return norm_log10
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_norm_log10));
  __pyx_r = ((PyObject *)__pyx_v_norm_log10);
  goto __pyx_L0;
 303: 
 304: 
+305: ctypedef struct lifetime_2pwl_params:
struct __pyx_t_8holodeck_4sams_7cyutils_lifetime_2pwl_params {
  double target_time;
  double mt;
  double mr;
  double sepa_init;
  double rchar;
  double gamma_inner;
  double gamma_outer;
  int nsteps;
};
 306:     double target_time
 307:     double mt
 308:     double mr
 309:     double sepa_init
 310:     double rchar
 311:     double gamma_inner
 312:     double gamma_outer
 313:     int nsteps
 314: 
 315: 
 316: @cython.boundscheck(False)
 317: @cython.wraparound(False)
 318: @cython.nonecheck(False)
 319: @cython.cdivision(True)
+320: cdef void _get_hardening_norm_2pwl(
static void __pyx_f_8holodeck_4sams_7cyutils__get_hardening_norm_2pwl(__Pyx_memviewslice __pyx_v_mtot, __Pyx_memviewslice __pyx_v_mrat, __pyx_t_8holodeck_4sams_7cyutils_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.cyutils._get_hardening_norm_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
}
 321:     double[:] mtot,
 322:     double[:] mrat,
 323:     lifetime_2pwl_params args,
 324:     # output
 325:     double[:] norm_log10,
 326: ):
 327: 
+328:     cdef double XTOL = 1e-3
  __pyx_v_XTOL = 1e-3;
+329:     cdef double RTOL = 1e-5
  __pyx_v_RTOL = 1e-5;
+330:     cdef int MITR = 100    # note: the function doesn't return an error on failure, it still returns last try
  __pyx_v_MITR = 0x64;
+331:     cdef double NORM_LOG10_LO = -20.0
  __pyx_v_NORM_LOG10_LO = -20.0;
+332:     cdef double NORM_LOG10_HI = +20.0
  __pyx_v_NORM_LOG10_HI = 20.0;
 333: 
+334:     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, 334, __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, 334, __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, 334, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_num = __pyx_t_3;
+335:     assert mtot.size == mrat.size
  #ifndef CYTHON_WITHOUT_ASSERTIONS
  if (unlikely(!Py_OptimizeFlag)) {
    __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, 335, __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, 335, __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, 335, __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, 335, __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, 335, __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, 335, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    if (unlikely(!__pyx_t_5)) {
      PyErr_SetNone(PyExc_AssertionError);
      __PYX_ERR(0, 335, __pyx_L1_error)
    }
  }
  #endif
 336:     cdef double time
 337: 
 338:     cdef int ii
+339:     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;
+340:         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]) )));
+341:         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]) )));
+342:         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_7cyutils_get_binary_lifetime_2pwl, __pyx_v_NORM_LOG10_LO, __pyx_v_NORM_LOG10_HI, ((__pyx_t_8holodeck_4sams_7cyutils_lifetime_2pwl_params *)(&__pyx_v_args)), __pyx_v_XTOL, __pyx_v_RTOL, __pyx_v_MITR, NULL);
  }
 343:             get_binary_lifetime_2pwl, NORM_LOG10_LO, NORM_LOG10_HI,
 344:             <lifetime_2pwl_params *> &args, XTOL, RTOL, MITR, NULL
 345:         )
 346:         # time = get_binary_lifetime_2pwl(norm_log10[ii], <lifetime_2pwl_params *> &args)
 347:         # total_time[ii] = time + args.target_time
 348: 
+349:     return
  goto __pyx_L0;
 350: 
 351: 
 352: @cython.boundscheck(False)
 353: @cython.wraparound(False)
 354: @cython.nonecheck(False)
 355: @cython.cdivision(True)
+356: cdef double get_binary_lifetime_2pwl(double norm_log10, void *args):
static double __pyx_f_8holodeck_4sams_7cyutils_get_binary_lifetime_2pwl(double __pyx_v_norm_log10, void *__pyx_v_args) {
  __pyx_t_8holodeck_4sams_7cyutils_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;
}
+357:     cdef lifetime_2pwl_params *pars = <lifetime_2pwl_params *> args
  __pyx_v_pars = ((__pyx_t_8holodeck_4sams_7cyutils_lifetime_2pwl_params *)__pyx_v_args);
 358: 
+359:     cdef double risco_log10 = log10(3.0 * MY_SCHW * pars.mt)
  __pyx_v_risco_log10 = log10(((3.0 * __pyx_v_8holodeck_4sams_7cyutils_MY_SCHW) * __pyx_v_pars->mt));
+360:     cdef double sepa_log10 = log10(pars.sepa_init)
  __pyx_v_sepa_log10 = log10(__pyx_v_pars->sepa_init);
+361:     cdef double norm = pow(10.0, norm_log10)
  __pyx_v_norm = pow(10.0, __pyx_v_norm_log10);
 362: 
 363:     # step-size, in log10-space, to go from sepa_init to ISCO
+364:     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));
+365:     cdef double time = 0.0
  __pyx_v_time = 0.0;
 366: 
 367:     cdef int ii
 368:     cdef double sepa_right, dadt_right, dt
 369: 
+370:     cdef double sepa_left = pow(10.0, sepa_log10)
  __pyx_v_sepa_left = pow(10.0, __pyx_v_sepa_log10);
+371:     cdef double dadt_left = _hard_func_2pwl_gw(
  __pyx_v_dadt_left = __pyx_f_8holodeck_4sams_7cyutils__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);
 372:         pars.mt, pars.mr, sepa_left,
 373:         norm, pars.rchar, pars.gamma_inner, pars.gamma_outer
 374:     )
 375: 
+376:     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;
+377:         sepa_log10 -= dx
    __pyx_v_sepa_log10 = (__pyx_v_sepa_log10 - __pyx_v_dx);
+378:         sepa_right = pow(10.0, sepa_log10)
    __pyx_v_sepa_right = pow(10.0, __pyx_v_sepa_log10);
 379: 
 380:         # Get total hardening rate at k+1 edge
+381:         dadt_right = _hard_func_2pwl_gw(
    __pyx_v_dadt_right = __pyx_f_8holodeck_4sams_7cyutils__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);
 382:             pars.mt, pars.mr, sepa_right,
 383:             norm, pars.rchar, pars.gamma_inner, pars.gamma_outer
 384:         )
 385: 
 386:         # Find time to move from left to right
+387:         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));
+388:         time += dt
    __pyx_v_time = (__pyx_v_time + __pyx_v_dt);
 389: 
+390:         sepa_left = sepa_right
    __pyx_v_sepa_left = __pyx_v_sepa_right;
+391:         dadt_left = dadt_right
    __pyx_v_dadt_left = __pyx_v_dadt_right;
  }
 392: 
+393:     time = time - pars.target_time
  __pyx_v_time = (__pyx_v_time - __pyx_v_pars->target_time);
+394:     return time
  __pyx_r = __pyx_v_time;
  goto __pyx_L0;
 395: 
 396: 
+397: 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_7cyutils_9integrate_binary_evolution_2pwl(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_7cyutils_9integrate_binary_evolution_2pwl = {"integrate_binary_evolution_2pwl", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_9integrate_binary_evolution_2pwl, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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, 397, __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, 397, __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, 397, __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, 397, __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, 397, __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, 397, __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, 397, __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, 397, __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, 397, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.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_7cyutils_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_7cyutils_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_7cyutils_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.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, 397, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__29);
  __Pyx_GIVEREF(__pyx_tuple__29);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_9integrate_binary_evolution_2pwl, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 397, __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, 397, __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_cyutils_pyx, __pyx_n_s_integrate_binary_evolution_2pwl, 397, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__30)) __PYX_ERR(0, 397, __pyx_L1_error)
 398:     cdef lifetime_2pwl_params args
+399:     args.mt = mtot
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_mtot); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 399, __pyx_L1_error)
  __pyx_v_args.mt = __pyx_t_1;
+400:     args.mr = mrat
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_mrat); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 400, __pyx_L1_error)
  __pyx_v_args.mr = __pyx_t_1;
+401:     args.target_time = 0.0
  __pyx_v_args.target_time = 0.0;
+402:     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, 402, __pyx_L1_error)
  __pyx_v_args.sepa_init = __pyx_t_1;
+403:     args.rchar = rchar
  __pyx_t_1 = __pyx_PyFloat_AsDouble(__pyx_v_rchar); if (unlikely((__pyx_t_1 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 403, __pyx_L1_error)
  __pyx_v_args.rchar = __pyx_t_1;
+404:     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, 404, __pyx_L1_error)
  __pyx_v_args.gamma_inner = __pyx_t_1;
+405:     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, 405, __pyx_L1_error)
  __pyx_v_args.gamma_outer = __pyx_t_1;
+406:     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, 406, __pyx_L1_error)
  __pyx_v_args.nsteps = __pyx_t_2;
 407: 
+408:     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, 408, __pyx_L1_error)
  __pyx_v_time = __pyx_f_8holodeck_4sams_7cyutils_get_binary_lifetime_2pwl(__pyx_t_1, ((__pyx_t_8holodeck_4sams_7cyutils_lifetime_2pwl_params *)(&__pyx_v_args)));
+409:     return time
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_time); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 409, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_r = __pyx_t_3;
  __pyx_t_3 = 0;
  goto __pyx_L0;
 410: 
 411: 
 412: # ==================================================================================================
 413: # ====    Dynamic Binary Number - calculate number of binaries at each frequency    ====
 414: # ==================================================================================================
 415: 
 416: 
+417: def dynamic_binary_number_at_fobs(fobs_orb, sam, hard, cosmo):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_11dynamic_binary_number_at_fobs(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static PyMethodDef __pyx_mdef_8holodeck_4sams_7cyutils_11dynamic_binary_number_at_fobs = {"dynamic_binary_number_at_fobs", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_11dynamic_binary_number_at_fobs, METH_VARARGS|METH_KEYWORDS, 0};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_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, 417, __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, 417, __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, 417, __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, 417, __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, 417, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.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_7cyutils_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_7cyutils_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.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, 417, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__31);
  __Pyx_GIVEREF(__pyx_tuple__31);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_11dynamic_binary_number_at_fobs, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 417, __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, 417, __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_cyutils_pyx, __pyx_n_s_dynamic_binary_number_at_fobs, 417, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__32)) __PYX_ERR(0, 417, __pyx_L1_error)
 418: 
+419:     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, 419, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_v_dens = __pyx_t_1;
  __pyx_t_1 = 0;
 420: 
+421:     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, 421, __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, 421, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 421, __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, 421, __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;
+422:     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, 422, __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, 422, __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, 422, __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, 422, __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, 422, __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;
+423:     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, 423, __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, 423, __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, 423, __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, 423, __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, 423, __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, 423, __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;
 424: 
 425:     # ---- Fixed_Time_2pwl_SAM
 426: 
+427:     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, 427, __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, 427, __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, 427, __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, 427, __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;
  }
+428:         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, 428, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_v_gmt_time = __pyx_t_3;
    __pyx_t_3 = 0;
 429:         # if `sam` is using galaxy merger rate (GMR), then `gmt_time` will be `None`
+430:         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) {
/* … */
    }
+431:             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, 431, __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, 431, __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, 431, __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;
+432:             gmt_time = np.zeros(sam.shape)
      __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 432, __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, 432, __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, 432, __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, 432, __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;
 433: 
+434:         _dynamic_binary_number_at_fobs_2pwl(
    __pyx_t_26 = __pyx_f_8holodeck_4sams_7cyutils__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, 434, __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;
+435:             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, 435, __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, 435, __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, 435, __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, 435, __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, 435, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+436:             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, 436, __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, 436, __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, 436, __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, 436, __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, 436, __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, 436, __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, 436, __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, 436, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+437:             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, 437, __pyx_L1_error)
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mtot); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 437, __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, 437, __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, 437, __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, 437, __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, 437, __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, 437, __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, 437, __pyx_L1_error)
+438:             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, 438, __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, 438, __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, 438, __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, 438, __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, 438, __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, 438, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
 439:             # output:
+440:             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, 440, __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, 440, __pyx_L1_error)
 441:         )
 442: 
 443:     # ---- Hard_GW
 444: 
+445:     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, 445, __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, 445, __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, 445, __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, 445, __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, 445, __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, 445, __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, 445, __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, 445, __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;
  }
+446:         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, 446, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_3);
    __pyx_v_redz_prime = __pyx_t_3;
    __pyx_t_3 = 0;
 447:         # if `sam` is using galaxy merger rate (GMR), then `redz_prime` will be `None`
+448:         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) {
/* … */
    }
+449:             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, 449, __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, 449, __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, 449, __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;
+450:             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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __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, 450, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_slice_);
  __Pyx_GIVEREF(__pyx_slice_);
 451: 
+452:         _dynamic_binary_number_at_fobs_gw(
    __pyx_t_26 = __pyx_f_8holodeck_4sams_7cyutils__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, 452, __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;
+453:             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, 453, __pyx_L1_error)
+454:             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, 454, __pyx_L1_error)
    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_sam, __pyx_n_s_mtot); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 454, __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, 454, __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, 454, __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, 454, __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, 454, __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, 454, __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, 454, __pyx_L1_error)
+455:             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, 455, __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, 455, __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, 455, __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, 455, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 456:             # output:
+457:             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, 457, __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, 457, __pyx_L1_error)
 458:         )
 459: 
 460:     # ---- OTHER
 461: 
 462:     else:
+463:         raise ValueError(f"Unexpected `hard` value {hard}!")
  /*else*/ {
    __pyx_t_2 = PyTuple_New(3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 463, __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, 463, __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, 463, __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, 463, __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, 463, __pyx_L1_error)
  }
  __pyx_L3:;
 464: 
+465:     return redz_final, diff_num
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 465, __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;
 466: 
 467: @cython.boundscheck(False)
 468: @cython.wraparound(False)
 469: @cython.nonecheck(False)
 470: @cython.cdivision(True)
+471: cdef int _dynamic_binary_number_at_fobs_2pwl(
static int __pyx_f_8holodeck_4sams_7cyutils__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.cyutils._dynamic_binary_number_at_fobs_2pwl", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 472:     double[:] target_fobs_orb,
 473:     double sepa_init,
 474:     int num_steps,
 475: 
 476:     double[:, :] hard_norm,
 477:     double hard_rchar,
 478:     double hard_gamma_inner,
 479:     double hard_gamma_outer,
 480: 
 481:     double[:, :, :] dens,
 482:     double[:] mtot,
 483:     double[:] mrat,
 484:     double[:] redz,
 485:     double[:, :, :] gmt_time,
 486: 
 487:     double[:] redz_interp_grid,
 488:     double[:] dcom_interp_grid,
 489:     double[:] tage_interp_grid,
 490: 
 491:     # output
 492:     double[:, :, :, :] redz_final,
 493:     double[:, :, :, :] diff_num,
 494: ) except -1:
 495:     """Convert from binary volume-density (all separations) to binary number at particular frequencies.
 496:     """
 497: 
+498:     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, 498, __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, 498, __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, 498, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+499:     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, 499, __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, 499, __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, 499, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+500:     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, 500, __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, 500, __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, 500, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+501:     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, 501, __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, 501, __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, 501, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
+502:     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, 502, __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, 502, __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, 502, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_interp = __pyx_t_3;
+503:     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]) )));
+504:     cdef double sepa_init_log10 = log10(sepa_init)
  __pyx_v_sepa_init_log10 = log10(__pyx_v_sepa_init);
 505: 
 506:     cdef int ii, jj, kk, ff, step, interp_left_idx, interp_right_idx, new_interp_idx
 507:     cdef double mt, mr, norm, risco, dx, new_redz, gmt, ftarget, target_frst_orb
 508:     cdef double sepa_log10, sepa, sepa_left, sepa_right, dadt_left, dadt_right
 509:     cdef double time_evo, redz_left, redz_right, time_left, time_right, new_time
 510:     cdef double frst_orb_left, fobs_orb_left, frst_orb_right, fobs_orb_right
 511: 
 512:     # ---- Calculate ages corresponding to SAM `redz` grid
 513: 
+514:     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)))));
+515:     ii = 0
  __pyx_v_ii = 0;
 516:     cdef int rev
+517:     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;
 518:         # iterate in reverse order to match with `redz_interp_grid` which is decreasing
+519:         rev = n_redz - 1 - kk
    __pyx_v_rev = ((__pyx_v_n_redz - 1) - __pyx_v_kk);
 520:         # get to the right index of the interpolation-grid
+521:         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;
+522:             ii += 1
      __pyx_v_ii = (__pyx_v_ii + 1);
    }
 523: 
 524:         # interpolate
+525:         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);
  }
 526: 
 527:     # ---- calculate dynamic binary numbers for all SAM grid bins
 528: 
+529:     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;
+530:         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]) )));
 531: 
 532:         # Determine separation step-size, in log10-space, to integrate from sepa_init to ISCO
+533:         risco = 3.0 * MY_SCHW * mt     # ISCO is 3x combined schwarzschild radius
    __pyx_v_risco = ((3.0 * __pyx_v_8holodeck_4sams_7cyutils_MY_SCHW) * __pyx_v_mt);
+534:         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));
 535: 
+536:         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;
+537:             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]) )));
 538: 
 539:             # Binary evolution is determined by M and q only
 540:             # so integration is started for each of these bins
+541:             sepa_log10 = sepa_init_log10                # set initial separation to initial value
      __pyx_v_sepa_log10 = __pyx_v_sepa_init_log10;
+542:             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]) )));
 543: 
 544:             # Get total hardening rate at left-most edge
+545:             sepa_left = pow(10.0, sepa_log10)
      __pyx_v_sepa_left = pow(10.0, __pyx_v_sepa_log10);
+546:             dadt_left = _hard_func_2pwl_gw(
      __pyx_v_dadt_left = __pyx_f_8holodeck_4sams_7cyutils__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);
 547:                 mt, mr, sepa_left,
 548:                 norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 549:             )
 550: 
 551:             # get rest-frame orbital frequency of binary at left edge
+552:             frst_orb_left = kepler_freq_from_sepa(mt, sepa_left)
      __pyx_v_frst_orb_left = __pyx_f_8holodeck_4sams_7cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_sepa_left);
 553: 
 554:             # ---- Integrate of `num_steps` discrete intervals in binary separation from large to small
 555: 
+556:             time_evo = 0.0                  # track total binary evolution time
      __pyx_v_time_evo = 0.0;
+557:             interp_left_idx = 0                 # interpolation index, will be updated in each step
      __pyx_v_interp_left_idx = 0;
+558:             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;
 559:                 # Increment the current separation
+560:                 sepa_log10 -= dx
        __pyx_v_sepa_log10 = (__pyx_v_sepa_log10 - __pyx_v_dx);
+561:                 sepa_right = pow(10.0, sepa_log10)
        __pyx_v_sepa_right = pow(10.0, __pyx_v_sepa_log10);
+562:                 frst_orb_right = kepler_freq_from_sepa(mt, sepa_right)
        __pyx_v_frst_orb_right = __pyx_f_8holodeck_4sams_7cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_sepa_right);
 563: 
 564:                 # Get total hardening rate at the right-edge of this step (left-edge already obtained)
+565:                 dadt_right = _hard_func_2pwl_gw(
        __pyx_v_dadt_right = __pyx_f_8holodeck_4sams_7cyutils__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);
 566:                     mt, mr, sepa_right,
 567:                     norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 568:                 )
 569: 
 570:                 # Find time to move from left- to right- edges:  dt = da / (da/dt)
+571:                 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));
+572:                 time_evo += dt
        __pyx_v_time_evo = (__pyx_v_time_evo + __pyx_v_dt);
 573: 
 574:                 # ---- Iterate over starting redshift bins
 575: 
+576:                 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;
 577:                     # get the total time from each starting redshift, plus GMT time, plus evolution time to this step
+578:                     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]) )));
+579:                     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]));
 580:                     # also get the evolution-time to the left edge
+581:                     time_left = time_right - dt
          __pyx_v_time_left = (__pyx_v_time_right - __pyx_v_dt);
 582: 
 583:                     # if we pass the age of the universe, this binary has stalled, no further redshifts will work
 584:                     # NOTE: if `gmt_time` decreases faster than redshift bins increase the universe age,
 585:                     #       then systems in later `redz` bins may no longer stall, so we still need to calculate them
 586:                     #       i.e. we can NOT use a `break` statement here
+587:                     if time_left > age_universe:
          __pyx_t_7 = ((__pyx_v_time_left > __pyx_v_age_universe) != 0);
          if (__pyx_t_7) {
/* … */
          }
+588:                         continue
            goto __pyx_L15_continue;
 589: 
 590:                     # find the redshift bins corresponding to left- and right- side of step
 591:                     # left edge
+592:                     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_7cyutils_while_while_increasing(__pyx_v_interp_left_idx, __pyx_v_n_interp, __pyx_v_time_left, __pyx_v_tage_interp_grid);
 593: 
+594:                     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);
 595: 
 596:                     # double check that left-edge is within age of Universe (should rarely if ever be a problem
 597:                     # but possible due to rounding/interpolation errors
+598:                     if redz_left < 0.0:
          __pyx_t_7 = ((__pyx_v_redz_left < 0.0) != 0);
          if (__pyx_t_7) {
/* … */
          }
+599:                         continue
            goto __pyx_L15_continue;
 600: 
 601:                     # find right-edge starting from left edge, i.e. `interp_left_idx` (`interp_left_idx` is not a typo!)
+602:                     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_7cyutils_while_while_increasing(__pyx_v_interp_left_idx, __pyx_v_n_interp, __pyx_v_time_right, __pyx_v_tage_interp_grid);
 603:                     # NOTE: because `time_right` can be larger than age of universe, it can exceed `tage_interp_grid`
 604:                     #       in this case `interp_right_idx=n_interp-2`, and the `interp_at_index` function can still
 605:                     #       be used to extrapolate to further out values, which will likely be negative
 606: 
+607:                     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);
 608:                     # NOTE: at this point `redz_right` could be negative, even though `redz_left` is definitely not
+609:                     if redz_right < 0.0:
          __pyx_t_7 = ((__pyx_v_redz_right < 0.0) != 0);
          if (__pyx_t_7) {
/* … */
          }
+610:                         redz_right = 0.0
            __pyx_v_redz_right = 0.0;
 611: 
 612:                     # convert to frequencies
+613:                     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));
+614:                     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));
 615: 
 616:                     # ---- Iterate over all target frequencies
 617: 
 618:                     # NOTE: there should be a more efficient way to do this.
 619:                     #       Tried a different implementation in `_dynamic_binary_number_at_fobs_1`, but not working
 620:                     #       some of the frequency bins seem to be getting skipped in that version.
 621: 
+622:                     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;
+623:                         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]) )));
 624: 
 625:                         # If the integration-step does NOT bracket the target frequency, continue to next frequency
+626:                         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) {
/* … */
            }
+627:                             continue
              goto __pyx_L20_continue;
 628: 
 629:                         # ------------------------------------------------------
 630:                         # ---- TARGET FOUND ----
 631: 
 632:                         # At this point in the code, this target frequency is inbetween the left- and right- edges
 633:                         # of the integration step, so we can interpolate the evolution to exactly this frequency,
 634:                         # and perform the actual dynamic_binary_number calculation
 635: 
+636:                         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);
 637: 
 638:                         # `time_right` can be after age of Universe, make sure interpolated value is not
 639:                         #    if it is, then all higher-frequencies will also, so break out of target-frequency loop
+640:                         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) {
/* … */
            }
+641:                             break
              goto __pyx_L21_break;
 642: 
 643:                         # find index in interpolation grid for this exact time
+644:                         new_interp_idx = interp_left_idx      # start from left-step edge
            __pyx_v_new_interp_idx = __pyx_v_interp_left_idx;
+645:                         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_7cyutils_while_while_increasing(__pyx_v_new_interp_idx, __pyx_v_n_interp, __pyx_v_new_time, __pyx_v_tage_interp_grid);
 646: 
 647:                         # get redshift
+648:                         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);
 649:                         # get comoving distance
+650:                         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);
 651: 
 652:                         # Store redshift
+653:                         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;
 654: 
 655:                         # find rest-frame orbital frequency and binary separation
+656:                         target_frst_orb = ftarget * (1.0 + new_redz)
            __pyx_v_target_frst_orb = (__pyx_v_ftarget * (1.0 + __pyx_v_new_redz));
+657:                         sepa = kepler_sepa_from_freq(mt, target_frst_orb)
            __pyx_v_sepa = __pyx_f_8holodeck_4sams_7cyutils_kepler_sepa_from_freq(__pyx_v_mt, __pyx_v_target_frst_orb);
 658: 
 659:                         # calculate total hardening rate at this exact separation
+660:                         dadt = _hard_func_2pwl_gw(
            __pyx_v_dadt = __pyx_f_8holodeck_4sams_7cyutils__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);
 661:                             mt, mr, sepa,
 662:                             norm, hard_rchar, hard_gamma_inner, hard_gamma_outer
 663:                         )
 664: 
 665:                         # calculate residence/hardening time = f/[df/dt] = -(2/3) a/[da/dt]
+666:                         tres = - (2.0/3.0) * sepa / dadt
            __pyx_v_tres = (((-(2.0 / 3.0)) * __pyx_v_sepa) / __pyx_v_dadt);
 667: 
 668:                         # calculate number of binaries
+669:                         cosmo_fact = FOUR_PI_SPLC_OVER_MPC * (1.0 + new_redz) * pow(dcom / MY_MPC, 2)
            __pyx_v_cosmo_fact = ((__pyx_v_8holodeck_4sams_7cyutils_FOUR_PI_SPLC_OVER_MPC * (1.0 + __pyx_v_new_redz)) * pow((__pyx_v_dcom / __pyx_v_8holodeck_4sams_7cyutils_MY_MPC), 2.0));
+670:                         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:;
        }
 671: 
 672:                         # ----------------------
 673:                         # ------------------------------------------------------
 674: 
 675:                 # update new left edge
+676:                 dadt_left = dadt_right
        __pyx_v_dadt_left = __pyx_v_dadt_right;
+677:                 sepa_left = sepa_right
        __pyx_v_sepa_left = __pyx_v_sepa_right;
+678:                 frst_orb_left = frst_orb_right
        __pyx_v_frst_orb_left = __pyx_v_frst_orb_right;
      }
    }
  }
 679:                 # note that we _cannot_ do this for redz or freqs because the redshift _bin_ is changing
 680: 
+681:     free(redz_age)
  free(__pyx_v_redz_age);
 682: 
+683:     return 0
  __pyx_r = 0;
  goto __pyx_L0;
 684: 
 685: 
 686: @cython.boundscheck(False)
 687: @cython.wraparound(False)
 688: @cython.nonecheck(False)
 689: @cython.cdivision(True)
+690: cdef int _dynamic_binary_number_at_fobs_gw(
static int __pyx_f_8holodeck_4sams_7cyutils__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.cyutils._dynamic_binary_number_at_fobs_gw", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 691:     double[:] target_fobs_orb,
 692: 
 693:     double[:, :, :] dens,
 694:     double[:] mtot,
 695:     double[:] mrat,
 696:     double[:] redz,
 697:     double[:, :, :] redz_prime,
 698: 
 699:     double[:] redz_interp_grid,
 700:     double[:] dcom_interp_grid,
 701: 
 702:     # output
 703:     double[:, :, :, :] redz_final,
 704:     double[:, :, :, :] diff_num,
 705: ) except -1:
 706:     """Convert from binary volume-density (all separations) to binary number at particular frequencies.
 707:     """
 708: 
+709:     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, 709, __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, 709, __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, 709, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_mtot = __pyx_t_3;
+710:     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, 710, __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, 710, __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, 710, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_mrat = __pyx_t_3;
+711:     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, 711, __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, 711, __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, 711, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_redz = __pyx_t_3;
+712:     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, 712, __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, 712, __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, 712, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_freq = __pyx_t_3;
+713:     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, 713, __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, 713, __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, 713, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_interp = __pyx_t_3;
 714: 
 715:     cdef int ii, jj, kk, ff, interp_idx, _kk
 716:     cdef double mt, mr, ftarget, target_frst_orb, sepa, rad_isco, frst_orb_isco, rzp
 717: 
 718: 
 719:     # ---- calculate dynamic binary numbers for all SAM grid bins
 720: 
+721:     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;
+722:         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]) )));
+723:         rad_isco = 3.0 * MY_SCHW * mt
    __pyx_v_rad_isco = ((3.0 * __pyx_v_8holodeck_4sams_7cyutils_MY_SCHW) * __pyx_v_mt);
+724:         frst_orb_isco = kepler_freq_from_sepa(mt, rad_isco)
    __pyx_v_frst_orb_isco = __pyx_f_8holodeck_4sams_7cyutils_kepler_freq_from_sepa(__pyx_v_mt, __pyx_v_rad_isco);
 725: 
+726:         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;
+727:             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]) )));
 728: 
+729:             interp_idx = 0
      __pyx_v_interp_idx = 0;
+730:             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;
+731:                 kk = n_redz - 1 - _kk
        __pyx_v_kk = ((__pyx_v_n_redz - 1) - __pyx_v__kk);
 732: 
 733:                 # redz_prime is -1 for systems past age of Universe
+734:                 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]) ))));
+735:                 if rzp <= 0.0:
        __pyx_t_15 = ((__pyx_v_rzp <= 0.0) != 0);
        if (__pyx_t_15) {
/* … */
        }
+736:                     continue
          goto __pyx_L7_continue;
 737: 
+738:                 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;
+739:                     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;
 740: 
+741:                     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]) )));
 742:                     # find rest-frame orbital frequency and binary separation
+743:                     target_frst_orb = ftarget * (1.0 + rzp)
          __pyx_v_target_frst_orb = (__pyx_v_ftarget * (1.0 + __pyx_v_rzp));
 744:                     # if target frequency is above ISCO freq, then all future ones will be also, so: break
+745:                     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) {
/* … */
          }
+746:                         break
            goto __pyx_L11_break;
 747: 
 748:                     # get comoving distance
+749:                     interp_idx = while_while_decreasing(interp_idx, n_interp, rzp, redz_interp_grid)
          __pyx_v_interp_idx = __pyx_f_8holodeck_4sams_7cyutils_while_while_decreasing(__pyx_v_interp_idx, __pyx_v_n_interp, __pyx_v_rzp, __pyx_v_redz_interp_grid);
+750:                     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);
 751: 
 752:                     # calculate total hardening rate at this exact separation
+753:                     sepa = kepler_sepa_from_freq(mt, target_frst_orb)
          __pyx_v_sepa = __pyx_f_8holodeck_4sams_7cyutils_kepler_sepa_from_freq(__pyx_v_mt, __pyx_v_target_frst_orb);
+754:                     dadt = hard_gw(mt, mr, sepa)
          __pyx_v_dadt = __pyx_f_8holodeck_4sams_7cyutils_hard_gw(__pyx_v_mt, __pyx_v_mr, __pyx_v_sepa, 0);
 755: 
 756:                     # calculate residence/hardening time = f/[df/dt] = -(2/3) a/[da/dt]
+757:                     tres = - (2.0/3.0) * sepa / dadt
          __pyx_v_tres = (((-(2.0 / 3.0)) * __pyx_v_sepa) / __pyx_v_dadt);
 758: 
 759:                     # calculate number of binaries
+760:                     cosmo_fact = FOUR_PI_SPLC_OVER_MPC * (1.0 + rzp) * pow(dcom / MY_MPC, 2)
          __pyx_v_cosmo_fact = ((__pyx_v_8holodeck_4sams_7cyutils_FOUR_PI_SPLC_OVER_MPC * (1.0 + __pyx_v_rzp)) * pow((__pyx_v_dcom / __pyx_v_8holodeck_4sams_7cyutils_MY_MPC), 2.0));
+761:                     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:;
      }
    }
  }
 762: 
+763:     return 0
  __pyx_r = 0;
  goto __pyx_L0;
 764: 
 765: 
 766: 
 767: # ==================================================================================================
 768: # ====    DetStats Functions    ====
 769: # ==================================================================================================
 770: 
 771: 
+772: def gamma_of_rho_interp(rho, rsort, rho_interp_grid, gamma_interp_grid):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_13gamma_of_rho_interp(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_7cyutils_12gamma_of_rho_interp[] = "\n    rho : 1Darray of scalars\n        SNR of single sources, in flat array\n    rsort : 1Darray\n        order of flat rho values smallest to largest\n    rho_interp_grid : 1Darray\n        rho values corresponding to each gamma\n    gamma_interp_grid : 1Darray\n        gamma values corresponding to each rho\n\n    ";
static PyMethodDef __pyx_mdef_8holodeck_4sams_7cyutils_13gamma_of_rho_interp = {"gamma_of_rho_interp", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_13gamma_of_rho_interp, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_7cyutils_12gamma_of_rho_interp};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_13gamma_of_rho_interp(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_rho = 0;
  PyObject *__pyx_v_rsort = 0;
  PyObject *__pyx_v_rho_interp_grid = 0;
  PyObject *__pyx_v_gamma_interp_grid = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("gamma_of_rho_interp (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_rho,&__pyx_n_s_rsort,&__pyx_n_s_rho_interp_grid,&__pyx_n_s_gamma_interp_grid,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_rho)) != 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_rsort)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("gamma_of_rho_interp", 1, 4, 4, 1); __PYX_ERR(0, 772, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_rho_interp_grid)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("gamma_of_rho_interp", 1, 4, 4, 2); __PYX_ERR(0, 772, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_gamma_interp_grid)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("gamma_of_rho_interp", 1, 4, 4, 3); __PYX_ERR(0, 772, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "gamma_of_rho_interp") < 0)) __PYX_ERR(0, 772, __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_rho = values[0];
    __pyx_v_rsort = values[1];
    __pyx_v_rho_interp_grid = values[2];
    __pyx_v_gamma_interp_grid = values[3];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("gamma_of_rho_interp", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 772, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.cyutils.gamma_of_rho_interp", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_7cyutils_12gamma_of_rho_interp(__pyx_self, __pyx_v_rho, __pyx_v_rsort, __pyx_v_rho_interp_grid, __pyx_v_gamma_interp_grid);
  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_7cyutils_12gamma_of_rho_interp(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_rho, PyObject *__pyx_v_rsort, PyObject *__pyx_v_rho_interp_grid, PyObject *__pyx_v_gamma_interp_grid) {
  PyArrayObject *__pyx_v_gamma = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_gamma;
  __Pyx_Buffer __pyx_pybuffer_gamma;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("gamma_of_rho_interp", 0);
  __pyx_pybuffer_gamma.pybuffer.buf = NULL;
  __pyx_pybuffer_gamma.refcount = 0;
  __pyx_pybuffernd_gamma.data = NULL;
  __pyx_pybuffernd_gamma.rcbuffer = &__pyx_pybuffer_gamma;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_6, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_7, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_8, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_10, 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_gamma.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("holodeck.sams.cyutils.gamma_of_rho_interp", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_gamma.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF((PyObject *)__pyx_v_gamma);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__33 = PyTuple_Pack(5, __pyx_n_s_rho, __pyx_n_s_rsort, __pyx_n_s_rho_interp_grid, __pyx_n_s_gamma_interp_grid, __pyx_n_s_gamma); if (unlikely(!__pyx_tuple__33)) __PYX_ERR(0, 772, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__33);
  __Pyx_GIVEREF(__pyx_tuple__33);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_13gamma_of_rho_interp, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 772, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_gamma_of_rho_interp, __pyx_t_1) < 0) __PYX_ERR(0, 772, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__34 = (PyObject*)__Pyx_PyCode_New(4, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__33, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_cyutils_pyx, __pyx_n_s_gamma_of_rho_interp, 772, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__34)) __PYX_ERR(0, 772, __pyx_L1_error)
 773:     """
 774:     rho : 1Darray of scalars
 775:         SNR of single sources, in flat array
 776:     rsort : 1Darray
 777:         order of flat rho values smallest to largest
 778:     rho_interp_grid : 1Darray
 779:         rho values corresponding to each gamma
 780:     gamma_interp_grid : 1Darray
 781:         gamma values corresponding to each rho
 782: 
 783:     """
 784:     # pass in the interp grid
+785:     cdef np.ndarray[np.double_t, ndim=1] gamma = np.zeros(rho.shape)
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 785, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_zeros); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 785, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_rho, __pyx_n_s_shape); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 785, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __pyx_t_4 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
    if (likely(__pyx_t_4)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
      __Pyx_INCREF(__pyx_t_4);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_3, function);
    }
  }
  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2);
  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 785, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (!(likely(((__pyx_t_1) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_1, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 785, __pyx_L1_error)
  __pyx_t_5 = ((PyArrayObject *)__pyx_t_1);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_gamma.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_5numpy_double_t, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {
      __pyx_v_gamma = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_gamma.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 785, __pyx_L1_error)
    } else {__pyx_pybuffernd_gamma.diminfo[0].strides = __pyx_pybuffernd_gamma.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_gamma.diminfo[0].shape = __pyx_pybuffernd_gamma.rcbuffer->pybuffer.shape[0];
    }
  }
  __pyx_t_5 = 0;
  __pyx_v_gamma = ((PyArrayObject *)__pyx_t_1);
  __pyx_t_1 = 0;
 786: 
+787:     _gamma_of_rho_interp(rho, rsort, rho_interp_grid, gamma_interp_grid, gamma)
  __pyx_t_6 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_rho, PyBUF_WRITABLE); if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 787, __pyx_L1_error)
  __pyx_t_7 = __Pyx_PyObject_to_MemoryviewSlice_ds_long(__pyx_v_rsort, PyBUF_WRITABLE); if (unlikely(!__pyx_t_7.memview)) __PYX_ERR(0, 787, __pyx_L1_error)
  __pyx_t_8 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_rho_interp_grid, PyBUF_WRITABLE); if (unlikely(!__pyx_t_8.memview)) __PYX_ERR(0, 787, __pyx_L1_error)
  __pyx_t_9 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_gamma_interp_grid, PyBUF_WRITABLE); if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 787, __pyx_L1_error)
  __pyx_t_10 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(((PyObject *)__pyx_v_gamma), PyBUF_WRITABLE); if (unlikely(!__pyx_t_10.memview)) __PYX_ERR(0, 787, __pyx_L1_error)
  (void)(__pyx_f_8holodeck_4sams_7cyutils__gamma_of_rho_interp(__pyx_t_6, __pyx_t_7, __pyx_t_8, __pyx_t_9, __pyx_t_10));
  __PYX_XDEC_MEMVIEW(&__pyx_t_6, 1);
  __pyx_t_6.memview = NULL;
  __pyx_t_6.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_7, 1);
  __pyx_t_7.memview = NULL;
  __pyx_t_7.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_8, 1);
  __pyx_t_8.memview = NULL;
  __pyx_t_8.data = NULL;
  __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;
 788: 
+789:     return gamma
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_gamma));
  __pyx_r = ((PyObject *)__pyx_v_gamma);
  goto __pyx_L0;
 790: 
 791: @cython.boundscheck(False)
 792: @cython.wraparound(False)
 793: @cython.nonecheck(False)
 794: @cython.cdivision(True)
+795: cdef int _gamma_of_rho_interp(
static int __pyx_f_8holodeck_4sams_7cyutils__gamma_of_rho_interp(__Pyx_memviewslice __pyx_v_rho, __Pyx_memviewslice __pyx_v_rsort, __Pyx_memviewslice __pyx_v_rho_interp_grid, __Pyx_memviewslice __pyx_v_gamma_interp_grid, __Pyx_memviewslice __pyx_v_gamma) {
  int __pyx_v_n_rho;
  int __pyx_v_n_interp;
  int __pyx_v_ii;
  int __pyx_v_kk;
  int __pyx_v_rr;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_gamma_of_rho_interp", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_WriteUnraisable("holodeck.sams.cyutils._gamma_of_rho_interp", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 796:     double[:] rho, long[:] rsort,
 797:     double[:] rho_interp_grid, double[:] gamma_interp_grid,
 798:     # output
 799:     double[:] gamma
 800:     ):
 801:     """ Find gamma of rho by interpolation over rho and gamma grids.
 802:     """
 803: 
+804:     cdef int n_rho = rho.size
  __pyx_t_1 = __pyx_memoryview_fromslice(__pyx_v_rho, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 804, __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, 804, __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, 804, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  __pyx_v_n_rho = __pyx_t_3;
+805:     cdef int n_interp = rho_interp_grid.size
  __pyx_t_2 = __pyx_memoryview_fromslice(__pyx_v_rho_interp_grid, 1, (PyObject *(*)(char *)) __pyx_memview_get_double, (int (*)(char *, PyObject *)) __pyx_memview_set_double, 0);; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 805, __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, 805, __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, 805, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_n_interp = __pyx_t_3;
 806:     cdef int ii, kk, rr
+807:     ii = 0 # get rho in order using rho[rsort[ii]]
  __pyx_v_ii = 0;
 808: 
+809:     for kk in range(n_rho):
  __pyx_t_3 = __pyx_v_n_rho;
  __pyx_t_4 = __pyx_t_3;
  for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) {
    __pyx_v_kk = __pyx_t_5;
+810:         rr = rsort[kk] # index of next largest rho, equiv to rev in redz calculation
    __pyx_t_6 = __pyx_v_kk;
    __pyx_v_rr = (*((long *) ( /* dim=0 */ (__pyx_v_rsort.data + __pyx_t_6 * __pyx_v_rsort.strides[0]) )));
 811:         # print('kk =',kk,' rr =', rr, 'rho[rr] =', rho[rr])
 812:         # get to the right index of the interpolation-grid
+813:         while (rho_interp_grid[ii+1] < rho[rr]) and (ii < n_interp -2):
    while (1) {
      __pyx_t_6 = (__pyx_v_ii + 1);
      __pyx_t_8 = __pyx_v_rr;
      __pyx_t_9 = (((*((double *) ( /* dim=0 */ (__pyx_v_rho_interp_grid.data + __pyx_t_6 * __pyx_v_rho_interp_grid.strides[0]) ))) < (*((double *) ( /* dim=0 */ (__pyx_v_rho.data + __pyx_t_8 * __pyx_v_rho.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 - 2)) != 0);
      __pyx_t_7 = __pyx_t_9;
      __pyx_L7_bool_binop_done:;
      if (!__pyx_t_7) break;
+814:             ii += 1
      __pyx_v_ii = (__pyx_v_ii + 1);
    }
 815:         # print('ii =',ii, ' rho_interp[ii] =', rho_interp_grid[ii], ' rho_interp[ii+1] =', rho_interp_grid[ii+1])
 816:         # interpolate
+817:         gamma[rr] = interp_at_index(ii, rho[rr], rho_interp_grid, gamma_interp_grid)
    __pyx_t_8 = __pyx_v_rr;
    __pyx_t_6 = __pyx_v_rr;
    *((double *) ( /* dim=0 */ (__pyx_v_gamma.data + __pyx_t_6 * __pyx_v_gamma.strides[0]) )) = __pyx_f_8holodeck_7cyutils_interp_at_index(__pyx_v_ii, (*((double *) ( /* dim=0 */ (__pyx_v_rho.data + __pyx_t_8 * __pyx_v_rho.strides[0]) ))), __pyx_v_rho_interp_grid, __pyx_v_gamma_interp_grid);
  }
 818:         # print('rho =', rho[rr], ' gamma =', gamma[rr], '\n')\
 819: 
+820:     return 0
  __pyx_r = 0;
  goto __pyx_L0;
 821: 
 822: 
+823: def snr_ss(amp, F_iplus, F_icross, iotas, dur, Phi_0, S_i, freqs):
/* Python wrapper */
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_15snr_ss(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static char __pyx_doc_8holodeck_4sams_7cyutils_14snr_ss[] = " Calculate single source SNR\n\n\n    Parameters\n    ----------\n    amp : (F,R,L) NDarray\n        Dimensionless strain amplitude of loudest single sources\n    F_iplus : (P,F,S,L) NDarray\n        Antenna pattern function for each pulsar.\n    F_icross : (P,F,S,L) NDarray\n        Antenna pattern function for each pulsar.\n    iotas : (F,S,L) NDarray\n        Inclination, used to calculate:\n        a_pol = 1 + np.cos(iotas) **2\n        b_pol = -2 * np.cos(iotas)\n    dur : scalar\n        Duration of observations.\n    Phi_0 : (F,S,L) NDarray\n        Initial GW phase\n    S_i : (P,F,R,L) NDarray\n        Total noise of each pulsar wrt detection of each single source, in s^3\n    freqs : (F,) 1Darray\n        Observed frequency bin centers.\n\n    Returns\n    -------\n    snr_ss : (F,R,S,L) NDarray\n        SNR from the whole PTA for each single source with\n        each realized sky position (S) and realized strain (R)\n\n    ";
static PyMethodDef __pyx_mdef_8holodeck_4sams_7cyutils_15snr_ss = {"snr_ss", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8holodeck_4sams_7cyutils_15snr_ss, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8holodeck_4sams_7cyutils_14snr_ss};
static PyObject *__pyx_pw_8holodeck_4sams_7cyutils_15snr_ss(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  PyObject *__pyx_v_amp = 0;
  PyObject *__pyx_v_F_iplus = 0;
  PyObject *__pyx_v_F_icross = 0;
  PyObject *__pyx_v_iotas = 0;
  PyObject *__pyx_v_dur = 0;
  PyObject *__pyx_v_Phi_0 = 0;
  PyObject *__pyx_v_S_i = 0;
  PyObject *__pyx_v_freqs = 0;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("snr_ss (wrapper)", 0);
  {
    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_amp,&__pyx_n_s_F_iplus,&__pyx_n_s_F_icross,&__pyx_n_s_iotas,&__pyx_n_s_dur,&__pyx_n_s_Phi_0,&__pyx_n_s_S_i,&__pyx_n_s_freqs,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_amp)) != 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_F_iplus)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 1); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  2:
        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_F_icross)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 2); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  3:
        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_iotas)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 3); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  4:
        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_dur)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 4); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  5:
        if (likely((values[5] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_Phi_0)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 5); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  6:
        if (likely((values[6] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_S_i)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 6); __PYX_ERR(0, 823, __pyx_L3_error)
        }
        CYTHON_FALLTHROUGH;
        case  7:
        if (likely((values[7] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_freqs)) != 0)) kw_args--;
        else {
          __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, 7); __PYX_ERR(0, 823, __pyx_L3_error)
        }
      }
      if (unlikely(kw_args > 0)) {
        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "snr_ss") < 0)) __PYX_ERR(0, 823, __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_amp = values[0];
    __pyx_v_F_iplus = values[1];
    __pyx_v_F_icross = values[2];
    __pyx_v_iotas = values[3];
    __pyx_v_dur = values[4];
    __pyx_v_Phi_0 = values[5];
    __pyx_v_S_i = values[6];
    __pyx_v_freqs = values[7];
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L5_argtuple_error:;
  __Pyx_RaiseArgtupleInvalid("snr_ss", 1, 8, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 823, __pyx_L3_error)
  __pyx_L3_error:;
  __Pyx_AddTraceback("holodeck.sams.cyutils.snr_ss", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_8holodeck_4sams_7cyutils_14snr_ss(__pyx_self, __pyx_v_amp, __pyx_v_F_iplus, __pyx_v_F_icross, __pyx_v_iotas, __pyx_v_dur, __pyx_v_Phi_0, __pyx_v_S_i, __pyx_v_freqs);
  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_7cyutils_14snr_ss(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_amp, PyObject *__pyx_v_F_iplus, PyObject *__pyx_v_F_icross, PyObject *__pyx_v_iotas, PyObject *__pyx_v_dur, PyObject *__pyx_v_Phi_0, PyObject *__pyx_v_S_i, PyObject *__pyx_v_freqs) {
  PyObject *__pyx_v_nfreqs = NULL;
  PyObject *__pyx_v_nreals = NULL;
  PyObject *__pyx_v_nloudest = NULL;
  PyObject *__pyx_v_npsrs = NULL;
  PyObject *__pyx_v_nskies = NULL;
  PyArrayObject *__pyx_v_snr_ss = 0;
  __Pyx_LocalBuf_ND __pyx_pybuffernd_snr_ss;
  __Pyx_Buffer __pyx_pybuffer_snr_ss;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("snr_ss", 0);
  __pyx_pybuffer_snr_ss.pybuffer.buf = NULL;
  __pyx_pybuffer_snr_ss.refcount = 0;
  __pyx_pybuffernd_snr_ss.data = NULL;
  __pyx_pybuffernd_snr_ss.rcbuffer = &__pyx_pybuffer_snr_ss;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_3);
  __Pyx_XDECREF(__pyx_t_4);
  __PYX_XDEC_MEMVIEW(&__pyx_t_6, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_7, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_8, 1);
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __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_19, 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_snr_ss.rcbuffer->pybuffer);
  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}
  __Pyx_AddTraceback("holodeck.sams.cyutils.snr_ss", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  goto __pyx_L2;
  __pyx_L0:;
  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_snr_ss.rcbuffer->pybuffer);
  __pyx_L2:;
  __Pyx_XDECREF(__pyx_v_nfreqs);
  __Pyx_XDECREF(__pyx_v_nreals);
  __Pyx_XDECREF(__pyx_v_nloudest);
  __Pyx_XDECREF(__pyx_v_npsrs);
  __Pyx_XDECREF(__pyx_v_nskies);
  __Pyx_XDECREF((PyObject *)__pyx_v_snr_ss);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple__35 = PyTuple_Pack(14, __pyx_n_s_amp, __pyx_n_s_F_iplus, __pyx_n_s_F_icross, __pyx_n_s_iotas, __pyx_n_s_dur, __pyx_n_s_Phi_0, __pyx_n_s_S_i, __pyx_n_s_freqs, __pyx_n_s_nfreqs, __pyx_n_s_nreals, __pyx_n_s_nloudest, __pyx_n_s_npsrs, __pyx_n_s_nskies, __pyx_n_s_snr_ss); if (unlikely(!__pyx_tuple__35)) __PYX_ERR(0, 823, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__35);
  __Pyx_GIVEREF(__pyx_tuple__35);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8holodeck_4sams_7cyutils_15snr_ss, NULL, __pyx_n_s_holodeck_sams_cyutils); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 823, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_snr_ss, __pyx_t_1) < 0) __PYX_ERR(0, 823, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_codeobj__36 = (PyObject*)__Pyx_PyCode_New(8, 0, 14, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__35, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_holodeck_sams_cyutils_pyx, __pyx_n_s_snr_ss, 823, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__36)) __PYX_ERR(0, 823, __pyx_L1_error)
 824:     """ Calculate single source SNR
 825: 
 826: 
 827:     Parameters
 828:     ----------
 829:     amp : (F,R,L) NDarray
 830:         Dimensionless strain amplitude of loudest single sources
 831:     F_iplus : (P,F,S,L) NDarray
 832:         Antenna pattern function for each pulsar.
 833:     F_icross : (P,F,S,L) NDarray
 834:         Antenna pattern function for each pulsar.
 835:     iotas : (F,S,L) NDarray
 836:         Inclination, used to calculate:
 837:         a_pol = 1 + np.cos(iotas) **2
 838:         b_pol = -2 * np.cos(iotas)
 839:     dur : scalar
 840:         Duration of observations.
 841:     Phi_0 : (F,S,L) NDarray
 842:         Initial GW phase
 843:     S_i : (P,F,R,L) NDarray
 844:         Total noise of each pulsar wrt detection of each single source, in s^3
 845:     freqs : (F,) 1Darray
 846:         Observed frequency bin centers.
 847: 
 848:     Returns
 849:     -------
 850:     snr_ss : (F,R,S,L) NDarray
 851:         SNR from the whole PTA for each single source with
 852:         each realized sky position (S) and realized strain (R)
 853: 
 854:     """
+855:     nfreqs, nreals, nloudest = amp.shape[0], amp.shape[1], amp.shape[2]
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_amp, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_1, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 855, __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_amp, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_1, 1, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 855, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_amp, __pyx_n_s_shape); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 855, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_4 = __Pyx_GetItemInt(__pyx_t_1, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 855, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __pyx_v_nfreqs = __pyx_t_2;
  __pyx_t_2 = 0;
  __pyx_v_nreals = __pyx_t_3;
  __pyx_t_3 = 0;
  __pyx_v_nloudest = __pyx_t_4;
  __pyx_t_4 = 0;
+856:     npsrs, nskies = F_iplus.shape[0], F_iplus.shape[2]
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_F_iplus, __pyx_n_s_shape); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_3 = __Pyx_GetItemInt(__pyx_t_4, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_F_iplus, __pyx_n_s_shape); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __pyx_t_2 = __Pyx_GetItemInt(__pyx_t_4, 2, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 856, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
  __pyx_v_npsrs = __pyx_t_3;
  __pyx_t_3 = 0;
  __pyx_v_nskies = __pyx_t_2;
  __pyx_t_2 = 0;
+857:     cdef np.ndarray[np.double_t, ndim=4] snr_ss = np.zeros((nfreqs, nreals, nskies, nloudest))
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_zeros); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 857, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_3);
  __Pyx_INCREF(__pyx_v_nfreqs);
  __Pyx_GIVEREF(__pyx_v_nfreqs);
  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_nfreqs);
  __Pyx_INCREF(__pyx_v_nreals);
  __Pyx_GIVEREF(__pyx_v_nreals);
  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_nreals);
  __Pyx_INCREF(__pyx_v_nskies);
  __Pyx_GIVEREF(__pyx_v_nskies);
  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_nskies);
  __Pyx_INCREF(__pyx_v_nloudest);
  __Pyx_GIVEREF(__pyx_v_nloudest);
  PyTuple_SET_ITEM(__pyx_t_3, 3, __pyx_v_nloudest);
  __pyx_t_1 = NULL;
  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_4);
    if (likely(__pyx_t_1)) {
      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
      __Pyx_INCREF(__pyx_t_1);
      __Pyx_INCREF(function);
      __Pyx_DECREF_SET(__pyx_t_4, function);
    }
  }
  __pyx_t_2 = (__pyx_t_1) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_1, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_3);
  __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 857, __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, 857, __pyx_L1_error)
  __pyx_t_5 = ((PyArrayObject *)__pyx_t_2);
  {
    __Pyx_BufFmt_StackElem __pyx_stack[1];
    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_snr_ss.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_snr_ss = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.buf = NULL;
      __PYX_ERR(0, 857, __pyx_L1_error)
    } else {__pyx_pybuffernd_snr_ss.diminfo[0].strides = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_snr_ss.diminfo[0].shape = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_snr_ss.diminfo[1].strides = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_snr_ss.diminfo[1].shape = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.shape[1]; __pyx_pybuffernd_snr_ss.diminfo[2].strides = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.strides[2]; __pyx_pybuffernd_snr_ss.diminfo[2].shape = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.shape[2]; __pyx_pybuffernd_snr_ss.diminfo[3].strides = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.strides[3]; __pyx_pybuffernd_snr_ss.diminfo[3].shape = __pyx_pybuffernd_snr_ss.rcbuffer->pybuffer.shape[3];
    }
  }
  __pyx_t_5 = 0;
  __pyx_v_snr_ss = ((PyArrayObject *)__pyx_t_2);
  __pyx_t_2 = 0;
+858:     _snr_ss(
  (void)(__pyx_f_8holodeck_4sams_7cyutils__snr_ss(__pyx_t_6, __pyx_t_7, __pyx_t_8, __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_XDEC_MEMVIEW(&__pyx_t_6, 1);
  __pyx_t_6.memview = NULL;
  __pyx_t_6.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_7, 1);
  __pyx_t_7.memview = NULL;
  __pyx_t_7.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_8, 1);
  __pyx_t_8.memview = NULL;
  __pyx_t_8.data = NULL;
  __PYX_XDEC_MEMVIEW(&__pyx_t_9, 1);
  __pyx_t_9.memview = NULL;
  __pyx_t_9.data = NULL;
  __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_19, 1);
  __pyx_t_19.memview = NULL;
  __pyx_t_19.data = NULL;
+859:         amp, F_iplus, F_icross, iotas, dur, Phi_0, S_i, freqs,
  __pyx_t_6 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_amp, PyBUF_WRITABLE); if (unlikely(!__pyx_t_6.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_7 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(__pyx_v_F_iplus, PyBUF_WRITABLE); if (unlikely(!__pyx_t_7.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_8 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(__pyx_v_F_icross, PyBUF_WRITABLE); if (unlikely(!__pyx_t_8.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_9 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_iotas, PyBUF_WRITABLE); if (unlikely(!__pyx_t_9.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_v_dur); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_11 = __Pyx_PyObject_to_MemoryviewSlice_dsdsds_double(__pyx_v_Phi_0, PyBUF_WRITABLE); if (unlikely(!__pyx_t_11.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_12 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(__pyx_v_S_i, PyBUF_WRITABLE); if (unlikely(!__pyx_t_12.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
  __pyx_t_13 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_freqs, PyBUF_WRITABLE); if (unlikely(!__pyx_t_13.memview)) __PYX_ERR(0, 859, __pyx_L1_error)
+860:         npsrs, nfreqs, nreals, nskies, nloudest,
  __pyx_t_14 = __Pyx_PyInt_As_long(__pyx_v_npsrs); if (unlikely((__pyx_t_14 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 860, __pyx_L1_error)
  __pyx_t_15 = __Pyx_PyInt_As_long(__pyx_v_nfreqs); if (unlikely((__pyx_t_15 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 860, __pyx_L1_error)
  __pyx_t_16 = __Pyx_PyInt_As_long(__pyx_v_nreals); if (unlikely((__pyx_t_16 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 860, __pyx_L1_error)
  __pyx_t_17 = __Pyx_PyInt_As_long(__pyx_v_nskies); if (unlikely((__pyx_t_17 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 860, __pyx_L1_error)
  __pyx_t_18 = __Pyx_PyInt_As_long(__pyx_v_nloudest); if (unlikely((__pyx_t_18 == (long)-1) && PyErr_Occurred())) __PYX_ERR(0, 860, __pyx_L1_error)
+861:         snr_ss)
  __pyx_t_19 = __Pyx_PyObject_to_MemoryviewSlice_dsdsdsds_double(((PyObject *)__pyx_v_snr_ss), PyBUF_WRITABLE); if (unlikely(!__pyx_t_19.memview)) __PYX_ERR(0, 861, __pyx_L1_error)
+862:     return snr_ss
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(((PyObject *)__pyx_v_snr_ss));
  __pyx_r = ((PyObject *)__pyx_v_snr_ss);
  goto __pyx_L0;
 863: 
 864: @cython.boundscheck(False)
 865: @cython.wraparound(False)
 866: @cython.nonecheck(False)
 867: @cython.cdivision(True)
+868: cdef int _snr_ss(
static int __pyx_f_8holodeck_4sams_7cyutils__snr_ss(__Pyx_memviewslice __pyx_v_amp, __Pyx_memviewslice __pyx_v_F_iplus, __Pyx_memviewslice __pyx_v_F_icross, __Pyx_memviewslice __pyx_v_iotas, double __pyx_v_dur, __Pyx_memviewslice __pyx_v_Phi_0, __Pyx_memviewslice __pyx_v_S_i, __Pyx_memviewslice __pyx_v_freqs, long __pyx_v_npsrs, long __pyx_v_nfreqs, long __pyx_v_nreals, long __pyx_v_nskies, long __pyx_v_nloudest, __Pyx_memviewslice __pyx_v_snr_ss) {
  int __pyx_v_pp;
  int __pyx_v_ff;
  int __pyx_v_rr;
  int __pyx_v_ss;
  int __pyx_v_ll;
  float __pyx_v_a_pol;
  float __pyx_v_b_pol;
  float __pyx_v_Phi_T;
  float __pyx_v_pta_snr_sq;
  float __pyx_v_coef;
  float __pyx_v_term1;
  float __pyx_v_term2;
  float __pyx_v_term3;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("_snr_ss", 0);
/* … */
  /* function exit code */
  __pyx_r = 0;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 869:     double[:,:,:] amp,
 870:     double[:,:,:,:] F_iplus,
 871:     double[:,:,:,:] F_icross,
 872:     double[:,:,:] iotas,
 873:     double dur,
 874:     double[:,:,:] Phi_0,
 875:     double[:,:,:,:] S_i,
 876:     double[:] freqs,
 877:     long npsrs, long nfreqs, long nreals, long nskies, long nloudest,
 878:     # output
 879:     double[:,:,:,:] snr_ss
 880:     ):
 881:     """
 882: 
 883:     Parameters
 884:     ----------
 885:     amp : (F,R,L) NDarray
 886:         Dimensionless strain amplitude of loudest single sources
 887:     F_iplus : (P,F,S,L) NDarray
 888:         Antenna pattern function for each pulsar.
 889:     F_icross : (P,F,S,L) NDarray
 890:         Antenna pattern function for each pulsar.
 891:     iotas : (F,S,L) NDarray
 892:         Inclination, used to calculate:
 893:         a_pol = 1 + np.cos(iotas) **2
 894:         b_pol = -2 * np.cos(iotas)
 895:     dur : scalar
 896:         Duration of observations.
 897:     Phi_0 : (F,S,L) NDarray
 898:         Initial GW phase
 899:     S_i : (P,F,R,L) NDarray
 900:         Total noise of each pulsar wrt detection of each single source, in s^3
 901:     freqs : (F,) 1Darray
 902:         Observed frequency bin centers.
 903:     snr_ss : (F,R,S,L) NDarray
 904:         Pointer to single source SNR array, to be calculated.
 905: 
 906:     NOTE: This may be improved by moving some of the math outside the function.
 907:     I.e., passing in sin/cos of NDarrays to be used.
 908:     """
 909: 
 910:     cdef int pp, ff, rr, ss, ll
 911:     cdef float a_pol, b_pol, Phi_T, pta_snr_sq, coef, term1, term2, term3
 912:     # print('npsrs %d, nfreqs %d, nreals %d, nskies %d, nloudest %d' % (npsrs, nfreqs, nreals, nskies, nloudest))
 913: 
+914:     for ff in range(nfreqs):
  __pyx_t_1 = __pyx_v_nfreqs;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_ff = __pyx_t_3;
+915:         for ss in range(nskies):
    __pyx_t_4 = __pyx_v_nskies;
    __pyx_t_5 = __pyx_t_4;
    for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
      __pyx_v_ss = __pyx_t_6;
+916:             for ll in range(nloudest):
      __pyx_t_7 = __pyx_v_nloudest;
      __pyx_t_8 = __pyx_t_7;
      for (__pyx_t_9 = 0; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {
        __pyx_v_ll = __pyx_t_9;
+917:                 a_pol = 1 + pow(cos(iotas[ff,ss,ll]), 2.0)
        __pyx_t_10 = __pyx_v_ff;
        __pyx_t_11 = __pyx_v_ss;
        __pyx_t_12 = __pyx_v_ll;
        __pyx_v_a_pol = (1.0 + pow(cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_iotas.data + __pyx_t_10 * __pyx_v_iotas.strides[0]) ) + __pyx_t_11 * __pyx_v_iotas.strides[1]) ) + __pyx_t_12 * __pyx_v_iotas.strides[2]) )))), 2.0));
+918:                 b_pol = -2 * cos(iotas[ff,ss,ll])
        __pyx_t_12 = __pyx_v_ff;
        __pyx_t_11 = __pyx_v_ss;
        __pyx_t_10 = __pyx_v_ll;
        __pyx_v_b_pol = (-2.0 * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_iotas.data + __pyx_t_12 * __pyx_v_iotas.strides[0]) ) + __pyx_t_11 * __pyx_v_iotas.strides[1]) ) + __pyx_t_10 * __pyx_v_iotas.strides[2]) )))));
+919:                 Phi_T = 2 * M_PI * freqs[ff] * dur + Phi_0[ff,ss,ll]
        __pyx_t_10 = __pyx_v_ff;
        __pyx_t_11 = __pyx_v_ff;
        __pyx_t_12 = __pyx_v_ss;
        __pyx_t_13 = __pyx_v_ll;
        __pyx_v_Phi_T = ((((2.0 * M_PI) * (*((double *) ( /* dim=0 */ (__pyx_v_freqs.data + __pyx_t_10 * __pyx_v_freqs.strides[0]) )))) * __pyx_v_dur) + (*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_11 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_12 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_13 * __pyx_v_Phi_0.strides[2]) ))));
+920:                 for rr in range(nreals):
        __pyx_t_14 = __pyx_v_nreals;
        __pyx_t_15 = __pyx_t_14;
        for (__pyx_t_16 = 0; __pyx_t_16 < __pyx_t_15; __pyx_t_16+=1) {
          __pyx_v_rr = __pyx_t_16;
+921:                     pta_snr_sq = 0
          __pyx_v_pta_snr_sq = 0.0;
+922:                     for pp in range(npsrs):
          __pyx_t_17 = __pyx_v_npsrs;
          __pyx_t_18 = __pyx_t_17;
          for (__pyx_t_19 = 0; __pyx_t_19 < __pyx_t_18; __pyx_t_19+=1) {
            __pyx_v_pp = __pyx_t_19;
 923:                         # calculate coefficient depending on
 924:                         # function of amp, S_i, and freqs
+925:                         coef = pow(amp[ff,rr,ll], 2.0) / (S_i[pp,ff,rr,ll] * 8 * pow(M_PI * freqs[ff], 3.0))
            __pyx_t_13 = __pyx_v_ff;
            __pyx_t_12 = __pyx_v_rr;
            __pyx_t_11 = __pyx_v_ll;
            __pyx_t_10 = __pyx_v_pp;
            __pyx_t_20 = __pyx_v_ff;
            __pyx_t_21 = __pyx_v_rr;
            __pyx_t_22 = __pyx_v_ll;
            __pyx_t_23 = __pyx_v_ff;
            __pyx_v_coef = (pow((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_amp.data + __pyx_t_13 * __pyx_v_amp.strides[0]) ) + __pyx_t_12 * __pyx_v_amp.strides[1]) ) + __pyx_t_11 * __pyx_v_amp.strides[2]) ))), 2.0) / (((*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_S_i.data + __pyx_t_10 * __pyx_v_S_i.strides[0]) ) + __pyx_t_20 * __pyx_v_S_i.strides[1]) ) + __pyx_t_21 * __pyx_v_S_i.strides[2]) ) + __pyx_t_22 * __pyx_v_S_i.strides[3]) ))) * 8.0) * pow((M_PI * (*((double *) ( /* dim=0 */ (__pyx_v_freqs.data + __pyx_t_23 * __pyx_v_freqs.strides[0]) )))), 3.0)));
 926: 
 927:                         # calculate terms that depend on p, f, s, and l
 928:                         # functions of F_iplus, F_icross, a_pol, b_pol, Phi_0, and Phi_T
 929:                         term1 = (
+930:                             pow(a_pol * F_iplus[pp,ff,ss,ll], 2.0)
            __pyx_t_23 = __pyx_v_pp;
            __pyx_t_22 = __pyx_v_ff;
            __pyx_t_21 = __pyx_v_ss;
            __pyx_t_20 = __pyx_v_ll;
+931:                             * (Phi_T * (1.0 + 2.0 * pow(sin(Phi_0[ff,ss,ll]), 2.0))
            __pyx_t_10 = __pyx_v_ff;
            __pyx_t_11 = __pyx_v_ss;
            __pyx_t_12 = __pyx_v_ll;
/* … */
            __pyx_v_term1 = (pow((__pyx_v_a_pol * (*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_F_iplus.data + __pyx_t_23 * __pyx_v_F_iplus.strides[0]) ) + __pyx_t_22 * __pyx_v_F_iplus.strides[1]) ) + __pyx_t_21 * __pyx_v_F_iplus.strides[2]) ) + __pyx_t_20 * __pyx_v_F_iplus.strides[3]) )))), 2.0) * (((__pyx_v_Phi_T * (1.0 + (2.0 * pow(sin((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_10 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_11 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_12 * __pyx_v_Phi_0.strides[2]) )))), 2.0)))) + (cos(__pyx_v_Phi_T) * ((-1.0 * sin(__pyx_v_Phi_T)) + (4.0 * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_13 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_24 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_25 * __pyx_v_Phi_0.strides[2]) )))))))) - (4.0 * sin((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_26 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_27 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_28 * __pyx_v_Phi_0.strides[2]) )))))));
+932:                                 + cos(Phi_T) * (-1.0 * sin(Phi_T) + 4.0 * cos(Phi_0[ff,ss,ll]))
            __pyx_t_13 = __pyx_v_ff;
            __pyx_t_24 = __pyx_v_ss;
            __pyx_t_25 = __pyx_v_ll;
+933:                                 - 4.0 * sin(Phi_0[ff,ss,ll])
            __pyx_t_26 = __pyx_v_ff;
            __pyx_t_27 = __pyx_v_ss;
            __pyx_t_28 = __pyx_v_ll;
 934:                                 )
 935:                         )
 936:                         term2 = (
+937:                             pow(b_pol * F_icross[pp,ff,ss,ll], 2.0)
            __pyx_t_28 = __pyx_v_pp;
            __pyx_t_27 = __pyx_v_ff;
            __pyx_t_26 = __pyx_v_ss;
            __pyx_t_25 = __pyx_v_ll;
+938:                             * (Phi_T * (1.0 + 2.0 * pow(cos(Phi_0[ff,ss,ll]), 2.0))
            __pyx_t_24 = __pyx_v_ff;
            __pyx_t_13 = __pyx_v_ss;
            __pyx_t_12 = __pyx_v_ll;
/* … */
            __pyx_v_term2 = (pow((__pyx_v_b_pol * (*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_F_icross.data + __pyx_t_28 * __pyx_v_F_icross.strides[0]) ) + __pyx_t_27 * __pyx_v_F_icross.strides[1]) ) + __pyx_t_26 * __pyx_v_F_icross.strides[2]) ) + __pyx_t_25 * __pyx_v_F_icross.strides[3]) )))), 2.0) * (((__pyx_v_Phi_T * (1.0 + (2.0 * pow(cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_24 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_13 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_12 * __pyx_v_Phi_0.strides[2]) )))), 2.0)))) + (sin(__pyx_v_Phi_T) * cos(__pyx_v_Phi_T))) - (4.0 * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_11 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_10 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_20 * __pyx_v_Phi_0.strides[2]) )))))));
+939:                                 + sin(Phi_T) * cos(Phi_T) - 4.0 * cos(Phi_0[ff,ss,ll])
            __pyx_t_11 = __pyx_v_ff;
            __pyx_t_10 = __pyx_v_ss;
            __pyx_t_20 = __pyx_v_ll;
 940:                                 )
 941:                         )
 942:                         term3 = (
+943:                             -2.0 * a_pol * b_pol * F_iplus[pp,ff,ss,ll] * F_icross[pp,ff,ss,ll]
            __pyx_t_20 = __pyx_v_pp;
            __pyx_t_10 = __pyx_v_ff;
            __pyx_t_11 = __pyx_v_ss;
            __pyx_t_12 = __pyx_v_ll;
            __pyx_t_13 = __pyx_v_pp;
            __pyx_t_24 = __pyx_v_ff;
            __pyx_t_25 = __pyx_v_ss;
            __pyx_t_26 = __pyx_v_ll;
+944:                             * (2.0 * Phi_T * sin(Phi_T) *cos(Phi_0[ff,ss,ll])
            __pyx_t_27 = __pyx_v_ff;
            __pyx_t_28 = __pyx_v_ss;
            __pyx_t_21 = __pyx_v_ll;
/* … */
            __pyx_v_term3 = (((((-2.0 * __pyx_v_a_pol) * __pyx_v_b_pol) * (*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_F_iplus.data + __pyx_t_20 * __pyx_v_F_iplus.strides[0]) ) + __pyx_t_10 * __pyx_v_F_iplus.strides[1]) ) + __pyx_t_11 * __pyx_v_F_iplus.strides[2]) ) + __pyx_t_12 * __pyx_v_F_iplus.strides[3]) )))) * (*((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_F_icross.data + __pyx_t_13 * __pyx_v_F_icross.strides[0]) ) + __pyx_t_24 * __pyx_v_F_icross.strides[1]) ) + __pyx_t_25 * __pyx_v_F_icross.strides[2]) ) + __pyx_t_26 * __pyx_v_F_icross.strides[3]) )))) * ((((2.0 * __pyx_v_Phi_T) * sin(__pyx_v_Phi_T)) * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_27 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_28 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_21 * __pyx_v_Phi_0.strides[2]) ))))) + (sin(__pyx_v_Phi_T) * (((sin(__pyx_v_Phi_T) - (2.0 * sin((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_22 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_23 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_29 * __pyx_v_Phi_0.strides[2]) )))))) + ((2.0 * cos(__pyx_v_Phi_T)) * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_30 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_31 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_32 * __pyx_v_Phi_0.strides[2]) )))))) - (2.0 * cos((*((double *) ( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_Phi_0.data + __pyx_t_33 * __pyx_v_Phi_0.strides[0]) ) + __pyx_t_34 * __pyx_v_Phi_0.strides[1]) ) + __pyx_t_35 * __pyx_v_Phi_0.strides[2]) )))))))));
+945:                                 + sin(Phi_T) * (sin(Phi_T) - 2.0 * sin(Phi_0[ff,ss,ll])
            __pyx_t_22 = __pyx_v_ff;
            __pyx_t_23 = __pyx_v_ss;
            __pyx_t_29 = __pyx_v_ll;
+946:                                                 + 2.0 * cos(Phi_T) * cos(Phi_0[ff,ss,ll])
            __pyx_t_30 = __pyx_v_ff;
            __pyx_t_31 = __pyx_v_ss;
            __pyx_t_32 = __pyx_v_ll;
+947:                                                 - 2.0 * cos(Phi_0[ff,ss,ll])
            __pyx_t_33 = __pyx_v_ff;
            __pyx_t_34 = __pyx_v_ss;
            __pyx_t_35 = __pyx_v_ll;
 948:                                                 )
 949:                             )
 950:                         )
+951:                         pta_snr_sq += coef*(term1 + term2 + term3) # sum snr^2 of all pulsars for a single source
            __pyx_v_pta_snr_sq = (__pyx_v_pta_snr_sq + (__pyx_v_coef * ((__pyx_v_term1 + __pyx_v_term2) + __pyx_v_term3)));
          }
 952: 
 953:                     # set snr for a single source, using sum from all pulsars
+954:                     snr_ss[ff,rr,ss,ll] = sqrt(pta_snr_sq)
          __pyx_t_35 = __pyx_v_ff;
          __pyx_t_34 = __pyx_v_rr;
          __pyx_t_33 = __pyx_v_ss;
          __pyx_t_32 = __pyx_v_ll;
          *((double *) ( /* dim=3 */ (( /* dim=2 */ (( /* dim=1 */ (( /* dim=0 */ (__pyx_v_snr_ss.data + __pyx_t_35 * __pyx_v_snr_ss.strides[0]) ) + __pyx_t_34 * __pyx_v_snr_ss.strides[1]) ) + __pyx_t_33 * __pyx_v_snr_ss.strides[2]) ) + __pyx_t_32 * __pyx_v_snr_ss.strides[3]) )) = sqrt(__pyx_v_pta_snr_sq);
        }
      }
    }
  }
 955: 
 956: