From 1f7a9f54222128b19b42c85a9565d2ea56e1690b Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:06:37 +0300 Subject: [PATCH 01/18] trying entry point --- .../package-test-cython-as-entry.yml | 70 + CyEulerBallistic/cy_euler.html | 1607 -------- CyEulerBallistic/cy_euler.pyx | 3 +- CyEulerBallistic/trajectory_calc.html | 3599 ----------------- CyEulerBallistic/trajectory_calc.pyx | 148 +- CyEulerBallistic/trajectory_data.html | 1500 ------- CyEulerBallistic/trajectory_data.pxd | 16 +- CyEulerBallistic/trajectory_data.pyi | 14 +- CyEulerBallistic/trajectory_data.pyx | 11 +- CyEulerBallistic/vector.html | 2461 ----------- pyproject.toml | 3 + 11 files changed, 210 insertions(+), 9222 deletions(-) create mode 100644 .github/workflows/package-test-cython-as-entry.yml delete mode 100644 CyEulerBallistic/cy_euler.html delete mode 100644 CyEulerBallistic/trajectory_calc.html delete mode 100644 CyEulerBallistic/trajectory_data.html delete mode 100644 CyEulerBallistic/vector.html diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml new file mode 100644 index 0000000..9fccb2c --- /dev/null +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -0,0 +1,70 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python cythonized package tests (uv) + +on: + pull_request: + branches: + - '*' + workflow_dispatch: + + +jobs: + test: + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest, macos-13, macos-14 ] + python-version: ["3.9", "3.10", "3.11", "3.12"] + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Install uv and set the python version ${{ matrix.python-version }} + uses: astral-sh/setup-uv@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + uv sync --dev + + - name: Build cython modules + run: | + uv pip install -e .[dev] + + - name: Install from pr #170 + run: | + uv pip uninstall py_ballisticcalc + git clone -b engine_entry_point https://github.com/o-murphy/py-ballisticcalc.git + cd py-ballisticcalc + uv pip install -e .[dev] + cd ../ + + - name: Run unittest tests in binary mode + run: | + cd py-ballisticcalc + pytest tests --no-header --no-summary -v --engine CyEulerBallistic + if [ $? -ne 0 ]; then + echo "Pytest failed, running without capture" + pytest tests -v --engine CyEulerBallistic + else + echo "Pytest succeeded." + fi + shell: bash + if: runner.os != 'Windows' + + - name: Run unittest tests in binary mode on Windows + run: | + cd py-ballisticcalc + pytest tests --no-header --no-summary -v --engine CyEulerBallistic + if %ERRORLEVEL% neq 0 ( + echo Pytest failed, running without capture + pytest tests -v --engine CyEulerBallistic + ) else ( + echo Pytest succeeded. + ) + shell: cmd + if: runner.os == 'Windows' diff --git a/CyEulerBallistic/cy_euler.html b/CyEulerBallistic/cy_euler.html deleted file mode 100644 index 0c256a1..0000000 --- a/CyEulerBallistic/cy_euler.html +++ /dev/null @@ -1,1607 +0,0 @@ - - - - - - Cython: cy_euler.pyx - - - -

Generated by Cython 3.0.12

-

- 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: cy_euler.c

-
+001: # noinspection PyUnresolvedReferences
-
  __pyx_t_2 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_2) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
 002: from cython cimport final
-
 003: from libc.stdlib cimport malloc, free
-
 004: from libc.math cimport fabs, pow, atan2, exp, sqrt, sin, cos
-
 005: from CyEulerBallistic.vector cimport CVector
-
+006: import warnings
-
  __pyx_t_2 = __Pyx_ImportDottedModule(__pyx_n_s_warnings, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_warnings, __pyx_t_2) < 0) __PYX_ERR(0, 6, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
 007: 
-
 008: @final
-
+009: cdef Config_t config_bind(object config):
-
static struct __pyx_t_16CyEulerBallistic_8cy_euler_Config_t __pyx_f_16CyEulerBallistic_8cy_euler_config_bind(PyObject *__pyx_v_config) {
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_Config_t __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.config_bind", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 010:     return Config_t(
-
+011:         config.max_calc_step_size_feet,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_max_calc_step_size_feet); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 11, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 11, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.max_calc_step_size_feet = __pyx_t_3;
-
+012:         config.chart_resolution,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_chart_resolution); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 12, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 12, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.chart_resolution = __pyx_t_3;
-
+013:         config.cZeroFindingAccuracy,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cZeroFindingAccuracy); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 13, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cZeroFindingAccuracy = __pyx_t_3;
-
+014:         config.cMinimumVelocity,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cMinimumVelocity); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cMinimumVelocity = __pyx_t_3;
-
+015:         config.cMaximumDrop,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cMaximumDrop); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 15, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 15, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cMaximumDrop = __pyx_t_3;
-
+016:         config.cMaxIterations,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cMaxIterations); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 16, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_4 = __Pyx_PyInt_As_int(__pyx_t_2); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cMaxIterations = __pyx_t_4;
-
+017:         config.cGravityConstant,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cGravityConstant); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 17, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cGravityConstant = __pyx_t_3;
-
+018:         config.cMinimumAltitude,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_config, __pyx_n_s_cMinimumAltitude); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 18, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 18, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.cMinimumAltitude = __pyx_t_3;
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 019:     )
-
 020: 
-
+021: cdef double cy_get_calc_step(Config_t * config, double step = 0):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_get_calc_step(struct __pyx_t_16CyEulerBallistic_8cy_euler_Config_t *__pyx_v_config, struct __pyx_opt_args_16CyEulerBallistic_8cy_euler_cy_get_calc_step *__pyx_optional_args) {
-  double __pyx_v_step = ((double)0.0);
-  double __pyx_v_preferred_step;
-  double __pyx_r;
-  if (__pyx_optional_args) {
-    if (__pyx_optional_args->__pyx_n > 0) {
-      __pyx_v_step = __pyx_optional_args->step;
-    }
-  }
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+022:     cdef double preferred_step = config.max_calc_step_size_feet
-
  __pyx_t_1 = __pyx_v_config->max_calc_step_size_feet;
-  __pyx_v_preferred_step = __pyx_t_1;
-
+023:     if step == 0:
-
  __pyx_t_2 = (__pyx_v_step == 0.0);
-  if (__pyx_t_2) {
-/* … */
-  }
-
+024:         return preferred_step / 2.0
-
    __pyx_r = (__pyx_v_preferred_step / 2.0);
-    goto __pyx_L0;
-
+025:     return min(step, preferred_step) / 2.0
-
  __pyx_t_1 = __pyx_v_preferred_step;
-  __pyx_t_3 = __pyx_v_step;
-  __pyx_t_2 = (__pyx_t_1 < __pyx_t_3);
-  if (__pyx_t_2) {
-    __pyx_t_4 = __pyx_t_1;
-  } else {
-    __pyx_t_4 = __pyx_t_3;
-  }
-  __pyx_r = (__pyx_t_4 / 2.0);
-  goto __pyx_L0;
-
 026: 
-
+027: cdef MachList_t cy_table_to_mach(list[object] data):
-
static struct __pyx_t_16CyEulerBallistic_8cy_euler_MachList_t __pyx_f_16CyEulerBallistic_8cy_euler_cy_table_to_mach(PyObject *__pyx_v_data) {
-  int __pyx_v_data_len;
-  double *__pyx_v_result;
-  int __pyx_v_i;
-  PyObject *__pyx_v_dp = 0;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_MachList_t __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.cy_table_to_mach", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_dp);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+028:     cdef int data_len = len(data)
-
  if (unlikely(__pyx_v_data == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    __PYX_ERR(0, 28, __pyx_L1_error)
-  }
-  __pyx_t_1 = __Pyx_PyList_GET_SIZE(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 28, __pyx_L1_error)
-  __pyx_v_data_len = __pyx_t_1;
-
+029:     cdef double * result = <double *> malloc(data_len * sizeof(double))
-
  __pyx_v_result = ((double *)malloc((__pyx_v_data_len * (sizeof(double)))));
-
+030:     if result is NULL:
-
  __pyx_t_2 = (__pyx_v_result == NULL);
-  if (unlikely(__pyx_t_2)) {
-/* … */
-  }
-
+031:         raise MemoryError("Unable to allocate memory for result array")
-
    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_MemoryError, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 31, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 31, __pyx_L1_error)
-/* … */
-  __pyx_tuple_ = PyTuple_Pack(1, __pyx_kp_u_Unable_to_allocate_memory_for_re); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 31, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple_);
-  __Pyx_GIVEREF(__pyx_tuple_);
-
 032: 
-
 033:     cdef int i
-
 034:     cdef object dp  # Assuming dp is an object with a Mach attribute
-
 035: 
-
 036:     # Populate the C array
-
+037:     for i in range(data_len):
-
  __pyx_t_4 = __pyx_v_data_len;
-  __pyx_t_5 = __pyx_t_4;
-  for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
-    __pyx_v_i = __pyx_t_6;
-
+038:         dp = data[i]
-
    if (unlikely(__pyx_v_data == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 38, __pyx_L1_error)
-    }
-    __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_data, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 38, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_XDECREF_SET(__pyx_v_dp, __pyx_t_3);
-    __pyx_t_3 = 0;
-
+039:         result[i] = dp.Mach  # Access the Mach attribute and store it in the C array
-
    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_dp, __pyx_n_s_Mach); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 39, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 39, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    (__pyx_v_result[__pyx_v_i]) = __pyx_t_7;
-  }
-
 040: 
-
 041:     return MachList_t(
-
+042:         array=result,
-
  __pyx_t_8.array = __pyx_v_result;
-
+043:         length=data_len
-
  __pyx_t_8.length = __pyx_v_data_len;
-  __pyx_r = __pyx_t_8;
-  goto __pyx_L0;
-
 044:     )
-
 045: 
-
+046: cdef Curve_t cy_calculate_curve(list[object] data_points):
-
static struct __pyx_t_16CyEulerBallistic_8cy_euler_Curve_t __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_curve(PyObject *__pyx_v_data_points) {
-  double __pyx_v_rate;
-  double __pyx_v_x1;
-  double __pyx_v_x2;
-  double __pyx_v_x3;
-  double __pyx_v_y1;
-  double __pyx_v_y2;
-  double __pyx_v_y3;
-  double __pyx_v_a;
-  double __pyx_v_b;
-  double __pyx_v_c;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_Curve_t __pyx_v_curve;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_CurvePoint_t *__pyx_v_curve_points;
-  int __pyx_v_i;
-  int __pyx_v_num_points;
-  int __pyx_v_len_data_points;
-  int __pyx_v_len_data_range;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_Curve_t __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.cy_calculate_curve", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 047:     cdef double rate, x1, x2, x3, y1, y2, y3, a, b, c
-
 048:     cdef Curve_t curve
-
 049:     cdef CurvePoint_t * curve_points
-
 050:     cdef int i, num_points, len_data_points, len_data_range
-
 051: 
-
+052:     len_data_points = len(data_points)
-
  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    __PYX_ERR(0, 52, __pyx_L1_error)
-  }
-  __pyx_t_1 = __Pyx_PyList_GET_SIZE(__pyx_v_data_points); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 52, __pyx_L1_error)
-  __pyx_v_len_data_points = __pyx_t_1;
-
+053:     len_data_range = len_data_points - 1
-
  __pyx_v_len_data_range = (__pyx_v_len_data_points - 1);
-
 054: 
-
 055:     # Allocate memory for the curve_points array
-
+056:     curve_points = <CurvePoint_t *> malloc(len_data_points * sizeof(CurvePoint_t))
-
  __pyx_v_curve_points = ((struct __pyx_t_16CyEulerBallistic_8cy_euler_CurvePoint_t *)malloc((__pyx_v_len_data_points * (sizeof(struct __pyx_t_16CyEulerBallistic_8cy_euler_CurvePoint_t)))));
-
+057:     if curve_points is NULL:
-
  __pyx_t_2 = (__pyx_v_curve_points == NULL);
-  if (unlikely(__pyx_t_2)) {
-/* … */
-  }
-
+058:         raise MemoryError("Unable to allocate memory for curve points")
-
    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_MemoryError, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 58, __pyx_L1_error)
-/* … */
-  __pyx_tuple__2 = PyTuple_Pack(1, __pyx_kp_u_Unable_to_allocate_memory_for_cu); if (unlikely(!__pyx_tuple__2)) __PYX_ERR(0, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__2);
-  __Pyx_GIVEREF(__pyx_tuple__2);
-
 059: 
-
 060:     # First point: Calculate rate and initialize the first curve point
-
+061:     rate = (data_points[1].CD - data_points[0].CD) / (data_points[1].Mach - data_points[0].Mach)
-
  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 61, __pyx_L1_error)
-  }
-  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_data_points, 1, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_CD); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 61, __pyx_L1_error)
-  }
-  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_data_points, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_CD); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 61, __pyx_L1_error)
-  }
-  __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_data_points, 1, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_Mach); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 61, __pyx_L1_error)
-  }
-  __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_data_points, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_Mach); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyNumber_Subtract(__pyx_t_4, __pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = __Pyx_PyNumber_Divide(__pyx_t_3, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_v_rate = __pyx_t_7;
-
+062:     curve_points[0] = CurvePoint_t(0, rate, data_points[0].CD - data_points[0].Mach * rate)
-
  __pyx_t_8.a = 0.0;
-  __pyx_t_8.b = __pyx_v_rate;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 62, __pyx_L1_error)
-  }
-  __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_CD); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 62, __pyx_L1_error)
-  }
-  __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_Mach); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_rate); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_4 = PyNumber_Multiply(__pyx_t_3, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = PyNumber_Subtract(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_8.c = __pyx_t_7;
-  (__pyx_v_curve_points[0]) = __pyx_t_8;
-
 063: 
-
 064:     # Loop through the data points and calculate the curve points
-
+065:     for i in range(1, len_data_range):
-
  __pyx_t_9 = __pyx_v_len_data_range;
-  __pyx_t_10 = __pyx_t_9;
-  for (__pyx_t_11 = 1; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
-    __pyx_v_i = __pyx_t_11;
-
+066:         x1 = data_points[i - 1].Mach
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 66, __pyx_L1_error)
-    }
-    __pyx_t_12 = (__pyx_v_i - 1);
-    __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 66, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_Mach); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 66, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_v_x1 = __pyx_t_7;
-
+067:         x2 = data_points[i].Mach
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 67, __pyx_L1_error)
-    }
-    __pyx_t_4 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_Mach); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 67, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 67, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_v_x2 = __pyx_t_7;
-
+068:         x3 = data_points[i + 1].Mach
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 68, __pyx_L1_error)
-    }
-    __pyx_t_12 = (__pyx_v_i + 1);
-    __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 68, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_Mach); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 68, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_v_x3 = __pyx_t_7;
-
+069:         y1 = data_points[i - 1].CD
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 69, __pyx_L1_error)
-    }
-    __pyx_t_12 = (__pyx_v_i - 1);
-    __pyx_t_4 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 69, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_CD); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 69, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 69, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_v_y1 = __pyx_t_7;
-
+070:         y2 = data_points[i].CD
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 70, __pyx_L1_error)
-    }
-    __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_v_i, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 70, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_CD); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 70, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_4); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 70, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_v_y2 = __pyx_t_7;
-
+071:         y3 = data_points[i + 1].CD
-
    if (unlikely(__pyx_v_data_points == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 71, __pyx_L1_error)
-    }
-    __pyx_t_12 = (__pyx_v_i + 1);
-    __pyx_t_4 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 71, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_CD); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 71, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 71, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_v_y3 = __pyx_t_7;
-
+072:         a = ((y3 - y1) * (x2 - x1) - (y2 - y1) * (x3 - x1)) / (
-
    __pyx_v_a = ((((__pyx_v_y3 - __pyx_v_y1) * (__pyx_v_x2 - __pyx_v_x1)) - ((__pyx_v_y2 - __pyx_v_y1) * (__pyx_v_x3 - __pyx_v_x1))) / ((((__pyx_v_x3 * __pyx_v_x3) - (__pyx_v_x1 * __pyx_v_x1)) * (__pyx_v_x2 - __pyx_v_x1)) - (((__pyx_v_x2 * __pyx_v_x2) - (__pyx_v_x1 * __pyx_v_x1)) * (__pyx_v_x3 - __pyx_v_x1))));
-
 073:                 (x3 * x3 - x1 * x1) * (x2 - x1) - (x2 * x2 - x1 * x1) * (x3 - x1))
-
+074:         b = (y2 - y1 - a * (x2 * x2 - x1 * x1)) / (x2 - x1)
-
    __pyx_v_b = (((__pyx_v_y2 - __pyx_v_y1) - (__pyx_v_a * ((__pyx_v_x2 * __pyx_v_x2) - (__pyx_v_x1 * __pyx_v_x1)))) / (__pyx_v_x2 - __pyx_v_x1));
-
+075:         c = y1 - (a * x1 * x1 + b * x1)
-
    __pyx_v_c = (__pyx_v_y1 - (((__pyx_v_a * __pyx_v_x1) * __pyx_v_x1) + (__pyx_v_b * __pyx_v_x1)));
-
+076:         curve_points[i] = CurvePoint_t(a, b, c)
-
    __pyx_t_8.a = __pyx_v_a;
-    __pyx_t_8.b = __pyx_v_b;
-    __pyx_t_8.c = __pyx_v_c;
-    (__pyx_v_curve_points[__pyx_v_i]) = __pyx_t_8;
-  }
-
 077: 
-
 078:     # Last point: Calculate rate for the final point and set the last curve point
-
+079:     num_points = len_data_points
-
  __pyx_v_num_points = __pyx_v_len_data_points;
-
+080:     rate = (data_points[num_points - 1].CD - data_points[num_points - 2].CD) / \
-
  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 80, __pyx_L1_error)
-  }
-  __pyx_t_12 = (__pyx_v_num_points - 1);
-  __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_CD); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 80, __pyx_L1_error)
-  }
-  __pyx_t_12 = (__pyx_v_num_points - 2);
-  __pyx_t_6 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_CD); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = PyNumber_Subtract(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-/* … */
-  __pyx_t_3 = __Pyx_PyNumber_Divide(__pyx_t_6, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 80, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_v_rate = __pyx_t_7;
-
+081:            (data_points[num_points - 1].Mach - data_points[num_points - 2].Mach)
-
  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 81, __pyx_L1_error)
-  }
-  __pyx_t_12 = (__pyx_v_num_points - 1);
-  __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 81, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_Mach); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 81, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 81, __pyx_L1_error)
-  }
-  __pyx_t_12 = (__pyx_v_num_points - 2);
-  __pyx_t_5 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 81, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_Mach); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 81, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyNumber_Subtract(__pyx_t_4, __pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 81, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+082:     curve_points[num_points - 1] = CurvePoint_t(0, rate, data_points[num_points - 1].CD - data_points[
-
  __pyx_t_8.a = 0.0;
-  __pyx_t_8.b = __pyx_v_rate;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 82, __pyx_L1_error)
-  }
-  __pyx_t_12 = (__pyx_v_num_points - 1);
-  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 82, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_CD); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 82, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(__pyx_v_data_points == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 82, __pyx_L1_error)
-  }
-/* … */
-  __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_data_points, __pyx_t_12, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 82, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-/* … */
-  __pyx_t_3 = PyNumber_Subtract(__pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 82, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_7 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_7 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 82, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_8.c = __pyx_t_7;
-  (__pyx_v_curve_points[(__pyx_v_num_points - 1)]) = __pyx_t_8;
-
+083:         num_points - 2].Mach * rate)
-
  __pyx_t_12 = (__pyx_v_num_points - 2);
-/* … */
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_Mach); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 83, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_rate); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 83, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyNumber_Multiply(__pyx_t_6, __pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 83, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 084: 
-
 085:     # Set the length of the curve
-
+086:     curve.length = len_data_points
-
  __pyx_v_curve.length = __pyx_v_len_data_points;
-
+087:     curve.points = curve_points
-
  __pyx_v_curve.points = __pyx_v_curve_points;
-
 088: 
-
+089:     return curve
-
  __pyx_r = __pyx_v_curve;
-  goto __pyx_L0;
-
 090: 
-
+091: cdef double cy_calculate_by_curve_and_mach_list(MachList_t *mach_list, Curve_t *curve, double mach):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_by_curve_and_mach_list(struct __pyx_t_16CyEulerBallistic_8cy_euler_MachList_t *__pyx_v_mach_list, struct __pyx_t_16CyEulerBallistic_8cy_euler_Curve_t *__pyx_v_curve, double __pyx_v_mach) {
-  int __pyx_v_num_points;
-  int __pyx_v_mlo;
-  int __pyx_v_mhi;
-  int __pyx_v_mid;
-  int __pyx_v_m;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_CurvePoint_t __pyx_v_curve_m;
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 092:     cdef int num_points, mlo, mhi, mid, m
-
 093:     cdef CurvePoint_t curve_m
-
 094: 
-
 095:     # Get the number of points in the curve
-
+096:     num_points = int(curve.length)
-
  __pyx_v_num_points = ((int)__pyx_v_curve->length);
-
 097: 
-
 098:     # Set the initial range for binary search
-
+099:     mlo = 0
-
  __pyx_v_mlo = 0;
-
+100:     mhi = num_points - 2  # Assuming we have at least 2 points
-
  __pyx_v_mhi = (__pyx_v_num_points - 2);
-
 101: 
-
 102:     # Perform binary search to find the closest Mach values
-
+103:     while mhi - mlo > 1:
-
  while (1) {
-    __pyx_t_1 = ((__pyx_v_mhi - __pyx_v_mlo) > 1);
-    if (!__pyx_t_1) break;
-
+104:         mid = (mhi + mlo) // 2
-
    __pyx_v_mid = ((__pyx_v_mhi + __pyx_v_mlo) / 2);
-
+105:         if mach_list.array[mid] < mach:
-
    __pyx_t_1 = ((__pyx_v_mach_list->array[__pyx_v_mid]) < __pyx_v_mach);
-    if (__pyx_t_1) {
-/* … */
-      goto __pyx_L5;
-    }
-
+106:             mlo = mid
-
      __pyx_v_mlo = __pyx_v_mid;
-
 107:         else:
-
+108:             mhi = mid
-
    /*else*/ {
-      __pyx_v_mhi = __pyx_v_mid;
-    }
-    __pyx_L5:;
-  }
-
 109: 
-
 110:     # Determine the closest point to `mach`
-
+111:     if mach_list.array[mhi] - mach > mach - mach_list.array[mlo]:
-
  __pyx_t_1 = (((__pyx_v_mach_list->array[__pyx_v_mhi]) - __pyx_v_mach) > (__pyx_v_mach - (__pyx_v_mach_list->array[__pyx_v_mlo])));
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L6;
-  }
-
+112:         m = mlo
-
    __pyx_v_m = __pyx_v_mlo;
-
 113:     else:
-
+114:         m = mhi
-
  /*else*/ {
-    __pyx_v_m = __pyx_v_mhi;
-  }
-  __pyx_L6:;
-
 115: 
-
 116:     # Retrieve the corresponding CurvePoint_t from the curve
-
+117:     curve_m = curve.points[m]
-
  __pyx_v_curve_m = (__pyx_v_curve->points[__pyx_v_m]);
-
 118: 
-
 119:     # Return the calculated value using the curve coefficients
-
+120:     return curve_m.c + mach * (curve_m.b + curve_m.a * mach)
-
  __pyx_r = (__pyx_v_curve_m.c + (__pyx_v_mach * (__pyx_v_curve_m.b + (__pyx_v_curve_m.a * __pyx_v_mach))));
-  goto __pyx_L0;
-
 121: 
-
+122: cdef double cy_drag_by_mach(ShotData_t * t, double mach):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_drag_by_mach(struct __pyx_t_16CyEulerBallistic_8cy_euler_ShotData_t *__pyx_v_t, double __pyx_v_mach) {
-  double __pyx_v_cd;
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.cy_drag_by_mach", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 123:     """ Drag force = V^2 * Cd * AirDensity * S / 2m where:
-
 124:         cStandardDensity of Air = 0.076474 lb/ft^3
-
 125:         S is cross-section = d^2 pi/4, where d is bullet diameter in inches
-
 126:         m is bullet mass in pounds
-
 127:     bc contains m/d^2 in units lb/in^2, which we multiply by 144 to convert to lb/ft^2
-
 128:     Thus: The magic constant found here = StandardDensity * pi / (4 * 2 * 144)
-
 129:     """
-
+130:     cdef double cd = cy_calculate_by_curve_and_mach_list(&t.mach_list, &t.curve, mach)
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_by_curve_and_mach_list((&__pyx_v_t->mach_list), (&__pyx_v_t->curve), __pyx_v_mach); if (unlikely(__pyx_t_1 == ((double)-1) && PyErr_Occurred())) __PYX_ERR(0, 130, __pyx_L1_error)
-  __pyx_v_cd = __pyx_t_1;
-
+131:     return cd * 2.08551e-04 / t.bc
-
  __pyx_r = ((__pyx_v_cd * 2.08551e-04) / __pyx_v_t->bc);
-  goto __pyx_L0;
-
 132: 
-
+133: cdef double cy_spin_drift(ShotData_t * t, double time):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_spin_drift(struct __pyx_t_16CyEulerBallistic_8cy_euler_ShotData_t *__pyx_v_t, double __pyx_v_time) {
-  int __pyx_v_sign;
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 134:     """Litz spin-drift approximation
-
 135:     :param time: Time of flight
-
 136:     :return: windage due to spin drift, in feet
-
 137:     """
-
 138:     cdef int sign
-
+139:     if (t.twist != 0) and (t.stability_coefficient != 0):
-
  __pyx_t_2 = (__pyx_v_t->twist != 0.0);
-  if (__pyx_t_2) {
-  } else {
-    __pyx_t_1 = __pyx_t_2;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_2 = (__pyx_v_t->stability_coefficient != 0.0);
-  __pyx_t_1 = __pyx_t_2;
-  __pyx_L4_bool_binop_done:;
-  if (__pyx_t_1) {
-/* … */
-  }
-
+140:         sign = 1 if t.twist > 0 else -1
-
    __pyx_t_1 = (__pyx_v_t->twist > 0.0);
-    if (__pyx_t_1) {
-      __pyx_t_3 = 1;
-    } else {
-      __pyx_t_3 = -1;
-    }
-    __pyx_v_sign = __pyx_t_3;
-
+141:         return sign * (1.25 * (t.stability_coefficient + 1.2) * pow(time, 1.83)) / 12
-
    __pyx_r = ((__pyx_v_sign * ((1.25 * (__pyx_v_t->stability_coefficient + 1.2)) * pow(__pyx_v_time, 1.83))) / 12.0);
-    goto __pyx_L0;
-
+142:     return 0
-
  __pyx_r = 0.0;
-  goto __pyx_L0;
-
 143: 
-
+144: cdef void cy_update_stability_coefficient(ShotData_t * t):
-
static void __pyx_f_16CyEulerBallistic_8cy_euler_cy_update_stability_coefficient(struct __pyx_t_16CyEulerBallistic_8cy_euler_ShotData_t *__pyx_v_t) {
-  double __pyx_v_twist_rate;
-  double __pyx_v_length;
-  double __pyx_v_sd;
-  double __pyx_v_fv;
-  double __pyx_v_ft;
-  double __pyx_v_pt;
-  double __pyx_v_ftp;
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.cy_update_stability_coefficient", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-}
-
 145:     """Miller stability coefficient"""
-
 146:     cdef:
-
 147:         double twist_rate, length, sd, fv, ft, pt, ftp
-
+148:     if t.twist and t.length and t.diameter:
-
  __pyx_t_2 = (__pyx_v_t->twist != 0);
-  if (__pyx_t_2) {
-  } else {
-    __pyx_t_1 = __pyx_t_2;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_2 = (__pyx_v_t->length != 0);
-  if (__pyx_t_2) {
-  } else {
-    __pyx_t_1 = __pyx_t_2;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_2 = (__pyx_v_t->diameter != 0);
-  __pyx_t_1 = __pyx_t_2;
-  __pyx_L4_bool_binop_done:;
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L3;
-  }
-
+149:         twist_rate = fabs(t.twist) / t.diameter
-
    __pyx_v_twist_rate = (fabs(__pyx_v_t->twist) / __pyx_v_t->diameter);
-
+150:         length = t.length / t.diameter
-
    __pyx_v_length = (__pyx_v_t->length / __pyx_v_t->diameter);
-
+151:         sd = 30.0 * t.weight / (pow(twist_rate, 2) * pow(t.diameter, 3) * length * (1 + pow(length, 2)))
-
    __pyx_v_sd = ((30.0 * __pyx_v_t->weight) / (((pow(__pyx_v_twist_rate, 2.0) * pow(__pyx_v_t->diameter, 3.0)) * __pyx_v_length) * (1.0 + pow(__pyx_v_length, 2.0))));
-
+152:         fv = pow(t.muzzle_velocity / 2800, 1.0 / 3.0)
-
    __pyx_v_fv = pow((__pyx_v_t->muzzle_velocity / 2800.0), (1.0 / 3.0));
-
+153:         ft = (t.atmo._t0 * 9.0 / 5.0) + 32.0  # Convert from Celsius to Fahrenheit
-
    __pyx_v_ft = (((__pyx_v_t->atmo._t0 * 9.0) / 5.0) + 32.0);
-
+154:         pt = t.atmo._p0 / 33.8639  # Convert hPa to inHg
-
    __pyx_v_pt = (__pyx_v_t->atmo._p0 / 33.8639);
-
+155:         ftp = ((ft + 460.0) / (59.0 + 460.0)) * (29.92 / pt)
-
    __pyx_v_ftp = (((__pyx_v_ft + 460.0) / (59.0 + 460.0)) * (29.92 / __pyx_v_pt));
-
+156:         t.stability_coefficient = sd * fv * ftp
-
    __pyx_v_t->stability_coefficient = ((__pyx_v_sd * __pyx_v_fv) * __pyx_v_ftp);
-
 157:     else:
-
+158:         t.stability_coefficient = 0.0
-
  /*else*/ {
-    __pyx_v_t->stability_coefficient = 0.0;
-  }
-  __pyx_L3:;
-
+159:     print(f"Stability coefficient: {t.stability_coefficient}; {twist_rate}, {length}, {sd}, {fv}, {ft}, {pt}, {ftp}")
-
  __pyx_t_3 = PyTuple_New(16); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = 0;
-  __pyx_t_5 = 127;
-  __Pyx_INCREF(__pyx_kp_u_Stability_coefficient);
-  __pyx_t_4 += 23;
-  __Pyx_GIVEREF(__pyx_kp_u_Stability_coefficient);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_kp_u_Stability_coefficient);
-  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_t->stability_coefficient); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_t_6, __pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7);
-  __Pyx_GIVEREF(__pyx_t_7);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7);
-  __pyx_t_7 = 0;
-  __Pyx_INCREF(__pyx_kp_u__3);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__3);
-  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_kp_u__3);
-  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_twist_rate); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_6 = __Pyx_PyObject_FormatSimple(__pyx_t_7, __pyx_empty_unicode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_6);
-  __Pyx_GIVEREF(__pyx_t_6);
-  PyTuple_SET_ITEM(__pyx_t_3, 3, __pyx_t_6);
-  __pyx_t_6 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 4, __pyx_kp_u__4);
-  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_length); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_t_6, __pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7);
-  __Pyx_GIVEREF(__pyx_t_7);
-  PyTuple_SET_ITEM(__pyx_t_3, 5, __pyx_t_7);
-  __pyx_t_7 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 6, __pyx_kp_u__4);
-  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_sd); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_6 = __Pyx_PyObject_FormatSimple(__pyx_t_7, __pyx_empty_unicode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_6);
-  __Pyx_GIVEREF(__pyx_t_6);
-  PyTuple_SET_ITEM(__pyx_t_3, 7, __pyx_t_6);
-  __pyx_t_6 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 8, __pyx_kp_u__4);
-  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_fv); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_t_6, __pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7);
-  __Pyx_GIVEREF(__pyx_t_7);
-  PyTuple_SET_ITEM(__pyx_t_3, 9, __pyx_t_7);
-  __pyx_t_7 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 10, __pyx_kp_u__4);
-  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_ft); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_6 = __Pyx_PyObject_FormatSimple(__pyx_t_7, __pyx_empty_unicode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_6);
-  __Pyx_GIVEREF(__pyx_t_6);
-  PyTuple_SET_ITEM(__pyx_t_3, 11, __pyx_t_6);
-  __pyx_t_6 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 12, __pyx_kp_u__4);
-  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_pt); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_FormatSimple(__pyx_t_6, __pyx_empty_unicode); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_7) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_7);
-  __Pyx_GIVEREF(__pyx_t_7);
-  PyTuple_SET_ITEM(__pyx_t_3, 13, __pyx_t_7);
-  __pyx_t_7 = 0;
-  __Pyx_INCREF(__pyx_kp_u__4);
-  __pyx_t_4 += 2;
-  __Pyx_GIVEREF(__pyx_kp_u__4);
-  PyTuple_SET_ITEM(__pyx_t_3, 14, __pyx_kp_u__4);
-  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_ftp); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_6 = __Pyx_PyObject_FormatSimple(__pyx_t_7, __pyx_empty_unicode); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_5 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) > __pyx_t_5) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_6) : __pyx_t_5;
-  __pyx_t_4 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_6);
-  __Pyx_GIVEREF(__pyx_t_6);
-  PyTuple_SET_ITEM(__pyx_t_3, 15, __pyx_t_6);
-  __pyx_t_6 = 0;
-  __pyx_t_6 = __Pyx_PyUnicode_Join(__pyx_t_3, 16, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 159, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 160: 
-
 161: # Function to free memory for Curve_t
-
+162: cdef void free_curve(Curve_t *curve):
-
static void __pyx_f_16CyEulerBallistic_8cy_euler_free_curve(struct __pyx_t_16CyEulerBallistic_8cy_euler_Curve_t *__pyx_v_curve) {
-/* … */
-  /* function exit code */
-}
-
+163:     if curve.points is not NULL:
-
  __pyx_t_1 = (__pyx_v_curve->points != NULL);
-  if (__pyx_t_1) {
-/* … */
-  }
-
+164:         free(curve.points)
-
    free(__pyx_v_curve->points);
-
 165: 
-
 166: # Function to free memory for MachList_t
-
+167: cdef void free_mach_list(MachList_t *mach_list):
-
static void __pyx_f_16CyEulerBallistic_8cy_euler_free_mach_list(struct __pyx_t_16CyEulerBallistic_8cy_euler_MachList_t *__pyx_v_mach_list) {
-/* … */
-  /* function exit code */
-}
-
+168:     if mach_list.array is not NULL:
-
  __pyx_t_1 = (__pyx_v_mach_list->array != NULL);
-  if (__pyx_t_1) {
-/* … */
-  }
-
+169:         free(<void *> mach_list.array)
-
    free(((void *)__pyx_v_mach_list->array));
-
 170: 
-
 171: # Function to free memory for ShotData_t
-
+172: cdef void free_trajectory(ShotData_t *t):
-
static void __pyx_f_16CyEulerBallistic_8cy_euler_free_trajectory(struct __pyx_t_16CyEulerBallistic_8cy_euler_ShotData_t *__pyx_v_t) {
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.free_trajectory", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-}
-
 173:     # Free memory for curve and mach_list
-
+174:     free_curve(&t.curve)
-
  __pyx_f_16CyEulerBallistic_8cy_euler_free_curve((&__pyx_v_t->curve)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 174, __pyx_L1_error)
-
+175:     free_mach_list(&t.mach_list)
-
  __pyx_f_16CyEulerBallistic_8cy_euler_free_mach_list((&__pyx_v_t->mach_list)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 175, __pyx_L1_error)
-
 176: 
-
+177: cdef double cy_get_correction(double distance, double offset):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_get_correction(double __pyx_v_distance, double __pyx_v_offset) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+178:     if distance != 0:
-
  __pyx_t_1 = (__pyx_v_distance != 0.0);
-  if (__pyx_t_1) {
-/* … */
-  }
-
+179:         return atan2(offset, distance)
-
    __pyx_r = atan2(__pyx_v_offset, __pyx_v_distance);
-    goto __pyx_L0;
-
+180:     return 0  # better None
-
  __pyx_r = 0.0;
-  goto __pyx_L0;
-
 181: 
-
+182: cdef double cy_calculate_energy(double bullet_weight, double velocity):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_energy(double __pyx_v_bullet_weight, double __pyx_v_velocity) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+183:     return bullet_weight * pow(velocity, 2) / 450400
-
  __pyx_r = ((__pyx_v_bullet_weight * pow(__pyx_v_velocity, 2.0)) / 450400.0);
-  goto __pyx_L0;
-
 184: 
-
+185: cdef double cy_calculate_ogw(double bullet_weight, double velocity):
-
static double __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_ogw(double __pyx_v_bullet_weight, double __pyx_v_velocity) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+186:     return pow(bullet_weight, 2) * pow(velocity, 3) * 1.5e-12
-
  __pyx_r = ((pow(__pyx_v_bullet_weight, 2.0) * pow(__pyx_v_velocity, 3.0)) * 1.5e-12);
-  goto __pyx_L0;
-
 187: 
-
+188: cdef double cDegreesFtoR = 459.67
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cDegreesFtoR = 459.67;
-
+189: cdef double cDegreesCtoK = 273.15
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK = 273.15;
-
+190: cdef double cSpeedOfSoundImperial = 49.0223
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cSpeedOfSoundImperial = 49.0223;
-
+191: cdef double cSpeedOfSoundMetric = 20.0467
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cSpeedOfSoundMetric = 20.0467;
-
+192: cdef double cLapseRateKperFoot = -0.0019812
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cLapseRateKperFoot = -0.0019812;
-
+193: cdef double cLapseRateImperial = -3.56616e-03
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cLapseRateImperial = -3.56616e-03;
-
+194: cdef double cPressureExponent = 5.2559
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cPressureExponent = 5.2559;
-
+195: cdef double cLowestTempF = -130
-
  __pyx_v_16CyEulerBallistic_8cy_euler_cLowestTempF = -130.0;
-
+196: cdef double mToFeet = 3.28084
-
  __pyx_v_16CyEulerBallistic_8cy_euler_mToFeet = 3.28084;
-
 197: 
-
 198: # Function to calculate density ratio and Mach speed at altitude
-
+199: cdef void update_density_factor_and_mach_for_altitude(
-
static void __pyx_f_16CyEulerBallistic_8cy_euler_update_density_factor_and_mach_for_altitude(struct __pyx_t_16CyEulerBallistic_8cy_euler_Atmosphere_t *__pyx_v_atmo, double __pyx_v_altitude, double *__pyx_v_density_ratio, double *__pyx_v_mach) {
-  double __pyx_v_celsius;
-  double __pyx_v_kelvin;
-  double __pyx_v_pressure;
-  double __pyx_v_density_delta;
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("CyEulerBallistic.cy_euler.update_density_factor_and_mach_for_altitude", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-}
-
 200:         Atmosphere_t * atmo, double altitude, double * density_ratio, double * mach
-
 201: ):
-
 202:     """
-
 203:     :param altitude: ASL in units of feet
-
 204:     :return: density ratio and Mach 1 (fps) for the specified altitude
-
 205:     """
-
 206:     cdef double celsius, kelvin, pressure, density_delta
-
+207:     if fabs(atmo._a0 - altitude) < 30:
-
  __pyx_t_1 = (fabs((__pyx_v_atmo->_a0 - __pyx_v_altitude)) < 30.0);
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L3;
-  }
-
+208:         density_ratio[0] = atmo.density_ratio
-
    __pyx_t_2 = __pyx_v_atmo->density_ratio;
-    (__pyx_v_density_ratio[0]) = __pyx_t_2;
-
+209:         mach[0] = atmo._mach
-
    __pyx_t_2 = __pyx_v_atmo->_mach;
-    (__pyx_v_mach[0]) = __pyx_t_2;
-
 210:     else:
-
+211:         celsius = (altitude - atmo._a0) * cLapseRateKperFoot + atmo._t0
-
  /*else*/ {
-    __pyx_v_celsius = (((__pyx_v_altitude - __pyx_v_atmo->_a0) * __pyx_v_16CyEulerBallistic_8cy_euler_cLapseRateKperFoot) + __pyx_v_atmo->_t0);
-
 212: 
-
+213:         if altitude > 36089:
-
    __pyx_t_1 = (__pyx_v_altitude > 36089.0);
-    if (__pyx_t_1) {
-/* … */
-    }
-
+214:             warnings.warn("Density request for altitude above troposphere."
-
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_warnings); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 214, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_warn); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 214, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-/* … */
-      __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 214, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 215:                             " Atmospheric model not valid here.", RuntimeWarning)
-
+216:         if celsius < -cDegreesCtoK:
-
    __pyx_t_1 = (__pyx_v_celsius < (-__pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK));
-    if (__pyx_t_1) {
-/* … */
-      goto __pyx_L5;
-    }
-
+217:             warnings.warn(f"Invalid temperature: {celsius}°C. Adjusted to absolute zero "
-
      __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_warnings); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_warn); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_4 = PyTuple_New(5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_6 = 0;
-      __pyx_t_7 = 127;
-      __Pyx_INCREF(__pyx_kp_u_Invalid_temperature);
-      __pyx_t_6 += 21;
-      __Pyx_GIVEREF(__pyx_kp_u_Invalid_temperature);
-      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_kp_u_Invalid_temperature);
-      __pyx_t_8 = PyFloat_FromDouble(__pyx_v_celsius); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_9 = __Pyx_PyObject_FormatSimple(__pyx_t_8, __pyx_empty_unicode); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_7 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) > __pyx_t_7) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) : __pyx_t_7;
-      __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_9);
-      PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_9);
-      __pyx_t_9 = 0;
-      __Pyx_INCREF(__pyx_kp_u_C_Adjusted_to_absolute_zero_It_m);
-      __pyx_t_7 = (255 > __pyx_t_7) ? 255 : __pyx_t_7;
-      __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_kp_u_C_Adjusted_to_absolute_zero_It_m);
-      __Pyx_GIVEREF(__pyx_kp_u_C_Adjusted_to_absolute_zero_It_m);
-      PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_kp_u_C_Adjusted_to_absolute_zero_It_m);
-/* … */
-      __pyx_t_8 = __Pyx_PyUnicode_Join(__pyx_t_4, 5, __pyx_t_6, __pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 217, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+218:                           f"It must be >= {-cDegreesFtoR} to avoid a domain error.", RuntimeWarning)
-
      __pyx_t_9 = PyFloat_FromDouble((-__pyx_v_16CyEulerBallistic_8cy_euler_cDegreesFtoR)); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 218, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_8 = __Pyx_PyObject_FormatSimple(__pyx_t_9, __pyx_empty_unicode); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 218, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __pyx_t_7 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_8) > __pyx_t_7) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_8) : __pyx_t_7;
-      __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_8);
-      __Pyx_GIVEREF(__pyx_t_8);
-      PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_t_8);
-      __pyx_t_8 = 0;
-      __Pyx_INCREF(__pyx_kp_u_to_avoid_a_domain_error);
-      __pyx_t_6 += 25;
-      __Pyx_GIVEREF(__pyx_kp_u_to_avoid_a_domain_error);
-      PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_kp_u_to_avoid_a_domain_error);
-/* … */
-      __pyx_t_4 = NULL;
-      __pyx_t_10 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (unlikely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_4)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-          __pyx_t_10 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[3] = {__pyx_t_4, __pyx_t_8, __pyx_builtin_RuntimeWarning};
-        __pyx_t_3 = __Pyx_PyObject_FastCall(__pyx_t_5, __pyx_callargs+1-__pyx_t_10, 2+__pyx_t_10);
-        __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 217, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+219:             celsius = -cDegreesCtoK
-
      __pyx_v_celsius = (-__pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK);
-
+220:         elif celsius < atmo.cLowestTempC:
-
    __pyx_t_1 = (__pyx_v_celsius < __pyx_v_atmo->cLowestTempC);
-    if (__pyx_t_1) {
-/* … */
-    }
-    __pyx_L5:;
-
+221:             celsius = atmo.cLowestTempC
-
      __pyx_t_2 = __pyx_v_atmo->cLowestTempC;
-      __pyx_v_celsius = __pyx_t_2;
-
+222:             warnings.warn(f"Reached minimum temperature limit. Adjusted to {celsius}°C "
-
      __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_warnings); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_warn); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_6 = 0;
-      __pyx_t_7 = 127;
-      __Pyx_INCREF(__pyx_kp_u_Reached_minimum_temperature_limi);
-      __pyx_t_6 += 47;
-      __Pyx_GIVEREF(__pyx_kp_u_Reached_minimum_temperature_limi);
-      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_kp_u_Reached_minimum_temperature_limi);
-      __pyx_t_4 = PyFloat_FromDouble(__pyx_v_celsius); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_9 = __Pyx_PyObject_FormatSimple(__pyx_t_4, __pyx_empty_unicode); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_7 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) > __pyx_t_7) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) : __pyx_t_7;
-      __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9);
-      __Pyx_GIVEREF(__pyx_t_9);
-      PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_9);
-      __pyx_t_9 = 0;
-      __Pyx_INCREF(__pyx_kp_u_C_redefine_cLowestTempF_constant);
-      __pyx_t_7 = (255 > __pyx_t_7) ? 255 : __pyx_t_7;
-      __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_kp_u_C_redefine_cLowestTempF_constant);
-      __Pyx_GIVEREF(__pyx_kp_u_C_redefine_cLowestTempF_constant);
-      PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_kp_u_C_redefine_cLowestTempF_constant);
-      __pyx_t_9 = __Pyx_PyUnicode_Join(__pyx_t_5, 3, __pyx_t_6, __pyx_t_7); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-
+223:                           "redefine 'cLowestTempF' constant to increase it ", RuntimeWarning)
-
      __pyx_t_5 = NULL;
-      __pyx_t_10 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (unlikely(PyMethod_Check(__pyx_t_8))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_8);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_8, function);
-          __pyx_t_10 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[3] = {__pyx_t_5, __pyx_t_9, __pyx_builtin_RuntimeWarning};
-        __pyx_t_3 = __Pyx_PyObject_FastCall(__pyx_t_8, __pyx_callargs+1-__pyx_t_10, 2+__pyx_t_10);
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-        if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 222, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 224: 
-
+225:         kelvin = celsius + cDegreesCtoK
-
    __pyx_v_kelvin = (__pyx_v_celsius + __pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK);
-
+226:         pressure = atmo._p0 * pow(1 + cLapseRateKperFoot * (altitude - atmo._a0) / (atmo._t0 + cDegreesCtoK),
-
    __pyx_v_pressure = (__pyx_v_atmo->_p0 * pow((1.0 + ((__pyx_v_16CyEulerBallistic_8cy_euler_cLapseRateKperFoot * (__pyx_v_altitude - __pyx_v_atmo->_a0)) / (__pyx_v_atmo->_t0 + __pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK))), __pyx_v_16CyEulerBallistic_8cy_euler_cPressureExponent));
-
 227:                             cPressureExponent)
-
+228:         density_delta = ((atmo._t0 + cDegreesCtoK) * pressure) / (atmo._p0 * kelvin)
-
    __pyx_v_density_delta = (((__pyx_v_atmo->_t0 + __pyx_v_16CyEulerBallistic_8cy_euler_cDegreesCtoK) * __pyx_v_pressure) / (__pyx_v_atmo->_p0 * __pyx_v_kelvin));
-
+229:         density_ratio[0] = atmo.density_ratio * density_delta
-
    (__pyx_v_density_ratio[0]) = (__pyx_v_atmo->density_ratio * __pyx_v_density_delta);
-
 230:         # Alternative exponential approximation to density:
-
 231:         #density_ratio[0] = atmo.density_ratio * exp(-(altitude - atmo._a0) / 34112.0)
-
+232:         mach[0] = sqrt(kelvin) * cSpeedOfSoundMetric * mToFeet
-
    (__pyx_v_mach[0]) = ((sqrt(__pyx_v_kelvin) * __pyx_v_16CyEulerBallistic_8cy_euler_cSpeedOfSoundMetric) * __pyx_v_16CyEulerBallistic_8cy_euler_mToFeet);
-  }
-  __pyx_L3:;
-
 233:         #debug
-
 234:         #print(f"Altitude: {altitude}, {atmo._t0}°C now {celsius}°C, pressure {atmo._p0} now {pressure}hPa >> {density_ratio[0]} from density_delta {density_delta}")
-
 235: 
-
+236: cdef CVector wind_to_c_vector(Wind_t * w):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_8cy_euler_wind_to_c_vector(struct __pyx_t_16CyEulerBallistic_8cy_euler_Wind_t *__pyx_v_w) {
-  double __pyx_v_range_component;
-  double __pyx_v_cross_component;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 237:     cdef:
-
 238:         # Downrange (x-axis) wind velocity component:
-
+239:         double range_component = w.velocity * cos(w.direction_from)
-
  __pyx_v_range_component = (__pyx_v_w->velocity * cos(__pyx_v_w->direction_from));
-
 240:         # Downrange (x-axis) wind velocity component:
-
+241:         double cross_component = w.velocity * sin(w.direction_from)
-
  __pyx_v_cross_component = (__pyx_v_w->velocity * sin(__pyx_v_w->direction_from));
-
+242:     return CVector(range_component, 0., cross_component)
-
  __pyx_t_1.x = __pyx_v_range_component;
-  __pyx_t_1.y = 0.;
-  __pyx_t_1.z = __pyx_v_cross_component;
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 243: 
-
 244: # cdef void free_trajectory(ShotData_t * t):
-
 245: #     if t.mach_list != NULL:
-
 246: #         if t.mach_list.array != NULL:
-
 247: #             free(t.mach_list.array)  # Free the array inside MachList_t
-
 248: #             t.mach_list.array = NULL  # Avoid dangling pointer
-
 249: #
-
 250: #         free(t.mach_list)  # Free the MachList_t struct itself
-
 251: #         t.mach_list = NULL  # Avoid dangling pointer
-
 252: 
-
 253: 
-
 254: #
-
 255: # # Function to calculate the curve
-
 256: # cdef Curve_t calculate_curve(list[object] data_points):
-
 257: #     cdef double rate, x1, x2, x3, y1, y2, y3, a, b, c
-
 258: #     cdef Curve_t curve
-
 259: #     cdef int i, num_points, len_data_points, len_data_range
-
 260: #
-
 261: #     len_data_points = len(data_points)
-
 262: #     len_data_range = len_data_points - 1
-
 263: #
-
 264: #     # Allocate memory for the memory view (typed array of CurvePoint_t)
-
 265: #     curve.points = <CurvePoint_t[:]>malloc(len_data_points * sizeof(CurvePoint_t))
-
 266: #     if curve.points is NULL:
-
 267: #         raise MemoryError("Unable to allocate memory for curve points")
-
 268: #
-
 269: #     # First point: Calculate rate and initialize the first curve point
-
 270: #     rate = (data_points[1].CD - data_points[0].CD) / (data_points[1].Mach - data_points[0].Mach)
-
 271: #     curve.points[0] = CurvePoint_t(0, rate, data_points[0].CD - data_points[0].Mach * rate)
-
 272: #
-
 273: #     # Loop through the data points and calculate the curve points
-
 274: #     for i in range(1, len_data_range):
-
 275: #         x1 = data_points[i - 1].Mach
-
 276: #         x2 = data_points[i].Mach
-
 277: #         x3 = data_points[i + 1].Mach
-
 278: #         y1 = data_points[i - 1].CD
-
 279: #         y2 = data_points[i].CD
-
 280: #         y3 = data_points[i + 1].CD
-
 281: #         a = ((y3 - y1) * (x2 - x1) - (y2 - y1) * (x3 - x1)) / (
-
 282: #                 (x3 * x3 - x1 * x1) * (x2 - x1) - (x2 * x2 - x1 * x1) * (x3 - x1))
-
 283: #         b = (y2 - y1 - a * (x2 * x2 - x1 * x1)) / (x2 - x1)
-
 284: #         c = y1 - (a * x1 * x1 + b * x1)
-
 285: #         curve.points[i] = CurvePoint_t(a, b, c)
-
 286: #
-
 287: #     # Last point: Calculate rate for the final point and set the last curve point
-
 288: #     num_points = len_data_points
-
 289: #     rate = (data_points[num_points - 1].CD - data_points[num_points - 2].CD) / \
-
 290: #            (data_points[num_points - 1].Mach - data_points[num_points - 2].Mach)
-
 291: #     curve.points[len_data_points - 1] = CurvePoint_t(0, rate, data_points[num_points - 1].CD - data_points[num_points - 1].Mach * rate)
-
 292: #
-
 293: #     return curve
-
diff --git a/CyEulerBallistic/cy_euler.pyx b/CyEulerBallistic/cy_euler.pyx index ee0c121..03e9e45 100644 --- a/CyEulerBallistic/cy_euler.pyx +++ b/CyEulerBallistic/cy_euler.pyx @@ -145,7 +145,7 @@ cdef void cy_update_stability_coefficient(ShotData_t * t): """Miller stability coefficient""" cdef: double twist_rate, length, sd, fv, ft, pt, ftp - if t.twist and t.length and t.diameter: + if t.twist and t.length and t.diameter and t.atmo._p0: twist_rate = fabs(t.twist) / t.diameter length = t.length / t.diameter sd = 30.0 * t.weight / (pow(twist_rate, 2) * pow(t.diameter, 3) * length * (1 + pow(length, 2))) @@ -156,7 +156,6 @@ cdef void cy_update_stability_coefficient(ShotData_t * t): t.stability_coefficient = sd * fv * ftp else: t.stability_coefficient = 0.0 - print(f"Stability coefficient: {t.stability_coefficient}; {twist_rate}, {length}, {sd}, {fv}, {ft}, {pt}, {ftp}") # Function to free memory for Curve_t cdef void free_curve(Curve_t *curve): diff --git a/CyEulerBallistic/trajectory_calc.html b/CyEulerBallistic/trajectory_calc.html deleted file mode 100644 index ef44705..0000000 --- a/CyEulerBallistic/trajectory_calc.html +++ /dev/null @@ -1,3599 +0,0 @@ - - - - - - Cython: trajectory_calc.pyx - - - -

Generated by Cython 3.0.12

-

- 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: trajectory_calc.c

-
+001: """
-
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_3) < 0) __PYX_ERR(1, 1, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 002: # Total Score: 2394, Possible Score: 45200
-
 003: # Total Non-Empty Lines: 452
-
 004: # Python Overhead Lines: 152
-
 005: # Cythonization Percentage: 94.70%
-
 006: # Python Overhead Lines Percentage: 33.63%
-
 007: """
-
 008: 
-
 009: # noinspection PyUnresolvedReferences
-
 010: from cython cimport final
-
 011: from libc.math cimport fabs, sin, cos, tan, atan, atan2
-
 012: # noinspection PyUnresolvedReferences
-
 013: from CyEulerBallistic.vector cimport CVector, add, sub, mag, mul_c, mul_v, neg, norm, mag
-
 014: # noinspection PyUnresolvedReferences
-
 015: from CyEulerBallistic.trajectory_data cimport CTrajFlag, TrajectoryData
-
 016: # noinspection PyUnresolvedReferences
-
 017: from CyEulerBallistic.cy_euler cimport (
-
 018:     Config_t,
-
 019:     Wind_t,
-
 020:     Atmosphere_t,
-
 021:     ShotData_t,
-
 022:     config_bind,
-
 023:     update_density_factor_and_mach_for_altitude,
-
 024:     cy_table_to_mach,
-
 025:     cy_calculate_curve,
-
 026:     cy_calculate_by_curve_and_mach_list,
-
 027:     cy_spin_drift,
-
 028:     cy_drag_by_mach,
-
 029:     cy_get_correction,
-
 030:     cy_calculate_energy,
-
 031:     cy_calculate_ogw,
-
 032:     cy_update_stability_coefficient,
-
 033:     free_trajectory,
-
 034:     wind_to_c_vector,
-
 035: )
-
 036: 
-
+037: import warnings
-
  __pyx_t_2 = __Pyx_ImportDottedModule(__pyx_n_s_warnings, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 37, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_warnings, __pyx_t_2) < 0) __PYX_ERR(1, 37, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
 038: 
-
+039: from py_ballisticcalc.logger import logger
-
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 39, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(__pyx_n_s_logger);
-  __Pyx_GIVEREF(__pyx_n_s_logger);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_logger)) __PYX_ERR(1, 39, __pyx_L1_error);
-  __pyx_t_3 = __Pyx_Import(__pyx_n_s_py_ballisticcalc_logger, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 39, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_logger); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 39, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_logger, __pyx_t_2) < 0) __PYX_ERR(1, 39, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+040: from py_ballisticcalc.unit import Angular, Unit, Velocity, Distance, Energy, Weight
-
  __pyx_t_3 = PyList_New(6); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_n_s_Angular);
-  __Pyx_GIVEREF(__pyx_n_s_Angular);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 0, __pyx_n_s_Angular)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_Unit);
-  __Pyx_GIVEREF(__pyx_n_s_Unit);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 1, __pyx_n_s_Unit)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_Velocity);
-  __Pyx_GIVEREF(__pyx_n_s_Velocity);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 2, __pyx_n_s_Velocity)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_Distance);
-  __Pyx_GIVEREF(__pyx_n_s_Distance);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 3, __pyx_n_s_Distance)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_Energy);
-  __Pyx_GIVEREF(__pyx_n_s_Energy);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 4, __pyx_n_s_Energy)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_Weight);
-  __Pyx_GIVEREF(__pyx_n_s_Weight);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 5, __pyx_n_s_Weight)) __PYX_ERR(1, 40, __pyx_L1_error);
-  __pyx_t_2 = __Pyx_Import(__pyx_n_s_py_ballisticcalc_unit, __pyx_t_3, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Angular); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Angular, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Unit); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Unit, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Velocity); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Velocity, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Distance); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Distance, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Energy); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Energy, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_Weight); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_Weight, __pyx_t_3) < 0) __PYX_ERR(1, 40, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+041: from py_ballisticcalc.exceptions import ZeroFindingError, RangeError
-
  __pyx_t_2 = PyList_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(__pyx_n_s_ZeroFindingError);
-  __Pyx_GIVEREF(__pyx_n_s_ZeroFindingError);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_ZeroFindingError)) __PYX_ERR(1, 41, __pyx_L1_error);
-  __Pyx_INCREF(__pyx_n_s_RangeError);
-  __Pyx_GIVEREF(__pyx_n_s_RangeError);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 1, __pyx_n_s_RangeError)) __PYX_ERR(1, 41, __pyx_L1_error);
-  __pyx_t_3 = __Pyx_Import(__pyx_n_s_py_ballisticcalc_exceptions, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_ZeroFindingError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_ZeroFindingError, __pyx_t_2) < 0) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_RangeError); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_RangeError, __pyx_t_2) < 0) __PYX_ERR(1, 41, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+042: from py_ballisticcalc.constants import cMaxWindDistanceFeet
-
  __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 42, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_n_s_cMaxWindDistanceFeet);
-  __Pyx_GIVEREF(__pyx_n_s_cMaxWindDistanceFeet);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_3, 0, __pyx_n_s_cMaxWindDistanceFeet)) __PYX_ERR(1, 42, __pyx_L1_error);
-  __pyx_t_2 = __Pyx_Import(__pyx_n_s_py_ballisticcalc_constants, __pyx_t_3, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 42, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_ImportFrom(__pyx_t_2, __pyx_n_s_cMaxWindDistanceFeet); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 42, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_cMaxWindDistanceFeet, __pyx_t_3) < 0) __PYX_ERR(1, 42, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+043: from bisect import bisect_left
-
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 43, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(__pyx_n_s_bisect_left);
-  __Pyx_GIVEREF(__pyx_n_s_bisect_left);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_bisect_left)) __PYX_ERR(1, 43, __pyx_L1_error);
-  __pyx_t_3 = __Pyx_Import(__pyx_n_s_bisect, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 43, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_bisect_left); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 43, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_bisect_left, __pyx_t_2) < 0) __PYX_ERR(1, 43, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 044: 
-
 045: 
-
 046: __all__ = (
-
+047:     'EulerTrajectoryCalc',
-
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__7) < 0) __PYX_ERR(1, 46, __pyx_L1_error)
-
 048: )
-
 049: 
-
 050: 
-
 051: @final
-
+052: cdef class _TrajectoryDataFilter:
-
struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter {
-  PyObject_HEAD
-  struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_vtab;
-  int filter;
-  int current_flag;
-  int seen_zero;
-  int current_item;
-  double previous_mach;
-  double previous_time;
-  double next_range_distance;
-  double range_step;
-  double time_step;
-  double look_angle;
-};
-/* … */
-struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter {
-  void (*setup_seen_zero)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double, double);
-  void (*clear_current_flag)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *);
-  int (*should_record)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, struct __pyx_t_16CyEulerBallistic_6vector_CVector, double, double, double);
-  int (*check_next_range)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double);
-  void (*check_next_time)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double);
-  void (*check_mach_crossing)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double);
-  void (*check_zero_crossing)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, struct __pyx_t_16CyEulerBallistic_6vector_CVector);
-};
-static struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_vtabptr_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter;
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_setup_seen_zero(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double, double);
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_clear_current_flag(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *);
-static int __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_should_record(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, struct __pyx_t_16CyEulerBallistic_6vector_CVector, double, double, double);
-static int __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_range(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double);
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_time(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double);
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_mach_crossing(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, double, double);
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_zero_crossing(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *, struct __pyx_t_16CyEulerBallistic_6vector_CVector);
-
-
 053:     cdef:
-
 054:         int filter, current_flag, seen_zero
-
 055:         int current_item
-
 056:         double previous_mach, previous_time, next_range_distance, range_step, time_step, look_angle
-
 057: 
-
+058:     def __cinit__(_TrajectoryDataFilter self,
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  int __pyx_v_filter_flags;
-  double __pyx_v_range_step;
-  double __pyx_v_time_step;
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_filter_flags,&__pyx_n_s_range_step,&__pyx_n_s_time_step,0};
-  PyObject* values[3] = {0,0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_filter_flags)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 58, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_range_step)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 58, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, 1); __PYX_ERR(1, 58, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_time_step);
-          if (value) { values[2] = __Pyx_Arg_NewRef_VARARGS(value); kw_args--; }
-          else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 58, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "__cinit__") < 0)) __PYX_ERR(1, 58, __pyx_L3_error)
-      }
-    } else {
-      switch (__pyx_nargs) {
-        case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-        values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-    }
-    __pyx_v_filter_flags = __Pyx_PyInt_As_int(values[0]); if (unlikely((__pyx_v_filter_flags == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 59, __pyx_L3_error)
-    __pyx_v_range_step = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_range_step == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 59, __pyx_L3_error)
-    if (values[2]) {
-      __pyx_v_time_step = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_time_step == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 59, __pyx_L3_error)
-    } else {
-      __pyx_v_time_step = ((double)0.0);
-    }
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 0, 2, 3, __pyx_nargs); __PYX_ERR(1, 58, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._TrajectoryDataFilter.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter___cinit__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *)__pyx_v_self), __pyx_v_filter_flags, __pyx_v_range_step, __pyx_v_time_step);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter___cinit__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, int __pyx_v_filter_flags, double __pyx_v_range_step, double __pyx_v_time_step) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  return __pyx_r;
-}
-
 059:                   int filter_flags, double range_step, double time_step = 0.0) -> None:
-
+060:         self.filter = filter_flags
-
  __pyx_v_self->filter = __pyx_v_filter_flags;
-
+061:         self.current_flag = CTrajFlag.NONE
-
  __pyx_v_self->current_flag = __pyx_e_16CyEulerBallistic_15trajectory_data_NONE;
-
+062:         self.seen_zero = CTrajFlag.NONE
-
  __pyx_v_self->seen_zero = __pyx_e_16CyEulerBallistic_15trajectory_data_NONE;
-
+063:         self.time_step = time_step
-
  __pyx_v_self->time_step = __pyx_v_time_step;
-
+064:         self.range_step = range_step
-
  __pyx_v_self->range_step = __pyx_v_range_step;
-
+065:         self.previous_mach = 0.0
-
  __pyx_v_self->previous_mach = 0.0;
-
+066:         self.previous_time = 0.0
-
  __pyx_v_self->previous_time = 0.0;
-
+067:         self.next_range_distance = 0.0
-
  __pyx_v_self->next_range_distance = 0.0;
-
+068:         self.look_angle = 0
-
  __pyx_v_self->look_angle = 0.0;
-
 069: 
-
+070:     cdef void setup_seen_zero(_TrajectoryDataFilter self, double height, double barrel_elevation, double look_angle):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_setup_seen_zero(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, double __pyx_v_height, double __pyx_v_barrel_elevation, double __pyx_v_look_angle) {
-/* … */
-  /* function exit code */
-}
-
+071:         if height >= 0:
-
  __pyx_t_1 = (__pyx_v_height >= 0.0);
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L3;
-  }
-
+072:             self.seen_zero |= CTrajFlag.ZERO_UP
-
    __pyx_v_self->seen_zero = (__pyx_v_self->seen_zero | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_UP);
-
+073:         elif height < 0 and barrel_elevation < look_angle:
-
  __pyx_t_2 = (__pyx_v_height < 0.0);
-  if (__pyx_t_2) {
-  } else {
-    __pyx_t_1 = __pyx_t_2;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_2 = (__pyx_v_barrel_elevation < __pyx_v_look_angle);
-  __pyx_t_1 = __pyx_t_2;
-  __pyx_L4_bool_binop_done:;
-  if (__pyx_t_1) {
-/* … */
-  }
-  __pyx_L3:;
-
+074:             self.seen_zero |= CTrajFlag.ZERO_DOWN
-
    __pyx_v_self->seen_zero = (__pyx_v_self->seen_zero | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_DOWN);
-
+075:         self.look_angle = look_angle
-
  __pyx_v_self->look_angle = __pyx_v_look_angle;
-
 076: 
-
+077:     cdef void clear_current_flag(_TrajectoryDataFilter self):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_clear_current_flag(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self) {
-/* … */
-  /* function exit code */
-}
-
+078:         self.current_flag = CTrajFlag.NONE
-
  __pyx_v_self->current_flag = __pyx_e_16CyEulerBallistic_15trajectory_data_NONE;
-
 079: 
-
+080:     cdef bint should_record(_TrajectoryDataFilter self,
-
static int __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_should_record(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_range_vector, double __pyx_v_velocity, double __pyx_v_mach, double __pyx_v_time) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._TrajectoryDataFilter.should_record", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 081:                             CVector range_vector,
-
 082:                             double velocity,
-
 083:                             double mach,
-
 084:                             double time,
-
 085:                             ):
-
+086:         self.check_zero_crossing(range_vector)
-
  __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_zero_crossing(__pyx_v_self, __pyx_v_range_vector); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 86, __pyx_L1_error)
-
+087:         self.check_mach_crossing(velocity, mach)
-
  __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_mach_crossing(__pyx_v_self, __pyx_v_velocity, __pyx_v_mach); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 87, __pyx_L1_error)
-
+088:         if self.check_next_range(range_vector.x, self.range_step):
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_range(__pyx_v_self, __pyx_v_range_vector.x, __pyx_v_self->range_step); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 88, __pyx_L1_error)
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L3;
-  }
-
+089:             self.previous_time = time
-
    __pyx_v_self->previous_time = __pyx_v_time;
-
+090:         elif self.time_step > 0:
-
  __pyx_t_1 = (__pyx_v_self->time_step > 0.0);
-  if (__pyx_t_1) {
-/* … */
-  }
-  __pyx_L3:;
-
+091:             self.check_next_time(time)
-
    __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_time(__pyx_v_self, __pyx_v_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 91, __pyx_L1_error)
-
+092:         return (self.current_flag & self.filter) != 0
-
  __pyx_r = ((__pyx_v_self->current_flag & __pyx_v_self->filter) != 0);
-  goto __pyx_L0;
-
 093: 
-
+094:     cdef bint check_next_range(_TrajectoryDataFilter self, double next_range, double step):
-
static int __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_range(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, double __pyx_v_next_range, double __pyx_v_step) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
 095:         # Next range check
-
+096:         if next_range >= self.next_range_distance:
-
  __pyx_t_1 = (__pyx_v_next_range >= __pyx_v_self->next_range_distance);
-  if (__pyx_t_1) {
-/* … */
-  }
-
+097:             self.current_flag |= CTrajFlag.RANGE
-
    __pyx_v_self->current_flag = (__pyx_v_self->current_flag | __pyx_e_16CyEulerBallistic_15trajectory_data_RANGE);
-
+098:             self.next_range_distance += step
-
    __pyx_v_self->next_range_distance = (__pyx_v_self->next_range_distance + __pyx_v_step);
-
+099:             return True
-
    __pyx_r = 1;
-    goto __pyx_L0;
-
+100:         return False
-
  __pyx_r = 0;
-  goto __pyx_L0;
-
 101: 
-
+102:     cdef void check_next_time(self, double time):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_next_time(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, double __pyx_v_time) {
-/* … */
-  /* function exit code */
-}
-
+103:         if time > self.previous_time + self.time_step:
-
  __pyx_t_1 = (__pyx_v_time > (__pyx_v_self->previous_time + __pyx_v_self->time_step));
-  if (__pyx_t_1) {
-/* … */
-  }
-
+104:             self.current_flag |= CTrajFlag.RANGE
-
    __pyx_v_self->current_flag = (__pyx_v_self->current_flag | __pyx_e_16CyEulerBallistic_15trajectory_data_RANGE);
-
+105:             self.previous_time = time
-
    __pyx_v_self->previous_time = __pyx_v_time;
-
 106: 
-
+107:     cdef void check_mach_crossing(_TrajectoryDataFilter self, double velocity, double mach):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_mach_crossing(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, double __pyx_v_velocity, double __pyx_v_mach) {
-  double __pyx_v_current_mach;
-/* … */
-  /* function exit code */
-}
-
 108:         # Mach crossing check
-
+109:         cdef double current_mach = velocity / mach
-
  __pyx_v_current_mach = (__pyx_v_velocity / __pyx_v_mach);
-
+110:         if self.previous_mach > 1 >= current_mach:
-
  __pyx_t_1 = (__pyx_v_self->previous_mach > 1.0);
-  if (__pyx_t_1) {
-    __pyx_t_1 = (1.0 >= __pyx_v_current_mach);
-  }
-  if (__pyx_t_1) {
-/* … */
-  }
-
+111:             self.current_flag |= CTrajFlag.MACH
-
    __pyx_v_self->current_flag = (__pyx_v_self->current_flag | __pyx_e_16CyEulerBallistic_15trajectory_data_MACH);
-
+112:         self.previous_mach = current_mach
-
  __pyx_v_self->previous_mach = __pyx_v_current_mach;
-
 113: 
-
+114:     cdef void check_zero_crossing(_TrajectoryDataFilter self, CVector range_vector):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_check_zero_crossing(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_self, struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_range_vector) {
-  double __pyx_v_reference_height;
-/* … */
-  /* function exit code */
-}
-
 115:         # Zero-crossing checks
-
 116: 
-
+117:         if range_vector.x > 0:
-
  __pyx_t_1 = (__pyx_v_range_vector.x > 0.0);
-  if (__pyx_t_1) {
-/* … */
-  }
-
 118:             # Zero reference line is the sight line defined by look_angle
-
+119:             reference_height = range_vector.x * tan(self.look_angle)
-
    __pyx_v_reference_height = (__pyx_v_range_vector.x * tan(__pyx_v_self->look_angle));
-
 120:             # If we haven't seen ZERO_UP, we look for that first
-
+121:             if not (self.seen_zero & CTrajFlag.ZERO_UP):
-
    __pyx_t_1 = (!((__pyx_v_self->seen_zero & __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_UP) != 0));
-    if (__pyx_t_1) {
-/* … */
-      goto __pyx_L4;
-    }
-
+122:                 if range_vector.x >= reference_height:
-
      __pyx_t_1 = (__pyx_v_range_vector.x >= __pyx_v_reference_height);
-      if (__pyx_t_1) {
-/* … */
-      }
-
+123:                     self.current_flag |= CTrajFlag.ZERO_UP
-
        __pyx_v_self->current_flag = (__pyx_v_self->current_flag | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_UP);
-
+124:                     self.seen_zero |= CTrajFlag.ZERO_UP
-
        __pyx_v_self->seen_zero = (__pyx_v_self->seen_zero | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_UP);
-
 125:             # We've crossed above sight line; now look for crossing back through it
-
+126:             elif not (self.seen_zero & CTrajFlag.ZERO_DOWN):
-
    __pyx_t_1 = (!((__pyx_v_self->seen_zero & __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_DOWN) != 0));
-    if (__pyx_t_1) {
-/* … */
-    }
-    __pyx_L4:;
-
+127:                 if range_vector.x < reference_height:
-
      __pyx_t_1 = (__pyx_v_range_vector.x < __pyx_v_reference_height);
-      if (__pyx_t_1) {
-/* … */
-      }
-
+128:                     self.current_flag |= CTrajFlag.ZERO_DOWN
-
        __pyx_v_self->current_flag = (__pyx_v_self->current_flag | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_DOWN);
-
+129:                     self.seen_zero |= CTrajFlag.ZERO_DOWN
-
        __pyx_v_self->seen_zero = (__pyx_v_self->seen_zero | __pyx_e_16CyEulerBallistic_15trajectory_data_ZERO_DOWN);
-
 130: 
-
 131: @final
-
+132: cdef class _WindSock:
-
struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock {
-  PyObject_HEAD
-  struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_vtab;
-  PyObject *winds;
-  int current;
-  double next_range;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector _last_vector_cache;
-  int _length;
-};
-/* … */
-struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__WindSock {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector (*current_vector)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *);
-  void (*update_cache)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *);
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector (*vector_for_range)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *, double);
-};
-static struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_vtabptr_16CyEulerBallistic_15trajectory_calc__WindSock;
-static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_current_vector(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *);
-static void __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_update_cache(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *);
-static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_vector_for_range(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *, double);
-
-
 133:     cdef:
-
 134:         list[Wind_t] winds
-
 135:         int current
-
 136:         double next_range
-
 137:         CVector _last_vector_cache
-
 138:         int _length
-
 139: 
-
+140:     def __cinit__(_WindSock self, object winds):
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_9_WindSock_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_9_WindSock_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_winds = 0;
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_winds,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_winds)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 140, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "__cinit__") < 0)) __PYX_ERR(1, 140, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-    }
-    __pyx_v_winds = values[0];
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 140, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._WindSock.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_9_WindSock___cinit__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *)__pyx_v_self), __pyx_v_winds);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_calc_9_WindSock___cinit__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_v_self, PyObject *__pyx_v_winds) {
-  PyObject *__pyx_7genexpr__pyx_v_w = NULL;
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._WindSock.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_7genexpr__pyx_v_w);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+141:         self.winds = [
-
  { /* enter inner scope */
-    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 141, __pyx_L5_error)
-    __Pyx_GOTREF(__pyx_t_1);
-/* … */
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->winds);
-  __Pyx_DECREF(__pyx_v_self->winds);
-  __pyx_v_self->winds = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+142:             Wind_t(
-
      __pyx_t_5 = __Pyx_PyDict_NewPresized(4); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 142, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_5);
-
+143:                 w.velocity.get_in(Unit.FPS),
-
      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_7genexpr__pyx_v_w, __pyx_n_s_velocity); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_get_in); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_Unit); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_FPS); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_7 = NULL;
-      __pyx_t_10 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (likely(PyMethod_Check(__pyx_t_8))) {
-        __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_8);
-        if (likely(__pyx_t_7)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_7);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_8, function);
-          __pyx_t_10 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_9};
-        __pyx_t_6 = __Pyx_PyObject_FastCall(__pyx_t_8, __pyx_callargs+1-__pyx_t_10, 1+__pyx_t_10);
-        __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-        if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 143, __pyx_L5_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-      __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_t_6 = PyFloat_FromDouble(__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 143, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_velocity, __pyx_t_6) < 0) __PYX_ERR(1, 142, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-
+144:                 w.direction_from.get_in(Unit.Radian),
-
      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_7genexpr__pyx_v_w, __pyx_n_s_direction_from); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_get_in); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_Unit); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_Radian); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_8 = NULL;
-      __pyx_t_10 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (likely(PyMethod_Check(__pyx_t_9))) {
-        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_9);
-        if (likely(__pyx_t_8)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_9);
-          __Pyx_INCREF(__pyx_t_8);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_9, function);
-          __pyx_t_10 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[2] = {__pyx_t_8, __pyx_t_7};
-        __pyx_t_6 = __Pyx_PyObject_FastCall(__pyx_t_9, __pyx_callargs+1-__pyx_t_10, 1+__pyx_t_10);
-        __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 144, __pyx_L5_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      }
-      __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_t_6 = PyFloat_FromDouble(__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 144, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_direction_from, __pyx_t_6) < 0) __PYX_ERR(1, 142, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-
+145:                 w.until_distance.get_in(Unit.Foot),
-
      __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_7genexpr__pyx_v_w, __pyx_n_s_until_distance); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_get_in); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_Unit); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_Foot); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __pyx_t_9 = NULL;
-      __pyx_t_10 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (likely(PyMethod_Check(__pyx_t_7))) {
-        __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
-        if (likely(__pyx_t_9)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-          __Pyx_INCREF(__pyx_t_9);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_7, function);
-          __pyx_t_10 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[2] = {__pyx_t_9, __pyx_t_8};
-        __pyx_t_6 = __Pyx_PyObject_FastCall(__pyx_t_7, __pyx_callargs+1-__pyx_t_10, 1+__pyx_t_10);
-        __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 145, __pyx_L5_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-      __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_t_6 = PyFloat_FromDouble(__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 145, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_until_distance, __pyx_t_6) < 0) __PYX_ERR(1, 142, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-
+146:                 w.MAX_DISTANCE_FEET
-
      __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_7genexpr__pyx_v_w, __pyx_n_s_MAX_DISTANCE_FEET); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 146, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 146, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_t_6 = PyFloat_FromDouble(__pyx_t_11); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 146, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_MAX_DISTANCE_FEET, __pyx_t_6) < 0) __PYX_ERR(1, 142, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      if (unlikely(__Pyx_ListComp_Append(__pyx_t_1, (PyObject*)__pyx_t_5))) __PYX_ERR(1, 141, __pyx_L5_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-
+147:             ) for w in winds
-
    if (likely(PyList_CheckExact(__pyx_v_winds)) || PyTuple_CheckExact(__pyx_v_winds)) {
-      __pyx_t_2 = __pyx_v_winds; __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_winds); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 147, __pyx_L5_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 147, __pyx_L5_error)
-    }
-    for (;;) {
-      if (likely(!__pyx_t_4)) {
-        if (likely(PyList_CheckExact(__pyx_t_2))) {
-          {
-            Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_2);
-            #if !CYTHON_ASSUME_SAFE_MACROS
-            if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 147, __pyx_L5_error)
-            #endif
-            if (__pyx_t_3 >= __pyx_temp) 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(1, 147, __pyx_L5_error)
-          #else
-          __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 147, __pyx_L5_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          #endif
-        } else {
-          {
-            Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_2);
-            #if !CYTHON_ASSUME_SAFE_MACROS
-            if (unlikely((__pyx_temp < 0))) __PYX_ERR(1, 147, __pyx_L5_error)
-            #endif
-            if (__pyx_t_3 >= __pyx_temp) 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(1, 147, __pyx_L5_error)
-          #else
-          __pyx_t_5 = __Pyx_PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 147, __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(1, 147, __pyx_L5_error)
-          }
-          break;
-        }
-        __Pyx_GOTREF(__pyx_t_5);
-      }
-      __Pyx_XDECREF_SET(__pyx_7genexpr__pyx_v_w, __pyx_t_5);
-      __pyx_t_5 = 0;
-/* … */
-    }
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_w); __pyx_7genexpr__pyx_v_w = 0;
-    goto __pyx_L9_exit_scope;
-    __pyx_L5_error:;
-    __Pyx_XDECREF(__pyx_7genexpr__pyx_v_w); __pyx_7genexpr__pyx_v_w = 0;
-    goto __pyx_L1_error;
-    __pyx_L9_exit_scope:;
-  } /* exit inner scope */
-
 148:         ]
-
+149:         self.current = 0
-
  __pyx_v_self->current = 0;
-
+150:         self.next_range = cMaxWindDistanceFeet
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_cMaxWindDistanceFeet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 150, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_11 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_11 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 150, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_self->next_range = __pyx_t_11;
-
+151:         self._last_vector_cache = CVector(0.0, 0.0, 0.0)
-
  __pyx_t_12.x = 0.0;
-  __pyx_t_12.y = 0.0;
-  __pyx_t_12.z = 0.0;
-  __pyx_v_self->_last_vector_cache = __pyx_t_12;
-
+152:         self._length = len(self.winds)
-
  __pyx_t_1 = __pyx_v_self->winds;
-  __Pyx_INCREF(__pyx_t_1);
-  if (unlikely(__pyx_t_1 == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "object of type 'NoneType' has no len()");
-    __PYX_ERR(1, 152, __pyx_L1_error)
-  }
-  __pyx_t_3 = __Pyx_PyList_GET_SIZE(__pyx_t_1); if (unlikely(__pyx_t_3 == ((Py_ssize_t)-1))) __PYX_ERR(1, 152, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_self->_length = __pyx_t_3;
-
 153: 
-
 154:         # Initialize cache correctly
-
+155:         self.update_cache()
-
  __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_update_cache(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 155, __pyx_L1_error)
-
 156: 
-
+157:     cdef CVector current_vector(_WindSock self):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_current_vector(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_v_self) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+158:         return self._last_vector_cache
-
  __pyx_r = __pyx_v_self->_last_vector_cache;
-  goto __pyx_L0;
-
 159: 
-
+160:     cdef void update_cache(_WindSock self):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_update_cache(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_v_self) {
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_Wind_t __pyx_v_cur_wind;
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._WindSock.update_cache", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-}
-
 161:         cdef Wind_t cur_wind
-
+162:         if self.current < self._length:
-
  __pyx_t_1 = (__pyx_v_self->current < __pyx_v_self->_length);
-  if (__pyx_t_1) {
-/* … */
-    goto __pyx_L3;
-  }
-
+163:             cur_wind = self.winds[self.current]
-
    if (unlikely(__pyx_v_self->winds == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(1, 163, __pyx_L1_error)
-    }
-    __pyx_t_2 = __Pyx_GetItemInt_List(__pyx_v_self->winds, __pyx_v_self->current, int, 1, __Pyx_PyInt_From_int, 1, 1, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 163, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __pyx_convert__from_py_struct____pyx_t_16CyEulerBallistic_8cy_euler_Wind_t(__pyx_t_2); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 163, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_v_cur_wind = __pyx_t_3;
-
+164:             self._last_vector_cache = wind_to_c_vector(&cur_wind)
-
    __pyx_t_4 = __pyx_f_16CyEulerBallistic_8cy_euler_wind_to_c_vector((&__pyx_v_cur_wind)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 164, __pyx_L1_error)
-    __pyx_v_self->_last_vector_cache = __pyx_t_4;
-
+165:             self.next_range = cur_wind.until_distance
-
    __pyx_t_5 = __pyx_v_cur_wind.until_distance;
-    __pyx_v_self->next_range = __pyx_t_5;
-
 166:         else:
-
+167:             self._last_vector_cache = CVector(0.0, 0.0, 0.0)
-
  /*else*/ {
-    __pyx_t_4.x = 0.0;
-    __pyx_t_4.y = 0.0;
-    __pyx_t_4.z = 0.0;
-    __pyx_v_self->_last_vector_cache = __pyx_t_4;
-
+168:             self.next_range = cMaxWindDistanceFeet
-
    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_cMaxWindDistanceFeet); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 168, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_5 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 168, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_v_self->next_range = __pyx_t_5;
-  }
-  __pyx_L3:;
-
 169: 
-
+170:     cdef CVector vector_for_range(_WindSock self, double next_range):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_vector_for_range(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *__pyx_v_self, double __pyx_v_next_range) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._WindSock.vector_for_range", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+171:         if next_range >= self.next_range:
-
  __pyx_t_1 = (__pyx_v_next_range >= __pyx_v_self->next_range);
-  if (__pyx_t_1) {
-/* … */
-  }
-
 172:         # if next_range + 1e-6 >= self.next_range:
-
+173:             self.current += 1
-
    __pyx_v_self->current = (__pyx_v_self->current + 1);
-
+174:             if self.current >= self._length:
-
    __pyx_t_1 = (__pyx_v_self->current >= __pyx_v_self->_length);
-    if (__pyx_t_1) {
-/* … */
-      goto __pyx_L4;
-    }
-
+175:                 self._last_vector_cache = CVector(0.0, 0.0, 0.0)
-
      __pyx_t_2.x = 0.0;
-      __pyx_t_2.y = 0.0;
-      __pyx_t_2.z = 0.0;
-      __pyx_v_self->_last_vector_cache = __pyx_t_2;
-
+176:                 self.next_range = cMaxWindDistanceFeet
-
      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_cMaxWindDistanceFeet); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 176, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_3); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 176, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_v_self->next_range = __pyx_t_4;
-
 177:             else:
-
+178:                 self.update_cache()  # This will trigger cache updates.
-
    /*else*/ {
-      __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_update_cache(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 178, __pyx_L1_error)
-    }
-    __pyx_L4:;
-
+179:         return self._last_vector_cache
-
  __pyx_r = __pyx_v_self->_last_vector_cache;
-  goto __pyx_L0;
-
 180: 
-
 181: 
-
+182: cdef class EulerTrajectoryCalc:
-
struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc {
-  PyObject_HEAD
-  struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_vtab;
-  PyObject *_table_data;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector gravity_vector;
-  PyObject *_config;
-  struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *ws;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_Config_t _EulerTrajectoryCalc__config;
-  struct __pyx_t_16CyEulerBallistic_8cy_euler_ShotData_t _EulerTrajectoryCalc__shot;
-};
-/* … */
-struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc {
-  double (*get_calc_step)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *, struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_get_calc_step *__pyx_optional_args);
-  void (*_free_trajectory)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *);
-  void (*_init_trajectory)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *, PyObject *);
-  PyObject *(*_zero_angle)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *, PyObject *, PyObject *);
-  PyObject *(*_integrate)(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *, double, double, int, struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__integrate *__pyx_optional_args);
-};
-static struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_vtabptr_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc;
-
 183:     cdef:
-
 184:         list[object] _table_data
-
 185:         CVector gravity_vector
-
+186:         public object _config
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_1__get__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config___get__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config___get__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->_config);
-  __pyx_r = __pyx_v_self->_config;
-  goto __pyx_L0;
-
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_2__set__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self), ((PyObject *)__pyx_v_value));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_2__set__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->_config);
-  __Pyx_DECREF(__pyx_v_self->_config);
-  __pyx_v_self->_config = __pyx_v_value;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_5__del__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_4__del__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_7_config_4__del__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->_config);
-  __Pyx_DECREF(__pyx_v_self->_config);
-  __pyx_v_self->_config = Py_None;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 187:         _WindSock ws
-
 188:         Config_t __config
-
 189:         ShotData_t __shot
-
 190: 
-
+191:     def __cinit__(EulerTrajectoryCalc self, object _config):
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v__config = 0;
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_config,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_config)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 191, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "__cinit__") < 0)) __PYX_ERR(1, 191, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-    }
-    __pyx_v__config = values[0];
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 1, 1, __pyx_nargs); __PYX_ERR(1, 191, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc___cinit__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self), __pyx_v__config);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc___cinit__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v__config) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+192:         self._config = _config
-
  __Pyx_INCREF(__pyx_v__config);
-  __Pyx_GIVEREF(__pyx_v__config);
-  __Pyx_GOTREF(__pyx_v_self->_config);
-  __Pyx_DECREF(__pyx_v_self->_config);
-  __pyx_v_self->_config = __pyx_v__config;
-
+193:         self.gravity_vector = CVector(.0, self._config.cGravityConstant, .0)
-
  __pyx_t_1.x = .0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->_config, __pyx_n_s_cGravityConstant); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 193, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 193, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_1.y = __pyx_t_3;
-  __pyx_t_1.z = .0;
-  __pyx_v_self->gravity_vector = __pyx_t_1;
-
 194: 
-
 195:     # def __dealloc__(EulerTrajectoryCalc self):
-
 196:     #     free_trajectory(&self.__shot)
-
 197: 
-
+198:     cdef double get_calc_step(self, double step = 0):
-
static double __pyx_f_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_get_calc_step(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_get_calc_step *__pyx_optional_args) {
-  double __pyx_v_step = ((double)0.0);
-  double __pyx_v_preferred_step;
-  double __pyx_r;
-  if (__pyx_optional_args) {
-    if (__pyx_optional_args->__pyx_n > 0) {
-      __pyx_v_step = __pyx_optional_args->step;
-    }
-  }
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-/* … */
-struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_get_calc_step {
-  int __pyx_n;
-  double step;
-};
-
+199:         cdef double preferred_step = self.__config.max_calc_step_size_feet
-
  __pyx_t_1 = __pyx_v_self->_EulerTrajectoryCalc__config.max_calc_step_size_feet;
-  __pyx_v_preferred_step = __pyx_t_1;
-
 200:         # cdef double defined_max = 0.5  # const will be better optimized with cython
-
+201:         if step == 0:
-
  __pyx_t_2 = (__pyx_v_step == 0.0);
-  if (__pyx_t_2) {
-/* … */
-  }
-
+202:             return preferred_step / 2.0
-
    __pyx_r = (__pyx_v_preferred_step / 2.0);
-    goto __pyx_L0;
-
+203:         return min(step, preferred_step) / 2.0
-
  __pyx_t_1 = __pyx_v_preferred_step;
-  __pyx_t_3 = __pyx_v_step;
-  __pyx_t_2 = (__pyx_t_1 < __pyx_t_3);
-  if (__pyx_t_2) {
-    __pyx_t_4 = __pyx_t_1;
-  } else {
-    __pyx_t_4 = __pyx_t_3;
-  }
-  __pyx_r = (__pyx_t_4 / 2.0);
-  goto __pyx_L0;
-
 204: 
-
+205:     @property
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_10table_data_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_10table_data_1__get__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_10table_data___get__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_10table_data___get__(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 206:     def table_data(self) -> list[object]:
-
+207:         return self._table_data
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->_table_data);
-  __pyx_r = __pyx_v_self->_table_data;
-  goto __pyx_L0;
-
 208: 
-
+209:     def zero_angle(self, object shot_info, object distance) -> Angular:
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_3zero_angle(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_2zero_angle, "EulerTrajectoryCalc.zero_angle(self, shot_info, distance) -> Angular");
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_3zero_angle(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  PyObject *__pyx_v_shot_info = 0;
-  PyObject *__pyx_v_distance = 0;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("zero_angle (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_shot_info,&__pyx_n_s_distance,0};
-  PyObject* values[2] = {0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  2: values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_shot_info)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 209, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_distance)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 209, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("zero_angle", 1, 2, 2, 1); __PYX_ERR(1, 209, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "zero_angle") < 0)) __PYX_ERR(1, 209, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 2)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-      values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-    }
-    __pyx_v_shot_info = values[0];
-    __pyx_v_distance = values[1];
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("zero_angle", 1, 2, 2, __pyx_nargs); __PYX_ERR(1, 209, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.zero_angle", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_2zero_angle(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self), __pyx_v_shot_info, __pyx_v_distance);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_2zero_angle(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v_shot_info, PyObject *__pyx_v_distance) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.zero_angle", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+210:         return self._zero_angle(shot_info, distance)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_zero_angle(__pyx_v_self, __pyx_v_shot_info, __pyx_v_distance); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 210, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 211: 
-
+212:     def trajectory(self, object shot_info, object max_range, object dist_step,
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_5trajectory(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_4trajectory, "EulerTrajectoryCalc.trajectory(self, shot_info, max_range, dist_step, bool extra_data=False, double time_step=0.0) -> object");
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_5trajectory(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  PyObject *__pyx_v_shot_info = 0;
-  PyObject *__pyx_v_max_range = 0;
-  PyObject *__pyx_v_dist_step = 0;
-  int __pyx_v_extra_data;
-  double __pyx_v_time_step;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("trajectory (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_shot_info,&__pyx_n_s_max_range,&__pyx_n_s_dist_step,&__pyx_n_s_extra_data,&__pyx_n_s_time_step,0};
-  PyObject* values[5] = {0,0,0,0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  5: values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
-        CYTHON_FALLTHROUGH;
-        case  4: values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_shot_info)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 212, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_max_range)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 212, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("trajectory", 0, 3, 5, 1); __PYX_ERR(1, 212, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_dist_step)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[2]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 212, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("trajectory", 0, 3, 5, 2); __PYX_ERR(1, 212, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  3:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_extra_data);
-          if (value) { values[3] = __Pyx_Arg_NewRef_FASTCALL(value); kw_args--; }
-          else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 212, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  4:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_time_step);
-          if (value) { values[4] = __Pyx_Arg_NewRef_FASTCALL(value); kw_args--; }
-          else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 212, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "trajectory") < 0)) __PYX_ERR(1, 212, __pyx_L3_error)
-      }
-    } else {
-      switch (__pyx_nargs) {
-        case  5: values[4] = __Pyx_Arg_FASTCALL(__pyx_args, 4);
-        CYTHON_FALLTHROUGH;
-        case  4: values[3] = __Pyx_Arg_FASTCALL(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = __Pyx_Arg_FASTCALL(__pyx_args, 2);
-        values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-        values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-    }
-    __pyx_v_shot_info = values[0];
-    __pyx_v_max_range = values[1];
-    __pyx_v_dist_step = values[2];
-    if (values[3]) {
-      __pyx_v_extra_data = __Pyx_PyObject_IsTrue(values[3]); if (unlikely((__pyx_v_extra_data == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 213, __pyx_L3_error)
-    } else {
-/* … */
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_4trajectory(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v_shot_info, PyObject *__pyx_v_max_range, PyObject *__pyx_v_dist_step, int __pyx_v_extra_data, double __pyx_v_time_step) {
-  enum __pyx_t_16CyEulerBallistic_15trajectory_data_CTrajFlag __pyx_v_filter_flags;
-  PyObject *__pyx_v_t = 0;
-  PyObject *__pyx_r = NULL;
-  __Pyx_INCREF(__pyx_v_dist_step);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.trajectory", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_t);
-  __Pyx_XDECREF(__pyx_v_dist_step);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+213:                    bint extra_data = False, double time_step = 0.0) -> object:
-
      __pyx_v_extra_data = ((int)0);
-    }
-    if (values[4]) {
-      __pyx_v_time_step = __pyx_PyFloat_AsDouble(values[4]); if (unlikely((__pyx_v_time_step == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 213, __pyx_L3_error)
-    } else {
-      __pyx_v_time_step = ((double)0.0);
-    }
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("trajectory", 0, 3, 5, __pyx_nargs); __PYX_ERR(1, 212, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc.trajectory", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc_4trajectory(((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self), __pyx_v_shot_info, __pyx_v_max_range, __pyx_v_dist_step, __pyx_v_extra_data, __pyx_v_time_step);
-
 214:         # hack to reload config if it was changed explicit on existed instance
-
+215:         self.__config = config_bind(self._config)
-
  __pyx_t_1 = __pyx_v_self->_config;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_f_16CyEulerBallistic_8cy_euler_config_bind(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 215, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_self->_EulerTrajectoryCalc__config = __pyx_t_2;
-
+216:         self.gravity_vector = CVector(.0, self.__config.cGravityConstant, .0)
-
  __pyx_t_3.x = .0;
-  __pyx_t_3.y = __pyx_v_self->_EulerTrajectoryCalc__config.cGravityConstant;
-  __pyx_t_3.z = .0;
-  __pyx_v_self->gravity_vector = __pyx_t_3;
-
 217: 
-
 218:         cdef:
-
+219:             CTrajFlag filter_flags = CTrajFlag.RANGE
-
  __pyx_v_filter_flags = __pyx_e_16CyEulerBallistic_15trajectory_data_RANGE;
-
 220: 
-
+221:         if extra_data:
-
  if (__pyx_v_extra_data) {
-/* … */
-  }
-
+222:             dist_step = Distance.Foot(self.__config.chart_resolution)
-
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_Distance); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 222, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_Foot); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 222, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_4 = PyFloat_FromDouble(__pyx_v_self->_EulerTrajectoryCalc__config.chart_resolution); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 222, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_6 = NULL;
-    __pyx_t_7 = 0;
-    #if CYTHON_UNPACK_METHODS
-    if (unlikely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_6)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_6);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-        __pyx_t_7 = 1;
-      }
-    }
-    #endif
-    {
-      PyObject *__pyx_callargs[2] = {__pyx_t_6, __pyx_t_4};
-      __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_5, __pyx_callargs+1-__pyx_t_7, 1+__pyx_t_7);
-      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 222, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    }
-    __Pyx_DECREF_SET(__pyx_v_dist_step, __pyx_t_1);
-    __pyx_t_1 = 0;
-
+223:             filter_flags = CTrajFlag.ALL
-
    __pyx_v_filter_flags = __pyx_e_16CyEulerBallistic_15trajectory_data_ALL;
-
 224: 
-
+225:         self._init_trajectory(shot_info)
-
  ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_init_trajectory(__pyx_v_self, __pyx_v_shot_info); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 225, __pyx_L1_error)
-
+226:         cdef list[object] t = self._integrate(max_range._feet, dist_step._feet, filter_flags, time_step)
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_max_range, __pyx_n_s_feet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 226, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_8 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_8 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 226, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_dist_step, __pyx_n_s_feet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 226, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_9 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_9 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 226, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_10.__pyx_n = 1;
-  __pyx_t_10.time_step = __pyx_v_time_step;
-  __pyx_t_1 = ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_integrate(__pyx_v_self, __pyx_t_8, __pyx_t_9, __pyx_v_filter_flags, &__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 226, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_t = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+227:         self._free_trajectory()
-
  ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_free_trajectory(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 227, __pyx_L1_error)
-
+228:         return t
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_t);
-  __pyx_r = __pyx_v_t;
-  goto __pyx_L0;
-
 229: 
-
+230:     cdef void _free_trajectory(self):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__free_trajectory(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self) {
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc._free_trajectory", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-}
-
+231:         free_trajectory(&self.__shot)
-
  __pyx_f_16CyEulerBallistic_8cy_euler_free_trajectory((&__pyx_v_self->_EulerTrajectoryCalc__shot)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 231, __pyx_L1_error)
-
 232: 
-
+233:     cdef void _init_trajectory(self, object shot_info):
-
static void __pyx_f_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__init_trajectory(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v_shot_info) {
-/* … */
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc._init_trajectory", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-}
-
+234:         self._table_data = shot_info.ammo.dm.drag_table
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 234, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dm); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 234, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_drag_table); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 234, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (!(likely(PyList_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None) || __Pyx_RaiseUnexpectedTypeError("list", __pyx_t_1))) __PYX_ERR(1, 234, __pyx_L1_error)
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->_table_data);
-  __Pyx_DECREF(__pyx_v_self->_table_data);
-  __pyx_v_self->_table_data = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+235:         self.__shot = ShotData_t(
-
  __pyx_v_self->_EulerTrajectoryCalc__shot = __pyx_t_3;
-
+236:             bc=shot_info.ammo.dm.BC,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 236, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dm); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 236, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_BC); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 236, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 236, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.bc = __pyx_t_4;
-
+237:             curve=cy_calculate_curve(self._table_data),
-
  __pyx_t_1 = __pyx_v_self->_table_data;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_5 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_curve(((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 237, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.curve = __pyx_t_5;
-
+238:             mach_list=cy_table_to_mach(self._table_data),
-
  __pyx_t_1 = __pyx_v_self->_table_data;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_6 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_table_to_mach(((PyObject*)__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 238, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.mach_list = __pyx_t_6;
-
+239:             look_angle=shot_info.look_angle._rad,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_look_angle); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 239, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_rad); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 239, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 239, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.look_angle = __pyx_t_4;
-
+240:             twist=shot_info.weapon.twist._inch,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_weapon); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 240, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_twist); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 240, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_inch); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 240, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 240, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.twist = __pyx_t_4;
-
+241:             length=shot_info.ammo.dm.length._inch,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 241, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_dm); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 241, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_length); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 241, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_inch); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 241, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 241, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.length = __pyx_t_4;
-
+242:             diameter=shot_info.ammo.dm.diameter._inch,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 242, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dm); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 242, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_diameter); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 242, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_inch); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 242, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 242, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.diameter = __pyx_t_4;
-
+243:             weight=shot_info.ammo.dm.weight._grain,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 243, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_dm); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 243, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_weight); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 243, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_grain); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 243, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 243, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.weight = __pyx_t_4;
-
+244:             barrel_elevation=shot_info.barrel_elevation._rad,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_barrel_elevation); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 244, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_rad); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 244, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 244, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.barrel_elevation = __pyx_t_4;
-
+245:             barrel_azimuth=shot_info.barrel_azimuth._rad,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_barrel_azimuth); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 245, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_rad); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 245, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 245, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.barrel_azimuth = __pyx_t_4;
-
+246:             sight_height=shot_info.weapon.sight_height._feet,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_weapon); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 246, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_sight_height); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 246, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_feet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 246, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 246, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.sight_height = __pyx_t_4;
-
+247:             cant_cosine=cos(shot_info.cant_angle._rad),
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_cant_angle); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 247, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_rad); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 247, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 247, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.cant_cosine = cos(__pyx_t_4);
-
+248:             cant_sine=sin(shot_info.cant_angle._rad),
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_cant_angle); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 248, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_rad); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 248, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 248, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.cant_sine = sin(__pyx_t_4);
-
+249:             alt0=shot_info.atmo.altitude._feet,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 249, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_altitude); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 249, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_feet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 249, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 249, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_3.alt0 = __pyx_t_4;
-
+250:             calc_step=self.get_calc_step(),
-
  __pyx_t_4 = ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->get_calc_step(__pyx_v_self, NULL); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 250, __pyx_L1_error)
-  __pyx_t_3.calc_step = __pyx_t_4;
-
 251:             # calc_step=cy_get_calc_step(self.__config),
-
+252:             diameter=shot_info.ammo.dm.diameter._inch,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 252, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_dm); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 252, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_diameter); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 252, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_inch); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 252, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 252, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_3.diameter = __pyx_t_4;
-  __pyx_t_3.stability_coefficient = 0.0;
-
 253:             stability_coefficient=0.0,
-
 254:             atmo=Atmosphere_t(
-
+255:                 _t0=shot_info.atmo._t0,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 255, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_t0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 255, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 255, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_7._t0 = __pyx_t_4;
-
+256:                 _a0=shot_info.atmo._a0,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 256, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_a0); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 256, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 256, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_7._a0 = __pyx_t_4;
-
+257:                 _p0=shot_info.atmo._p0,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 257, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_p0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 257, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 257, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_7._p0 = __pyx_t_4;
-
+258:                 _mach=shot_info.atmo._mach,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 258, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_mach); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 258, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 258, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_7._mach = __pyx_t_4;
-
+259:                 density_ratio=shot_info.atmo.density_ratio,
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 259, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_density_ratio); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 259, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 259, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_7.density_ratio = __pyx_t_4;
-
+260:                 cLowestTempC=shot_info.atmo.cLowestTempC,
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 260, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_cLowestTempC); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 260, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_2); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 260, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_7.cLowestTempC = __pyx_t_4;
-  __pyx_t_3.atmo = __pyx_t_7;
-
 261:             )
-
 262:         )
-
+263:         self.__shot.muzzle_velocity = shot_info.ammo.get_velocity_for_temp(shot_info.atmo.powder_temp)._fps
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_ammo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_get_velocity_for_temp); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_atmo); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_powder_temp); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = NULL;
-  __pyx_t_10 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_8))) {
-    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_8);
-    if (likely(__pyx_t_1)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
-      __Pyx_INCREF(__pyx_t_1);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_8, function);
-      __pyx_t_10 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_t_9};
-    __pyx_t_2 = __Pyx_PyObject_FastCall(__pyx_t_8, __pyx_callargs+1-__pyx_t_10, 1+__pyx_t_10);
-    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-    if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 263, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  }
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_fps); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_8); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 263, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_v_self->_EulerTrajectoryCalc__shot.muzzle_velocity = __pyx_t_4;
-
+264:         cy_update_stability_coefficient(&self.__shot)
-
  __pyx_f_16CyEulerBallistic_8cy_euler_cy_update_stability_coefficient((&__pyx_v_self->_EulerTrajectoryCalc__shot)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 264, __pyx_L1_error)
-
 265: 
-
+266:         self.ws = _WindSock(shot_info.winds)
-
  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_winds); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 266, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_calc__WindSock), __pyx_t_8); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 266, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __Pyx_GIVEREF(__pyx_t_2);
-  __Pyx_GOTREF((PyObject *)__pyx_v_self->ws);
-  __Pyx_DECREF((PyObject *)__pyx_v_self->ws);
-  __pyx_v_self->ws = ((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__WindSock *)__pyx_t_2);
-  __pyx_t_2 = 0;
-
 267: 
-
 268: 
-
+269:     cdef object _zero_angle(EulerTrajectoryCalc self, object shot_info, object distance):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__zero_angle(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, PyObject *__pyx_v_shot_info, PyObject *__pyx_v_distance) {
-  double __pyx_v__cZeroFindingAccuracy;
-  double __pyx_v__cMaxIterations;
-  double __pyx_v_zero_distance;
-  double __pyx_v_height_at_zero;
-  double __pyx_v_maximum_range;
-  int __pyx_v_iterations_count;
-  double __pyx_v_zero_finding_error;
-  PyObject *__pyx_v_t = 0;
-  double __pyx_v_height;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_10);
-  __Pyx_XDECREF(__pyx_t_11);
-  __Pyx_XDECREF(__pyx_t_12);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_XDECREF(__pyx_t_14);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc._zero_angle", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_t);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 270:         # hack to reload config if it was changed explicit on existed instance
-
+271:         self.__config = config_bind(self._config)
-
  __pyx_t_1 = __pyx_v_self->_config;
-  __Pyx_INCREF(__pyx_t_1);
-  __pyx_t_2 = __pyx_f_16CyEulerBallistic_8cy_euler_config_bind(__pyx_t_1); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 271, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_self->_EulerTrajectoryCalc__config = __pyx_t_2;
-
+272:         self.gravity_vector = CVector(.0, self.__config.cGravityConstant, .0)
-
  __pyx_t_3.x = .0;
-  __pyx_t_3.y = __pyx_v_self->_EulerTrajectoryCalc__config.cGravityConstant;
-  __pyx_t_3.z = .0;
-  __pyx_v_self->gravity_vector = __pyx_t_3;
-
 273: 
-
 274:         cdef:
-
 275:             # early bindings
-
+276:             double _cZeroFindingAccuracy = self.__config.cZeroFindingAccuracy
-
  __pyx_t_4 = __pyx_v_self->_EulerTrajectoryCalc__config.cZeroFindingAccuracy;
-  __pyx_v__cZeroFindingAccuracy = __pyx_t_4;
-
+277:             double _cMaxIterations = self.__config.cMaxIterations
-
  __pyx_t_5 = __pyx_v_self->_EulerTrajectoryCalc__config.cMaxIterations;
-  __pyx_v__cMaxIterations = __pyx_t_5;
-
 278: 
-
 279:         cdef:
-
+280:             double zero_distance = cos(shot_info.look_angle._rad) * distance._feet
-
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_look_angle); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_rad); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = PyFloat_FromDouble(cos(__pyx_t_4)); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_distance, __pyx_n_s_feet); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_7 = PyNumber_Multiply(__pyx_t_6, __pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_7); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 280, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_v_zero_distance = __pyx_t_4;
-
+281:             double height_at_zero = sin(shot_info.look_angle._rad) * distance._feet
-
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_shot_info, __pyx_n_s_look_angle); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_rad); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_1); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = PyFloat_FromDouble(sin(__pyx_t_4)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_distance, __pyx_n_s_feet); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_6 = PyNumber_Multiply(__pyx_t_1, __pyx_t_7); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 281, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_v_height_at_zero = __pyx_t_4;
-
+282:             double maximum_range = zero_distance
-
  __pyx_v_maximum_range = __pyx_v_zero_distance;
-
+283:             int iterations_count = 0
-
  __pyx_v_iterations_count = 0;
-
+284:             double zero_finding_error = _cZeroFindingAccuracy * 2
-
  __pyx_v_zero_finding_error = (__pyx_v__cZeroFindingAccuracy * 2.0);
-
 285: 
-
 286:             object t
-
 287:             double height
-
 288: 
-
+289:         self._init_trajectory(shot_info)
-
  ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_init_trajectory(__pyx_v_self, __pyx_v_shot_info); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 289, __pyx_L1_error)
-
+290:         self.__shot.barrel_azimuth = 0.0
-
  __pyx_v_self->_EulerTrajectoryCalc__shot.barrel_azimuth = 0.0;
-
+291:         self.__shot.barrel_elevation = atan(height_at_zero / zero_distance)
-
  __pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation = atan((__pyx_v_height_at_zero / __pyx_v_zero_distance));
-
+292:         self.__shot.twist = 0
-
  __pyx_v_self->_EulerTrajectoryCalc__shot.twist = 0.0;
-
+293:         maximum_range -= 1.5 * self.__shot.calc_step
-
  __pyx_v_maximum_range = (__pyx_v_maximum_range - (1.5 * __pyx_v_self->_EulerTrajectoryCalc__shot.calc_step));
-
 294: 
-
 295:         # x = horizontal distance down range, y = drop, z = windage
-
+296:         while zero_finding_error > _cZeroFindingAccuracy and iterations_count < _cMaxIterations:
-
  while (1) {
-    __pyx_t_9 = (__pyx_v_zero_finding_error > __pyx_v__cZeroFindingAccuracy);
-    if (__pyx_t_9) {
-    } else {
-      __pyx_t_8 = __pyx_t_9;
-      goto __pyx_L5_bool_binop_done;
-    }
-    __pyx_t_9 = (__pyx_v_iterations_count < __pyx_v__cMaxIterations);
-    __pyx_t_8 = __pyx_t_9;
-    __pyx_L5_bool_binop_done:;
-    if (!__pyx_t_8) break;
-
+297:             t = self._integrate(maximum_range, zero_distance, CTrajFlag.NONE)[0]
-
    __pyx_t_6 = ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_integrate(__pyx_v_self, __pyx_v_maximum_range, __pyx_v_zero_distance, __pyx_e_16CyEulerBallistic_15trajectory_data_NONE, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 297, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    if (unlikely(__pyx_t_6 == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(1, 297, __pyx_L1_error)
-    }
-    __pyx_t_7 = __Pyx_GetItemInt_List(__pyx_t_6, 0, long, 1, __Pyx_PyInt_From_long, 1, 0, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 297, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_t, __pyx_t_7);
-    __pyx_t_7 = 0;
-
+298:             height = t.height._feet  # use there internal shortcut instead of (t.height >> Distance.Foot)
-
    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_v_t, __pyx_n_s_height); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 298, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_feet); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 298, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_4 = __pyx_PyFloat_AsDouble(__pyx_t_6); if (unlikely((__pyx_t_4 == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 298, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_v_height = __pyx_t_4;
-
+299:             zero_finding_error = fabs(height - height_at_zero)
-
    __pyx_v_zero_finding_error = fabs((__pyx_v_height - __pyx_v_height_at_zero));
-
+300:             if zero_finding_error > _cZeroFindingAccuracy:
-
    __pyx_t_8 = (__pyx_v_zero_finding_error > __pyx_v__cZeroFindingAccuracy);
-    if (__pyx_t_8) {
-/* … */
-      goto __pyx_L7;
-    }
-
+301:                 self.__shot.barrel_elevation -= (height - height_at_zero) / zero_distance
-
      __pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation = (__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation - ((__pyx_v_height - __pyx_v_height_at_zero) / __pyx_v_zero_distance));
-
 302:             else:  # last barrel_elevation hit zero!
-
+303:                 break
-
    /*else*/ {
-      goto __pyx_L4_break;
-    }
-    __pyx_L7:;
-
+304:             iterations_count += 1
-
    __pyx_v_iterations_count = (__pyx_v_iterations_count + 1);
-  }
-  __pyx_L4_break:;
-
+305:         self._free_trajectory()
-
  ((struct __pyx_vtabstruct_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *)__pyx_v_self->__pyx_vtab)->_free_trajectory(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 305, __pyx_L1_error)
-
+306:         if zero_finding_error > _cZeroFindingAccuracy:
-
  __pyx_t_8 = (__pyx_v_zero_finding_error > __pyx_v__cZeroFindingAccuracy);
-  if (unlikely(__pyx_t_8)) {
-/* … */
-  }
-
+307:             raise ZeroFindingError(zero_finding_error, iterations_count, Angular.Radian(self.__shot.barrel_elevation))
-
    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_ZeroFindingError); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_1 = PyFloat_FromDouble(__pyx_v_zero_finding_error); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_10 = __Pyx_PyInt_From_int(__pyx_v_iterations_count); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_10);
-    __Pyx_GetModuleGlobalName(__pyx_t_12, __pyx_n_s_Angular); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_12);
-    __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_12, __pyx_n_s_Radian); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_13);
-    __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-    __pyx_t_12 = PyFloat_FromDouble(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 307, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_12);
-    __pyx_t_14 = NULL;
-    __pyx_t_15 = 0;
-    #if CYTHON_UNPACK_METHODS
-    if (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_15 = 1;
-      }
-    }
-    #endif
-    {
-      PyObject *__pyx_callargs[2] = {__pyx_t_14, __pyx_t_12};
-      __pyx_t_11 = __Pyx_PyObject_FastCall(__pyx_t_13, __pyx_callargs+1-__pyx_t_15, 1+__pyx_t_15);
-      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-      __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-      if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 307, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_11);
-      __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-    }
-    __pyx_t_13 = NULL;
-    __pyx_t_15 = 0;
-    #if CYTHON_UNPACK_METHODS
-    if (unlikely(PyMethod_Check(__pyx_t_7))) {
-      __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_7);
-      if (likely(__pyx_t_13)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_13);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_7, function);
-        __pyx_t_15 = 1;
-      }
-    }
-    #endif
-    {
-      PyObject *__pyx_callargs[4] = {__pyx_t_13, __pyx_t_1, __pyx_t_10, __pyx_t_11};
-      __pyx_t_6 = __Pyx_PyObject_FastCall(__pyx_t_7, __pyx_callargs+1-__pyx_t_15, 3+__pyx_t_15);
-      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-      if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 307, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    }
-    __Pyx_Raise(__pyx_t_6, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __PYX_ERR(1, 307, __pyx_L1_error)
-
+308:         return Angular.Radian(self.__shot.barrel_elevation)
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_Angular); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 308, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_Radian); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 308, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 308, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_10 = NULL;
-  __pyx_t_15 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (unlikely(PyMethod_Check(__pyx_t_11))) {
-    __pyx_t_10 = PyMethod_GET_SELF(__pyx_t_11);
-    if (likely(__pyx_t_10)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_11);
-      __Pyx_INCREF(__pyx_t_10);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_11, function);
-      __pyx_t_15 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_10, __pyx_t_7};
-    __pyx_t_6 = __Pyx_PyObject_FastCall(__pyx_t_11, __pyx_callargs+1-__pyx_t_15, 1+__pyx_t_15);
-    __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 308, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-  }
-  __pyx_r = __pyx_t_6;
-  __pyx_t_6 = 0;
-  goto __pyx_L0;
-
 309: 
-
 310: 
-
+311:     cdef list[object] _integrate(EulerTrajectoryCalc self,
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__integrate(struct __pyx_obj_16CyEulerBallistic_15trajectory_calc_EulerTrajectoryCalc *__pyx_v_self, double __pyx_v_maximum_range, double __pyx_v_record_step, int __pyx_v_filter_flags, struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__integrate *__pyx_optional_args) {
-  double __pyx_v_time_step = ((double)0.0);
-  double __pyx_v_velocity;
-  double __pyx_v_delta_time;
-  double __pyx_v_density_factor;
-  double __pyx_v_mach;
-  PyObject *__pyx_v_ranges = 0;
-  double __pyx_v_time;
-  double __pyx_v_drag;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_range_vector;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_velocity_vector;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_delta_range_vector;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_velocity_adjusted;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_gravity_vector;
-  double __pyx_v_calc_step;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_wind_vector;
-  struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *__pyx_v_data_filter = 0;
-  double __pyx_v__cMinimumVelocity;
-  double __pyx_v__cMaximumDrop;
-  double __pyx_v__cMinimumAltitude;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v__dir_vector;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v__temp1;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v__temp2;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v__temp3;
-  double __pyx_v_min_step;
-  int __pyx_v_it;
-  PyObject *__pyx_v_reason = NULL;
-  PyObject *__pyx_r = NULL;
-  if (__pyx_optional_args) {
-    if (__pyx_optional_args->__pyx_n > 0) {
-      __pyx_v_time_step = __pyx_optional_args->time_step;
-    }
-  }
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.EulerTrajectoryCalc._integrate", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_ranges);
-  __Pyx_XDECREF((PyObject *)__pyx_v_data_filter);
-  __Pyx_XDECREF(__pyx_v_reason);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-struct __pyx_opt_args_16CyEulerBallistic_15trajectory_calc_19EulerTrajectoryCalc__integrate {
-  int __pyx_n;
-  double time_step;
-};
-
 312:                           double maximum_range, double record_step, int filter_flags, double time_step = 0.0):
-
 313:         cdef:
-
 314:             double velocity, delta_time
-
+315:             double density_factor = .0
-
  __pyx_v_density_factor = .0;
-
+316:             double mach = .0
-
  __pyx_v_mach = .0;
-
+317:             list[object] ranges = []
-
  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 317, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_ranges = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+318:             double time = .0
-
  __pyx_v_time = .0;
-
+319:             double drag = .0
-
  __pyx_v_drag = .0;
-
 320:             CVector range_vector, velocity_vector
-
 321:             CVector delta_range_vector, velocity_adjusted
-
+322:             CVector gravity_vector = CVector(.0, self.__config.cGravityConstant, .0)
-
  __pyx_t_2.x = .0;
-  __pyx_t_2.y = __pyx_v_self->_EulerTrajectoryCalc__config.cGravityConstant;
-  __pyx_t_2.z = .0;
-  __pyx_v_gravity_vector = __pyx_t_2;
-
+323:             double calc_step = self.__shot.calc_step
-
  __pyx_t_3 = __pyx_v_self->_EulerTrajectoryCalc__shot.calc_step;
-  __pyx_v_calc_step = __pyx_t_3;
-
 324: 
-
 325:             # region Initialize wind-related variables to first wind reading (if any)
-
+326:             CVector wind_vector = self.ws.current_vector()
-
  __pyx_t_2 = __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_current_vector(__pyx_v_self->ws); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 326, __pyx_L1_error)
-  __pyx_v_wind_vector = __pyx_t_2;
-
 327:             # endregion
-
 328: 
-
 329:             _TrajectoryDataFilter data_filter
-
 330: 
-
 331:         cdef:
-
 332:             # early bindings
-
+333:             double _cMinimumVelocity = self.__config.cMinimumVelocity
-
  __pyx_t_3 = __pyx_v_self->_EulerTrajectoryCalc__config.cMinimumVelocity;
-  __pyx_v__cMinimumVelocity = __pyx_t_3;
-
+334:             double _cMaximumDrop = self.__config.cMaximumDrop
-
  __pyx_t_3 = __pyx_v_self->_EulerTrajectoryCalc__config.cMaximumDrop;
-  __pyx_v__cMaximumDrop = __pyx_t_3;
-
+335:             double _cMinimumAltitude = self.__config.cMinimumAltitude
-
  __pyx_t_3 = __pyx_v_self->_EulerTrajectoryCalc__config.cMinimumAltitude;
-  __pyx_v__cMinimumAltitude = __pyx_t_3;
-
 336: 
-
 337:         cdef:
-
 338:             # temp vectors
-
 339:             CVector _dir_vector, _temp1, _temp2, _temp3
-
 340: 
-
 341:         # region Initialize velocity and position of projectile
-
+342:         velocity = self.__shot.muzzle_velocity
-
  __pyx_t_3 = __pyx_v_self->_EulerTrajectoryCalc__shot.muzzle_velocity;
-  __pyx_v_velocity = __pyx_t_3;
-
 343:         # x: downrange distance, y: drop, z: windage
-
+344:         range_vector = CVector(.0, -self.__shot.cant_cosine * self.__shot.sight_height, -self.__shot.cant_sine * self.__shot.sight_height)
-
  __pyx_t_2.x = .0;
-  __pyx_t_2.y = ((-__pyx_v_self->_EulerTrajectoryCalc__shot.cant_cosine) * __pyx_v_self->_EulerTrajectoryCalc__shot.sight_height);
-  __pyx_t_2.z = ((-__pyx_v_self->_EulerTrajectoryCalc__shot.cant_sine) * __pyx_v_self->_EulerTrajectoryCalc__shot.sight_height);
-  __pyx_v_range_vector = __pyx_t_2;
-
+345:         _dir_vector = CVector(cos(self.__shot.barrel_elevation) * cos(self.__shot.barrel_azimuth),
-
  __pyx_t_2.x = (cos(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation) * cos(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_azimuth));
-
+346:                                  sin(self.__shot.barrel_elevation),
-
  __pyx_t_2.y = sin(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation);
-
+347:                                  cos(self.__shot.barrel_elevation) * sin(self.__shot.barrel_azimuth))
-
  __pyx_t_2.z = (cos(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation) * sin(__pyx_v_self->_EulerTrajectoryCalc__shot.barrel_azimuth));
-  __pyx_v__dir_vector = __pyx_t_2;
-
+348:         velocity_vector = mul_c(&_dir_vector, velocity)
-
  __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_mul_c((&__pyx_v__dir_vector), __pyx_v_velocity); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 348, __pyx_L1_error)
-  __pyx_v_velocity_vector = __pyx_t_2;
-
 349:         # endregion
-
 350: 
-
+351:         min_step = min(calc_step, record_step)
-
  __pyx_t_3 = __pyx_v_record_step;
-  __pyx_t_4 = __pyx_v_calc_step;
-  __pyx_t_6 = (__pyx_t_3 < __pyx_t_4);
-  if (__pyx_t_6) {
-    __pyx_t_5 = __pyx_t_3;
-  } else {
-    __pyx_t_5 = __pyx_t_4;
-  }
-  __pyx_v_min_step = __pyx_t_5;
-
 352:         # With non-zero look_angle, rounding can suggest multiple adjacent zero-crossings
-
+353:         data_filter = _TrajectoryDataFilter(filter_flags=filter_flags,
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_7 = __Pyx_PyInt_From_int(__pyx_v_filter_flags); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_filter_flags, __pyx_t_7) < 0) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-/* … */
-  __pyx_t_7 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter), __pyx_empty_tuple, __pyx_t_1); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_data_filter = ((struct __pyx_obj_16CyEulerBallistic_15trajectory_calc__TrajectoryDataFilter *)__pyx_t_7);
-  __pyx_t_7 = 0;
-
+354:                                             range_step=record_step,
-
  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_record_step); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 354, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_range_step, __pyx_t_7) < 0) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+355:                                             time_step=time_step)
-
  __pyx_t_7 = PyFloat_FromDouble(__pyx_v_time_step); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 355, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_time_step, __pyx_t_7) < 0) __PYX_ERR(1, 353, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+356:         data_filter.setup_seen_zero(range_vector.y, self.__shot.barrel_elevation, self.__shot.look_angle)
-
  __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_setup_seen_zero(__pyx_v_data_filter, __pyx_v_range_vector.y, __pyx_v_self->_EulerTrajectoryCalc__shot.barrel_elevation, __pyx_v_self->_EulerTrajectoryCalc__shot.look_angle); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 356, __pyx_L1_error)
-
 357: 
-
 358:         #region Trajectory Loop
-
+359:         warnings.simplefilter("once")  # used to avoid multiple warnings in a loop
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_warnings); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 359, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_simplefilter); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 359, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = NULL;
-  __pyx_t_9 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (unlikely(PyMethod_Check(__pyx_t_8))) {
-    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_8);
-    if (likely(__pyx_t_1)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);
-      __Pyx_INCREF(__pyx_t_1);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_8, function);
-      __pyx_t_9 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_1, __pyx_n_u_once};
-    __pyx_t_7 = __Pyx_PyObject_FastCall(__pyx_t_8, __pyx_callargs+1-__pyx_t_9, 1+__pyx_t_9);
-    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-    if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 359, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  }
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+360:         cdef int it = 0
-
  __pyx_v_it = 0;
-
+361:         while range_vector.x <= maximum_range + min_step:
-
  while (1) {
-    __pyx_t_6 = (__pyx_v_range_vector.x <= (__pyx_v_maximum_range + __pyx_v_min_step));
-    if (!__pyx_t_6) break;
-
+362:             it += 1
-
    __pyx_v_it = (__pyx_v_it + 1);
-
+363:             data_filter.current_flag = CTrajFlag.NONE
-
    __pyx_v_data_filter->current_flag = __pyx_e_16CyEulerBallistic_15trajectory_data_NONE;
-
 364: 
-
 365:             # Update wind reading at current point in trajectory
-
+366:             if range_vector.x >= self.ws.next_range:  # require check before call to improve performance
-
    __pyx_t_6 = (__pyx_v_range_vector.x >= __pyx_v_self->ws->next_range);
-    if (__pyx_t_6) {
-/* … */
-    }
-
+367:                 wind_vector = self.ws.vector_for_range(range_vector.x)
-
      __pyx_t_2 = __pyx_f_16CyEulerBallistic_15trajectory_calc_9_WindSock_vector_for_range(__pyx_v_self->ws, __pyx_v_range_vector.x); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 367, __pyx_L1_error)
-      __pyx_v_wind_vector = __pyx_t_2;
-
 368: 
-
 369:             # overwrite density_factor and mach by pointer
-
+370:             update_density_factor_and_mach_for_altitude(&self.__shot.atmo,
-
    __pyx_f_16CyEulerBallistic_8cy_euler_update_density_factor_and_mach_for_altitude((&__pyx_v_self->_EulerTrajectoryCalc__shot.atmo), (__pyx_v_self->_EulerTrajectoryCalc__shot.alt0 + __pyx_v_range_vector.y), (&__pyx_v_density_factor), (&__pyx_v_mach)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 370, __pyx_L1_error)
-
 371:                 self.__shot.alt0 + range_vector.y, &density_factor, &mach)
-
 372: 
-
+373:             if filter_flags:
-
    __pyx_t_6 = (__pyx_v_filter_flags != 0);
-    if (__pyx_t_6) {
-/* … */
-    }
-
 374: 
-
 375:                 # Record TrajectoryData row
-
 376:                 # if data_filter.should_record(range_vector, velocity, mach, record_step, self.look_angle, time):
-
+377:                 if data_filter.should_record(range_vector, velocity, mach, time):
-
      __pyx_t_6 = __pyx_f_16CyEulerBallistic_15trajectory_calc_21_TrajectoryDataFilter_should_record(__pyx_v_data_filter, __pyx_v_range_vector, __pyx_v_velocity, __pyx_v_mach, __pyx_v_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 377, __pyx_L1_error)
-      if (__pyx_t_6) {
-/* … */
-      }
-
+378:                     ranges.append(create_trajectory_row(
-
        __pyx_t_7 = __pyx_f_16CyEulerBallistic_15trajectory_calc_create_trajectory_row(__pyx_v_time, __pyx_v_range_vector, __pyx_v_velocity_vector, __pyx_v_velocity, __pyx_v_mach, __pyx_t_5, __pyx_v_self->_EulerTrajectoryCalc__shot.look_angle, __pyx_v_density_factor, __pyx_v_drag, __pyx_v_self->_EulerTrajectoryCalc__shot.weight, __pyx_v_data_filter->current_flag); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 378, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_ranges, __pyx_t_7); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(1, 378, __pyx_L1_error)
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
 379:                         time, range_vector, velocity_vector,
-
+380:                         velocity, mach, cy_spin_drift(&self.__shot, time), self.__shot.look_angle,
-
        __pyx_t_5 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_spin_drift((&__pyx_v_self->_EulerTrajectoryCalc__shot), __pyx_v_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 380, __pyx_L1_error)
-
 381:                         density_factor, drag, self.__shot.weight, data_filter.current_flag
-
 382:                     ))
-
 383: 
-
 384:             #region Ballistic calculation step
-
 385:             # use just cdef methods to maximize speed
-
 386: 
-
+387:             velocity_adjusted = sub(&velocity_vector, &wind_vector)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_sub((&__pyx_v_velocity_vector), (&__pyx_v_wind_vector)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 387, __pyx_L1_error)
-    __pyx_v_velocity_adjusted = __pyx_t_2;
-
+388:             velocity = mag(&velocity_adjusted)
-
    __pyx_t_5 = __pyx_f_16CyEulerBallistic_6vector_mag((&__pyx_v_velocity_adjusted)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 388, __pyx_L1_error)
-    __pyx_v_velocity = __pyx_t_5;
-
+389:             delta_time = calc_step / max(1.0, velocity)
-
    __pyx_t_5 = __pyx_v_velocity;
-    __pyx_t_3 = 1.0;
-    __pyx_t_6 = (__pyx_t_5 > __pyx_t_3);
-    if (__pyx_t_6) {
-      __pyx_t_4 = __pyx_t_5;
-    } else {
-      __pyx_t_4 = __pyx_t_3;
-    }
-    __pyx_v_delta_time = (__pyx_v_calc_step / __pyx_t_4);
-
+390:             drag = density_factor * velocity * cy_drag_by_mach(&self.__shot, velocity / mach)
-
    __pyx_t_4 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_drag_by_mach((&__pyx_v_self->_EulerTrajectoryCalc__shot), (__pyx_v_velocity / __pyx_v_mach)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 390, __pyx_L1_error)
-    __pyx_v_drag = ((__pyx_v_density_factor * __pyx_v_velocity) * __pyx_t_4);
-
 391: 
-
+392:             _temp1 = mul_c(&velocity_adjusted, drag)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_mul_c((&__pyx_v_velocity_adjusted), __pyx_v_drag); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 392, __pyx_L1_error)
-    __pyx_v__temp1 = __pyx_t_2;
-
+393:             _temp2 = sub(&_temp1, &gravity_vector)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_sub((&__pyx_v__temp1), (&__pyx_v_gravity_vector)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 393, __pyx_L1_error)
-    __pyx_v__temp2 = __pyx_t_2;
-
+394:             _temp3 = mul_c(&_temp2, delta_time)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_mul_c((&__pyx_v__temp2), __pyx_v_delta_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 394, __pyx_L1_error)
-    __pyx_v__temp3 = __pyx_t_2;
-
 395: 
-
+396:             velocity_vector = sub(&velocity_vector, &_temp3)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_sub((&__pyx_v_velocity_vector), (&__pyx_v__temp3)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 396, __pyx_L1_error)
-    __pyx_v_velocity_vector = __pyx_t_2;
-
 397: 
-
+398:             delta_range_vector = mul_c(&velocity_vector, delta_time)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_mul_c((&__pyx_v_velocity_vector), __pyx_v_delta_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 398, __pyx_L1_error)
-    __pyx_v_delta_range_vector = __pyx_t_2;
-
+399:             range_vector = add(&range_vector, &delta_range_vector)
-
    __pyx_t_2 = __pyx_f_16CyEulerBallistic_6vector_add((&__pyx_v_range_vector), (&__pyx_v_delta_range_vector)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 399, __pyx_L1_error)
-    __pyx_v_range_vector = __pyx_t_2;
-
 400: 
-
+401:             velocity = mag(&velocity_vector)
-
    __pyx_t_4 = __pyx_f_16CyEulerBallistic_6vector_mag((&__pyx_v_velocity_vector)); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 401, __pyx_L1_error)
-    __pyx_v_velocity = __pyx_t_4;
-
+402:             time += delta_time
-
    __pyx_v_time = (__pyx_v_time + __pyx_v_delta_time);
-
 403: 
-
+404:             if (
-
    if (__pyx_t_6) {
-/* … */
-    }
-  }
-
+405:                     velocity < _cMinimumVelocity
-
    __pyx_t_11 = (__pyx_v_velocity < __pyx_v__cMinimumVelocity);
-    if (!__pyx_t_11) {
-    } else {
-      __pyx_t_6 = __pyx_t_11;
-      goto __pyx_L9_bool_binop_done;
-    }
-
+406:                     or range_vector.y < _cMaximumDrop
-
    __pyx_t_11 = (__pyx_v_range_vector.y < __pyx_v__cMaximumDrop);
-    if (!__pyx_t_11) {
-    } else {
-      __pyx_t_6 = __pyx_t_11;
-      goto __pyx_L9_bool_binop_done;
-    }
-
+407:                     or self.__shot.alt0 + range_vector.y < _cMinimumAltitude
-
    __pyx_t_11 = ((__pyx_v_self->_EulerTrajectoryCalc__shot.alt0 + __pyx_v_range_vector.y) < __pyx_v__cMinimumAltitude);
-    __pyx_t_6 = __pyx_t_11;
-    __pyx_L9_bool_binop_done:;
-
 408:             ):
-
+409:                 ranges.append(create_trajectory_row(
-
      __pyx_t_7 = __pyx_f_16CyEulerBallistic_15trajectory_calc_create_trajectory_row(__pyx_v_time, __pyx_v_range_vector, __pyx_v_velocity_vector, __pyx_v_velocity, __pyx_v_mach, __pyx_t_4, __pyx_v_self->_EulerTrajectoryCalc__shot.look_angle, __pyx_v_density_factor, __pyx_v_drag, __pyx_v_self->_EulerTrajectoryCalc__shot.weight, __pyx_v_data_filter->current_flag); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 409, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_ranges, __pyx_t_7); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(1, 409, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
 410:                     time, range_vector, velocity_vector,
-
+411:                     velocity, mach, cy_spin_drift(&self.__shot, time), self.__shot.look_angle,
-
      __pyx_t_4 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_spin_drift((&__pyx_v_self->_EulerTrajectoryCalc__shot), __pyx_v_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 411, __pyx_L1_error)
-
 412:                     density_factor, drag, self.__shot.weight, data_filter.current_flag
-
 413:                 ))
-
 414: 
-
+415:                 if velocity < _cMinimumVelocity:
-
      __pyx_t_6 = (__pyx_v_velocity < __pyx_v__cMinimumVelocity);
-      if (__pyx_t_6) {
-/* … */
-        goto __pyx_L12;
-      }
-
+416:                     reason = RangeError.MinimumVelocityReached
-
        __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_RangeError); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 416, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_MinimumVelocityReached); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 416, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __pyx_v_reason = __pyx_t_8;
-        __pyx_t_8 = 0;
-
+417:                 elif range_vector.y < _cMaximumDrop:
-
      __pyx_t_6 = (__pyx_v_range_vector.y < __pyx_v__cMaximumDrop);
-      if (__pyx_t_6) {
-/* … */
-        goto __pyx_L12;
-      }
-
+418:                     reason = RangeError.MaximumDropReached
-
        __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_RangeError); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 418, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_MaximumDropReached); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 418, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __pyx_v_reason = __pyx_t_7;
-        __pyx_t_7 = 0;
-
 419:                 else:
-
+420:                     reason = RangeError.MinimumAltitudeReached
-
      /*else*/ {
-        __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_RangeError); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 420, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_MinimumAltitudeReached); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 420, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-        __pyx_v_reason = __pyx_t_8;
-        __pyx_t_8 = 0;
-      }
-      __pyx_L12:;
-
+421:                 raise RangeError(reason, ranges)
-
      __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_RangeError); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 421, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_1 = NULL;
-      __pyx_t_9 = 0;
-      #if CYTHON_UNPACK_METHODS
-      if (unlikely(PyMethod_Check(__pyx_t_7))) {
-        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_7);
-        if (likely(__pyx_t_1)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-          __Pyx_INCREF(__pyx_t_1);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_7, function);
-          __pyx_t_9 = 1;
-        }
-      }
-      #endif
-      {
-        PyObject *__pyx_callargs[3] = {__pyx_t_1, __pyx_v_reason, __pyx_v_ranges};
-        __pyx_t_8 = __Pyx_PyObject_FastCall(__pyx_t_7, __pyx_callargs+1-__pyx_t_9, 2+__pyx_t_9);
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 421, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-      __Pyx_Raise(__pyx_t_8, 0, 0, 0);
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __PYX_ERR(1, 421, __pyx_L1_error)
-
 422:             #endregion
-
 423: 
-
 424:         #endregion
-
 425:         # If filter_flags == 0 then all we want is the ending value
-
+426:         if len(ranges)==0:
-
  __pyx_t_12 = __Pyx_PyList_GET_SIZE(__pyx_v_ranges); if (unlikely(__pyx_t_12 == ((Py_ssize_t)-1))) __PYX_ERR(1, 426, __pyx_L1_error)
-  __pyx_t_6 = (__pyx_t_12 == 0);
-  if (__pyx_t_6) {
-/* … */
-  }
-
+427:             ranges.append(create_trajectory_row(
-
    __pyx_t_8 = __pyx_f_16CyEulerBallistic_15trajectory_calc_create_trajectory_row(__pyx_v_time, __pyx_v_range_vector, __pyx_v_velocity_vector, __pyx_v_velocity, __pyx_v_mach, __pyx_t_4, __pyx_v_self->_EulerTrajectoryCalc__shot.look_angle, __pyx_v_density_factor, __pyx_v_drag, __pyx_v_self->_EulerTrajectoryCalc__shot.weight, __pyx_e_16CyEulerBallistic_15trajectory_data_NONE); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 427, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_ranges, __pyx_t_8); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(1, 427, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
 428:                 time, range_vector, velocity_vector,
-
+429:                 velocity, mach, cy_spin_drift(&self.__shot, time), self.__shot.look_angle,
-
    __pyx_t_4 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_spin_drift((&__pyx_v_self->_EulerTrajectoryCalc__shot), __pyx_v_time); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 429, __pyx_L1_error)
-
 430:                 density_factor, drag, self.__shot.weight, CTrajFlag.NONE))
-
+431:         logger.debug(f"euler cy it {it}")
-
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_logger); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 431, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_debug); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 431, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = __Pyx_PyUnicode_From_int(__pyx_v_it, 0, ' ', 'd'); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 431, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_13 = __Pyx_PyUnicode_Concat(__pyx_kp_u_euler_cy_it, __pyx_t_7); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 431, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = NULL;
-  __pyx_t_9 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (unlikely(PyMethod_Check(__pyx_t_1))) {
-    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_1);
-    if (likely(__pyx_t_7)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_1, function);
-      __pyx_t_9 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_7, __pyx_t_13};
-    __pyx_t_8 = __Pyx_PyObject_FastCall(__pyx_t_1, __pyx_callargs+1-__pyx_t_9, 1+__pyx_t_9);
-    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-    if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 431, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  }
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+432:         return ranges
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_ranges);
-  __pyx_r = __pyx_v_ranges;
-  goto __pyx_L0;
-
 433: 
-
 434: 
-
+435: cdef object create_trajectory_row(double time, CVector range_vector, CVector velocity_vector,
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc_create_trajectory_row(double __pyx_v_time, struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_range_vector, struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_v_velocity_vector, double __pyx_v_velocity, double __pyx_v_mach, double __pyx_v_spin_drift, double __pyx_v_look_angle, double __pyx_v_density_factor, double __pyx_v_drag, double __pyx_v_weight, int __pyx_v_flag) {
-  double __pyx_v_windage;
-  double __pyx_v_drop_adjustment;
-  double __pyx_v_windage_adjustment;
-  double __pyx_v_trajectory_angle;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc.create_trajectory_row", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 436:                            double velocity, double mach, double spin_drift, double look_angle,
-
 437:                            double density_factor, double drag, double weight, int flag):
-
 438: 
-
 439:     cdef:
-
+440:         double windage = range_vector.z + spin_drift
-
  __pyx_v_windage = (__pyx_v_range_vector.z + __pyx_v_spin_drift);
-
+441:         double drop_adjustment = cy_get_correction(range_vector.x, range_vector.y)
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_get_correction(__pyx_v_range_vector.x, __pyx_v_range_vector.y); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 441, __pyx_L1_error)
-  __pyx_v_drop_adjustment = __pyx_t_1;
-
+442:         double windage_adjustment = cy_get_correction(range_vector.x, windage)
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_get_correction(__pyx_v_range_vector.x, __pyx_v_windage); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 442, __pyx_L1_error)
-  __pyx_v_windage_adjustment = __pyx_t_1;
-
+443:         double trajectory_angle = atan2(velocity_vector.y, velocity_vector.x);
-
  __pyx_v_trajectory_angle = atan2(__pyx_v_velocity_vector.y, __pyx_v_velocity_vector.x);
-
 444: 
-
+445:     return TrajectoryData(
-
  __Pyx_XDECREF(__pyx_r);
-/* … */
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData), __pyx_empty_tuple, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 445, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_3;
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
-
+446:         time=time,
-
  __pyx_t_2 = __Pyx_PyDict_NewPresized(16); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_time); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_time, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+447:         distance=_new_feet(range_vector.x),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet(__pyx_v_range_vector.x); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 447, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_distance, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+448:         velocity=_new_fps(velocity),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_fps(__pyx_v_velocity); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 448, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_velocity, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+449:         mach=velocity / mach,
-
  __pyx_t_3 = PyFloat_FromDouble((__pyx_v_velocity / __pyx_v_mach)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 449, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_mach_2, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+450:         height=_new_feet(range_vector.y),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet(__pyx_v_range_vector.y); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 450, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_height, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+451:         target_drop=_new_feet(
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet(((__pyx_v_range_vector.y - (__pyx_v_range_vector.x * tan(__pyx_v_look_angle))) * cos(__pyx_v_look_angle))); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 451, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_target_drop, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 452:             (range_vector.y - range_vector.x * tan(look_angle)) * cos(look_angle)
-
 453:         ),
-
+454:         drop_adj=_new_rad(drop_adjustment - (look_angle if range_vector.x else 0)),
-
  __pyx_t_4 = (__pyx_v_range_vector.x != 0);
-  if (__pyx_t_4) {
-    __pyx_t_1 = __pyx_v_look_angle;
-  } else {
-    __pyx_t_1 = 0.0;
-  }
-  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_rad((__pyx_v_drop_adjustment - __pyx_t_1)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 454, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_drop_adj, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+455:         windage=_new_feet(windage),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet(__pyx_v_windage); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 455, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_windage, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+456:         windage_adj=_new_rad(windage_adjustment),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_rad(__pyx_v_windage_adjustment); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 456, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_windage_adj, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+457:         look_distance=_new_feet(range_vector.x / cos(look_angle)),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet((__pyx_v_range_vector.x / cos(__pyx_v_look_angle))); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 457, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_look_distance, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+458:         angle=_new_rad(trajectory_angle),
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_rad(__pyx_v_trajectory_angle); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 458, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_angle, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+459:         density_factor=density_factor - 1,
-
  __pyx_t_3 = PyFloat_FromDouble((__pyx_v_density_factor - 1.0)); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 459, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_density_factor, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+460:         drag=drag,
-
  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_drag); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 460, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_drag, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+461:         energy=_new_ft_lb(cy_calculate_energy(weight, velocity)),
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_energy(__pyx_v_weight, __pyx_v_velocity); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 461, __pyx_L1_error)
-  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_ft_lb(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 461, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_energy, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+462:         ogw=_new_lb(cy_calculate_ogw(weight, velocity)),
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_8cy_euler_cy_calculate_ogw(__pyx_v_weight, __pyx_v_velocity); if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 462, __pyx_L1_error)
-  __pyx_t_3 = __pyx_f_16CyEulerBallistic_15trajectory_calc__new_lb(__pyx_t_1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 462, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_ogw, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+463:         flag=flag
-
  __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_flag); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 463, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_t_2, __pyx_n_s_flag, __pyx_t_3) < 0) __PYX_ERR(1, 446, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 464:     )
-
 465: 
-
 466: 
-
+467: cdef object _new_feet(double v):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc__new_feet(double __pyx_v_v) {
-  PyObject *__pyx_v_d = NULL;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._new_feet", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_d);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+468:     d = object.__new__(Distance)
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_builtin_object, __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 468, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_Distance); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 468, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  __pyx_t_5 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_5 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_5, 1+__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 468, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_v_d = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+469:     d._value = v * 12
-
  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_v * 12.0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 469, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_value, __pyx_t_1) < 0) __PYX_ERR(1, 469, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
+470:     d._defined_units = Unit.Foot
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_Unit); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 470, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_Foot); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 470, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_defined_units, __pyx_t_2) < 0) __PYX_ERR(1, 470, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+471:     return d
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_d);
-  __pyx_r = __pyx_v_d;
-  goto __pyx_L0;
-
 472: 
-
 473: 
-
+474: cdef object _new_fps(double v):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc__new_fps(double __pyx_v_v) {
-  PyObject *__pyx_v_d = NULL;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._new_fps", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_d);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+475:     d = object.__new__(Velocity)
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_builtin_object, __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 475, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_Velocity); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 475, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  __pyx_t_5 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_5 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_5, 1+__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 475, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_v_d = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+476:     d._value = v / 3.2808399
-
  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_v / 3.2808399)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 476, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_value, __pyx_t_1) < 0) __PYX_ERR(1, 476, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
+477:     d._defined_units = Unit.FPS
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_Unit); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 477, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_FPS); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 477, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_defined_units, __pyx_t_2) < 0) __PYX_ERR(1, 477, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+478:     return d
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_d);
-  __pyx_r = __pyx_v_d;
-  goto __pyx_L0;
-
 479: 
-
 480: 
-
+481: cdef object _new_rad(double v):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc__new_rad(double __pyx_v_v) {
-  PyObject *__pyx_v_d = NULL;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._new_rad", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_d);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+482:     d = object.__new__(Angular)
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_builtin_object, __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 482, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_Angular); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 482, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  __pyx_t_5 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_5 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_5, 1+__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 482, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_v_d = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+483:     d._value = v
-
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 483, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_value, __pyx_t_1) < 0) __PYX_ERR(1, 483, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
+484:     d._defined_units = Unit.Radian
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_Unit); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 484, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_Radian); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 484, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_defined_units, __pyx_t_2) < 0) __PYX_ERR(1, 484, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+485:     return d
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_d);
-  __pyx_r = __pyx_v_d;
-  goto __pyx_L0;
-
 486: 
-
 487: 
-
+488: cdef object _new_ft_lb(double v):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc__new_ft_lb(double __pyx_v_v) {
-  PyObject *__pyx_v_d = NULL;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._new_ft_lb", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_d);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+489:     d = object.__new__(Energy)
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_builtin_object, __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 489, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_Energy); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 489, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  __pyx_t_5 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_5 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_5, 1+__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 489, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_v_d = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+490:     d._value = v
-
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 490, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_value, __pyx_t_1) < 0) __PYX_ERR(1, 490, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
+491:     d._defined_units = Unit.FootPound
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_Unit); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 491, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_FootPound); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 491, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_defined_units, __pyx_t_2) < 0) __PYX_ERR(1, 491, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+492:     return d
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_d);
-  __pyx_r = __pyx_v_d;
-  goto __pyx_L0;
-
 493: 
-
 494: 
-
+495: cdef object _new_lb(double v):
-
static PyObject *__pyx_f_16CyEulerBallistic_15trajectory_calc__new_lb(double __pyx_v_v) {
-  PyObject *__pyx_v_d = NULL;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_calc._new_lb", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_d);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+496:     d = object.__new__(Weight)
-
  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_builtin_object, __pyx_n_s_new); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 496, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_Weight); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 496, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  __pyx_t_5 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_5 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_4, __pyx_t_3};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_5, 1+__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 496, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_v_d = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+497:     d._value = v / 0.000142857143
-
  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_v / 0.000142857143)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 497, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_value, __pyx_t_1) < 0) __PYX_ERR(1, 497, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
+498:     d._defined_units = Unit.Pound
-
  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_Unit); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 498, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_Pound); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 498, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_d, __pyx_n_s_defined_units, __pyx_t_2) < 0) __PYX_ERR(1, 498, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+499:     return d
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_d);
-  __pyx_r = __pyx_v_d;
-  goto __pyx_L0;
-
 500: 
-
 501: 
-
 502: 
-
 503: # # using integrate_1() slower than direct operations
-
 504: # integrate(&range_vector, &velocity_vector, &wind_vector, &gravity_vector, &time, &drag, &velocity,
-
 505: #           density_factor, mach, calc_step, self.drag_by_mach)
-
 506: 
-
 507: # cdef void integrate_1(CVector *range_vector, CVector *velocity_vector, CVector *wind_vector,
-
 508: #                       CVector *gravity_vector, double *time, double *drag, double *velocity,
-
 509: #                       double density_factor, double mach, double calc_step,
-
 510: #                       object drag_by_mach):
-
 511: #     cdef CVector velocity_adjusted
-
 512: #     cdef CVector delta_range_vector
-
 513: #     cdef CVector _temp1, _temp2, _temp3
-
 514: #     cdef double delta_time
-
 515: #
-
 516: #     velocity_adjusted = sub(velocity_vector, wind_vector)
-
 517: #     velocity[0] = mag(&velocity_adjusted)
-
 518: #     delta_time = calc_step / max(1.0, velocity[0])
-
 519: #
-
 520: #     # Call function pointer
-
 521: #     drag[0] = density_factor * velocity[0] * drag_by_mach(velocity[0] / mach)
-
 522: #
-
 523: #     _temp1 = mul_c(&velocity_adjusted, drag[0])
-
 524: #     _temp2 = sub(&_temp1, gravity_vector)
-
 525: #     _temp3 = mul_c(&_temp2, delta_time)
-
 526: #
-
 527: #     # Modify velocity_vector in place
-
 528: #     velocity_vector[0] = sub(velocity_vector, &_temp3)
-
 529: #
-
 530: #     delta_range_vector = mul_c(velocity_vector, delta_time)
-
 531: #
-
 532: #     # Modify range_vector in place
-
 533: #     range_vector[0] = add(range_vector, &delta_range_vector)
-
 534: #
-
 535: #     velocity[0] = mag(velocity_vector)
-
 536: #     time[0] += delta_time
-
diff --git a/CyEulerBallistic/trajectory_calc.pyx b/CyEulerBallistic/trajectory_calc.pyx index 52c7bbd..4dd6c6c 100644 --- a/CyEulerBallistic/trajectory_calc.pyx +++ b/CyEulerBallistic/trajectory_calc.pyx @@ -12,7 +12,7 @@ from libc.math cimport fabs, sin, cos, tan, atan, atan2 # noinspection PyUnresolvedReferences from CyEulerBallistic.vector cimport CVector, add, sub, mag, mul_c, mul_v, neg, norm, mag # noinspection PyUnresolvedReferences -from CyEulerBallistic.trajectory_data cimport CTrajFlag, TrajectoryData +from CyEulerBallistic.trajectory_data cimport CTrajFlag, TrajectoryData, BaseTrajData # noinspection PyUnresolvedReferences from CyEulerBallistic.cy_euler cimport ( Config_t, @@ -36,13 +36,12 @@ from CyEulerBallistic.cy_euler cimport ( import warnings -from py_ballisticcalc.logger import logger +from py_ballisticcalc.logger import logger, get_debug from py_ballisticcalc.unit import Angular, Unit, Velocity, Distance, Energy, Weight from py_ballisticcalc.exceptions import ZeroFindingError, RangeError from py_ballisticcalc.constants import cMaxWindDistanceFeet from bisect import bisect_left - __all__ = ( 'EulerTrajectoryCalc', ) @@ -53,18 +52,24 @@ cdef class _TrajectoryDataFilter: cdef: int filter, current_flag, seen_zero int current_item - double previous_mach, previous_time, next_range_distance, range_step, time_step, look_angle + double previous_mach, previous_time, previous_v_mach, next_record_distance + double range_step, time_of_last_record, time_step, look_angle + CVector previous_position, previous_velocity - def __cinit__(_TrajectoryDataFilter self, - int filter_flags, double range_step, double time_step = 0.0) -> None: + def __cinit__(_TrajectoryDataFilter self, int filter_flags, double range_step, + CVector initial_position, CVector initial_velocity, double time_step = 0.0) -> None: self.filter = filter_flags self.current_flag = CTrajFlag.NONE self.seen_zero = CTrajFlag.NONE self.time_step = time_step self.range_step = range_step + self.time_of_last_record = 0.0 + self.next_record_distance = 0.0 self.previous_mach = 0.0 self.previous_time = 0.0 - self.next_range_distance = 0.0 + self.previous_position = initial_position + self.previous_velocity = initial_velocity + self.previous_v_mach = 0.0 self.look_angle = 0 cdef void setup_seen_zero(_TrajectoryDataFilter self, double height, double barrel_elevation, double look_angle): @@ -77,54 +82,95 @@ cdef class _TrajectoryDataFilter: cdef void clear_current_flag(_TrajectoryDataFilter self): self.current_flag = CTrajFlag.NONE - cdef bint should_record(_TrajectoryDataFilter self, - CVector range_vector, - double velocity, + cdef BaseTrajData should_record(_TrajectoryDataFilter self, + CVector position, + CVector velocity, double mach, double time, ): - self.check_zero_crossing(range_vector) - self.check_mach_crossing(velocity, mach) - if self.check_next_range(range_vector.x, self.range_step): - self.previous_time = time + cdef BaseTrajData data = None + cdef double ratio + cdef CVector temp_position, temp_velocity + cdef CVector temp_sub_position, temp_sub_velocity + cdef CVector temp_mul_position, temp_mul_velocity + + #region DEBUG + if get_debug(): + logger.debug( + f"should_record called with time={time}, " + f"position=({position.x}, {position.y}, {position.z}), " + f"velocity=({velocity.x}, {velocity.y}, {velocity.z}), mach={mach}" + ) + #endregion + if (self.range_step > 0) and (position.x >= self.next_record_distance): + while self.next_record_distance + self.range_step < position.x: + # Handle case where we have stepped past more than one record distance + self.next_record_distance += self.range_step + if position.x > self.previous_position.x: + # Interpolate to get BaseTrajData at the record distance + ratio = (self.next_record_distance - self.previous_position.x) / (position.x - self.previous_position.x) + temp_sub_position = sub(&position, &self.previous_position) + temp_mul_position = mul_c(&temp_sub_position, ratio) + temp_position = add(&self.previous_position, &temp_mul_position) + temp_sub_velocity = sub(&velocity, &self.previous_velocity) + temp_mul_velocity = mul_c(&temp_sub_velocity, ratio) + temp_velocity = add(&self.previous_velocity, &temp_mul_velocity) + data = BaseTrajData( + time=self.previous_time + (time - self.previous_time) * ratio, + position=temp_position, + velocity=temp_velocity, + mach=self.previous_mach + (mach - self.previous_mach) * ratio + ) + self.current_flag |= CTrajFlag.RANGE + self.next_record_distance += self.range_step + self.time_of_last_record = time elif self.time_step > 0: self.check_next_time(time) - return (self.current_flag & self.filter) != 0 - - cdef bint check_next_range(_TrajectoryDataFilter self, double next_range, double step): - # Next range check - if next_range >= self.next_range_distance: - self.current_flag |= CTrajFlag.RANGE - self.next_range_distance += step - return True - return False + self.check_zero_crossing(position) + self.check_mach_crossing(mag(&velocity), mach) + if (self.current_flag & self.filter) != 0 and data is None: + data = BaseTrajData(time=time, position=position, + velocity=velocity, mach=mach) + self.previous_time = time + self.previous_position = position + self.previous_velocity = velocity + self.previous_mach = mach + #region DEBUG + if get_debug(): + if data is not None: + logger.debug( + f"should_record returning BaseTrajData time={data.time}, " + f"position=({data.position.x}, {data.position.y}, {data.position.z}), " + f"velocity=({data.velocity.x}, {data.velocity.y}, {data.velocity.z}), mach={data.mach}" + ) + else: + logger.debug("should_record returning None") + #endregion + return data - cdef void check_next_time(self, double time): - if time > self.previous_time + self.time_step: + cdef void check_next_time(_TrajectoryDataFilter self, double time): + if time > self.time_of_last_record + self.time_step: self.current_flag |= CTrajFlag.RANGE - self.previous_time = time + self.time_of_last_record = time cdef void check_mach_crossing(_TrajectoryDataFilter self, double velocity, double mach): - # Mach crossing check - cdef double current_mach = velocity / mach - if self.previous_mach > 1 >= current_mach: + cdef double current_v_mach = velocity / mach + if self.previous_v_mach > 1 >= current_v_mach: self.current_flag |= CTrajFlag.MACH - self.previous_mach = current_mach + self.previous_v_mach = current_v_mach cdef void check_zero_crossing(_TrajectoryDataFilter self, CVector range_vector): - # Zero-crossing checks - if range_vector.x > 0: # Zero reference line is the sight line defined by look_angle reference_height = range_vector.x * tan(self.look_angle) # If we haven't seen ZERO_UP, we look for that first if not (self.seen_zero & CTrajFlag.ZERO_UP): - if range_vector.x >= reference_height: + if range_vector.y >= reference_height: self.current_flag |= CTrajFlag.ZERO_UP self.seen_zero |= CTrajFlag.ZERO_UP # We've crossed above sight line; now look for crossing back through it elif not (self.seen_zero & CTrajFlag.ZERO_DOWN): - if range_vector.x < reference_height: + if range_vector.y < reference_height: self.current_flag |= CTrajFlag.ZERO_DOWN self.seen_zero |= CTrajFlag.ZERO_DOWN @@ -219,7 +265,7 @@ cdef class EulerTrajectoryCalc: CTrajFlag filter_flags = CTrajFlag.RANGE if extra_data: - dist_step = Distance.Foot(self.__config.chart_resolution) + #dist_step = Distance.Foot(self.__config.chart_resolution) filter_flags = CTrajFlag.ALL self._init_trajectory(shot_info) @@ -284,7 +330,7 @@ cdef class EulerTrajectoryCalc: double zero_finding_error = _cZeroFindingAccuracy * 2 object t - double height + double height, last_distance_foot, proportion self._init_trajectory(shot_info) self.__shot.barrel_azimuth = 0.0 @@ -294,9 +340,16 @@ cdef class EulerTrajectoryCalc: # x = horizontal distance down range, y = drop, z = windage while zero_finding_error > _cZeroFindingAccuracy and iterations_count < _cMaxIterations: - t = self._integrate(maximum_range, zero_distance, CTrajFlag.NONE)[0] - height = t.height._feet # use there internal shortcut instead of (t.height >> Distance.Foot) + try: + t = self._integrate(maximum_range, zero_distance, CTrajFlag.NONE)[0] + height = t.height._feet # use internal shortcut instead of (t.height >> Distance.Foot) + except RangeError as e: + last_distance_foot = e.last_distance._feet + proportion = (last_distance_foot) / zero_distance + height = (e.incomplete_trajectory[-1].height._feet) / proportion + zero_finding_error = fabs(height - height_at_zero) + if zero_finding_error > _cZeroFindingAccuracy: self.__shot.barrel_elevation -= (height - height_at_zero) / zero_distance else: # last barrel_elevation hit zero! @@ -327,6 +380,7 @@ cdef class EulerTrajectoryCalc: # endregion _TrajectoryDataFilter data_filter + BaseTrajData data cdef: # early bindings @@ -350,9 +404,8 @@ cdef class EulerTrajectoryCalc: min_step = min(calc_step, record_step) # With non-zero look_angle, rounding can suggest multiple adjacent zero-crossings - data_filter = _TrajectoryDataFilter(filter_flags=filter_flags, - range_step=record_step, - time_step=time_step) + data_filter = _TrajectoryDataFilter(filter_flags=filter_flags, range_step=record_step, + initial_position=range_vector, initial_velocity=velocity_vector, time_step=time_step) data_filter.setup_seen_zero(range_vector.y, self.__shot.barrel_elevation, self.__shot.look_angle) #region Trajectory Loop @@ -373,11 +426,11 @@ cdef class EulerTrajectoryCalc: if filter_flags: # Record TrajectoryData row - # if data_filter.should_record(range_vector, velocity, mach, record_step, self.look_angle, time): - if data_filter.should_record(range_vector, velocity, mach, time): + data = data_filter.should_record(range_vector, velocity_vector, mach, time) + if data is not None: ranges.append(create_trajectory_row( - time, range_vector, velocity_vector, - velocity, mach, cy_spin_drift(&self.__shot, time), self.__shot.look_angle, + data.time, data.position, data.velocity, mag(&data.velocity), data.mach, + cy_spin_drift(&self.__shot, time), self.__shot.look_angle, density_factor, drag, self.__shot.weight, data_filter.current_flag )) @@ -420,10 +473,9 @@ cdef class EulerTrajectoryCalc: reason = RangeError.MinimumAltitudeReached raise RangeError(reason, ranges) #endregion - #endregion - # If filter_flags == 0 then all we want is the ending value - if len(ranges)==0: + # Ensure that we have at least two data points in trajectory + if len(ranges) < 2: ranges.append(create_trajectory_row( time, range_vector, velocity_vector, velocity, mach, cy_spin_drift(&self.__shot, time), self.__shot.look_angle, diff --git a/CyEulerBallistic/trajectory_data.html b/CyEulerBallistic/trajectory_data.html deleted file mode 100644 index b84b441..0000000 --- a/CyEulerBallistic/trajectory_data.html +++ /dev/null @@ -1,1500 +0,0 @@ - - - - - - Cython: trajectory_data.pyx - - - -

Generated by Cython 3.0.12

-

- 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: trajectory_data.c

-
+001: from cython cimport final
-
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 1, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_3) < 0) __PYX_ERR(1, 1, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 002: 
-
 003: 
-
+004: from py_ballisticcalc.unit import PreferredUnits
-
  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(__pyx_n_s_PreferredUnits);
-  __Pyx_GIVEREF(__pyx_n_s_PreferredUnits);
-  if (__Pyx_PyList_SET_ITEM(__pyx_t_2, 0, __pyx_n_s_PreferredUnits)) __PYX_ERR(1, 4, __pyx_L1_error);
-  __pyx_t_3 = __Pyx_Import(__pyx_n_s_py_ballisticcalc_unit, __pyx_t_2, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_ImportFrom(__pyx_t_3, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_PreferredUnits, __pyx_t_2) < 0) __PYX_ERR(1, 4, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 005: 
-
 006: 
-
 007: @final
-
 008: cdef class TrajectoryData:
-
+009:     __slots__ = ('time', 'distance', 'velocity',
-
  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData, __pyx_n_s_slots, __pyx_tuple__5) < 0) __PYX_ERR(1, 9, __pyx_L1_error)
-  PyType_Modified(__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData);
-
 010:                  'mach', 'height', 'target_drop', 'drop_adj',
-
 011:                  'windage', 'windage_adj', 'look_distance',
-
 012:                  'angle', 'density_factor', 'drag', 'energy', 'ogw', 'flag')
-
 013: 
-
+014:     _fields = __slots__
-
  __Pyx_GetNameInClass(__pyx_t_3, (PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData, __pyx_n_s_slots); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData, __pyx_n_s_fields, __pyx_t_3) < 0) __PYX_ERR(1, 14, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  PyType_Modified(__pyx_ptype_16CyEulerBallistic_15trajectory_data_TrajectoryData);
-
 015: 
-
+016:     def __cinit__(TrajectoryData self,
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  double __pyx_v_time;
-  PyObject *__pyx_v_distance = 0;
-  PyObject *__pyx_v_velocity = 0;
-  double __pyx_v_mach;
-  PyObject *__pyx_v_height = 0;
-  PyObject *__pyx_v_target_drop = 0;
-  PyObject *__pyx_v_drop_adj = 0;
-  PyObject *__pyx_v_windage = 0;
-  PyObject *__pyx_v_windage_adj = 0;
-  PyObject *__pyx_v_look_distance = 0;
-  PyObject *__pyx_v_angle = 0;
-  double __pyx_v_density_factor;
-  double __pyx_v_drag;
-  PyObject *__pyx_v_energy = 0;
-  PyObject *__pyx_v_ogw = 0;
-  int __pyx_v_flag;
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_time,&__pyx_n_s_distance,&__pyx_n_s_velocity,&__pyx_n_s_mach,&__pyx_n_s_height,&__pyx_n_s_target_drop,&__pyx_n_s_drop_adj,&__pyx_n_s_windage,&__pyx_n_s_windage_adj,&__pyx_n_s_look_distance,&__pyx_n_s_angle,&__pyx_n_s_density_factor,&__pyx_n_s_drag,&__pyx_n_s_energy,&__pyx_n_s_ogw,&__pyx_n_s_flag,0};
-  PyObject* values[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case 16: values[15] = __Pyx_Arg_VARARGS(__pyx_args, 15);
-        CYTHON_FALLTHROUGH;
-        case 15: values[14] = __Pyx_Arg_VARARGS(__pyx_args, 14);
-        CYTHON_FALLTHROUGH;
-        case 14: values[13] = __Pyx_Arg_VARARGS(__pyx_args, 13);
-        CYTHON_FALLTHROUGH;
-        case 13: values[12] = __Pyx_Arg_VARARGS(__pyx_args, 12);
-        CYTHON_FALLTHROUGH;
-        case 12: values[11] = __Pyx_Arg_VARARGS(__pyx_args, 11);
-        CYTHON_FALLTHROUGH;
-        case 11: values[10] = __Pyx_Arg_VARARGS(__pyx_args, 10);
-        CYTHON_FALLTHROUGH;
-        case 10: values[9] = __Pyx_Arg_VARARGS(__pyx_args, 9);
-        CYTHON_FALLTHROUGH;
-        case  9: values[8] = __Pyx_Arg_VARARGS(__pyx_args, 8);
-        CYTHON_FALLTHROUGH;
-        case  8: values[7] = __Pyx_Arg_VARARGS(__pyx_args, 7);
-        CYTHON_FALLTHROUGH;
-        case  7: values[6] = __Pyx_Arg_VARARGS(__pyx_args, 6);
-        CYTHON_FALLTHROUGH;
-        case  6: values[5] = __Pyx_Arg_VARARGS(__pyx_args, 5);
-        CYTHON_FALLTHROUGH;
-        case  5: values[4] = __Pyx_Arg_VARARGS(__pyx_args, 4);
-        CYTHON_FALLTHROUGH;
-        case  4: values[3] = __Pyx_Arg_VARARGS(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_time)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_distance)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 1); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_velocity)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[2]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 2); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  3:
-        if (likely((values[3] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_mach)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[3]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 3); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  4:
-        if (likely((values[4] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_height)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[4]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 4); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  5:
-        if (likely((values[5] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_target_drop)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[5]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 5); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  6:
-        if (likely((values[6] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_drop_adj)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[6]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 6); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  7:
-        if (likely((values[7] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_windage)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[7]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 7); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  8:
-        if (likely((values[8] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_windage_adj)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[8]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 8); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  9:
-        if (likely((values[9] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_look_distance)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[9]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 9); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 10:
-        if (likely((values[10] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_angle)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[10]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 10); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 11:
-        if (likely((values[11] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_density_factor)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[11]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 11); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 12:
-        if (likely((values[12] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_drag)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[12]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 12); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 13:
-        if (likely((values[13] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_energy)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[13]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 13); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 14:
-        if (likely((values[14] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_ogw)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[14]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 14); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case 15:
-        if (likely((values[15] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_flag)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[15]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, 15); __PYX_ERR(1, 16, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "__cinit__") < 0)) __PYX_ERR(1, 16, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 16)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-      values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-      values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-      values[3] = __Pyx_Arg_VARARGS(__pyx_args, 3);
-      values[4] = __Pyx_Arg_VARARGS(__pyx_args, 4);
-      values[5] = __Pyx_Arg_VARARGS(__pyx_args, 5);
-      values[6] = __Pyx_Arg_VARARGS(__pyx_args, 6);
-      values[7] = __Pyx_Arg_VARARGS(__pyx_args, 7);
-      values[8] = __Pyx_Arg_VARARGS(__pyx_args, 8);
-      values[9] = __Pyx_Arg_VARARGS(__pyx_args, 9);
-      values[10] = __Pyx_Arg_VARARGS(__pyx_args, 10);
-      values[11] = __Pyx_Arg_VARARGS(__pyx_args, 11);
-      values[12] = __Pyx_Arg_VARARGS(__pyx_args, 12);
-      values[13] = __Pyx_Arg_VARARGS(__pyx_args, 13);
-      values[14] = __Pyx_Arg_VARARGS(__pyx_args, 14);
-      values[15] = __Pyx_Arg_VARARGS(__pyx_args, 15);
-    }
-    __pyx_v_time = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_time == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 17, __pyx_L3_error)
-    __pyx_v_distance = values[1];
-    __pyx_v_velocity = values[2];
-    __pyx_v_mach = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_mach == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 20, __pyx_L3_error)
-    __pyx_v_height = values[4];
-    __pyx_v_target_drop = values[5];
-    __pyx_v_drop_adj = values[6];
-    __pyx_v_windage = values[7];
-    __pyx_v_windage_adj = values[8];
-    __pyx_v_look_distance = values[9];
-    __pyx_v_angle = values[10];
-    __pyx_v_density_factor = __pyx_PyFloat_AsDouble(values[11]); if (unlikely((__pyx_v_density_factor == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 28, __pyx_L3_error)
-    __pyx_v_drag = __pyx_PyFloat_AsDouble(values[12]); if (unlikely((__pyx_v_drag == (double)-1) && PyErr_Occurred())) __PYX_ERR(1, 29, __pyx_L3_error)
-    __pyx_v_energy = values[13];
-    __pyx_v_ogw = values[14];
-    __pyx_v_flag = __Pyx_PyInt_As_int(values[15]); if (unlikely((__pyx_v_flag == (int)-1) && PyErr_Occurred())) __PYX_ERR(1, 32, __pyx_L3_error)
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 16, 16, __pyx_nargs); __PYX_ERR(1, 16, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_data.TrajectoryData.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData___cinit__(((struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *)__pyx_v_self), __pyx_v_time, __pyx_v_distance, __pyx_v_velocity, __pyx_v_mach, __pyx_v_height, __pyx_v_target_drop, __pyx_v_drop_adj, __pyx_v_windage, __pyx_v_windage_adj, __pyx_v_look_distance, __pyx_v_angle, __pyx_v_density_factor, __pyx_v_drag, __pyx_v_energy, __pyx_v_ogw, __pyx_v_flag);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData___cinit__(struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *__pyx_v_self, double __pyx_v_time, PyObject *__pyx_v_distance, PyObject *__pyx_v_velocity, double __pyx_v_mach, PyObject *__pyx_v_height, PyObject *__pyx_v_target_drop, PyObject *__pyx_v_drop_adj, PyObject *__pyx_v_windage, PyObject *__pyx_v_windage_adj, PyObject *__pyx_v_look_distance, PyObject *__pyx_v_angle, double __pyx_v_density_factor, double __pyx_v_drag, PyObject *__pyx_v_energy, PyObject *__pyx_v_ogw, int __pyx_v_flag) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 017:                     double time,
-
 018:                     object distance,
-
 019:                     object velocity,
-
 020:                     double mach,
-
 021:                     object height,
-
 022:                     object target_drop,
-
 023:                     object drop_adj,
-
 024:                     object windage,
-
 025:                     object windage_adj,
-
 026:                     object look_distance,
-
 027:                     object angle,
-
 028:                     double density_factor,
-
 029:                     double drag,
-
 030:                     object energy,
-
 031:                     object ogw,
-
 032:                     int flag,
-
 033:                     ):
-
+034:         self.time = time
-
  __pyx_v_self->time = __pyx_v_time;
-
+035:         self.distance = distance
-
  __Pyx_INCREF(__pyx_v_distance);
-  __Pyx_GIVEREF(__pyx_v_distance);
-  __Pyx_GOTREF(__pyx_v_self->distance);
-  __Pyx_DECREF(__pyx_v_self->distance);
-  __pyx_v_self->distance = __pyx_v_distance;
-
+036:         self.velocity = velocity
-
  __Pyx_INCREF(__pyx_v_velocity);
-  __Pyx_GIVEREF(__pyx_v_velocity);
-  __Pyx_GOTREF(__pyx_v_self->velocity);
-  __Pyx_DECREF(__pyx_v_self->velocity);
-  __pyx_v_self->velocity = __pyx_v_velocity;
-
+037:         self.mach = mach
-
  __pyx_v_self->mach = __pyx_v_mach;
-
+038:         self.height = height
-
  __Pyx_INCREF(__pyx_v_height);
-  __Pyx_GIVEREF(__pyx_v_height);
-  __Pyx_GOTREF(__pyx_v_self->height);
-  __Pyx_DECREF(__pyx_v_self->height);
-  __pyx_v_self->height = __pyx_v_height;
-
+039:         self.target_drop = target_drop
-
  __Pyx_INCREF(__pyx_v_target_drop);
-  __Pyx_GIVEREF(__pyx_v_target_drop);
-  __Pyx_GOTREF(__pyx_v_self->target_drop);
-  __Pyx_DECREF(__pyx_v_self->target_drop);
-  __pyx_v_self->target_drop = __pyx_v_target_drop;
-
+040:         self.drop_adj = drop_adj
-
  __Pyx_INCREF(__pyx_v_drop_adj);
-  __Pyx_GIVEREF(__pyx_v_drop_adj);
-  __Pyx_GOTREF(__pyx_v_self->drop_adj);
-  __Pyx_DECREF(__pyx_v_self->drop_adj);
-  __pyx_v_self->drop_adj = __pyx_v_drop_adj;
-
+041:         self.windage = windage
-
  __Pyx_INCREF(__pyx_v_windage);
-  __Pyx_GIVEREF(__pyx_v_windage);
-  __Pyx_GOTREF(__pyx_v_self->windage);
-  __Pyx_DECREF(__pyx_v_self->windage);
-  __pyx_v_self->windage = __pyx_v_windage;
-
+042:         self.windage_adj = windage_adj
-
  __Pyx_INCREF(__pyx_v_windage_adj);
-  __Pyx_GIVEREF(__pyx_v_windage_adj);
-  __Pyx_GOTREF(__pyx_v_self->windage_adj);
-  __Pyx_DECREF(__pyx_v_self->windage_adj);
-  __pyx_v_self->windage_adj = __pyx_v_windage_adj;
-
+043:         self.look_distance = look_distance
-
  __Pyx_INCREF(__pyx_v_look_distance);
-  __Pyx_GIVEREF(__pyx_v_look_distance);
-  __Pyx_GOTREF(__pyx_v_self->look_distance);
-  __Pyx_DECREF(__pyx_v_self->look_distance);
-  __pyx_v_self->look_distance = __pyx_v_look_distance;
-
+044:         self.angle = angle
-
  __Pyx_INCREF(__pyx_v_angle);
-  __Pyx_GIVEREF(__pyx_v_angle);
-  __Pyx_GOTREF(__pyx_v_self->angle);
-  __Pyx_DECREF(__pyx_v_self->angle);
-  __pyx_v_self->angle = __pyx_v_angle;
-
+045:         self.density_factor = density_factor
-
  __pyx_v_self->density_factor = __pyx_v_density_factor;
-
+046:         self.drag = drag
-
  __pyx_v_self->drag = __pyx_v_drag;
-
+047:         self.energy = energy
-
  __Pyx_INCREF(__pyx_v_energy);
-  __Pyx_GIVEREF(__pyx_v_energy);
-  __Pyx_GOTREF(__pyx_v_self->energy);
-  __Pyx_DECREF(__pyx_v_self->energy);
-  __pyx_v_self->energy = __pyx_v_energy;
-
+048:         self.ogw = ogw
-
  __Pyx_INCREF(__pyx_v_ogw);
-  __Pyx_GIVEREF(__pyx_v_ogw);
-  __Pyx_GOTREF(__pyx_v_self->ogw);
-  __Pyx_DECREF(__pyx_v_self->ogw);
-  __pyx_v_self->ogw = __pyx_v_ogw;
-
+049:         self.flag = flag
-
  __pyx_v_self->flag = __pyx_v_flag;
-
 050: 
-
+051:     def formatted(TrajectoryData self) -> tuple[str, ...]:
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_3formatted(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_15trajectory_data_14TrajectoryData_2formatted, "TrajectoryData.formatted(self) -> tuple[str, ...]\n\n        :return: matrix of formatted strings for each value of trajectory in default prefer_units\n        ");
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_3formatted(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("formatted (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  if (unlikely(__pyx_nargs > 0)) {
-    __Pyx_RaiseArgtupleInvalid("formatted", 1, 0, 0, __pyx_nargs); return NULL;}
-  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "formatted", 0))) return NULL;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_2formatted(((struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_2formatted(struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *__pyx_v_self) {
-  PyObject *__pyx_v__fmt = 0;
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_XDECREF(__pyx_t_10);
-  __Pyx_XDECREF(__pyx_t_11);
-  __Pyx_XDECREF(__pyx_t_12);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_XDECREF(__pyx_t_14);
-  __Pyx_XDECREF(__pyx_t_15);
-  __Pyx_XDECREF(__pyx_t_16);
-  __Pyx_XDECREF(__pyx_t_17);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_data.TrajectoryData.formatted", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v__fmt);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 052:         """
-
 053:         :return: matrix of formatted strings for each value of trajectory in default prefer_units
-
 054:         """
-
 055: 
-
+056:         def _fmt(v, u) -> str:
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted_1_fmt(PyObject *__pyx_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt, "simple formatter");
-static PyMethodDef __pyx_mdef_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted_1_fmt = {"_fmt", (PyCFunction)(void*)(__Pyx_PyCFunction_FastCallWithKeywords)__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted_1_fmt, __Pyx_METH_FASTCALL|METH_KEYWORDS, __pyx_doc_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt};
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted_1_fmt(PyObject *__pyx_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  PyObject *__pyx_v_v = 0;
-  PyObject *__pyx_v_u = 0;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_fmt (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_v,&__pyx_n_s_u,0};
-  PyObject* values[2] = {0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  2: values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_v)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 56, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_u)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(1, 56, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("_fmt", 1, 2, 2, 1); __PYX_ERR(1, 56, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "_fmt") < 0)) __PYX_ERR(1, 56, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 2)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-      values[1] = __Pyx_Arg_FASTCALL(__pyx_args, 1);
-    }
-    __pyx_v_v = values[0];
-    __pyx_v_u = values[1];
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_fmt", 1, 2, 2, __pyx_nargs); __PYX_ERR(1, 56, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_data.TrajectoryData.formatted._fmt", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_self, __pyx_v_v, __pyx_v_u);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_v, PyObject *__pyx_v_u) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_data.TrajectoryData.formatted._fmt", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-  __pyx_tuple__3 = PyTuple_Pack(2, __pyx_n_s_v, __pyx_n_s_u); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(1, 56, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__3);
-  __Pyx_GIVEREF(__pyx_tuple__3);
-/* … */
-  __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 56, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_return, __pyx_n_s_str) < 0) __PYX_ERR(1, 56, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted_1_fmt, 0, __pyx_n_s_formatted_locals__fmt, NULL, __pyx_n_s_CyEulerBallistic_trajectory_data_2, __pyx_d, ((PyObject *)__pyx_codeobj__4)); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 56, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_CyFunction_SetAnnotationsDict(__pyx_t_2, __pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v__fmt = __pyx_t_2;
-  __pyx_t_2 = 0;
-  __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(2, 0, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_CyEulerBallistic_trajectory_data, __pyx_n_s_fmt, 56, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(1, 56, __pyx_L1_error)
-
 057:             """simple formatter"""
-
+058:             return f"{v >> u:.{u.accuracy}f} {u.symbol}"
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 127;
-  __pyx_t_4 = PyNumber_Rshift(__pyx_v_v, __pyx_v_u); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = 0;
-  __pyx_t_7 = 127;
-  __Pyx_INCREF(__pyx_kp_u_);
-  __pyx_t_6 += 1;
-  __Pyx_GIVEREF(__pyx_kp_u_);
-  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_kp_u_);
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_v_u, __pyx_n_s_accuracy); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_9 = __Pyx_PyObject_FormatSimple(__pyx_t_8, __pyx_empty_unicode); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_7 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) > __pyx_t_7) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) : __pyx_t_7;
-  __pyx_t_6 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9);
-  __Pyx_GIVEREF(__pyx_t_9);
-  PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_9);
-  __pyx_t_9 = 0;
-  __Pyx_INCREF(__pyx_n_u_f);
-  __pyx_t_6 += 1;
-  __Pyx_GIVEREF(__pyx_n_u_f);
-  PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_n_u_f);
-  __pyx_t_9 = __Pyx_PyUnicode_Join(__pyx_t_5, 3, __pyx_t_6, __pyx_t_7); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = __Pyx_PyObject_Format(__pyx_t_4, __pyx_t_9); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-  __pyx_t_3 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) > __pyx_t_3) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) : __pyx_t_3;
-  __pyx_t_2 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5);
-  __Pyx_GIVEREF(__pyx_t_5);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_5);
-  __pyx_t_5 = 0;
-  __Pyx_INCREF(__pyx_kp_u__2);
-  __pyx_t_2 += 1;
-  __Pyx_GIVEREF(__pyx_kp_u__2);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_kp_u__2);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_u, __pyx_n_s_symbol); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_9 = __Pyx_PyObject_FormatSimple(__pyx_t_5, __pyx_empty_unicode); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_3 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) > __pyx_t_3) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_9) : __pyx_t_3;
-  __pyx_t_2 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_9);
-  __Pyx_GIVEREF(__pyx_t_9);
-  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_t_9);
-  __pyx_t_9 = 0;
-  __pyx_t_9 = __Pyx_PyUnicode_Join(__pyx_t_1, 3, __pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 58, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_r = ((PyObject*)__pyx_t_9);
-  __pyx_t_9 = 0;
-  goto __pyx_L0;
-
 059: 
-
+060:         return (
-
  __Pyx_XDECREF(__pyx_r);
-
+061:             f'{self.time:.3f} s',
-
  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_self->time); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_1 = __Pyx_PyObject_Format(__pyx_t_2, __pyx_kp_u_3f); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyUnicode_ConcatInPlace(__pyx_t_1, __pyx_kp_u_s); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-/* … */
-  __pyx_t_16 = PyTuple_New(16); if (unlikely(!__pyx_t_16)) __PYX_ERR(1, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_16);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 0, __pyx_t_2)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 1, __pyx_t_3)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 2, __pyx_t_1)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_5);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 3, __pyx_t_5)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_6);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 4, __pyx_t_6)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_4);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 5, __pyx_t_4)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_7);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 6, __pyx_t_7)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_8);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 7, __pyx_t_8)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_9);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 8, __pyx_t_9)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_10);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 9, __pyx_t_10)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_11);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 10, __pyx_t_11)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_12);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 11, __pyx_t_12)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_14);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 12, __pyx_t_14)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_15);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 13, __pyx_t_15)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_13);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 14, __pyx_t_13)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_17);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_16, 15, __pyx_t_17)) __PYX_ERR(1, 61, __pyx_L1_error);
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_1 = 0;
-  __pyx_t_5 = 0;
-  __pyx_t_6 = 0;
-  __pyx_t_4 = 0;
-  __pyx_t_7 = 0;
-  __pyx_t_8 = 0;
-  __pyx_t_9 = 0;
-  __pyx_t_10 = 0;
-  __pyx_t_11 = 0;
-  __pyx_t_12 = 0;
-  __pyx_t_14 = 0;
-  __pyx_t_15 = 0;
-  __pyx_t_13 = 0;
-  __pyx_t_17 = 0;
-  __pyx_r = ((PyObject*)__pyx_t_16);
-  __pyx_t_16 = 0;
-  goto __pyx_L0;
-
+062:             _fmt(self.distance, PreferredUnits.distance),
-
  __pyx_t_1 = __pyx_v_self->distance;
-  __Pyx_INCREF(__pyx_t_1);
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_distance); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_1, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+063:             _fmt(self.velocity, PreferredUnits.velocity),
-
  __pyx_t_4 = __pyx_v_self->velocity;
-  __Pyx_INCREF(__pyx_t_4);
-  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 63, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_velocity); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 63, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 63, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-
+064:             f'{self.mach:.2f} mach',
-
  __pyx_t_5 = PyFloat_FromDouble(__pyx_v_self->mach); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = __Pyx_PyObject_Format(__pyx_t_5, __pyx_kp_u_2f); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = __Pyx_PyUnicode_ConcatInPlace(__pyx_t_4, __pyx_kp_u_mach_2); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+065:             _fmt(self.height, PreferredUnits.drop),
-
  __pyx_t_4 = __pyx_v_self->height;
-  __Pyx_INCREF(__pyx_t_4);
-  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 65, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_drop); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 65, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_4, __pyx_t_7); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 65, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+066:             _fmt(self.target_drop, PreferredUnits.drop),
-
  __pyx_t_7 = __pyx_v_self->target_drop;
-  __Pyx_INCREF(__pyx_t_7);
-  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 66, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_drop); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 66, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_7, __pyx_t_8); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 66, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+067:             _fmt(self.drop_adj, PreferredUnits.adjustment),
-
  __pyx_t_8 = __pyx_v_self->drop_adj;
-  __Pyx_INCREF(__pyx_t_8);
-  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 67, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_adjustment); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 67, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_8, __pyx_t_9); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 67, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-
+068:             _fmt(self.windage, PreferredUnits.drop),
-
  __pyx_t_9 = __pyx_v_self->windage;
-  __Pyx_INCREF(__pyx_t_9);
-  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 68, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_drop); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 68, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_9, __pyx_t_10); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 68, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-
+069:             _fmt(self.windage_adj, PreferredUnits.adjustment),
-
  __pyx_t_10 = __pyx_v_self->windage_adj;
-  __Pyx_INCREF(__pyx_t_10);
-  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 69, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_adjustment); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 69, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-  __pyx_t_9 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_10, __pyx_t_11); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 69, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-
+070:             _fmt(self.look_distance, PreferredUnits.distance),
-
  __pyx_t_11 = __pyx_v_self->look_distance;
-  __Pyx_INCREF(__pyx_t_11);
-  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_distance); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_12);
-  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-  __pyx_t_10 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_11, __pyx_t_12); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-
+071:             _fmt(self.angle, PreferredUnits.angular),
-
  __pyx_t_12 = __pyx_v_self->angle;
-  __Pyx_INCREF(__pyx_t_12);
-  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 71, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __pyx_t_13 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_angular); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 71, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-  __pyx_t_11 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_12, __pyx_t_13); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 71, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-
+072:             f'{self.density_factor:.3e}',
-
  __pyx_t_13 = PyFloat_FromDouble(__pyx_v_self->density_factor); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 72, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __pyx_t_12 = __Pyx_PyObject_Format(__pyx_t_13, __pyx_kp_u_3e); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 72, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_12);
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-
+073:             f'{self.drag:.3f}',
-
  __pyx_t_13 = PyFloat_FromDouble(__pyx_v_self->drag); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 73, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __pyx_t_14 = __Pyx_PyObject_Format(__pyx_t_13, __pyx_kp_u_3f); if (unlikely(!__pyx_t_14)) __PYX_ERR(1, 73, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_14);
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-
+074:             _fmt(self.energy, PreferredUnits.energy),
-
  __pyx_t_13 = __pyx_v_self->energy;
-  __Pyx_INCREF(__pyx_t_13);
-  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_15)) __PYX_ERR(1, 74, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_15);
-  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_n_s_energy); if (unlikely(!__pyx_t_16)) __PYX_ERR(1, 74, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_16);
-  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-  __pyx_t_15 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_13, __pyx_t_16); if (unlikely(!__pyx_t_15)) __PYX_ERR(1, 74, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_15);
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
-
+075:             _fmt(self.ogw, PreferredUnits.ogw),
-
  __pyx_t_16 = __pyx_v_self->ogw;
-  __Pyx_INCREF(__pyx_t_16);
-  __Pyx_GetModuleGlobalName(__pyx_t_13, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 75, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __pyx_t_17 = __Pyx_PyObject_GetAttrStr(__pyx_t_13, __pyx_n_s_ogw); if (unlikely(!__pyx_t_17)) __PYX_ERR(1, 75, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_17);
-  __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-  __pyx_t_13 = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_9formatted__fmt(__pyx_v__fmt, __pyx_t_16, __pyx_t_17); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 75, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
-  __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-
 076: 
-
 077:             # TrajFlag.name(self.flag)
-
+078:             f"{self.flag}"  # TODO: fix flag.name
-
  __pyx_t_17 = __Pyx_PyUnicode_From_int(__pyx_v_self->flag, 0, ' ', 'd'); if (unlikely(!__pyx_t_17)) __PYX_ERR(1, 78, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_17);
-
 079:         )
-
 080: 
-
+081:     def in_def_units(TrajectoryData self) -> tuple[float, ...]:
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_5in_def_units(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_15trajectory_data_14TrajectoryData_4in_def_units, "TrajectoryData.in_def_units(self) -> tuple[float, ...]\n\n        :return: matrix of floats of the trajectory in default prefer_units\n        ");
-static PyObject *__pyx_pw_16CyEulerBallistic_15trajectory_data_14TrajectoryData_5in_def_units(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("in_def_units (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  if (unlikely(__pyx_nargs > 0)) {
-    __Pyx_RaiseArgtupleInvalid("in_def_units", 1, 0, 0, __pyx_nargs); return NULL;}
-  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "in_def_units", 0))) return NULL;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_4in_def_units(((struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_15trajectory_data_14TrajectoryData_4in_def_units(struct __pyx_obj_16CyEulerBallistic_15trajectory_data_TrajectoryData *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_XDECREF(__pyx_t_10);
-  __Pyx_XDECREF(__pyx_t_11);
-  __Pyx_XDECREF(__pyx_t_12);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_XDECREF(__pyx_t_14);
-  __Pyx_XDECREF(__pyx_t_15);
-  __Pyx_XDECREF(__pyx_t_16);
-  __Pyx_XDECREF(__pyx_t_17);
-  __Pyx_AddTraceback("CyEulerBallistic.trajectory_data.TrajectoryData.in_def_units", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 082:         """
-
 083:         :return: matrix of floats of the trajectory in default prefer_units
-
 084:         """
-
+085:         return (
-
  __Pyx_XDECREF(__pyx_r);
-
+086:             self.time,
-
  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_self->time); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 86, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-/* … */
-  __pyx_t_17 = PyTuple_New(16); if (unlikely(!__pyx_t_17)) __PYX_ERR(1, 86, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_17);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_1)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 1, __pyx_t_2)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 2, __pyx_t_3)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_4);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 3, __pyx_t_4)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_5);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 4, __pyx_t_5)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_6);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 5, __pyx_t_6)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_7);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 6, __pyx_t_7)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_8);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 7, __pyx_t_8)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_9);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 8, __pyx_t_9)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_10);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 9, __pyx_t_10)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_11);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 10, __pyx_t_11)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_12);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 11, __pyx_t_12)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_13);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 12, __pyx_t_13)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_14);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 13, __pyx_t_14)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_15);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 14, __pyx_t_15)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_16);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_17, 15, __pyx_t_16)) __PYX_ERR(1, 86, __pyx_L1_error);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_4 = 0;
-  __pyx_t_5 = 0;
-  __pyx_t_6 = 0;
-  __pyx_t_7 = 0;
-  __pyx_t_8 = 0;
-  __pyx_t_9 = 0;
-  __pyx_t_10 = 0;
-  __pyx_t_11 = 0;
-  __pyx_t_12 = 0;
-  __pyx_t_13 = 0;
-  __pyx_t_14 = 0;
-  __pyx_t_15 = 0;
-  __pyx_t_16 = 0;
-  __pyx_r = ((PyObject*)__pyx_t_17);
-  __pyx_t_17 = 0;
-  goto __pyx_L0;
-
+087:             self.distance >> PreferredUnits.distance,
-
  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 87, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_distance); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 87, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = PyNumber_Rshift(__pyx_v_self->distance, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 87, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+088:             self.velocity >> PreferredUnits.velocity,
-
  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 88, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_velocity); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 88, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = PyNumber_Rshift(__pyx_v_self->velocity, __pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 88, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+089:             self.mach,
-
  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_self->mach); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 89, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-
+090:             self.height >> PreferredUnits.drop,
-
  __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 90, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_drop); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 90, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyNumber_Rshift(__pyx_v_self->height, __pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 90, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-
+091:             self.target_drop >> PreferredUnits.drop,
-
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 91, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_drop); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 91, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __pyx_t_6 = PyNumber_Rshift(__pyx_v_self->target_drop, __pyx_t_7); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 91, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+092:             self.drop_adj >> PreferredUnits.adjustment,
-
  __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 92, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_7, __pyx_n_s_adjustment); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 92, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  __pyx_t_7 = PyNumber_Rshift(__pyx_v_self->drop_adj, __pyx_t_8); if (unlikely(!__pyx_t_7)) __PYX_ERR(1, 92, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+093:             self.windage >> PreferredUnits.drop,
-
  __Pyx_GetModuleGlobalName(__pyx_t_8, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 93, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __pyx_t_9 = __Pyx_PyObject_GetAttrStr(__pyx_t_8, __pyx_n_s_drop); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 93, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  __pyx_t_8 = PyNumber_Rshift(__pyx_v_self->windage, __pyx_t_9); if (unlikely(!__pyx_t_8)) __PYX_ERR(1, 93, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-
+094:             self.windage_adj >> PreferredUnits.adjustment,
-
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 94, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_adjustment); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 94, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-  __pyx_t_9 = PyNumber_Rshift(__pyx_v_self->windage_adj, __pyx_t_10); if (unlikely(!__pyx_t_9)) __PYX_ERR(1, 94, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_9);
-  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-
+095:             self.look_distance >> PreferredUnits.distance,
-
  __Pyx_GetModuleGlobalName(__pyx_t_10, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 95, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __pyx_t_11 = __Pyx_PyObject_GetAttrStr(__pyx_t_10, __pyx_n_s_distance); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 95, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-  __pyx_t_10 = PyNumber_Rshift(__pyx_v_self->look_distance, __pyx_t_11); if (unlikely(!__pyx_t_10)) __PYX_ERR(1, 95, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_10);
-  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-
+096:             self.angle >> PreferredUnits.angular,
-
  __Pyx_GetModuleGlobalName(__pyx_t_11, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 96, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __pyx_t_12 = __Pyx_PyObject_GetAttrStr(__pyx_t_11, __pyx_n_s_angular); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 96, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_12);
-  __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-  __pyx_t_11 = PyNumber_Rshift(__pyx_v_self->angle, __pyx_t_12); if (unlikely(!__pyx_t_11)) __PYX_ERR(1, 96, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_11);
-  __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
-
+097:             self.density_factor,
-
  __pyx_t_12 = PyFloat_FromDouble(__pyx_v_self->density_factor); if (unlikely(!__pyx_t_12)) __PYX_ERR(1, 97, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_12);
-
+098:             self.drag,
-
  __pyx_t_13 = PyFloat_FromDouble(__pyx_v_self->drag); if (unlikely(!__pyx_t_13)) __PYX_ERR(1, 98, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_13);
-
+099:             self.energy >> PreferredUnits.energy,
-
  __Pyx_GetModuleGlobalName(__pyx_t_14, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_14)) __PYX_ERR(1, 99, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_14);
-  __pyx_t_15 = __Pyx_PyObject_GetAttrStr(__pyx_t_14, __pyx_n_s_energy); if (unlikely(!__pyx_t_15)) __PYX_ERR(1, 99, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_15);
-  __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-  __pyx_t_14 = PyNumber_Rshift(__pyx_v_self->energy, __pyx_t_15); if (unlikely(!__pyx_t_14)) __PYX_ERR(1, 99, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_14);
-  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-
+100:             self.ogw >> PreferredUnits.ogw,
-
  __Pyx_GetModuleGlobalName(__pyx_t_15, __pyx_n_s_PreferredUnits); if (unlikely(!__pyx_t_15)) __PYX_ERR(1, 100, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_15);
-  __pyx_t_16 = __Pyx_PyObject_GetAttrStr(__pyx_t_15, __pyx_n_s_ogw); if (unlikely(!__pyx_t_16)) __PYX_ERR(1, 100, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_16);
-  __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-  __pyx_t_15 = PyNumber_Rshift(__pyx_v_self->ogw, __pyx_t_16); if (unlikely(!__pyx_t_15)) __PYX_ERR(1, 100, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_15);
-  __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
-
+101:             self.flag
-
  __pyx_t_16 = __Pyx_PyInt_From_int(__pyx_v_self->flag); if (unlikely(!__pyx_t_16)) __PYX_ERR(1, 101, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_16);
-
 102:         )
-
diff --git a/CyEulerBallistic/trajectory_data.pxd b/CyEulerBallistic/trajectory_data.pxd index 4c6ff9b..a515f10 100644 --- a/CyEulerBallistic/trajectory_data.pxd +++ b/CyEulerBallistic/trajectory_data.pxd @@ -1,12 +1,22 @@ +from CyEulerBallistic.vector cimport CVector + cdef enum CTrajFlag: NONE = 0 ZERO_UP = 1 ZERO_DOWN = 2 + ZERO = ZERO_UP | ZERO_DOWN MACH = 4 RANGE = 8 - DANGER = 16 - ZERO = ZERO_UP | ZERO_DOWN - ALL = RANGE | ZERO_UP | ZERO_DOWN | MACH | DANGER + APEX = 16 + ALL = RANGE | ZERO_UP | ZERO_DOWN | MACH | APEX + + +cdef class BaseTrajData: + cdef: + readonly double time + readonly CVector position + readonly CVector velocity + readonly double mach cdef class TrajectoryData: diff --git a/CyEulerBallistic/trajectory_data.pyi b/CyEulerBallistic/trajectory_data.pyi index 1da4ef1..4adb659 100644 --- a/CyEulerBallistic/trajectory_data.pyi +++ b/CyEulerBallistic/trajectory_data.pyi @@ -1,9 +1,19 @@ # type: ignore -from py_ballisticcalc.unit import Angular, Distance, Energy, Velocity, Weight from typing_extensions import NamedTuple, Union, Tuple +from py_ballisticcalc.unit import Angular, Distance, Energy, Velocity, Weight, Vector + __all__ = ['TrajectoryData'] + +class BaseTrajData(NamedTuple): + """Minimal data for one point in ballistic trajectory""" + time: float + position: Vector + velocity: Vector + mach: float + + class TrajectoryData(NamedTuple): __slots__: Tuple[str, ...] _field: Tuple[str, ...] @@ -24,5 +34,7 @@ class TrajectoryData(NamedTuple): energy: Energy ogw: Weight flag: Union[int] + def formatted(self) -> tuple[str, ...]: ... + def in_def_units(self) -> tuple[float, ...]: ... diff --git a/CyEulerBallistic/trajectory_data.pyx b/CyEulerBallistic/trajectory_data.pyx index c3e196d..b56af13 100644 --- a/CyEulerBallistic/trajectory_data.pyx +++ b/CyEulerBallistic/trajectory_data.pyx @@ -1,8 +1,17 @@ from cython cimport final - from py_ballisticcalc.unit import PreferredUnits +from CyEulerBallistic.vector cimport CVector + +@final +cdef class BaseTrajData: + __slots__ = ('time', 'position', 'velocity', 'mach') + def __cinit__(BaseTrajData self, double time, CVector position, CVector velocity, double mach): + self.time = time + self.position = position + self.velocity = velocity + self.mach = mach @final cdef class TrajectoryData: diff --git a/CyEulerBallistic/vector.html b/CyEulerBallistic/vector.html deleted file mode 100644 index 93c26bd..0000000 --- a/CyEulerBallistic/vector.html +++ /dev/null @@ -1,2461 +0,0 @@ - - - - - - Cython: vector.pyx - - - -

Generated by Cython 3.0.12

-

- 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: vector.c

-
+001: from libc.math cimport sqrt, fabs
-
  __pyx_t_7 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_7) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
 002: from cython cimport final
-
 003: 
-
+004: try:
-
  {
-    /*try:*/ {
-/* … */
-    }
-    __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-    goto __pyx_L7_try_end;
-    __pyx_L2_error:;
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-/* … */
-    __pyx_L4_except_error:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L1_error;
-    __pyx_L3_exception_handled:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    __pyx_L7_try_end:;
-  }
-
+005:     import typing
-
      __pyx_t_4 = __Pyx_ImportDottedModule(__pyx_n_s_typing, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 5, __pyx_L2_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      if (PyDict_SetItem(__pyx_d, __pyx_n_s_typing, __pyx_t_4) < 0) __PYX_ERR(0, 5, __pyx_L2_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+006:     import dataclasses
-
      __pyx_t_4 = __Pyx_ImportDottedModule(__pyx_n_s_dataclasses, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 6, __pyx_L2_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      if (PyDict_SetItem(__pyx_d, __pyx_n_s_dataclasses, __pyx_t_4) < 0) __PYX_ERR(0, 6, __pyx_L2_error)
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+007: except ImportError:
-
    __pyx_t_5 = __Pyx_PyErr_ExceptionMatches(__pyx_builtin_ImportError);
-    if (__pyx_t_5) {
-      __Pyx_ErrRestore(0,0,0);
-      goto __pyx_L3_exception_handled;
-    }
-    goto __pyx_L4_except_error;
-
 008:     pass  # The modules don't actually have to exists for Cython to use them as annotations
-
 009: 
-
+010: __all__ = ('Vector',)
-
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_all, __pyx_tuple__3) < 0) __PYX_ERR(0, 10, __pyx_L1_error)
-
 011: 
-
 012: @final
-
 013: @dataclasses.dataclass
-
+014: cdef class Vector:
-
  __pyx_t_4 = __Pyx_Load_dataclasses_Module(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_DataclassParams); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = __Pyx_PyDict_NewPresized(11); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_init, Py_True) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_repr, Py_True) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_eq, Py_True) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_unsafe_hash, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_frozen, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_kw_only, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_kw_only, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_match_args, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_slots, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_weakref_slot, Py_False) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  __pyx_t_7 = __Pyx_DataclassesCallHelper(__pyx_t_6, __pyx_t_4); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector, __pyx_n_s_dataclass_params, __pyx_t_7) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  PyType_Modified(__pyx_ptype_16CyEulerBallistic_6vector_Vector);
-  __pyx_t_7 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector, __pyx_n_s_dataclass_fields, __pyx_t_7) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  PyType_Modified(__pyx_ptype_16CyEulerBallistic_6vector_Vector);
-/* … */
-  if (__Pyx_SetItemOnTypeDict((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector, __pyx_n_s_hash, Py_None) < 0) __PYX_ERR(0, 14, __pyx_L1_error)
-  PyType_Modified(__pyx_ptype_16CyEulerBallistic_6vector_Vector);
-/* … */
-struct __pyx_vtabstruct_16CyEulerBallistic_6vector_Vector {
-  double (*_magnitude)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *(*_mul_by_const)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *, double);
-  double (*_mul_by_vector)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *(*_add)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *(*_subtract)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *(*_negate)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *(*_normalize)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector (*c_vector)(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *);
-};
-static struct __pyx_vtabstruct_16CyEulerBallistic_6vector_Vector *__pyx_vtabptr_16CyEulerBallistic_6vector_Vector;
-
 015: 
-
+016:     def __cinit__(Vector self, double x, double y, double z):
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  double __pyx_v_x;
-  double __pyx_v_y;
-  double __pyx_v_z;
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_x,&__pyx_n_s_y,&__pyx_n_s_z,0};
-  PyObject* values[3] = {0,0,0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  3: values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_VARARGS(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_x)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_y)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[1]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 3, 3, 1); __PYX_ERR(0, 16, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_GetKwValue_VARARGS(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_z)) != 0)) {
-          (void)__Pyx_Arg_NewRef_VARARGS(values[2]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-        else {
-          __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 3, 3, 2); __PYX_ERR(0, 16, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "__cinit__") < 0)) __PYX_ERR(0, 16, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 3)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_VARARGS(__pyx_args, 0);
-      values[1] = __Pyx_Arg_VARARGS(__pyx_args, 1);
-      values[2] = __Pyx_Arg_VARARGS(__pyx_args, 2);
-    }
-    __pyx_v_x = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_x == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-    __pyx_v_y = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_y == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-    __pyx_v_z = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_z == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 16, __pyx_L3_error)
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 3, 3, __pyx_nargs); __PYX_ERR(0, 16, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector___cinit__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), __pyx_v_x, __pyx_v_y, __pyx_v_z);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_VARARGS(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_6vector_6Vector___cinit__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_x, double __pyx_v_y, double __pyx_v_z) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  return __pyx_r;
-}
-
+017:         self._x = x
-
  __pyx_v_self->_x = __pyx_v_x;
-
+018:         self._y = y
-
  __pyx_v_self->_y = __pyx_v_y;
-
+019:         self._z = z
-
  __pyx_v_self->_z = __pyx_v_z;
-
 020: 
-
+021:     @property
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1x_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1x_1__get__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "self"); __PYX_ERR(0, 22, __pyx_L1_error)
-  }
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1x___get__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_1x___get__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.x.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 022:     def x(self: Vector) -> float:
-
+023:         return self._x
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_self->_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 23, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 024: 
-
+025:     @x.setter
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1x_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1x_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v) {
-  double __pyx_v_v;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  assert(__pyx_arg_v); {
-    __pyx_v_v = __pyx_PyFloat_AsDouble(__pyx_arg_v); if (unlikely((__pyx_v_v == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 26, __pyx_L3_error)
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.x.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1x_2__set__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((double)__pyx_v_v));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_6vector_6Vector_1x_2__set__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_v) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  return __pyx_r;
-}
-
 026:     def x(self, double v) -> None:
-
+027:         self._x = v
-
  __pyx_v_self->_x = __pyx_v_v;
-
 028: 
-
+029:     @property
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1y_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1y_1__get__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "self"); __PYX_ERR(0, 30, __pyx_L1_error)
-  }
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1y___get__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_1y___get__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.y.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 030:     def y(self: Vector) -> float:
-
+031:         return self._y
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_self->_y); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 31, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 032: 
-
+033:     @y.setter
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1y_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1y_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v) {
-  double __pyx_v_v;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  assert(__pyx_arg_v); {
-    __pyx_v_v = __pyx_PyFloat_AsDouble(__pyx_arg_v); if (unlikely((__pyx_v_v == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 34, __pyx_L3_error)
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.y.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1y_2__set__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((double)__pyx_v_v));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_6vector_6Vector_1y_2__set__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_v) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  return __pyx_r;
-}
-
 034:     def y(self, double v) -> None:
-
+035:         self._y = v
-
  __pyx_v_self->_y = __pyx_v_v;
-
 036: 
-
+037:     @property
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1z_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_1z_1__get__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(((PyObject *)__pyx_v_self) == Py_None)) {
-    PyErr_Format(PyExc_TypeError, "Argument '%.200s' must not be None", "self"); __PYX_ERR(0, 38, __pyx_L1_error)
-  }
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1z___get__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_1z___get__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.z.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 038:     def z(self: Vector) -> float:
-
+039:         return self._z
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_self->_z); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 39, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 040: 
-
+041:     @z.setter
-
/* Python wrapper */
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1z_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v); /*proto*/
-static int __pyx_pw_16CyEulerBallistic_6vector_6Vector_1z_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_arg_v) {
-  double __pyx_v_v;
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  assert(__pyx_arg_v); {
-    __pyx_v_v = __pyx_PyFloat_AsDouble(__pyx_arg_v); if (unlikely((__pyx_v_v == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 42, __pyx_L3_error)
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.z.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return -1;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_1z_2__set__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((double)__pyx_v_v));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_16CyEulerBallistic_6vector_6Vector_1z_2__set__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_v) {
-  int __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_r = 0;
-  return __pyx_r;
-}
-
 042:     def z(self, double v) -> None:
-
+043:         self._z = v
-
  __pyx_v_self->_z = __pyx_v_v;
-
 044: 
-
+045:     cdef double _magnitude(Vector self):
-
static double __pyx_f_16CyEulerBallistic_6vector_6Vector__magnitude(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+046:         return sqrt(self._x * self._x + self._y * self._y + self._z * self._z)
-
  __pyx_r = sqrt((((__pyx_v_self->_x * __pyx_v_self->_x) + (__pyx_v_self->_y * __pyx_v_self->_y)) + (__pyx_v_self->_z * __pyx_v_self->_z)));
-  goto __pyx_L0;
-
 047: 
-
+048:     def magnitude(Vector self):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_3magnitude(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_2magnitude, "Vector.magnitude(self)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_3magnitude(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("magnitude (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  if (unlikely(__pyx_nargs > 0)) {
-    __Pyx_RaiseArgtupleInvalid("magnitude", 1, 0, 0, __pyx_nargs); return NULL;}
-  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "magnitude", 0))) return NULL;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_2magnitude(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_2magnitude(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.magnitude", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+049:         return self._magnitude()
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_16CyEulerBallistic_6vector_6Vector__magnitude(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 49, __pyx_L1_error)
-  __pyx_t_2 = PyFloat_FromDouble(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 49, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = __pyx_t_2;
-  __pyx_t_2 = 0;
-  goto __pyx_L0;
-
 050: 
-
+051:     cdef Vector _mul_by_const(Vector self, double a):
-
static struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_const(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_a) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector._mul_by_const", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF((PyObject *)__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+052:         return Vector(self._x * a, self._y * a, self._z * a)
-
  __Pyx_XDECREF((PyObject *)__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->_x * __pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->_y * __pyx_v_a)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyFloat_FromDouble((__pyx_v_self->_z * __pyx_v_a)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1)) __PYX_ERR(0, 52, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2)) __PYX_ERR(0, 52, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_3);
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
-
 053: 
-
+054:     def mul_by_const(Vector self, double a):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_5mul_by_const(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_4mul_by_const, "Vector.mul_by_const(self, double a)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_5mul_by_const(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  double __pyx_v_a;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("mul_by_const (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_a,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_a)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 54, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "mul_by_const") < 0)) __PYX_ERR(0, 54, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-    }
-    __pyx_v_a = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_a == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 54, __pyx_L3_error)
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("mul_by_const", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 54, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.mul_by_const", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_4mul_by_const(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), __pyx_v_a);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_4mul_by_const(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, double __pyx_v_a) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.mul_by_const", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+055:         return self._mul_by_const(a)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_const(__pyx_v_self, __pyx_v_a)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 55, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 056: 
-
+057:     cdef double _mul_by_vector(Vector self, Vector b):
-
static double __pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_vector(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+058:         return self._x * b._x + self._y * b._y + self._z * b._z
-
  __pyx_r = (((__pyx_v_self->_x * __pyx_v_b->_x) + (__pyx_v_self->_y * __pyx_v_b->_y)) + (__pyx_v_self->_z * __pyx_v_b->_z));
-  goto __pyx_L0;
-
 059: 
-
+060:     def mul_by_vector(Vector self, Vector b):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_7mul_by_vector(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_6mul_by_vector, "Vector.mul_by_vector(self, Vector b)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_7mul_by_vector(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b = 0;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("mul_by_vector (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_b,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_b)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 60, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "mul_by_vector") < 0)) __PYX_ERR(0, 60, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-    }
-    __pyx_v_b = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)values[0]);
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("mul_by_vector", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 60, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.mul_by_vector", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_b), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "b", 0))) __PYX_ERR(0, 60, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_6mul_by_vector(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), __pyx_v_b);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_6mul_by_vector(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.mul_by_vector", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+061:         return self._mul_by_vector(b)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_vector(__pyx_v_self, __pyx_v_b); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 61, __pyx_L1_error)
-  __pyx_t_2 = PyFloat_FromDouble(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 61, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = __pyx_t_2;
-  __pyx_t_2 = 0;
-  goto __pyx_L0;
-
 062: 
-
+063:     cdef Vector _add(Vector self, Vector b):
-
static struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_f_16CyEulerBallistic_6vector_6Vector__add(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector._add", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF((PyObject *)__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+064:         return Vector(self._x + b._x, self._y + b._y, self._z + b._z)
-
  __Pyx_XDECREF((PyObject *)__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->_x + __pyx_v_b->_x)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->_y + __pyx_v_b->_y)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyFloat_FromDouble((__pyx_v_self->_z + __pyx_v_b->_z)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1)) __PYX_ERR(0, 64, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2)) __PYX_ERR(0, 64, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3)) __PYX_ERR(0, 64, __pyx_L1_error);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 64, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_3);
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
-
 065: 
-
+066:     def add(Vector self, Vector b):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_9add(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_8add, "Vector.add(self, Vector b)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_9add(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b = 0;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("add (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_b,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_b)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 66, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "add") < 0)) __PYX_ERR(0, 66, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-    }
-    __pyx_v_b = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)values[0]);
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("add", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 66, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_b), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "b", 0))) __PYX_ERR(0, 66, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_8add(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), __pyx_v_b);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_8add(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+067:         return self._add(b)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__add(__pyx_v_self, __pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 67, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 068: 
-
+069:     cdef Vector _subtract(Vector self, Vector b):
-
static struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_f_16CyEulerBallistic_6vector_6Vector__subtract(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector._subtract", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF((PyObject *)__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+070:         return Vector(self._x - b._x, self._y - b._y, self._z - b._z)
-
  __Pyx_XDECREF((PyObject *)__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble((__pyx_v_self->_x - __pyx_v_b->_x)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyFloat_FromDouble((__pyx_v_self->_y - __pyx_v_b->_y)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyFloat_FromDouble((__pyx_v_self->_z - __pyx_v_b->_z)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1)) __PYX_ERR(0, 70, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2)) __PYX_ERR(0, 70, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3)) __PYX_ERR(0, 70, __pyx_L1_error);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 70, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_3);
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
-
 071: 
-
+072:     def subtract(Vector self, Vector b):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_11subtract(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_10subtract, "Vector.subtract(self, Vector b)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_11subtract(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b = 0;
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("subtract (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  {
-    PyObject **__pyx_pyargnames[] = {&__pyx_n_s_b,0};
-  PyObject* values[1] = {0};
-    if (__pyx_kwds) {
-      Py_ssize_t kw_args;
-      switch (__pyx_nargs) {
-        case  1: values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = __Pyx_NumKwargs_FASTCALL(__pyx_kwds);
-      switch (__pyx_nargs) {
-        case  0:
-        if (likely((values[0] = __Pyx_GetKwValue_FASTCALL(__pyx_kwds, __pyx_kwvalues, __pyx_n_s_b)) != 0)) {
-          (void)__Pyx_Arg_NewRef_FASTCALL(values[0]);
-          kw_args--;
-        }
-        else if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 72, __pyx_L3_error)
-        else goto __pyx_L5_argtuple_error;
-      }
-      if (unlikely(kw_args > 0)) {
-        const Py_ssize_t kwd_pos_args = __pyx_nargs;
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_kwvalues, __pyx_pyargnames, 0, values + 0, kwd_pos_args, "subtract") < 0)) __PYX_ERR(0, 72, __pyx_L3_error)
-      }
-    } else if (unlikely(__pyx_nargs != 1)) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = __Pyx_Arg_FASTCALL(__pyx_args, 0);
-    }
-    __pyx_v_b = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)values[0]);
-  }
-  goto __pyx_L6_skip;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("subtract", 1, 1, 1, __pyx_nargs); __PYX_ERR(0, 72, __pyx_L3_error)
-  __pyx_L6_skip:;
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L3_error:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.subtract", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_b), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "b", 0))) __PYX_ERR(0, 72, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_10subtract(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), __pyx_v_b);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  {
-    Py_ssize_t __pyx_temp;
-    for (__pyx_temp=0; __pyx_temp < (Py_ssize_t)(sizeof(values)/sizeof(values[0])); ++__pyx_temp) {
-      __Pyx_Arg_XDECREF_FASTCALL(values[__pyx_temp]);
-    }
-  }
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_10subtract(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_b) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.subtract", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+073:         return self._subtract(b)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__subtract(__pyx_v_self, __pyx_v_b)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 73, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 074: 
-
+075:     cdef Vector _negate(Vector self):
-
static struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_f_16CyEulerBallistic_6vector_6Vector__negate(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector._negate", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF((PyObject *)__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+076:         return Vector(-self._x, -self._y, -self._z)
-
  __Pyx_XDECREF((PyObject *)__pyx_r);
-  __pyx_t_1 = PyFloat_FromDouble((-__pyx_v_self->_x)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 76, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyFloat_FromDouble((-__pyx_v_self->_y)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 76, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyFloat_FromDouble((-__pyx_v_self->_z)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 76, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 76, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_1);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1)) __PYX_ERR(0, 76, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_2);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2)) __PYX_ERR(0, 76, __pyx_L1_error);
-  __Pyx_GIVEREF(__pyx_t_3);
-  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3)) __PYX_ERR(0, 76, __pyx_L1_error);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector), __pyx_t_4, NULL); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 76, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_3);
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
-
 077: 
-
+078:     def negate(Vector self):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_13negate(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_12negate, "Vector.negate(self)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_13negate(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("negate (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  if (unlikely(__pyx_nargs > 0)) {
-    __Pyx_RaiseArgtupleInvalid("negate", 1, 0, 0, __pyx_nargs); return NULL;}
-  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "negate", 0))) return NULL;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_12negate(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_12negate(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.negate", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+079:         return self._negate()
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__negate(__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 79, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 080: 
-
+081:     cdef Vector _normalize(Vector self):
-
static struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_f_16CyEulerBallistic_6vector_6Vector__normalize(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  double __pyx_v_m;
-  struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector._normalize", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF((PyObject *)__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+082:         cdef double m = self._magnitude()
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_6vector_6Vector__magnitude(__pyx_v_self); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 82, __pyx_L1_error)
-  __pyx_v_m = __pyx_t_1;
-
+083:         if fabs(m) < 1e-10:
-
  __pyx_t_2 = (fabs(__pyx_v_m) < 1e-10);
-  if (__pyx_t_2) {
-/* … */
-  }
-
+084:             return Vector(self._x, self._y, self._z)
-
    __Pyx_XDECREF((PyObject *)__pyx_r);
-    __pyx_t_3 = PyFloat_FromDouble(__pyx_v_self->_x); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 84, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = PyFloat_FromDouble(__pyx_v_self->_y); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 84, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = PyFloat_FromDouble(__pyx_v_self->_z); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 84, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 84, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_3);
-    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_3)) __PYX_ERR(0, 84, __pyx_L1_error);
-    __Pyx_GIVEREF(__pyx_t_4);
-    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_4)) __PYX_ERR(0, 84, __pyx_L1_error);
-    __Pyx_GIVEREF(__pyx_t_5);
-    if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_t_5)) __PYX_ERR(0, 84, __pyx_L1_error);
-    __pyx_t_3 = 0;
-    __pyx_t_4 = 0;
-    __pyx_t_5 = 0;
-    __pyx_t_5 = __Pyx_PyObject_Call(((PyObject *)__pyx_ptype_16CyEulerBallistic_6vector_Vector), __pyx_t_6, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 84, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_5);
-    __pyx_t_5 = 0;
-    goto __pyx_L0;
-
+085:         return self._mul_by_const(1.0 / m)
-
  __Pyx_XDECREF((PyObject *)__pyx_r);
-  __pyx_t_5 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_const(__pyx_v_self, (1.0 / __pyx_v_m))); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 85, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_r = ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_t_5);
-  __pyx_t_5 = 0;
-  goto __pyx_L0;
-
 086: 
-
+087:     def normalize(Vector self):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_15normalize(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-); /*proto*/
-PyDoc_STRVAR(__pyx_doc_16CyEulerBallistic_6vector_6Vector_14normalize, "Vector.normalize(self)");
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_15normalize(PyObject *__pyx_v_self, 
-#if CYTHON_METH_FASTCALL
-PyObject *const *__pyx_args, Py_ssize_t __pyx_nargs, PyObject *__pyx_kwds
-#else
-PyObject *__pyx_args, PyObject *__pyx_kwds
-#endif
-) {
-  #if !CYTHON_METH_FASTCALL
-  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
-  #endif
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("normalize (wrapper)", 0);
-  #if !CYTHON_METH_FASTCALL
-  #if CYTHON_ASSUME_SAFE_MACROS
-  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
-  #else
-  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return NULL;
-  #endif
-  #endif
-  __pyx_kwvalues = __Pyx_KwValues_FASTCALL(__pyx_args, __pyx_nargs);
-  if (unlikely(__pyx_nargs > 0)) {
-    __Pyx_RaiseArgtupleInvalid("normalize", 1, 0, 0, __pyx_nargs); return NULL;}
-  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_FASTCALL(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "normalize", 0))) return NULL;
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_14normalize(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_14normalize(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.normalize", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+088:         return self._normalize()
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__normalize(__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 88, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 089: 
-
+090:     def __add__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_17__add__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_17__add__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__add__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 90, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 90, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_16__add__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_16__add__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__add__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+091:         return self._add(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__add(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 91, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 092: 
-
+093:     def __radd__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_19__radd__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_19__radd__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__radd__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 93, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 93, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_18__radd__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_18__radd__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__radd__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+094:         return self._add(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__add(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 94, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 095: 
-
+096:     def __iadd__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_21__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_21__iadd__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__iadd__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 96, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_20__iadd__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_20__iadd__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__iadd__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+097:         return self._add(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__add(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 97, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 098: 
-
+099:     def __sub__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_23__sub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_23__sub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__sub__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 99, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 99, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_22__sub__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_22__sub__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__sub__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+100:         return self._subtract(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__subtract(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 100, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 101: 
-
+102:     def __rsub__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_25__rsub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_25__rsub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__rsub__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 102, __pyx_L1_error)
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 102, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_24__rsub__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_24__rsub__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__rsub__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+103:         return self._subtract(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__subtract(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 103, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 104: 
-
+105:     def __isub__(Vector self, Vector other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_27__isub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_27__isub__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__isub__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_other), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "other", 0))) __PYX_ERR(0, 105, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_26__isub__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_26__isub__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__isub__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+106:         return self._subtract(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__subtract(__pyx_v_self, __pyx_v_other)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 106, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 107: 
-
+108:     def __mul__(Vector self, object other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_29__mul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_29__mul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__mul__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 108, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_28__mul__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((PyObject *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_28__mul__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, PyObject *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__mul__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+109:         if isinstance(other, (int, float)):
-
  __pyx_t_2 = PyInt_Check(__pyx_v_other); 
-  if (!__pyx_t_2) {
-  } else {
-    __pyx_t_1 = __pyx_t_2;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_2 = PyFloat_Check(__pyx_v_other); 
-  __pyx_t_1 = __pyx_t_2;
-  __pyx_L4_bool_binop_done:;
-  if (__pyx_t_1) {
-/* … */
-  }
-
+110:             return self._mul_by_const(<double>other)
-
    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_v_other); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 110, __pyx_L1_error)
-    __pyx_t_4 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_const(__pyx_v_self, ((double)__pyx_t_3))); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 110, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_r = __pyx_t_4;
-    __pyx_t_4 = 0;
-    goto __pyx_L0;
-
+111:         if isinstance(other, Vector):
-
  __pyx_t_1 = __Pyx_TypeCheck(__pyx_v_other, __pyx_ptype_16CyEulerBallistic_6vector_Vector); 
-  if (__pyx_t_1) {
-/* … */
-  }
-
+112:             return self._mul_by_vector(<Vector>other)
-
    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __pyx_f_16CyEulerBallistic_6vector_6Vector__mul_by_vector(__pyx_v_self, ((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_other)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 112, __pyx_L1_error)
-    __pyx_t_4 = PyFloat_FromDouble(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 112, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_r = __pyx_t_4;
-    __pyx_t_4 = 0;
-    goto __pyx_L0;
-
+113:         raise TypeError(other)
-
  __pyx_t_4 = __Pyx_PyObject_CallOneArg(__pyx_builtin_TypeError, __pyx_v_other); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 113, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_Raise(__pyx_t_4, 0, 0, 0);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __PYX_ERR(0, 113, __pyx_L1_error)
-
 114: 
-
+115:     def __rmul__(Vector self, object other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_31__rmul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_31__rmul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__rmul__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_self), __pyx_ptype_16CyEulerBallistic_6vector_Vector, 1, "self", 0))) __PYX_ERR(0, 115, __pyx_L1_error)
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_30__rmul__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((PyObject *)__pyx_v_other));
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_30__rmul__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, PyObject *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__rmul__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+116:         return self.__mul__(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_mul); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 116, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  __pyx_t_4 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(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_4 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_other};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_4, 1+__pyx_t_4);
-    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 116, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 117: 
-
+118:     def __imul__(Vector self, object other):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_33__imul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_33__imul__(PyObject *__pyx_v_self, PyObject *__pyx_v_other) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__imul__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_32__imul__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self), ((PyObject *)__pyx_v_other));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_32__imul__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self, PyObject *__pyx_v_other) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__imul__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+119:         return self.__mul__(other)
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_mul); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 119, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  __pyx_t_4 = 0;
-  #if CYTHON_UNPACK_METHODS
-  if (likely(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_4 = 1;
-    }
-  }
-  #endif
-  {
-    PyObject *__pyx_callargs[2] = {__pyx_t_3, __pyx_v_other};
-    __pyx_t_1 = __Pyx_PyObject_FastCall(__pyx_t_2, __pyx_callargs+1-__pyx_t_4, 1+__pyx_t_4);
-    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 119, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  }
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 120: 
-
+121:     def __neg__(Vector self):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_35__neg__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_35__neg__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__neg__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_34__neg__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_34__neg__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__neg__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+122:         return self._negate()
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = ((PyObject *)__pyx_f_16CyEulerBallistic_6vector_6Vector__negate(__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 122, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 123: 
-
+124:     def __str__(Vector self):
-
/* Python wrapper */
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_37__str__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_16CyEulerBallistic_6vector_6Vector_37__str__(PyObject *__pyx_v_self) {
-  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__str__ (wrapper)", 0);
-  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
-  __pyx_r = __pyx_pf_16CyEulerBallistic_6vector_6Vector_36__str__(((struct __pyx_obj_16CyEulerBallistic_6vector_Vector *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_16CyEulerBallistic_6vector_6Vector_36__str__(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("CyEulerBallistic.vector.Vector.__str__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+125:         return f"Vector(x={self._x}, y={self._y}, z={self._z})"
-
  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = PyTuple_New(7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 127;
-  __Pyx_INCREF(__pyx_kp_u_Vector_x);
-  __pyx_t_2 += 9;
-  __Pyx_GIVEREF(__pyx_kp_u_Vector_x);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_kp_u_Vector_x);
-  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_self->_x); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_FormatSimple(__pyx_t_4, __pyx_empty_unicode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_3 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) > __pyx_t_3) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) : __pyx_t_3;
-  __pyx_t_2 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5);
-  __Pyx_GIVEREF(__pyx_t_5);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5);
-  __pyx_t_5 = 0;
-  __Pyx_INCREF(__pyx_kp_u_y_2);
-  __pyx_t_2 += 4;
-  __Pyx_GIVEREF(__pyx_kp_u_y_2);
-  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_kp_u_y_2);
-  __pyx_t_5 = PyFloat_FromDouble(__pyx_v_self->_y); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = __Pyx_PyObject_FormatSimple(__pyx_t_5, __pyx_empty_unicode); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_3 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_4) > __pyx_t_3) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_4) : __pyx_t_3;
-  __pyx_t_2 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_4);
-  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_t_4);
-  __pyx_t_4 = 0;
-  __Pyx_INCREF(__pyx_kp_u_z_2);
-  __pyx_t_2 += 4;
-  __Pyx_GIVEREF(__pyx_kp_u_z_2);
-  PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_kp_u_z_2);
-  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_self->_z); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_FormatSimple(__pyx_t_4, __pyx_empty_unicode); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_3 = (__Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) > __pyx_t_3) ? __Pyx_PyUnicode_MAX_CHAR_VALUE(__pyx_t_5) : __pyx_t_3;
-  __pyx_t_2 += __Pyx_PyUnicode_GET_LENGTH(__pyx_t_5);
-  __Pyx_GIVEREF(__pyx_t_5);
-  PyTuple_SET_ITEM(__pyx_t_1, 5, __pyx_t_5);
-  __pyx_t_5 = 0;
-  __Pyx_INCREF(__pyx_kp_u_);
-  __pyx_t_2 += 1;
-  __Pyx_GIVEREF(__pyx_kp_u_);
-  PyTuple_SET_ITEM(__pyx_t_1, 6, __pyx_kp_u_);
-  __pyx_t_5 = __Pyx_PyUnicode_Join(__pyx_t_1, 7, __pyx_t_2, __pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_r = __pyx_t_5;
-  __pyx_t_5 = 0;
-  goto __pyx_L0;
-
 126: 
-
+127:     cdef CVector c_vector(Vector self):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_6Vector_c_vector(struct __pyx_obj_16CyEulerBallistic_6vector_Vector *__pyx_v_self) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+128:         return CVector(self._x, self._y, self._z)
-
  __pyx_t_1.x = __pyx_v_self->_x;
-  __pyx_t_1.y = __pyx_v_self->_y;
-  __pyx_t_1.z = __pyx_v_self->_z;
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 129: 
-
 130: 
-
+131: cdef double mag(CVector * v):
-
static double __pyx_f_16CyEulerBallistic_6vector_mag(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+132:     return sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
-
  __pyx_r = sqrt((((__pyx_v_v->x * __pyx_v_v->x) + (__pyx_v_v->y * __pyx_v_v->y)) + (__pyx_v_v->z * __pyx_v_v->z)));
-  goto __pyx_L0;
-
 133: 
-
+134: cdef CVector mul_c(CVector * v, double a):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_mul_c(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v, double __pyx_v_a) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+135:     return CVector(v.x * a, v.y * a, v.z * a)
-
  __pyx_t_1.x = (__pyx_v_v->x * __pyx_v_a);
-  __pyx_t_1.y = (__pyx_v_v->y * __pyx_v_a);
-  __pyx_t_1.z = (__pyx_v_v->z * __pyx_v_a);
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 136: 
-
+137: cdef double mul_v(CVector * v, CVector * b):
-
static double __pyx_f_16CyEulerBallistic_6vector_mul_v(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v, struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_b) {
-  double __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+138:     return v.x * b.x + v.y * b.y + v.z * b.z
-
  __pyx_r = (((__pyx_v_v->x * __pyx_v_b->x) + (__pyx_v_v->y * __pyx_v_b->y)) + (__pyx_v_v->z * __pyx_v_b->z));
-  goto __pyx_L0;
-
 139: 
-
+140: cdef CVector add(CVector * v, CVector * b):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_add(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v, struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_b) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+141:     return CVector(v.x + b.x, v.y + b.y, v.z + b.z)
-
  __pyx_t_1.x = (__pyx_v_v->x + __pyx_v_b->x);
-  __pyx_t_1.y = (__pyx_v_v->y + __pyx_v_b->y);
-  __pyx_t_1.z = (__pyx_v_v->z + __pyx_v_b->z);
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 142: 
-
+143: cdef CVector sub(CVector * v, CVector * b):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_sub(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v, struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_b) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+144:     return CVector(v.x - b.x, v.y - b.y, v.z - b.z)
-
  __pyx_t_1.x = (__pyx_v_v->x - __pyx_v_b->x);
-  __pyx_t_1.y = (__pyx_v_v->y - __pyx_v_b->y);
-  __pyx_t_1.z = (__pyx_v_v->z - __pyx_v_b->z);
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 145: 
-
+146: cdef CVector neg(CVector * v):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_neg(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v) {
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+147:     return CVector(-v.x, -v.y, -v.z)
-
  __pyx_t_1.x = (-__pyx_v_v->x);
-  __pyx_t_1.y = (-__pyx_v_v->y);
-  __pyx_t_1.z = (-__pyx_v_v->z);
-  __pyx_r = __pyx_t_1;
-  goto __pyx_L0;
-
 148: 
-
+149: cdef CVector norm(CVector * v):
-
static struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_f_16CyEulerBallistic_6vector_norm(struct __pyx_t_16CyEulerBallistic_6vector_CVector *__pyx_v_v) {
-  double __pyx_v_m;
-  struct __pyx_t_16CyEulerBallistic_6vector_CVector __pyx_r;
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("CyEulerBallistic.vector.norm", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_pretend_to_initialize(&__pyx_r);
-  __pyx_L0:;
-  return __pyx_r;
-}
-
+150:     cdef double m = mag(v)
-
  __pyx_t_1 = __pyx_f_16CyEulerBallistic_6vector_mag(__pyx_v_v); if (unlikely(__pyx_t_1 == ((double)-1) && PyErr_Occurred())) __PYX_ERR(0, 150, __pyx_L1_error)
-  __pyx_v_m = __pyx_t_1;
-
+151:     if fabs(m) < 1e-10:
-
  __pyx_t_2 = (fabs(__pyx_v_m) < 1e-10);
-  if (__pyx_t_2) {
-/* … */
-  }
-
+152:         return CVector(v.x, v.y, v.z)
-
    __pyx_t_3.x = __pyx_v_v->x;
-    __pyx_t_3.y = __pyx_v_v->y;
-    __pyx_t_3.z = __pyx_v_v->z;
-    __pyx_r = __pyx_t_3;
-    goto __pyx_L0;
-
+153:     return mul_c(v, 1.0 / m)
-
  __pyx_t_3 = __pyx_f_16CyEulerBallistic_6vector_mul_c(__pyx_v_v, (1.0 / __pyx_v_m)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 153, __pyx_L1_error)
-  __pyx_r = __pyx_t_3;
-  goto __pyx_L0;
-
diff --git a/pyproject.toml b/pyproject.toml index da07dc0..6e63a75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,9 @@ classifiers = [ ] dependencies = ["py_ballisticcalc==2.1.0b6"] +[project.entry-points.py_ballisticcalc] +engine = "CyEulerBallistic.trajectory_calc:EulerTrajectoryCalc" + [project.urls] "Homepage" = "https://github.com/o-murphy/CyEulerBallistic" "Bug Reports" = "https://github.com/o-murphy/CyEulerBallistic/issues" From f51e7d91b7c1f70a9e58f8197c66284f30215df6 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:57:14 +0300 Subject: [PATCH 02/18] use submodule --- .../package-test-cython-as-entry.yml | 5 +- .gitmodules | 3 + py-ballisticcalc | 1 + uv.lock | 489 ++++++++++++++++++ 4 files changed, 497 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 160000 py-ballisticcalc create mode 100644 uv.lock diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 9fccb2c..f6a995e 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -21,6 +21,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + submodules: 'true' + submodules-depth: 0 - name: Install uv and set the python version ${{ matrix.python-version }} uses: astral-sh/setup-uv@v5 @@ -38,8 +41,8 @@ jobs: - name: Install from pr #170 run: | uv pip uninstall py_ballisticcalc - git clone -b engine_entry_point https://github.com/o-murphy/py-ballisticcalc.git cd py-ballisticcalc + git checkout engine_entry_point uv pip install -e .[dev] cd ../ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..314d87f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "py-ballisticcalc"] + path = py-ballisticcalc + url = https://github.com/o-murphy/py-ballisticcalc diff --git a/py-ballisticcalc b/py-ballisticcalc new file mode 160000 index 0000000..a18059e --- /dev/null +++ b/py-ballisticcalc @@ -0,0 +1 @@ +Subproject commit a18059ee5226ede2b5a1f6427b64e8f720cc4ec9 diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..0f48c35 --- /dev/null +++ b/uv.lock @@ -0,0 +1,489 @@ +version = 1 +revision = 2 +requires-python = ">=3.9" +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version < '3.11'", +] + +[[package]] +name = "astroid" +version = "3.3.10" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/00/c2/9b2de9ed027f9fe5734a6c0c0a601289d796b3caaf1e372e23fa88a73047/astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce", size = 398941, upload-time = "2025-05-10T13:33:10.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/58/5260205b9968c20b6457ed82f48f9e3d6edf2f1f95103161798b73aeccf0/astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", size = 275388, upload-time = "2025-05-10T13:33:08.391Z" }, +] + +[[package]] +name = "bashlex" +version = "0.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/60/aae0bb54f9af5e0128ba90eb83d8d0d506ee8f0475c4fdda3deeda20b1d2/bashlex-0.18.tar.gz", hash = "sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee", size = 68742, upload-time = "2023-01-18T15:21:26.402Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539, upload-time = "2023-01-18T15:21:24.167Z" }, +] + +[[package]] +name = "bracex" +version = "2.5.post1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641, upload-time = "2024-09-28T21:41:22.017Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558, upload-time = "2024-09-28T21:41:21.016Z" }, +] + +[[package]] +name = "build" +version = "1.2.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701, upload-time = "2024-10-06T17:22:25.251Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950, upload-time = "2024-10-06T17:22:23.299Z" }, +] + +[[package]] +name = "certifi" +version = "2025.4.26" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, +] + +[[package]] +name = "cibuildwheel" +version = "2.23.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bashlex" }, + { name = "bracex" }, + { name = "certifi" }, + { name = "dependency-groups" }, + { name = "filelock" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/f5/2c06c8229e291e121cb26ed2efa1ba5d89053a93631d8f1d795f2dacabb8/cibuildwheel-2.23.3.tar.gz", hash = "sha256:d85dd15b7eb81711900d8129e67efb32b12f99cc00fc271ab060fa6270c38397", size = 295383, upload-time = "2025-04-26T10:41:28.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/8e/127e75e087c0a55903deb447a938e97935c6a56bfd20e6070bcc26c06d1b/cibuildwheel-2.23.3-py3-none-any.whl", hash = "sha256:0fa40073ae23a56d5f995d8405e82c1206049999bb89b92aa0835ee62ab8a891", size = 91792, upload-time = "2025-04-26T10:41:26.148Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "cyeulerballistic" +version = "2.1.0b6" +source = { editable = "." } +dependencies = [ + { name = "py-ballisticcalc" }, +] + +[package.optional-dependencies] +dev = [ + { name = "build" }, + { name = "cibuildwheel" }, + { name = "cython" }, + { name = "mypy" }, + { name = "pylint" }, + { name = "pytest" }, + { name = "setuptools" }, +] + +[package.metadata] +requires-dist = [ + { name = "build", marker = "extra == 'dev'" }, + { name = "cibuildwheel", marker = "extra == 'dev'" }, + { name = "cython", marker = "extra == 'dev'" }, + { name = "mypy", marker = "extra == 'dev'" }, + { name = "py-ballisticcalc", specifier = "==2.1.0b6" }, + { name = "pylint", marker = "extra == 'dev'" }, + { name = "pytest", marker = "extra == 'dev'" }, + { name = "setuptools", marker = "extra == 'dev'" }, +] +provides-extras = ["dev"] + +[[package]] +name = "cython" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/d3/bb000603e46144db2e5055219bbddcf7ab3b10012fcb342695694fb88141/cython-3.1.1.tar.gz", hash = "sha256:505ccd413669d5132a53834d792c707974248088c4f60c497deb1b416e366397", size = 3175446, upload-time = "2025-05-19T09:44:54.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/37/81/67060b1f3ef43faf039eb1badd27bd3e9c00ec8ff53db35b95760083ea45/cython-3.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7adff5b42d2556d073e9f321c2faa639a17fb195ec1de130327f60ec209d8", size = 2964150, upload-time = "2025-05-19T09:56:25.366Z" }, + { url = "https://files.pythonhosted.org/packages/ec/cf/d1bbc3330469d57f2ba4d6d3a0a5a83c503fea6c4a7fc24e1f706d60788e/cython-3.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b61b99205308c96b1162de59bd67ecadcad3d166a4a1f03a3d9e826c39cd375", size = 2827545, upload-time = "2025-05-19T09:56:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/86/9c/e9af4ee8559331e27e5b9b2f0c21c71fde0b8f8ec1425f826647e432cacc/cython-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14186bd96783d13b8fd0e5b289f2e137a8a25479638b73a1c7e4a99a8d70753", size = 3203093, upload-time = "2025-05-19T09:56:31.175Z" }, + { url = "https://files.pythonhosted.org/packages/6c/3c/322a76b8ca53e23fb016626170e2e10de7791e50736ee3da50cc57eeae65/cython-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3ccec55e2a534a712db14c6617b66f65ad149c014fad518fc3920f6edde770", size = 3324310, upload-time = "2025-05-19T09:56:34.638Z" }, + { url = "https://files.pythonhosted.org/packages/cc/60/335115586fb78ef5dd12151b6e09c9d30bc4353fc08539acdbbf2fd009c5/cython-3.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a585796939b09b3205b1980e4a55e745c0251e45a5c637afbcac3c6cc9ad6f90", size = 3385463, upload-time = "2025-05-19T09:56:36.99Z" }, + { url = "https://files.pythonhosted.org/packages/7d/20/c79d2a7970208f9624029a4fb1504e827c0c575e222729a4fb7dd736f517/cython-3.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3fa4bd840de63509c74867b4b092541720a01db1e07351206011c34e0777dc96", size = 3249043, upload-time = "2025-05-19T09:56:39.091Z" }, + { url = "https://files.pythonhosted.org/packages/23/1a/5b361d93c1f55fbe29be15375127dc0f64195fb9d7d9e3b4a4137fbe34b2/cython-3.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b68f1bc80387554eb43f2b62795c173bed9e37201f39dc5084ac437c90a79c9f", size = 3472158, upload-time = "2025-05-19T09:56:41.276Z" }, + { url = "https://files.pythonhosted.org/packages/37/80/66831d7eec4becda833d3bd0199e2de8f47881f045bf450763b4bbedfcc6/cython-3.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e851ab66a31794e40df1bc6f649cdc56c998c637f5a1b9410c97a90f6b6cb855", size = 3405190, upload-time = "2025-05-19T09:56:44.735Z" }, + { url = "https://files.pythonhosted.org/packages/62/72/55e71a5a03b73951f260b61ea272c4b7787a41871d7cd6ff77db16351681/cython-3.1.1-cp310-cp310-win32.whl", hash = "sha256:64915259276482fa23417b284d1fdc7e3a618ee2f819bb6ea7f974c075633df6", size = 2451446, upload-time = "2025-05-19T09:56:46.757Z" }, + { url = "https://files.pythonhosted.org/packages/f0/96/449d384dfe2523476a30bc45da041b5de15a3824530ae64a631efaed81a9/cython-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dee554f0a589377bdaea0eb70e212bf3f35dc6a51a2aa86c9351345e21fd2f07", size = 2650269, upload-time = "2025-05-19T09:56:49.046Z" }, + { url = "https://files.pythonhosted.org/packages/35/b3/bc75c0352214b5ced31ce5e0d051d0ad4ad916aa7a1d669d1876ad1e59aa/cython-3.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c360823e1063784efc2335617e0f28573d7a594c5a8a05d85e850a9621cccb1f", size = 2998590, upload-time = "2025-05-19T09:56:51.148Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0a/5840cdd7a1e8c0d2ffeb5e09afd32b8d10321cce33a2554ef10ea832a200/cython-3.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12e00b88147b03c148a95365f89dc1c45a0fc52f9c35aa75ff770ef65b615839", size = 2860818, upload-time = "2025-05-19T09:56:53.694Z" }, + { url = "https://files.pythonhosted.org/packages/63/2e/0fac02ce46f208af54d76c6c786b8dddeb207ca94aa85b0455f6cbaa472c/cython-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab644415458d782c16ba7252de9cec1e3125371641cafea2e53a8c1cf85dd58d", size = 3124262, upload-time = "2025-05-19T09:56:56.277Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/b7ae247b83b3f98966184c1a787001964132ae2e05a989769b1a5e7325da/cython-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5cb6c054daadaf01a88c8f49f3edd9e829c9b76a82cbb4269e3f9878254540b", size = 3215216, upload-time = "2025-05-19T09:56:58.674Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3b/c4e6c16b099a592dbd6cd615c4de901eb8cc2795d5445d77b8cd378de7da/cython-3.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af8f62cc9339b75fe8434325083e6a7cae88c9c21efd74bbb6ba4e3623219469", size = 3282597, upload-time = "2025-05-19T09:57:00.85Z" }, + { url = "https://files.pythonhosted.org/packages/06/dd/90a8fd8508298f1f16e2cbc665774047fbc81f0370125b6e32f0a182fc10/cython-3.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:689c1aad373556bd2ab1aa1c2dad8939a2891465a1fbd2cbbdd42b488fb40ec8", size = 3175592, upload-time = "2025-05-19T09:57:03.1Z" }, + { url = "https://files.pythonhosted.org/packages/af/ab/2cd4e8d5c46499ea2ca5b7c3ae4053db86465b35a8870ce5e847fee06aff/cython-3.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:953046c190fa9ab9a09a546a909b847cdbb4c1fe34e9bfa4a15b6ee1585a86aa", size = 3378435, upload-time = "2025-05-19T09:57:05.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/99/250fb399af2edd9861774f0c8b6c4b7d862aa52d966a07b860bcd723842a/cython-3.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:755a991601b27dd3555310d0f95b19a05e622a80d7b4e7a91fa6f5f3ef3f3b80", size = 3300519, upload-time = "2025-05-19T09:57:07.512Z" }, + { url = "https://files.pythonhosted.org/packages/37/09/1c5d470580d9b92107cadedc848f43e2f2102284f8b666ea9ab82f6fc101/cython-3.1.1-cp311-cp311-win32.whl", hash = "sha256:83b2af5c327f7da4f08afc34fddfaf6d24fa0c000b6b70a527c8125e493b6080", size = 2447287, upload-time = "2025-05-19T09:57:09.958Z" }, + { url = "https://files.pythonhosted.org/packages/30/67/c99ec81380cd9d2c798eb1572f61dbe50318958925049b39029f73fe6b52/cython-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:141ffd6279411c562f6b707adc56b63e965a4fd7f21db83f5d4fcbd8c50ac546", size = 2655739, upload-time = "2025-05-19T09:57:11.938Z" }, + { url = "https://files.pythonhosted.org/packages/78/06/83ff82381319ff68ae46f9dd3024b1d5101997e81a8e955811525b6f934b/cython-3.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9d7dc0e4d0cd491fac679a61e9ede348c64ca449f99a284f9a01851aa1dbc7f6", size = 3006334, upload-time = "2025-05-19T09:57:14.284Z" }, + { url = "https://files.pythonhosted.org/packages/c3/01/b4c46c6a27cd2da642bc987c1f9087265defbc96a1929d326b9034953f15/cython-3.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd689910002adfac8734f237cdea1573e38345f27ed7fd445482813b65a29457", size = 2836861, upload-time = "2025-05-19T09:57:16.129Z" }, + { url = "https://files.pythonhosted.org/packages/96/51/7936c5d01ec3c89be8de1756f284878d4a567627b7b1790455ac627fb833/cython-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f0434916994fe213ea7749268b88d77e3ebcbd1b99542cf64bb7d180f45470", size = 3074560, upload-time = "2025-05-19T09:57:18.797Z" }, + { url = "https://files.pythonhosted.org/packages/0d/81/34aeb787dcb2624a82a33e60276ed28d2da8a08c79660cf674b19be82248/cython-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:873aac4ac0b0fb197557c0ac15458b780b9221daa4a716881cbd1a9016c8459f", size = 3192645, upload-time = "2025-05-19T09:57:21.002Z" }, + { url = "https://files.pythonhosted.org/packages/e8/bf/1350ed6cb48158a4f096306a12bc4c26c6d20d3314f1f1978ea23afe0220/cython-3.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23b886a6c8a50b1101ccef2f2f3dc9c699b77633ef5bb5007090226c2ad3f9c2", size = 3241751, upload-time = "2025-05-19T09:57:23.118Z" }, + { url = "https://files.pythonhosted.org/packages/1e/f5/9ed5a898c41723e3da2317fd1f082d963ff08571caeded31cb945be589b5/cython-3.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dff0e7dd53a0ca35b64cda843253d5cac944db26663dc097b3a1adf2c49514ad", size = 3123562, upload-time = "2025-05-19T09:57:25.492Z" }, + { url = "https://files.pythonhosted.org/packages/c3/81/b5ce4393d3a0a75a8c6d9ad0b80a62263d892260b816eb3d569ef144511a/cython-3.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f7954b0b4b3302655d3caa6924261de5907a4e129bc22ace52fe9ae0cd5a758", size = 3333555, upload-time = "2025-05-19T09:57:29.232Z" }, + { url = "https://files.pythonhosted.org/packages/db/47/2c1fa4b4901f10d00e666931dd68d4bd7954d3caa900544d135424ef6178/cython-3.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dfa500fd7ae95ca152a5f8062b870532fa3e27efcef6d00612e1f28b9f72615f", size = 3282112, upload-time = "2025-05-19T09:57:31.904Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5b/b000d3ebff79429419d846e06c5c09f33fd010e1f6158d7ba553e1082253/cython-3.1.1-cp312-cp312-win32.whl", hash = "sha256:cd748fab8e4426dbcb2e0fa2979558333934d24365e0de5672fbabfe337d880c", size = 2462293, upload-time = "2025-05-19T09:57:34.964Z" }, + { url = "https://files.pythonhosted.org/packages/45/0e/e1370ed3216e4e164232d1891c2a2932a3874d1a8681f8c3565cafd98579/cython-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:307f216ed319ea07644f2ef9974406c830f01bc8e677e2147e9bfcdf9e3ca8ad", size = 2666710, upload-time = "2025-05-19T09:57:37.528Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ec/7bc61e156f71cefdc1c7c2a9b8d25facdf6d208f9e19a80aa4ae56a9842e/cython-3.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb5661941707bd41ec7a9c273d698113ac50392444f785088e9d9706c6a5937b", size = 2990324, upload-time = "2025-05-19T09:57:39.962Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/2f2550dcda3b54c65c9132ec95470cc4115b96a78163e539e0a02f767f05/cython-3.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:28b174f41718a7041cfbe0f48913020875ff1aaa4793942b2451ac6d2baf3f07", size = 2822556, upload-time = "2025-05-19T09:57:41.989Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f8/b7a14323ee8474be00909469dd115e84d28719aaf94a55623fd6366dcab5/cython-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c740a10cd0f50321d048c8ca318eefb4c42b8bffef982dcd89c946d374192702", size = 3060223, upload-time = "2025-05-19T09:57:46.439Z" }, + { url = "https://files.pythonhosted.org/packages/ca/90/9fe8b93fa239b4871252274892c232415f53d5af0859c4a6ac9b1cbf9950/cython-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7da069ca769903c5dee56c5f7ab47b2b7b91030eee48912630db5f4f3ec5954a", size = 3180196, upload-time = "2025-05-19T09:57:48.619Z" }, + { url = "https://files.pythonhosted.org/packages/01/95/8fe6282a846f8ce56bb62434b48053910c68c94ec5da3bd47bc2de0bb5e2/cython-3.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24c640c0746d984789fe2787a098f06cda456ef2dd78b90164d17884b350839a", size = 3208726, upload-time = "2025-05-19T09:57:51.258Z" }, + { url = "https://files.pythonhosted.org/packages/be/28/7db9e79a5099659f6e46c48577f582e6b542873159c3f65033a247e364b5/cython-3.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:426d78565eb91d3366569b20e92b8f14bffef5f57b2acd05b60bbb9ce5c056a1", size = 3112452, upload-time = "2025-05-19T09:57:53.365Z" }, + { url = "https://files.pythonhosted.org/packages/44/68/de53aff8db5f05efd9fe7f1435aa6019573b94ae151ef82a66ca20b4ec57/cython-3.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b181158b5761bdaf40f6854f016ab7ddff64d3db4fca55cb3ca0f73813dd76d6", size = 3305698, upload-time = "2025-05-19T09:57:55.485Z" }, + { url = "https://files.pythonhosted.org/packages/52/e9/a54f53ba5feeb00e187e24ba6fc7b085075e8ac53ed22797ac9d77db7422/cython-3.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7489559e6c5ecbba49d535c2e03cf77c2594a3190b6aca7da5b508ba1664a89a", size = 3258348, upload-time = "2025-05-19T09:57:57.605Z" }, + { url = "https://files.pythonhosted.org/packages/0c/07/8c1a2ff59af7976ba16afe8cd54a070ce2986924cacecc7812236bf7f1c7/cython-3.1.1-cp313-cp313-win32.whl", hash = "sha256:263cb0e497910fb5e0a361ad1393b6d728b092178afecc56e8a786f3739960c3", size = 2457891, upload-time = "2025-05-19T09:57:59.675Z" }, + { url = "https://files.pythonhosted.org/packages/79/5e/c469f7b42e145a06af79a3f7b599454c028a823c6a83adc867ddfd02f941/cython-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:e000f0533eedf3d6dfbe30bb3c58a054c58f0a7778390342fa577a0dc47adab3", size = 2665693, upload-time = "2025-05-19T09:58:02.262Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/d0177d096fa149e417510caf8c5e1c53554f168b918ddc52515d94c883dc/cython-3.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40f50b07c479eaf33981d81cad274c68cf9fb81dbe79cbf991f59491c88a4705", size = 2973317, upload-time = "2025-05-19T09:58:25.824Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/cb75a1e67a0a5d3c54e91f714a15d4ff631439446b71820045f3a84901a1/cython-3.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a92f6bd395eadea6eed722a8188d3bdd49db1c9fa3c38710456d6148ab71bad7", size = 2835598, upload-time = "2025-05-19T09:58:28.115Z" }, + { url = "https://files.pythonhosted.org/packages/d3/d7/6c30ba90d8800df4bd15e5468f7c880b5a81343f11254300b5326d8d7ff3/cython-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:268420b92307ae6c5a16e3cf0e2ba1ae3c861650e992893922a0ce08db07cfdb", size = 3211884, upload-time = "2025-05-19T09:58:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/66/5d/278c54e3d036305fac961d83ea1e9a675fb2a0c28aed2d908b637598daa6/cython-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a19188ecd385cdc649e3fec370f38d5fd7f1651aeed0b3fb403180f38fc88e8a", size = 3331865, upload-time = "2025-05-19T09:58:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/07/2f/8ecdd1bfaf302d73fc7058287599dc6c421dfd76c1022db43d4b96ff749f/cython-3.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fff6526bb6f4eea615663117b86de6ede0d17c477b600d3d8302be3502bd3c3", size = 3392535, upload-time = "2025-05-19T09:58:35.489Z" }, + { url = "https://files.pythonhosted.org/packages/de/8a/b7abf8b82c9706055ffeae23d23f959fb845fceb9b8543c107c496a8eb69/cython-3.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3192a61c2a532d3faccdff508bc8427de9530b587888218bfc0226eb33a84e11", size = 3254413, upload-time = "2025-05-19T09:58:37.604Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ec/33de7469fe1f8dff858c4867919985aa75bbfcb021938c445c286b006c49/cython-3.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:56c6768a6f601f93daab7c2487f9f110548a896a91e00a6e119445ada2575323", size = 3479692, upload-time = "2025-05-19T09:58:40.826Z" }, + { url = "https://files.pythonhosted.org/packages/2e/aa/2bc816b0293df1798ee449422b97a2b8f81c3b04260d65f6c856e69d8e74/cython-3.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:50ad80e2f438e9127a87c10927e6ac16a987df39c248b19ab2cd31330129be3c", size = 3408199, upload-time = "2025-05-19T09:58:43.166Z" }, + { url = "https://files.pythonhosted.org/packages/9c/4e/7eb59cd2e25477994c9beaa9f601c773208e28781016093388f8177f6489/cython-3.1.1-cp39-cp39-win32.whl", hash = "sha256:b194a65a0fd91f305d2d1e7010f44111774a28533e1e44dd2a76e7de81a219b9", size = 2456293, upload-time = "2025-05-19T09:58:45.178Z" }, + { url = "https://files.pythonhosted.org/packages/b4/ae/16ed166b8a9e5317e9a994138ed177ba52ee7588b2ae77e94f9c2f1b51eb/cython-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c8b8be01fd40b3e38a76c60a524f956548a3a7566e5530a833a48a695f3d6c12", size = 2655391, upload-time = "2025-05-19T09:58:47.511Z" }, + { url = "https://files.pythonhosted.org/packages/a7/97/8e8637e67afc09f1b51a617b15a0d1caf0b5159b0f79d47ab101e620e491/cython-3.1.1-py3-none-any.whl", hash = "sha256:07621e044f332d18139df2ccfcc930151fd323c2f61a58c82f304cffc9eb5280", size = 1220898, upload-time = "2025-05-19T09:44:50.614Z" }, +] + +[[package]] +name = "dependency-groups" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, +] + +[[package]] +name = "dill" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, +] + +[[package]] +name = "filelock" +version = "3.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "zipp" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "isort" +version = "6.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955, upload-time = "2025-02-26T21:13:16.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186, upload-time = "2025-02-26T21:13:14.911Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "mypy" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "pathspec" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416, upload-time = "2025-05-29T13:34:17.783Z" }, + { url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654, upload-time = "2025-05-29T13:32:37.878Z" }, + { url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192, upload-time = "2025-05-29T13:34:54.281Z" }, + { url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939, upload-time = "2025-05-29T13:33:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719, upload-time = "2025-05-29T13:21:52.09Z" }, + { url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053, upload-time = "2025-05-29T13:33:29.797Z" }, + { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" }, + { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" }, + { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" }, + { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" }, + { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" }, + { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" }, + { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" }, + { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" }, + { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" }, + { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" }, + { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" }, + { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" }, + { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" }, + { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" }, + { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" }, + { url = "https://files.pythonhosted.org/packages/bd/eb/c0759617fe2159aee7a653f13cceafbf7f0b6323b4197403f2e587ca947d/mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3", size = 10956081, upload-time = "2025-05-29T13:19:32.264Z" }, + { url = "https://files.pythonhosted.org/packages/70/35/df3c74a2967bdf86edea58b265feeec181d693432faed1c3b688b7c231e3/mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92", size = 10084422, upload-time = "2025-05-29T13:18:01.437Z" }, + { url = "https://files.pythonhosted.org/packages/b3/07/145ffe29f4b577219943b7b1dc0a71df7ead3c5bed4898686bd87c5b5cc2/mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436", size = 11879670, upload-time = "2025-05-29T13:17:45.971Z" }, + { url = "https://files.pythonhosted.org/packages/c6/94/0421562d6b046e22986758c9ae31865d10ea0ba607ae99b32c9d18b16f66/mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2", size = 12610528, upload-time = "2025-05-29T13:34:36.983Z" }, + { url = "https://files.pythonhosted.org/packages/1a/f1/39a22985b78c766a594ae1e0bbb6f8bdf5f31ea8d0c52291a3c211fd3cd5/mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20", size = 12871923, upload-time = "2025-05-29T13:32:21.823Z" }, + { url = "https://files.pythonhosted.org/packages/f3/8e/84db4fb0d01f43d2c82fa9072ca72a42c49e52d58f44307bbd747c977bc2/mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21", size = 9482931, upload-time = "2025-05-29T13:21:32.326Z" }, + { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "py-ballisticcalc" +version = "2.1.0b6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/07/52edb6f138f60a6fe29566d809a5e8886cabe3872909252f2a39d2dfc672/py_ballisticcalc-2.1.0b6.tar.gz", hash = "sha256:8e1c4844d84880da02b9c683df54595b86fd22982ff5030b8702103e1792a23e", size = 264475, upload-time = "2025-02-18T15:27:02.379Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ae/d2/aef4f6b01aba140dc7a4f7bdac79052e623136ff68f28414e7cc952a6d51/py_ballisticcalc-2.1.0b6-py3-none-any.whl", hash = "sha256:70f02f62e570836d23353b1d702324f3c8cbbb122515eaca5a620eb5e6ab24eb", size = 64783, upload-time = "2025-02-18T15:25:15.649Z" }, +] + +[[package]] +name = "pylint" +version = "3.3.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astroid" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "dill" }, + { name = "isort" }, + { name = "mccabe" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "tomlkit" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/e4/83e487d3ddd64ab27749b66137b26dc0c5b5c161be680e6beffdc99070b3/pylint-3.3.7.tar.gz", hash = "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", size = 1520709, upload-time = "2025-05-04T17:07:51.089Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/83/bff755d09e31b5d25cc7fdc4bf3915d1a404e181f1abf0359af376845c24/pylint-3.3.7-py3-none-any.whl", hash = "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d", size = 522565, upload-time = "2025-05-04T17:07:48.714Z" }, +] + +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, +] + +[[package]] +name = "pytest" +version = "8.3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885, upload-time = "2024-08-14T08:19:41.488Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955, upload-time = "2024-08-14T08:19:40.05Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, +] + +[[package]] +name = "zipp" +version = "3.22.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" }, +] From 1943a2fb65ca39666fe980a51bc814e084a3e6eb Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:59:00 +0300 Subject: [PATCH 03/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index f6a995e..3743e99 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -42,6 +42,7 @@ jobs: run: | uv pip uninstall py_ballisticcalc cd py-ballisticcalc + git fetch origin git checkout engine_entry_point uv pip install -e .[dev] cd ../ From 6a5ebcf62c21b8119ddd0f7c8b45d4872fcc5803 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:01:59 +0300 Subject: [PATCH 04/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 3743e99..5026327 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -43,7 +43,7 @@ jobs: uv pip uninstall py_ballisticcalc cd py-ballisticcalc git fetch origin - git checkout engine_entry_point + git checkout origin/engine_entry_point uv pip install -e .[dev] cd ../ From 41753f41d109aa3f2a347a59769df9acbc75a233 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:04:54 +0300 Subject: [PATCH 05/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 5026327..d71e41b 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -23,7 +23,6 @@ jobs: - uses: actions/checkout@v4 with: submodules: 'true' - submodules-depth: 0 - name: Install uv and set the python version ${{ matrix.python-version }} uses: astral-sh/setup-uv@v5 @@ -42,7 +41,7 @@ jobs: run: | uv pip uninstall py_ballisticcalc cd py-ballisticcalc - git fetch origin + git fetch --all git checkout origin/engine_entry_point uv pip install -e .[dev] cd ../ From d52426165210a50930e2441a974d19489e642d22 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:28:46 +0300 Subject: [PATCH 06/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index d71e41b..514efd4 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -42,7 +42,7 @@ jobs: uv pip uninstall py_ballisticcalc cd py-ballisticcalc git fetch --all - git checkout origin/engine_entry_point + git checkout origin/trying-entry-point uv pip install -e .[dev] cd ../ From cc0c4d43f4d55ebfb22a4acf09e10d8eeec0432a Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:32:41 +0300 Subject: [PATCH 07/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 514efd4..d71e41b 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -42,7 +42,7 @@ jobs: uv pip uninstall py_ballisticcalc cd py-ballisticcalc git fetch --all - git checkout origin/trying-entry-point + git checkout origin/engine_entry_point uv pip install -e .[dev] cd ../ From 58a144da4d287d9e0957be2d30380052243ad4d0 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:42:07 +0300 Subject: [PATCH 08/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index d71e41b..2978f63 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -40,9 +40,8 @@ jobs: - name: Install from pr #170 run: | uv pip uninstall py_ballisticcalc + git clone -b engine_entry_point https://github.com/o-murphy/py-ballisticcalc.git cd py-ballisticcalc - git fetch --all - git checkout origin/engine_entry_point uv pip install -e .[dev] cd ../ From cd28d7d0217816b84e4c4878a8b074c90bd16ef1 Mon Sep 17 00:00:00 2001 From: Dmytro Yaroshenko <73843436+o-murphy@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:44:01 +0300 Subject: [PATCH 09/18] use submodule --- .github/workflows/package-test-cython-as-entry.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 2978f63..54f2e9d 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -21,8 +21,8 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - with: - submodules: 'true' +# with: +# submodules: 'true' - name: Install uv and set the python version ${{ matrix.python-version }} uses: astral-sh/setup-uv@v5 From 27a925d7948b4fde0fd8a975cf92c0656e1d5a32 Mon Sep 17 00:00:00 2001 From: o-murphy Date: Tue, 3 Jun 2025 23:28:04 +0300 Subject: [PATCH 10/18] trying new test ci --- .../package-test-cython-as-entry.yml | 55 ++- .gitmodules | 3 - pyproject.toml | 2 +- tests/__init__.py | 0 tests/test_computer.py | 257 ------------- tests/test_mbc.py | 74 ---- tests/test_trajectory.py | 136 ------- uv.lock | 353 +++++++++--------- 8 files changed, 205 insertions(+), 675 deletions(-) delete mode 100644 .gitmodules delete mode 100644 tests/__init__.py delete mode 100644 tests/test_computer.py delete mode 100644 tests/test_mbc.py delete mode 100644 tests/test_trajectory.py diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml index 54f2e9d..0bd3f27 100644 --- a/.github/workflows/package-test-cython-as-entry.yml +++ b/.github/workflows/package-test-cython-as-entry.yml @@ -21,8 +21,6 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 -# with: -# submodules: 'true' - name: Install uv and set the python version ${{ matrix.python-version }} uses: astral-sh/setup-uv@v5 @@ -37,36 +35,37 @@ jobs: run: | uv pip install -e .[dev] - - name: Install from pr #170 - run: | - uv pip uninstall py_ballisticcalc - git clone -b engine_entry_point https://github.com/o-murphy/py-ballisticcalc.git + - name: Get py-ballisticcalc installed version + id: get_installed_version # This ID allows referencing its output + run: | + # Run the Python command to get the version + # The output is captured and set as a step output named 'pybc_version' + # This syntax works universally with 'bash' shell on Linux and Windows + echo "pybc_version=$(python -c 'from importlib.metadata import metadata; print(metadata("py-ballisticcalc")["Version"])')" >> "$GITHUB_OUTPUT" + shell: bash # Explicitly use bash for cross-platform compatibility + + - name: Install from specific tag based on installed version + run: | + # Access the version obtained from the previous step's output + # The 'steps.get_installed_version.outputs.pybc_version' syntax is universal + PYBC_VERSION="${{ steps.get_installed_version.outputs.pybc_version }}" + echo "Cloning py-ballisticcalc with tag: $PYBC_VERSION" + + # Clone the specific tag (version) using the obtained version + git clone --branch "$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc + + # Change into the cloned directory cd py-ballisticcalc + + # Install in editable mode with dev dependencies using uv uv pip install -e .[dev] + + # Go back to the original directory and clean up cd ../ + shell: bash # Ensure bash is used for the shell commands - - name: Run unittest tests in binary mode + - name: Run pytest run: | - cd py-ballisticcalc - pytest tests --no-header --no-summary -v --engine CyEulerBallistic - if [ $? -ne 0 ]; then - echo "Pytest failed, running without capture" - pytest tests -v --engine CyEulerBallistic - else - echo "Pytest succeeded." - fi + pytest tests -v --engine CyEulerBallistic shell: bash if: runner.os != 'Windows' - - - name: Run unittest tests in binary mode on Windows - run: | - cd py-ballisticcalc - pytest tests --no-header --no-summary -v --engine CyEulerBallistic - if %ERRORLEVEL% neq 0 ( - echo Pytest failed, running without capture - pytest tests -v --engine CyEulerBallistic - ) else ( - echo Pytest succeeded. - ) - shell: cmd - if: runner.os == 'Windows' diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 314d87f..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "py-ballisticcalc"] - path = py-ballisticcalc - url = https://github.com/o-murphy/py-ballisticcalc diff --git a/pyproject.toml b/pyproject.toml index 6e63a75..466b0ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python :: Implementation :: CPython", ] -dependencies = ["py_ballisticcalc==2.1.0b6"] +dependencies = ["py_ballisticcalc==2.1.1b1"] [project.entry-points.py_ballisticcalc] engine = "CyEulerBallistic.trajectory_calc:EulerTrajectoryCalc" diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_computer.py b/tests/test_computer.py deleted file mode 100644 index 5dacb72..0000000 --- a/tests/test_computer.py +++ /dev/null @@ -1,257 +0,0 @@ -"""Unittests for the py_ballisticcalc library""" - -import unittest -import copy -from py_ballisticcalc import ( - DragModel, Ammo, Weapon, Shot, Wind, Atmo, TableG7, RangeError, -) -from py_ballisticcalc.unit import * -from CyEulerBallistic import EulerCalculator - - -class TestComputer(unittest.TestCase): - """Basic verifications that wind, spin, and cant values produce effects of correct sign and magnitude""" - - def setUp(self): - """Baseline shot has barrel at zero elevation""" - self.range = 1000 - self.step = 100 - self.dm = DragModel(0.22, TableG7, 168, 0.308, 1.22) - self.ammo = Ammo(self.dm, Velocity.FPS(2600)) - self.weapon = Weapon(4, 12) - self.atmosphere = Atmo.icao() # Standard sea-level atmosphere - self.calc = EulerCalculator() - self.baseline_shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere) - self.baseline_trajectory = self.calc.fire(shot=self.baseline_shot, trajectory_range=self.range, - trajectory_step=self.step) - - # region Cant_angle - def test_cant_zero_elevation(self): - """Cant_angle = 90 degrees with zero barrel elevation should match baseline with: - drop+=sight_height, windage-=sight_height - """ - canted = copy.copy(self.baseline_shot) - canted.cant_angle = Angular.Degree(90) - t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step) - self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value, - self.baseline_trajectory[5].height.raw_value) - self.assertAlmostEqual(t.trajectory[5].windage.raw_value + self.weapon.sight_height.raw_value, - self.baseline_trajectory[5].windage.raw_value) - - def test_cant_positive_elevation(self): - """Cant_angle = 90 degrees with positive barrel elevation and zero twist should match baseline with: - drop+=sight_height, windage-=sight_height at muzzle, increasingly positive down-range - """ - canted = Shot(weapon=Weapon(sight_height=self.weapon.sight_height, twist=0, zero_elevation=Angular.Mil(2)), - ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90)) - t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step) - self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value, - self.baseline_trajectory[5].height.raw_value, 2) - self.assertAlmostEqual(t.trajectory[0].windage.raw_value, -self.weapon.sight_height.raw_value) - self.assertGreater(t.trajectory[5].windage.raw_value, t.trajectory[3].windage.raw_value) - - def test_cant_zero_sight_height(self): - """Cant_angle = 90 degrees with sight_height=0 and barrel_elevation=0 should match baseline with: - drop+=baseline.sight_height, windage no change - """ - canted = Shot(weapon=Weapon(sight_height=0, twist=self.weapon.twist), - ammo=self.ammo, atmo=self.atmosphere, cant_angle=Angular.Degree(90)) - t = self.calc.fire(canted, trajectory_range=self.range, trajectory_step=self.step) - self.assertAlmostEqual(t.trajectory[5].height.raw_value - self.weapon.sight_height.raw_value, - self.baseline_trajectory[5].height.raw_value) - self.assertAlmostEqual(t.trajectory[5].windage, self.baseline_trajectory[5].windage) - - # endregion Cant_angle - - # region Wind - def test_wind_from_left(self): - """Wind from left should increase windage""" - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[Wind(Velocity(5, Velocity.MPH), Angular(3, Angular.OClock))]) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].windage, self.baseline_trajectory[5].windage) - - def test_wind_from_right(self): - """Wind from right should decrease windage""" - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[Wind(Velocity(5, Velocity.MPH), Angular(9, Angular.OClock))]) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[5].windage, self.baseline_trajectory[5].windage) - - def test_wind_from_back(self): - """Wind from behind should decrease drop""" - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[Wind(Velocity(5, Velocity.MPH), Angular(0, Angular.OClock))]) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_wind_from_front(self): - """Wind from in front should increase drop""" - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[Wind(Velocity(5, Velocity.MPH), Angular(6, Angular.OClock))]) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_multiple_wind(self): - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[Wind(Velocity.MPS(4), Angular.OClock(9), until_distance=Distance.Meter(500)), - Wind(Velocity.MPS(4), Angular.OClock(3), until_distance=Distance.Meter(800))]) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[5].windage, self.baseline_trajectory[5].windage) - - def test_no_winds(self): - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=self.atmosphere, - winds=[]) - # set empty list - shot.winds = [] - try: - self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - except Exception as e: - self.fail("self.calc.fire() raised ExceptionType unexpectedly!") - - self.winds = None - try: - self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - except Exception as e: - self.fail("self.calc.fire() raised ExceptionType unexpectedly!") - - # endregion Wind - - # region Twist - def test_no_twist(self): - """Barrel with no twist should have no spin drift""" - shot = Shot(weapon=Weapon(twist=0), ammo=self.ammo, atmo=self.atmosphere) - t = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertEqual(t.trajectory[5].windage.raw_value, 0) - - def test_twist(self): - """Barrel with right-hand twist should have positive spin drift. - Barrel with left-hand twist should have negative spin drift. - Faster twist rates should produce larger drift. - """ - shot = Shot(weapon=Weapon(twist=12), ammo=self.ammo, atmo=self.atmosphere) - twist_right = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(twist_right.trajectory[5].windage.raw_value, 0) - shot = Shot(weapon=Weapon(twist=-8), ammo=self.ammo, atmo=self.atmosphere) - twist_left = self.calc.fire(shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(twist_left.trajectory[5].windage.raw_value, 0) - # Faster twist should produce larger drift: - self.assertGreater(-twist_left.trajectory[5].windage.raw_value, twist_right.trajectory[5].windage.raw_value) - - # endregion Twist - - # region Atmo - def test_humidity(self): - """Increasing relative humidity should decrease drop (due to decreasing density)""" - humid = Atmo(humidity=.9) # 90% humidity - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=humid) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_temp_atmo(self): - """Dropping temperature should increase drop (due to increasing density)""" - cold = Atmo(temperature=Temperature.Celsius(0)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=cold) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_altitude(self): - """Increasing altitude should decrease drop (due to decreasing density)""" - high = Atmo.icao(Distance.Foot(5000)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=high) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_pressure(self): - """Decreasing pressure should decrease drop (due to decreasing density)""" - thin = Atmo(pressure=Pressure.InHg(20.0)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=thin) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height) - - # endregion Atmo - - # region Ammo - def test_ammo_drag(self): - """Increasing ballistic coefficient (bc) should decrease drop""" - tdm = DragModel(self.dm.BC + 0.5, self.dm.drag_table, self.dm.weight, self.dm.diameter, self.dm.length) - slick = Ammo(tdm, self.ammo.mv) - shot = Shot(weapon=self.weapon, ammo=slick, atmo=self.atmosphere) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertGreater(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_ammo_optional(self): - """DragModel.weight and .diameter, and Ammo.length, are only relevant when computing - spin-drift. Drop should match baseline with those parameters omitted. - """ - tdm = DragModel(self.dm.BC, self.dm.drag_table) - tammo = Ammo(tdm, mv=self.ammo.mv) - shot = Shot(weapon=self.weapon, ammo=tammo, atmo=self.atmosphere) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertEqual(t.trajectory[5].height, self.baseline_trajectory[5].height) - - def test_powder_sensitivity(self): - """With _globalUsePowderSensitivity: Reducing temperature should reduce muzzle velocity""" - self.ammo.calc_powder_sens(Velocity.FPS(2550), Temperature.Celsius(0)) - - with self.subTest("don't uses powder sensitivity"): - cold = Atmo(temperature=Temperature.Celsius(-5)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=cold) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertEqual(t.trajectory[0].velocity, self.baseline_trajectory[0].velocity) - - self.ammo.use_powder_sensitivity = True - - with self.subTest("powder temperature the same as atmosphere temperature"): - cold = Atmo(temperature=Temperature.Celsius(-5)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=cold) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[0].velocity, self.baseline_trajectory[0].velocity) - - with self.subTest("different powder temperature"): - cold = Atmo(powder_t=Temperature.Celsius(-5)) - shot = Shot(weapon=self.weapon, ammo=self.ammo, atmo=cold) - t = self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - self.assertLess(t.trajectory[0].velocity, self.baseline_trajectory[0].velocity) - - self.ammo.use_powder_sensitivity = False - - # @unittest.skip("Raises ZeroDivisionError") - def test_zero_velocity(self): - tdm = DragModel(self.dm.BC + 0.5, self.dm.drag_table, self.dm.weight, self.dm.diameter, self.dm.length) - slick = Ammo(tdm, 0) - shot = Shot(weapon=self.weapon, ammo=slick, atmo=self.atmosphere) - - with self.assertRaises(RangeError): - self.calc.fire(shot=shot, trajectory_range=self.range, trajectory_step=self.step) - - # endregion Ammo - - # region Shot - def test_winds_sort(self): - winds = [ - Wind(Unit.MPS(0), Unit.Degree(90), Unit.Meter(100)), - Wind(Unit.MPS(1), Unit.Degree(60), Unit.Meter(300)), - Wind(Unit.MPS(2), Unit.Degree(30), Unit.Meter(200)), - Wind(Unit.MPS(2), Unit.Degree(30), Unit.Meter(50)), - ] - - # sorted_winds = sorted(winds, key=lambda winds: winds.until_distance.raw_value) - - # print() - shot = Shot( - None, None, 0, 0, 0, None, - winds - ) - sorted_winds = shot.winds - self.assertIs(sorted_winds[0], winds[3]) - self.assertIs(sorted_winds[1], winds[0]) - self.assertIs(sorted_winds[2], winds[2]) - self.assertIs(sorted_winds[3], winds[1]) - - -# endregion Shot - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_mbc.py b/tests/test_mbc.py deleted file mode 100644 index ddcdcf7..0000000 --- a/tests/test_mbc.py +++ /dev/null @@ -1,74 +0,0 @@ -"Unit tests of multiple-bc drag models" - -import unittest -from py_ballisticcalc import * - -from CyEulerBallistic import EulerCalculator - - -class TestMBC(unittest.TestCase): - - def setUp(self) -> None: - """Establish baseline trajectory""" - self.range = 1000 - self.step = 100 - self.dm = DragModel(0.22, TableG7) - self.ammo = Ammo(self.dm, Velocity.FPS(2600)) - self.weapon = Weapon(4, 12) - self.calc = EulerCalculator() - self.baseline_shot = Shot(weapon=self.weapon, ammo=self.ammo) - self.baseline_trajectory = self.calc.fire(shot=self.baseline_shot, trajectory_range=self.range, trajectory_step=self.step).trajectory - - def test_mbc1(self): - """We should get the same trajectory whether we give single bc or use multi-bc with single value""" - dm_multi = DragModelMultiBC([BCPoint(.22, V=Velocity.FPS(2500)), BCPoint(.22, V=Velocity.FPS(1500)), BCPoint(BC=.22, Mach=3)], TableG7) - multi_shot = Shot(weapon=self.weapon, ammo=Ammo(dm_multi, self.ammo.mv)) - multi_trajectory = self.calc.fire(shot=multi_shot, trajectory_range=self.range, trajectory_step=self.step).trajectory - for i in range(len(multi_trajectory)): - self.assertEqual(multi_trajectory[i].formatted(), self.baseline_trajectory[i].formatted()) - - def test_mbc2(self): - """Setting different bc above muzzle velocity should have no effect""" - dm_multi = DragModelMultiBC([BCPoint(.22, V=Velocity.FPS(2700)), BCPoint(.5, V=Velocity.FPS(3500))], TableG7) - multi_shot = Shot(weapon=self.weapon, ammo=Ammo(dm_multi, self.ammo.mv)) - multi_trajectory = self.calc.fire(shot=multi_shot, trajectory_range=self.range, trajectory_step=self.step).trajectory - for i in range(len(multi_trajectory)): - self.assertEqual(multi_trajectory[i].formatted(), self.baseline_trajectory[i].formatted()) - - def test_mbc3(self): - """Setting higher bc should result in higher downrange velocities""" - # So here we'll boost the bc for velocities lower than the baseline's velocity at 200 yards - dm_multi = DragModelMultiBC([BCPoint(.5, V=self.baseline_trajectory[3].velocity), BCPoint(.22, V=self.baseline_trajectory[2].velocity)], TableG7) - multi_shot = Shot(weapon=self.weapon, ammo=Ammo(dm_multi, self.ammo.mv)) - multi_trajectory = self.calc.fire(shot=multi_shot, trajectory_range=self.range, trajectory_step=self.step).trajectory - # Should show no change before 200 yards - self.assertAlmostEqual(multi_trajectory[1].velocity.raw_value, self.baseline_trajectory[1].velocity.raw_value, places=5) - # Should be faster at any point after 200 yards - self.assertGreater(multi_trajectory[4].velocity.raw_value, self.baseline_trajectory[4].velocity.raw_value) - - def test_mbc(self): - dm = DragModelMultiBC([BCPoint(0.275, V=Velocity.MPS(800)), BCPoint(0.255, V=Velocity.MPS(500)), BCPoint(0.26, V=Velocity.MPS(700))], - TableG7, weight=178, diameter=.308) - self.assertAlmostEqual(dm.drag_table[0].CD, 0.1259323091692403) - self.assertAlmostEqual(dm.drag_table[-1].CD, 0.1577125859466895) - - def test_mbc_valid(self): - # Litz's multi-bc table comversion to CDM, 338LM 285GR HORNADY ELD-M - dm = DragModelMultiBC([BCPoint(0.417, V=Velocity.MPS(745)), BCPoint(0.409, V=Velocity.MPS(662)), BCPoint(0.4, V=Velocity.MPS(580))], - drag_table=TableG7, - weight=Weight.Grain(285), - diameter=Distance.Inch(0.338) - ) - cds = [p.CD for p in dm.drag_table] - machs = [p.Mach for p in dm.drag_table] - reference = ( - (1, 0.3384895315), - (2, 0.2585639866), - (3, 0.2069547831), - (4, 0.1652052415), - (5, 0.1381406102), - ) - for mach, cd in reference: - idx = machs.index(mach) - with self.subTest(mach=mach): - self.assertAlmostEqual(cds[idx], cd, 3) diff --git a/tests/test_trajectory.py b/tests/test_trajectory.py deleted file mode 100644 index 6681fc4..0000000 --- a/tests/test_trajectory.py +++ /dev/null @@ -1,136 +0,0 @@ -"""Unittests for the py_ballisticcalc library""" - -import unittest -from math import fabs -from py_ballisticcalc import * -from CyEulerBallistic import EulerCalculator - - -class TestTrajectory(unittest.TestCase): - - def test_zero1(self): - dm = DragModel(0.365, TableG1, 69, 0.223, 0.9) - ammo = Ammo(dm, 2600) - weapon = Weapon(Distance(3.2, Distance.Inch)) - atmosphere = Atmo.icao() - calc = EulerCalculator() - zero_angle = calc.barrel_elevation_for_target(Shot(weapon=weapon, ammo=ammo, atmo=atmosphere), - Distance(100, Distance.Yard)) - - self.assertAlmostEqual(zero_angle >> Angular.Radian, 0.0016514, 6, - f'TestZero1 failed {zero_angle >> Angular.Radian:.10f}') - - def test_zero2(self): - dm = DragModel(0.223, TableG7, 69, 0.223, 0.9) - ammo = Ammo(dm, 2750) - weapon = Weapon(Distance(2, Distance.Inch)) - atmosphere = Atmo.icao() - calc = EulerCalculator() - zero_angle = calc.barrel_elevation_for_target(Shot(weapon=weapon, ammo=ammo, atmo=atmosphere), - Distance(100, Distance.Yard)) - - self.assertAlmostEqual(zero_angle >> Angular.Radian, 0.0012286, 6, - f'TestZero2 failed {zero_angle >> Angular.Radian:.10f}') - - def custom_assert_equal(self, a, b, accuracy, name): - with self.subTest(name=name): - self.assertLess(fabs(a - b), accuracy, f'Equality {name} failed (|{a} - {b}|, {accuracy} digits)') - - def validate_one(self, data: TrajectoryData, distance: float, velocity: float, - mach: float, energy: float, path: float, hold: float, - windage: float, wind_adjustment: float, time: float, ogv: float, - adjustment_unit: Unit): - - self.custom_assert_equal(distance, data.distance >> Distance.Yard, 0.1, "Distance") - self.custom_assert_equal(velocity, data.velocity >> Velocity.FPS, 5, "Velocity") - self.custom_assert_equal(mach, data.mach, 0.005, "Mach") - self.custom_assert_equal(energy, data.energy >> Energy.FootPound, 5, "Energy") - self.custom_assert_equal(time, data.time, 0.06, "Time") - self.custom_assert_equal(ogv, data.ogw >> Weight.Pound, 1, "OGV") - - if distance >= 800: - self.custom_assert_equal(path, data.height >> Distance.Inch, 4, 'Drop') - elif distance >= 500: - self.custom_assert_equal(path, data.height >> Distance.Inch, 1, 'Drop') - else: - self.custom_assert_equal(path, data.height >> Distance.Inch, 0.5, 'Drop') - - if distance > 1: - self.custom_assert_equal(hold, data.drop_adj >> adjustment_unit, 0.5, 'Hold') - - if distance >= 800: - self.custom_assert_equal(windage, data.windage >> Distance.Inch, 1.5, "Windage") - elif distance >= 500: - self.custom_assert_equal(windage, data.windage >> Distance.Inch, 1, "Windage") - else: - self.custom_assert_equal(windage, data.windage >> Distance.Inch, 0.5, "Windage") - - if distance > 1: - self.custom_assert_equal(wind_adjustment, - data.windage_adj >> adjustment_unit, 0.5, "WAdj") - - def test_path_g1(self): - dm = DragModel(0.223, TableG1, 168, 0.308, 1.282) - ammo = Ammo(dm, Velocity(2750, Velocity.FPS)) - weapon = Weapon(Distance(2, Distance.Inch), zero_elevation=Angular(0.001228, Angular.Radian)) - atmosphere = Atmo.icao() - shot_info = Shot(weapon=weapon, ammo=ammo, atmo=atmosphere, - winds=[Wind(Velocity(5, Velocity.MPH), Angular(10.5, Angular.OClock))]) - - calc = EulerCalculator() - data = calc.fire(shot_info, Distance.Yard(1000), Distance.Yard(100)).trajectory - self.assertEqual(len(data), 11, "Trajectory Row Count") - - # Dist(yd), vel(fps), Mach, energy(ft-lb), drop(in), drop(mil), wind(in), wind(mil), time, ogw - test_data = [ - [data[0], 0, 2750, 2.463, 2820.6, -2, 0, 0, 0, 0, 880, Angular.MOA], - [data[1], 100, 2351.2, 2.106, 2061, 0, 0, -0.6, -0.6, 0.118, 550, Angular.MOA], - [data[5], 500, 1169.1, 1.047, 509.8, -87.9, -16.8, -19.5, -3.7, 0.857, 67, Angular.MOA], - [data[10], 1000, 776.4, 0.695, 224.9, -823.9, -78.7, -87.5, -8.4, 2.495, 20, Angular.MOA] - ] - - failures = [] - - for i, d in enumerate(test_data): - try: - with self.subTest(f"validate one {i}"): - self.validate_one(*d) - except AssertionError as e: - failures.append(f"Subtest {i} failed: {str(e)}") - - if failures: - self.fail("\n".join(failures)) # Raise a single failure with all messages - - def test_path_g7(self): - dm = DragModel(0.223, TableG7, 168, 0.308, 1.282) - ammo = Ammo(dm, Velocity(2750, Velocity.FPS)) - weapon = Weapon(2, 12, zero_elevation=Angular.MOA(4.221)) - shot_info = Shot(weapon=weapon, ammo=ammo, winds=[Wind(Velocity(5, Velocity.MPH), Angular.Degree(-45))]) - - calc = EulerCalculator() - data = calc.fire(shot_info, Distance.Yard(1000), Distance.Yard(100)).trajectory - self.assertEqual(len(data), 11, "Trajectory Row Count") - - # Dist(yd), vel(fps), Mach, energy(ft-lb), drop(in), drop(mil), wind(in), wind(mil), time, ogw - test_data = [ - [data[0], 0, 2750, 2.46, 2821, -2.0, 0.0, 0.0, 0.00, 0.000, 880, Angular.Mil], - [data[1], 100, 2545, 2.28, 2416, 0.0, 0.0, -0.2, -0.06, 0.113, 698, Angular.Mil], - [data[5], 500, 1814, 1.62, 1227, -56.2, -3.2, -6.3, -0.36, 0.672, 252, Angular.Mil], - [data[10], 1000, 1086, 0.97, 440, -399.9, -11.3, -31.6, -0.90, 1.748, 54, Angular.Mil] - ] - - failures = [] - - for i, d in enumerate(test_data): - try: - with self.subTest(f"validate one {i}"): - self.validate_one(*d) - except AssertionError as e: - failures.append(f"Subtest {i} failed: {str(e)}") - - if failures: - self.fail("\n".join(failures)) # Raise a single failure with all messages - - -if __name__ == '__main__': - unittest.main() diff --git a/uv.lock b/uv.lock index 0f48c35..3d91f04 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 1 requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.12'", @@ -14,27 +14,27 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/c2/9b2de9ed027f9fe5734a6c0c0a601289d796b3caaf1e372e23fa88a73047/astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce", size = 398941, upload-time = "2025-05-10T13:33:10.405Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/c2/9b2de9ed027f9fe5734a6c0c0a601289d796b3caaf1e372e23fa88a73047/astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce", size = 398941 } wheels = [ - { url = "https://files.pythonhosted.org/packages/15/58/5260205b9968c20b6457ed82f48f9e3d6edf2f1f95103161798b73aeccf0/astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", size = 275388, upload-time = "2025-05-10T13:33:08.391Z" }, + { url = "https://files.pythonhosted.org/packages/15/58/5260205b9968c20b6457ed82f48f9e3d6edf2f1f95103161798b73aeccf0/astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", size = 275388 }, ] [[package]] name = "bashlex" version = "0.18" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/76/60/aae0bb54f9af5e0128ba90eb83d8d0d506ee8f0475c4fdda3deeda20b1d2/bashlex-0.18.tar.gz", hash = "sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee", size = 68742, upload-time = "2023-01-18T15:21:26.402Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/60/aae0bb54f9af5e0128ba90eb83d8d0d506ee8f0475c4fdda3deeda20b1d2/bashlex-0.18.tar.gz", hash = "sha256:5bb03a01c6d5676338c36fd1028009c8ad07e7d61d8a1ce3f513b7fff52796ee", size = 68742 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539, upload-time = "2023-01-18T15:21:24.167Z" }, + { url = "https://files.pythonhosted.org/packages/f4/be/6985abb1011fda8a523cfe21ed9629e397d6e06fb5bae99750402b25c95b/bashlex-0.18-py2.py3-none-any.whl", hash = "sha256:91d73a23a3e51711919c1c899083890cdecffc91d8c088942725ac13e9dcfffa", size = 69539 }, ] [[package]] name = "bracex" version = "2.5.post1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641, upload-time = "2024-09-28T21:41:22.017Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/6c/57418c4404cd22fe6275b8301ca2b46a8cdaa8157938017a9ae0b3edf363/bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6", size = 26641 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558, upload-time = "2024-09-28T21:41:21.016Z" }, + { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558 }, ] [[package]] @@ -48,18 +48,18 @@ dependencies = [ { name = "pyproject-hooks" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701, upload-time = "2024-10-06T17:22:25.251Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950, upload-time = "2024-10-06T17:22:23.299Z" }, + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950 }, ] [[package]] name = "certifi" version = "2025.4.26" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618 }, ] [[package]] @@ -77,18 +77,18 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/f5/2c06c8229e291e121cb26ed2efa1ba5d89053a93631d8f1d795f2dacabb8/cibuildwheel-2.23.3.tar.gz", hash = "sha256:d85dd15b7eb81711900d8129e67efb32b12f99cc00fc271ab060fa6270c38397", size = 295383, upload-time = "2025-04-26T10:41:28.258Z" } +sdist = { url = "https://files.pythonhosted.org/packages/50/f5/2c06c8229e291e121cb26ed2efa1ba5d89053a93631d8f1d795f2dacabb8/cibuildwheel-2.23.3.tar.gz", hash = "sha256:d85dd15b7eb81711900d8129e67efb32b12f99cc00fc271ab060fa6270c38397", size = 295383 } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/8e/127e75e087c0a55903deb447a938e97935c6a56bfd20e6070bcc26c06d1b/cibuildwheel-2.23.3-py3-none-any.whl", hash = "sha256:0fa40073ae23a56d5f995d8405e82c1206049999bb89b92aa0835ee62ab8a891", size = 91792, upload-time = "2025-04-26T10:41:26.148Z" }, + { url = "https://files.pythonhosted.org/packages/17/8e/127e75e087c0a55903deb447a938e97935c6a56bfd20e6070bcc26c06d1b/cibuildwheel-2.23.3-py3-none-any.whl", hash = "sha256:0fa40073ae23a56d5f995d8405e82c1206049999bb89b92aa0835ee62ab8a891", size = 91792 }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] [[package]] @@ -116,7 +116,7 @@ requires-dist = [ { name = "cibuildwheel", marker = "extra == 'dev'" }, { name = "cython", marker = "extra == 'dev'" }, { name = "mypy", marker = "extra == 'dev'" }, - { name = "py-ballisticcalc", specifier = "==2.1.0b6" }, + { name = "py-ballisticcalc", specifier = "==2.1.1b1" }, { name = "pylint", marker = "extra == 'dev'" }, { name = "pytest", marker = "extra == 'dev'" }, { name = "setuptools", marker = "extra == 'dev'" }, @@ -127,59 +127,59 @@ provides-extras = ["dev"] name = "cython" version = "3.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/d3/bb000603e46144db2e5055219bbddcf7ab3b10012fcb342695694fb88141/cython-3.1.1.tar.gz", hash = "sha256:505ccd413669d5132a53834d792c707974248088c4f60c497deb1b416e366397", size = 3175446, upload-time = "2025-05-19T09:44:54.347Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/d3/bb000603e46144db2e5055219bbddcf7ab3b10012fcb342695694fb88141/cython-3.1.1.tar.gz", hash = "sha256:505ccd413669d5132a53834d792c707974248088c4f60c497deb1b416e366397", size = 3175446 } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/81/67060b1f3ef43faf039eb1badd27bd3e9c00ec8ff53db35b95760083ea45/cython-3.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7adff5b42d2556d073e9f321c2faa639a17fb195ec1de130327f60ec209d8", size = 2964150, upload-time = "2025-05-19T09:56:25.366Z" }, - { url = "https://files.pythonhosted.org/packages/ec/cf/d1bbc3330469d57f2ba4d6d3a0a5a83c503fea6c4a7fc24e1f706d60788e/cython-3.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b61b99205308c96b1162de59bd67ecadcad3d166a4a1f03a3d9e826c39cd375", size = 2827545, upload-time = "2025-05-19T09:56:29.025Z" }, - { url = "https://files.pythonhosted.org/packages/86/9c/e9af4ee8559331e27e5b9b2f0c21c71fde0b8f8ec1425f826647e432cacc/cython-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14186bd96783d13b8fd0e5b289f2e137a8a25479638b73a1c7e4a99a8d70753", size = 3203093, upload-time = "2025-05-19T09:56:31.175Z" }, - { url = "https://files.pythonhosted.org/packages/6c/3c/322a76b8ca53e23fb016626170e2e10de7791e50736ee3da50cc57eeae65/cython-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3ccec55e2a534a712db14c6617b66f65ad149c014fad518fc3920f6edde770", size = 3324310, upload-time = "2025-05-19T09:56:34.638Z" }, - { url = "https://files.pythonhosted.org/packages/cc/60/335115586fb78ef5dd12151b6e09c9d30bc4353fc08539acdbbf2fd009c5/cython-3.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a585796939b09b3205b1980e4a55e745c0251e45a5c637afbcac3c6cc9ad6f90", size = 3385463, upload-time = "2025-05-19T09:56:36.99Z" }, - { url = "https://files.pythonhosted.org/packages/7d/20/c79d2a7970208f9624029a4fb1504e827c0c575e222729a4fb7dd736f517/cython-3.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3fa4bd840de63509c74867b4b092541720a01db1e07351206011c34e0777dc96", size = 3249043, upload-time = "2025-05-19T09:56:39.091Z" }, - { url = "https://files.pythonhosted.org/packages/23/1a/5b361d93c1f55fbe29be15375127dc0f64195fb9d7d9e3b4a4137fbe34b2/cython-3.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b68f1bc80387554eb43f2b62795c173bed9e37201f39dc5084ac437c90a79c9f", size = 3472158, upload-time = "2025-05-19T09:56:41.276Z" }, - { url = "https://files.pythonhosted.org/packages/37/80/66831d7eec4becda833d3bd0199e2de8f47881f045bf450763b4bbedfcc6/cython-3.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e851ab66a31794e40df1bc6f649cdc56c998c637f5a1b9410c97a90f6b6cb855", size = 3405190, upload-time = "2025-05-19T09:56:44.735Z" }, - { url = "https://files.pythonhosted.org/packages/62/72/55e71a5a03b73951f260b61ea272c4b7787a41871d7cd6ff77db16351681/cython-3.1.1-cp310-cp310-win32.whl", hash = "sha256:64915259276482fa23417b284d1fdc7e3a618ee2f819bb6ea7f974c075633df6", size = 2451446, upload-time = "2025-05-19T09:56:46.757Z" }, - { url = "https://files.pythonhosted.org/packages/f0/96/449d384dfe2523476a30bc45da041b5de15a3824530ae64a631efaed81a9/cython-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dee554f0a589377bdaea0eb70e212bf3f35dc6a51a2aa86c9351345e21fd2f07", size = 2650269, upload-time = "2025-05-19T09:56:49.046Z" }, - { url = "https://files.pythonhosted.org/packages/35/b3/bc75c0352214b5ced31ce5e0d051d0ad4ad916aa7a1d669d1876ad1e59aa/cython-3.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c360823e1063784efc2335617e0f28573d7a594c5a8a05d85e850a9621cccb1f", size = 2998590, upload-time = "2025-05-19T09:56:51.148Z" }, - { url = "https://files.pythonhosted.org/packages/bf/0a/5840cdd7a1e8c0d2ffeb5e09afd32b8d10321cce33a2554ef10ea832a200/cython-3.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12e00b88147b03c148a95365f89dc1c45a0fc52f9c35aa75ff770ef65b615839", size = 2860818, upload-time = "2025-05-19T09:56:53.694Z" }, - { url = "https://files.pythonhosted.org/packages/63/2e/0fac02ce46f208af54d76c6c786b8dddeb207ca94aa85b0455f6cbaa472c/cython-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab644415458d782c16ba7252de9cec1e3125371641cafea2e53a8c1cf85dd58d", size = 3124262, upload-time = "2025-05-19T09:56:56.277Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/b7ae247b83b3f98966184c1a787001964132ae2e05a989769b1a5e7325da/cython-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5cb6c054daadaf01a88c8f49f3edd9e829c9b76a82cbb4269e3f9878254540b", size = 3215216, upload-time = "2025-05-19T09:56:58.674Z" }, - { url = "https://files.pythonhosted.org/packages/b5/3b/c4e6c16b099a592dbd6cd615c4de901eb8cc2795d5445d77b8cd378de7da/cython-3.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af8f62cc9339b75fe8434325083e6a7cae88c9c21efd74bbb6ba4e3623219469", size = 3282597, upload-time = "2025-05-19T09:57:00.85Z" }, - { url = "https://files.pythonhosted.org/packages/06/dd/90a8fd8508298f1f16e2cbc665774047fbc81f0370125b6e32f0a182fc10/cython-3.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:689c1aad373556bd2ab1aa1c2dad8939a2891465a1fbd2cbbdd42b488fb40ec8", size = 3175592, upload-time = "2025-05-19T09:57:03.1Z" }, - { url = "https://files.pythonhosted.org/packages/af/ab/2cd4e8d5c46499ea2ca5b7c3ae4053db86465b35a8870ce5e847fee06aff/cython-3.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:953046c190fa9ab9a09a546a909b847cdbb4c1fe34e9bfa4a15b6ee1585a86aa", size = 3378435, upload-time = "2025-05-19T09:57:05.535Z" }, - { url = "https://files.pythonhosted.org/packages/b2/99/250fb399af2edd9861774f0c8b6c4b7d862aa52d966a07b860bcd723842a/cython-3.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:755a991601b27dd3555310d0f95b19a05e622a80d7b4e7a91fa6f5f3ef3f3b80", size = 3300519, upload-time = "2025-05-19T09:57:07.512Z" }, - { url = "https://files.pythonhosted.org/packages/37/09/1c5d470580d9b92107cadedc848f43e2f2102284f8b666ea9ab82f6fc101/cython-3.1.1-cp311-cp311-win32.whl", hash = "sha256:83b2af5c327f7da4f08afc34fddfaf6d24fa0c000b6b70a527c8125e493b6080", size = 2447287, upload-time = "2025-05-19T09:57:09.958Z" }, - { url = "https://files.pythonhosted.org/packages/30/67/c99ec81380cd9d2c798eb1572f61dbe50318958925049b39029f73fe6b52/cython-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:141ffd6279411c562f6b707adc56b63e965a4fd7f21db83f5d4fcbd8c50ac546", size = 2655739, upload-time = "2025-05-19T09:57:11.938Z" }, - { url = "https://files.pythonhosted.org/packages/78/06/83ff82381319ff68ae46f9dd3024b1d5101997e81a8e955811525b6f934b/cython-3.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9d7dc0e4d0cd491fac679a61e9ede348c64ca449f99a284f9a01851aa1dbc7f6", size = 3006334, upload-time = "2025-05-19T09:57:14.284Z" }, - { url = "https://files.pythonhosted.org/packages/c3/01/b4c46c6a27cd2da642bc987c1f9087265defbc96a1929d326b9034953f15/cython-3.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd689910002adfac8734f237cdea1573e38345f27ed7fd445482813b65a29457", size = 2836861, upload-time = "2025-05-19T09:57:16.129Z" }, - { url = "https://files.pythonhosted.org/packages/96/51/7936c5d01ec3c89be8de1756f284878d4a567627b7b1790455ac627fb833/cython-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f0434916994fe213ea7749268b88d77e3ebcbd1b99542cf64bb7d180f45470", size = 3074560, upload-time = "2025-05-19T09:57:18.797Z" }, - { url = "https://files.pythonhosted.org/packages/0d/81/34aeb787dcb2624a82a33e60276ed28d2da8a08c79660cf674b19be82248/cython-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:873aac4ac0b0fb197557c0ac15458b780b9221daa4a716881cbd1a9016c8459f", size = 3192645, upload-time = "2025-05-19T09:57:21.002Z" }, - { url = "https://files.pythonhosted.org/packages/e8/bf/1350ed6cb48158a4f096306a12bc4c26c6d20d3314f1f1978ea23afe0220/cython-3.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23b886a6c8a50b1101ccef2f2f3dc9c699b77633ef5bb5007090226c2ad3f9c2", size = 3241751, upload-time = "2025-05-19T09:57:23.118Z" }, - { url = "https://files.pythonhosted.org/packages/1e/f5/9ed5a898c41723e3da2317fd1f082d963ff08571caeded31cb945be589b5/cython-3.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dff0e7dd53a0ca35b64cda843253d5cac944db26663dc097b3a1adf2c49514ad", size = 3123562, upload-time = "2025-05-19T09:57:25.492Z" }, - { url = "https://files.pythonhosted.org/packages/c3/81/b5ce4393d3a0a75a8c6d9ad0b80a62263d892260b816eb3d569ef144511a/cython-3.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f7954b0b4b3302655d3caa6924261de5907a4e129bc22ace52fe9ae0cd5a758", size = 3333555, upload-time = "2025-05-19T09:57:29.232Z" }, - { url = "https://files.pythonhosted.org/packages/db/47/2c1fa4b4901f10d00e666931dd68d4bd7954d3caa900544d135424ef6178/cython-3.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dfa500fd7ae95ca152a5f8062b870532fa3e27efcef6d00612e1f28b9f72615f", size = 3282112, upload-time = "2025-05-19T09:57:31.904Z" }, - { url = "https://files.pythonhosted.org/packages/ed/5b/b000d3ebff79429419d846e06c5c09f33fd010e1f6158d7ba553e1082253/cython-3.1.1-cp312-cp312-win32.whl", hash = "sha256:cd748fab8e4426dbcb2e0fa2979558333934d24365e0de5672fbabfe337d880c", size = 2462293, upload-time = "2025-05-19T09:57:34.964Z" }, - { url = "https://files.pythonhosted.org/packages/45/0e/e1370ed3216e4e164232d1891c2a2932a3874d1a8681f8c3565cafd98579/cython-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:307f216ed319ea07644f2ef9974406c830f01bc8e677e2147e9bfcdf9e3ca8ad", size = 2666710, upload-time = "2025-05-19T09:57:37.528Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ec/7bc61e156f71cefdc1c7c2a9b8d25facdf6d208f9e19a80aa4ae56a9842e/cython-3.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb5661941707bd41ec7a9c273d698113ac50392444f785088e9d9706c6a5937b", size = 2990324, upload-time = "2025-05-19T09:57:39.962Z" }, - { url = "https://files.pythonhosted.org/packages/1a/86/2f2550dcda3b54c65c9132ec95470cc4115b96a78163e539e0a02f767f05/cython-3.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:28b174f41718a7041cfbe0f48913020875ff1aaa4793942b2451ac6d2baf3f07", size = 2822556, upload-time = "2025-05-19T09:57:41.989Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f8/b7a14323ee8474be00909469dd115e84d28719aaf94a55623fd6366dcab5/cython-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c740a10cd0f50321d048c8ca318eefb4c42b8bffef982dcd89c946d374192702", size = 3060223, upload-time = "2025-05-19T09:57:46.439Z" }, - { url = "https://files.pythonhosted.org/packages/ca/90/9fe8b93fa239b4871252274892c232415f53d5af0859c4a6ac9b1cbf9950/cython-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7da069ca769903c5dee56c5f7ab47b2b7b91030eee48912630db5f4f3ec5954a", size = 3180196, upload-time = "2025-05-19T09:57:48.619Z" }, - { url = "https://files.pythonhosted.org/packages/01/95/8fe6282a846f8ce56bb62434b48053910c68c94ec5da3bd47bc2de0bb5e2/cython-3.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24c640c0746d984789fe2787a098f06cda456ef2dd78b90164d17884b350839a", size = 3208726, upload-time = "2025-05-19T09:57:51.258Z" }, - { url = "https://files.pythonhosted.org/packages/be/28/7db9e79a5099659f6e46c48577f582e6b542873159c3f65033a247e364b5/cython-3.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:426d78565eb91d3366569b20e92b8f14bffef5f57b2acd05b60bbb9ce5c056a1", size = 3112452, upload-time = "2025-05-19T09:57:53.365Z" }, - { url = "https://files.pythonhosted.org/packages/44/68/de53aff8db5f05efd9fe7f1435aa6019573b94ae151ef82a66ca20b4ec57/cython-3.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b181158b5761bdaf40f6854f016ab7ddff64d3db4fca55cb3ca0f73813dd76d6", size = 3305698, upload-time = "2025-05-19T09:57:55.485Z" }, - { url = "https://files.pythonhosted.org/packages/52/e9/a54f53ba5feeb00e187e24ba6fc7b085075e8ac53ed22797ac9d77db7422/cython-3.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7489559e6c5ecbba49d535c2e03cf77c2594a3190b6aca7da5b508ba1664a89a", size = 3258348, upload-time = "2025-05-19T09:57:57.605Z" }, - { url = "https://files.pythonhosted.org/packages/0c/07/8c1a2ff59af7976ba16afe8cd54a070ce2986924cacecc7812236bf7f1c7/cython-3.1.1-cp313-cp313-win32.whl", hash = "sha256:263cb0e497910fb5e0a361ad1393b6d728b092178afecc56e8a786f3739960c3", size = 2457891, upload-time = "2025-05-19T09:57:59.675Z" }, - { url = "https://files.pythonhosted.org/packages/79/5e/c469f7b42e145a06af79a3f7b599454c028a823c6a83adc867ddfd02f941/cython-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:e000f0533eedf3d6dfbe30bb3c58a054c58f0a7778390342fa577a0dc47adab3", size = 2665693, upload-time = "2025-05-19T09:58:02.262Z" }, - { url = "https://files.pythonhosted.org/packages/66/06/d0177d096fa149e417510caf8c5e1c53554f168b918ddc52515d94c883dc/cython-3.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40f50b07c479eaf33981d81cad274c68cf9fb81dbe79cbf991f59491c88a4705", size = 2973317, upload-time = "2025-05-19T09:58:25.824Z" }, - { url = "https://files.pythonhosted.org/packages/0e/5a/cb75a1e67a0a5d3c54e91f714a15d4ff631439446b71820045f3a84901a1/cython-3.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a92f6bd395eadea6eed722a8188d3bdd49db1c9fa3c38710456d6148ab71bad7", size = 2835598, upload-time = "2025-05-19T09:58:28.115Z" }, - { url = "https://files.pythonhosted.org/packages/d3/d7/6c30ba90d8800df4bd15e5468f7c880b5a81343f11254300b5326d8d7ff3/cython-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:268420b92307ae6c5a16e3cf0e2ba1ae3c861650e992893922a0ce08db07cfdb", size = 3211884, upload-time = "2025-05-19T09:58:30.289Z" }, - { url = "https://files.pythonhosted.org/packages/66/5d/278c54e3d036305fac961d83ea1e9a675fb2a0c28aed2d908b637598daa6/cython-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a19188ecd385cdc649e3fec370f38d5fd7f1651aeed0b3fb403180f38fc88e8a", size = 3331865, upload-time = "2025-05-19T09:58:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/07/2f/8ecdd1bfaf302d73fc7058287599dc6c421dfd76c1022db43d4b96ff749f/cython-3.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fff6526bb6f4eea615663117b86de6ede0d17c477b600d3d8302be3502bd3c3", size = 3392535, upload-time = "2025-05-19T09:58:35.489Z" }, - { url = "https://files.pythonhosted.org/packages/de/8a/b7abf8b82c9706055ffeae23d23f959fb845fceb9b8543c107c496a8eb69/cython-3.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3192a61c2a532d3faccdff508bc8427de9530b587888218bfc0226eb33a84e11", size = 3254413, upload-time = "2025-05-19T09:58:37.604Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ec/33de7469fe1f8dff858c4867919985aa75bbfcb021938c445c286b006c49/cython-3.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:56c6768a6f601f93daab7c2487f9f110548a896a91e00a6e119445ada2575323", size = 3479692, upload-time = "2025-05-19T09:58:40.826Z" }, - { url = "https://files.pythonhosted.org/packages/2e/aa/2bc816b0293df1798ee449422b97a2b8f81c3b04260d65f6c856e69d8e74/cython-3.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:50ad80e2f438e9127a87c10927e6ac16a987df39c248b19ab2cd31330129be3c", size = 3408199, upload-time = "2025-05-19T09:58:43.166Z" }, - { url = "https://files.pythonhosted.org/packages/9c/4e/7eb59cd2e25477994c9beaa9f601c773208e28781016093388f8177f6489/cython-3.1.1-cp39-cp39-win32.whl", hash = "sha256:b194a65a0fd91f305d2d1e7010f44111774a28533e1e44dd2a76e7de81a219b9", size = 2456293, upload-time = "2025-05-19T09:58:45.178Z" }, - { url = "https://files.pythonhosted.org/packages/b4/ae/16ed166b8a9e5317e9a994138ed177ba52ee7588b2ae77e94f9c2f1b51eb/cython-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c8b8be01fd40b3e38a76c60a524f956548a3a7566e5530a833a48a695f3d6c12", size = 2655391, upload-time = "2025-05-19T09:58:47.511Z" }, - { url = "https://files.pythonhosted.org/packages/a7/97/8e8637e67afc09f1b51a617b15a0d1caf0b5159b0f79d47ab101e620e491/cython-3.1.1-py3-none-any.whl", hash = "sha256:07621e044f332d18139df2ccfcc930151fd323c2f61a58c82f304cffc9eb5280", size = 1220898, upload-time = "2025-05-19T09:44:50.614Z" }, + { url = "https://files.pythonhosted.org/packages/37/81/67060b1f3ef43faf039eb1badd27bd3e9c00ec8ff53db35b95760083ea45/cython-3.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7adff5b42d2556d073e9f321c2faa639a17fb195ec1de130327f60ec209d8", size = 2964150 }, + { url = "https://files.pythonhosted.org/packages/ec/cf/d1bbc3330469d57f2ba4d6d3a0a5a83c503fea6c4a7fc24e1f706d60788e/cython-3.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b61b99205308c96b1162de59bd67ecadcad3d166a4a1f03a3d9e826c39cd375", size = 2827545 }, + { url = "https://files.pythonhosted.org/packages/86/9c/e9af4ee8559331e27e5b9b2f0c21c71fde0b8f8ec1425f826647e432cacc/cython-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14186bd96783d13b8fd0e5b289f2e137a8a25479638b73a1c7e4a99a8d70753", size = 3203093 }, + { url = "https://files.pythonhosted.org/packages/6c/3c/322a76b8ca53e23fb016626170e2e10de7791e50736ee3da50cc57eeae65/cython-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3ccec55e2a534a712db14c6617b66f65ad149c014fad518fc3920f6edde770", size = 3324310 }, + { url = "https://files.pythonhosted.org/packages/cc/60/335115586fb78ef5dd12151b6e09c9d30bc4353fc08539acdbbf2fd009c5/cython-3.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a585796939b09b3205b1980e4a55e745c0251e45a5c637afbcac3c6cc9ad6f90", size = 3385463 }, + { url = "https://files.pythonhosted.org/packages/7d/20/c79d2a7970208f9624029a4fb1504e827c0c575e222729a4fb7dd736f517/cython-3.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3fa4bd840de63509c74867b4b092541720a01db1e07351206011c34e0777dc96", size = 3249043 }, + { url = "https://files.pythonhosted.org/packages/23/1a/5b361d93c1f55fbe29be15375127dc0f64195fb9d7d9e3b4a4137fbe34b2/cython-3.1.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b68f1bc80387554eb43f2b62795c173bed9e37201f39dc5084ac437c90a79c9f", size = 3472158 }, + { url = "https://files.pythonhosted.org/packages/37/80/66831d7eec4becda833d3bd0199e2de8f47881f045bf450763b4bbedfcc6/cython-3.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e851ab66a31794e40df1bc6f649cdc56c998c637f5a1b9410c97a90f6b6cb855", size = 3405190 }, + { url = "https://files.pythonhosted.org/packages/62/72/55e71a5a03b73951f260b61ea272c4b7787a41871d7cd6ff77db16351681/cython-3.1.1-cp310-cp310-win32.whl", hash = "sha256:64915259276482fa23417b284d1fdc7e3a618ee2f819bb6ea7f974c075633df6", size = 2451446 }, + { url = "https://files.pythonhosted.org/packages/f0/96/449d384dfe2523476a30bc45da041b5de15a3824530ae64a631efaed81a9/cython-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dee554f0a589377bdaea0eb70e212bf3f35dc6a51a2aa86c9351345e21fd2f07", size = 2650269 }, + { url = "https://files.pythonhosted.org/packages/35/b3/bc75c0352214b5ced31ce5e0d051d0ad4ad916aa7a1d669d1876ad1e59aa/cython-3.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c360823e1063784efc2335617e0f28573d7a594c5a8a05d85e850a9621cccb1f", size = 2998590 }, + { url = "https://files.pythonhosted.org/packages/bf/0a/5840cdd7a1e8c0d2ffeb5e09afd32b8d10321cce33a2554ef10ea832a200/cython-3.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:12e00b88147b03c148a95365f89dc1c45a0fc52f9c35aa75ff770ef65b615839", size = 2860818 }, + { url = "https://files.pythonhosted.org/packages/63/2e/0fac02ce46f208af54d76c6c786b8dddeb207ca94aa85b0455f6cbaa472c/cython-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab644415458d782c16ba7252de9cec1e3125371641cafea2e53a8c1cf85dd58d", size = 3124262 }, + { url = "https://files.pythonhosted.org/packages/23/04/b7ae247b83b3f98966184c1a787001964132ae2e05a989769b1a5e7325da/cython-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5cb6c054daadaf01a88c8f49f3edd9e829c9b76a82cbb4269e3f9878254540b", size = 3215216 }, + { url = "https://files.pythonhosted.org/packages/b5/3b/c4e6c16b099a592dbd6cd615c4de901eb8cc2795d5445d77b8cd378de7da/cython-3.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af8f62cc9339b75fe8434325083e6a7cae88c9c21efd74bbb6ba4e3623219469", size = 3282597 }, + { url = "https://files.pythonhosted.org/packages/06/dd/90a8fd8508298f1f16e2cbc665774047fbc81f0370125b6e32f0a182fc10/cython-3.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:689c1aad373556bd2ab1aa1c2dad8939a2891465a1fbd2cbbdd42b488fb40ec8", size = 3175592 }, + { url = "https://files.pythonhosted.org/packages/af/ab/2cd4e8d5c46499ea2ca5b7c3ae4053db86465b35a8870ce5e847fee06aff/cython-3.1.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:953046c190fa9ab9a09a546a909b847cdbb4c1fe34e9bfa4a15b6ee1585a86aa", size = 3378435 }, + { url = "https://files.pythonhosted.org/packages/b2/99/250fb399af2edd9861774f0c8b6c4b7d862aa52d966a07b860bcd723842a/cython-3.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:755a991601b27dd3555310d0f95b19a05e622a80d7b4e7a91fa6f5f3ef3f3b80", size = 3300519 }, + { url = "https://files.pythonhosted.org/packages/37/09/1c5d470580d9b92107cadedc848f43e2f2102284f8b666ea9ab82f6fc101/cython-3.1.1-cp311-cp311-win32.whl", hash = "sha256:83b2af5c327f7da4f08afc34fddfaf6d24fa0c000b6b70a527c8125e493b6080", size = 2447287 }, + { url = "https://files.pythonhosted.org/packages/30/67/c99ec81380cd9d2c798eb1572f61dbe50318958925049b39029f73fe6b52/cython-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:141ffd6279411c562f6b707adc56b63e965a4fd7f21db83f5d4fcbd8c50ac546", size = 2655739 }, + { url = "https://files.pythonhosted.org/packages/78/06/83ff82381319ff68ae46f9dd3024b1d5101997e81a8e955811525b6f934b/cython-3.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9d7dc0e4d0cd491fac679a61e9ede348c64ca449f99a284f9a01851aa1dbc7f6", size = 3006334 }, + { url = "https://files.pythonhosted.org/packages/c3/01/b4c46c6a27cd2da642bc987c1f9087265defbc96a1929d326b9034953f15/cython-3.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd689910002adfac8734f237cdea1573e38345f27ed7fd445482813b65a29457", size = 2836861 }, + { url = "https://files.pythonhosted.org/packages/96/51/7936c5d01ec3c89be8de1756f284878d4a567627b7b1790455ac627fb833/cython-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10f0434916994fe213ea7749268b88d77e3ebcbd1b99542cf64bb7d180f45470", size = 3074560 }, + { url = "https://files.pythonhosted.org/packages/0d/81/34aeb787dcb2624a82a33e60276ed28d2da8a08c79660cf674b19be82248/cython-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:873aac4ac0b0fb197557c0ac15458b780b9221daa4a716881cbd1a9016c8459f", size = 3192645 }, + { url = "https://files.pythonhosted.org/packages/e8/bf/1350ed6cb48158a4f096306a12bc4c26c6d20d3314f1f1978ea23afe0220/cython-3.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:23b886a6c8a50b1101ccef2f2f3dc9c699b77633ef5bb5007090226c2ad3f9c2", size = 3241751 }, + { url = "https://files.pythonhosted.org/packages/1e/f5/9ed5a898c41723e3da2317fd1f082d963ff08571caeded31cb945be589b5/cython-3.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:dff0e7dd53a0ca35b64cda843253d5cac944db26663dc097b3a1adf2c49514ad", size = 3123562 }, + { url = "https://files.pythonhosted.org/packages/c3/81/b5ce4393d3a0a75a8c6d9ad0b80a62263d892260b816eb3d569ef144511a/cython-3.1.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f7954b0b4b3302655d3caa6924261de5907a4e129bc22ace52fe9ae0cd5a758", size = 3333555 }, + { url = "https://files.pythonhosted.org/packages/db/47/2c1fa4b4901f10d00e666931dd68d4bd7954d3caa900544d135424ef6178/cython-3.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dfa500fd7ae95ca152a5f8062b870532fa3e27efcef6d00612e1f28b9f72615f", size = 3282112 }, + { url = "https://files.pythonhosted.org/packages/ed/5b/b000d3ebff79429419d846e06c5c09f33fd010e1f6158d7ba553e1082253/cython-3.1.1-cp312-cp312-win32.whl", hash = "sha256:cd748fab8e4426dbcb2e0fa2979558333934d24365e0de5672fbabfe337d880c", size = 2462293 }, + { url = "https://files.pythonhosted.org/packages/45/0e/e1370ed3216e4e164232d1891c2a2932a3874d1a8681f8c3565cafd98579/cython-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:307f216ed319ea07644f2ef9974406c830f01bc8e677e2147e9bfcdf9e3ca8ad", size = 2666710 }, + { url = "https://files.pythonhosted.org/packages/2c/ec/7bc61e156f71cefdc1c7c2a9b8d25facdf6d208f9e19a80aa4ae56a9842e/cython-3.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:cb5661941707bd41ec7a9c273d698113ac50392444f785088e9d9706c6a5937b", size = 2990324 }, + { url = "https://files.pythonhosted.org/packages/1a/86/2f2550dcda3b54c65c9132ec95470cc4115b96a78163e539e0a02f767f05/cython-3.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:28b174f41718a7041cfbe0f48913020875ff1aaa4793942b2451ac6d2baf3f07", size = 2822556 }, + { url = "https://files.pythonhosted.org/packages/9d/f8/b7a14323ee8474be00909469dd115e84d28719aaf94a55623fd6366dcab5/cython-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c740a10cd0f50321d048c8ca318eefb4c42b8bffef982dcd89c946d374192702", size = 3060223 }, + { url = "https://files.pythonhosted.org/packages/ca/90/9fe8b93fa239b4871252274892c232415f53d5af0859c4a6ac9b1cbf9950/cython-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7da069ca769903c5dee56c5f7ab47b2b7b91030eee48912630db5f4f3ec5954a", size = 3180196 }, + { url = "https://files.pythonhosted.org/packages/01/95/8fe6282a846f8ce56bb62434b48053910c68c94ec5da3bd47bc2de0bb5e2/cython-3.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24c640c0746d984789fe2787a098f06cda456ef2dd78b90164d17884b350839a", size = 3208726 }, + { url = "https://files.pythonhosted.org/packages/be/28/7db9e79a5099659f6e46c48577f582e6b542873159c3f65033a247e364b5/cython-3.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:426d78565eb91d3366569b20e92b8f14bffef5f57b2acd05b60bbb9ce5c056a1", size = 3112452 }, + { url = "https://files.pythonhosted.org/packages/44/68/de53aff8db5f05efd9fe7f1435aa6019573b94ae151ef82a66ca20b4ec57/cython-3.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b181158b5761bdaf40f6854f016ab7ddff64d3db4fca55cb3ca0f73813dd76d6", size = 3305698 }, + { url = "https://files.pythonhosted.org/packages/52/e9/a54f53ba5feeb00e187e24ba6fc7b085075e8ac53ed22797ac9d77db7422/cython-3.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7489559e6c5ecbba49d535c2e03cf77c2594a3190b6aca7da5b508ba1664a89a", size = 3258348 }, + { url = "https://files.pythonhosted.org/packages/0c/07/8c1a2ff59af7976ba16afe8cd54a070ce2986924cacecc7812236bf7f1c7/cython-3.1.1-cp313-cp313-win32.whl", hash = "sha256:263cb0e497910fb5e0a361ad1393b6d728b092178afecc56e8a786f3739960c3", size = 2457891 }, + { url = "https://files.pythonhosted.org/packages/79/5e/c469f7b42e145a06af79a3f7b599454c028a823c6a83adc867ddfd02f941/cython-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:e000f0533eedf3d6dfbe30bb3c58a054c58f0a7778390342fa577a0dc47adab3", size = 2665693 }, + { url = "https://files.pythonhosted.org/packages/66/06/d0177d096fa149e417510caf8c5e1c53554f168b918ddc52515d94c883dc/cython-3.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:40f50b07c479eaf33981d81cad274c68cf9fb81dbe79cbf991f59491c88a4705", size = 2973317 }, + { url = "https://files.pythonhosted.org/packages/0e/5a/cb75a1e67a0a5d3c54e91f714a15d4ff631439446b71820045f3a84901a1/cython-3.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a92f6bd395eadea6eed722a8188d3bdd49db1c9fa3c38710456d6148ab71bad7", size = 2835598 }, + { url = "https://files.pythonhosted.org/packages/d3/d7/6c30ba90d8800df4bd15e5468f7c880b5a81343f11254300b5326d8d7ff3/cython-3.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:268420b92307ae6c5a16e3cf0e2ba1ae3c861650e992893922a0ce08db07cfdb", size = 3211884 }, + { url = "https://files.pythonhosted.org/packages/66/5d/278c54e3d036305fac961d83ea1e9a675fb2a0c28aed2d908b637598daa6/cython-3.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a19188ecd385cdc649e3fec370f38d5fd7f1651aeed0b3fb403180f38fc88e8a", size = 3331865 }, + { url = "https://files.pythonhosted.org/packages/07/2f/8ecdd1bfaf302d73fc7058287599dc6c421dfd76c1022db43d4b96ff749f/cython-3.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fff6526bb6f4eea615663117b86de6ede0d17c477b600d3d8302be3502bd3c3", size = 3392535 }, + { url = "https://files.pythonhosted.org/packages/de/8a/b7abf8b82c9706055ffeae23d23f959fb845fceb9b8543c107c496a8eb69/cython-3.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3192a61c2a532d3faccdff508bc8427de9530b587888218bfc0226eb33a84e11", size = 3254413 }, + { url = "https://files.pythonhosted.org/packages/1c/ec/33de7469fe1f8dff858c4867919985aa75bbfcb021938c445c286b006c49/cython-3.1.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:56c6768a6f601f93daab7c2487f9f110548a896a91e00a6e119445ada2575323", size = 3479692 }, + { url = "https://files.pythonhosted.org/packages/2e/aa/2bc816b0293df1798ee449422b97a2b8f81c3b04260d65f6c856e69d8e74/cython-3.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:50ad80e2f438e9127a87c10927e6ac16a987df39c248b19ab2cd31330129be3c", size = 3408199 }, + { url = "https://files.pythonhosted.org/packages/9c/4e/7eb59cd2e25477994c9beaa9f601c773208e28781016093388f8177f6489/cython-3.1.1-cp39-cp39-win32.whl", hash = "sha256:b194a65a0fd91f305d2d1e7010f44111774a28533e1e44dd2a76e7de81a219b9", size = 2456293 }, + { url = "https://files.pythonhosted.org/packages/b4/ae/16ed166b8a9e5317e9a994138ed177ba52ee7588b2ae77e94f9c2f1b51eb/cython-3.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c8b8be01fd40b3e38a76c60a524f956548a3a7566e5530a833a48a695f3d6c12", size = 2655391 }, + { url = "https://files.pythonhosted.org/packages/a7/97/8e8637e67afc09f1b51a617b15a0d1caf0b5159b0f79d47ab101e620e491/cython-3.1.1-py3-none-any.whl", hash = "sha256:07621e044f332d18139df2ccfcc930151fd323c2f61a58c82f304cffc9eb5280", size = 1220898 }, ] [[package]] @@ -190,18 +190,18 @@ dependencies = [ { name = "packaging" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093, upload-time = "2025-05-02T00:34:29.452Z" } +sdist = { url = "https://files.pythonhosted.org/packages/62/55/f054de99871e7beb81935dea8a10b90cd5ce42122b1c3081d5282fdb3621/dependency_groups-1.3.1.tar.gz", hash = "sha256:78078301090517fd938c19f64a53ce98c32834dfe0dee6b88004a569a6adfefd", size = 10093 } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664, upload-time = "2025-05-02T00:34:27.085Z" }, + { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664 }, ] [[package]] name = "dill" version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976, upload-time = "2025-04-16T00:41:48.867Z" } +sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976 } wheels = [ - { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668, upload-time = "2025-04-16T00:41:47.671Z" }, + { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668 }, ] [[package]] @@ -211,18 +211,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674 }, ] [[package]] name = "filelock" version = "3.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, ] [[package]] @@ -230,38 +230,38 @@ name = "importlib-metadata" version = "8.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "zipp" }, + { name = "zipp", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" } +sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641 } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656, upload-time = "2025-04-27T15:29:00.214Z" }, + { url = "https://files.pythonhosted.org/packages/20/b0/36bd937216ec521246249be3bf9855081de4c5e06a0c9b4219dbeda50373/importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd", size = 27656 }, ] [[package]] name = "iniconfig" version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, ] [[package]] name = "isort" version = "6.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955, upload-time = "2025-02-26T21:13:16.955Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186, upload-time = "2025-02-26T21:13:14.911Z" }, + { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186 }, ] [[package]] name = "mccabe" version = "0.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, ] [[package]] @@ -274,97 +274,98 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139, upload-time = "2025-05-29T13:46:12.532Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139 } wheels = [ - { url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416, upload-time = "2025-05-29T13:34:17.783Z" }, - { url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654, upload-time = "2025-05-29T13:32:37.878Z" }, - { url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192, upload-time = "2025-05-29T13:34:54.281Z" }, - { url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939, upload-time = "2025-05-29T13:33:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719, upload-time = "2025-05-29T13:21:52.09Z" }, - { url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053, upload-time = "2025-05-29T13:33:29.797Z" }, - { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498, upload-time = "2025-05-29T13:18:54.066Z" }, - { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755, upload-time = "2025-05-29T13:34:00.851Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138, upload-time = "2025-05-29T13:32:55.082Z" }, - { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156, upload-time = "2025-05-29T13:19:12.963Z" }, - { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426, upload-time = "2025-05-29T13:20:22.72Z" }, - { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319, upload-time = "2025-05-29T13:21:17.582Z" }, - { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927, upload-time = "2025-05-29T13:35:52.328Z" }, - { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082, upload-time = "2025-05-29T13:35:33.378Z" }, - { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306, upload-time = "2025-05-29T13:21:02.164Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764, upload-time = "2025-05-29T13:20:42.826Z" }, - { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233, upload-time = "2025-05-29T13:18:37.446Z" }, - { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547, upload-time = "2025-05-29T13:20:02.836Z" }, - { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753, upload-time = "2025-05-29T13:18:18.167Z" }, - { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338, upload-time = "2025-05-29T13:19:48.079Z" }, - { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764, upload-time = "2025-05-29T13:46:04.47Z" }, - { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356, upload-time = "2025-05-29T13:35:13.553Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745, upload-time = "2025-05-29T13:17:24.409Z" }, - { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200, upload-time = "2025-05-29T13:33:44.92Z" }, - { url = "https://files.pythonhosted.org/packages/bd/eb/c0759617fe2159aee7a653f13cceafbf7f0b6323b4197403f2e587ca947d/mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3", size = 10956081, upload-time = "2025-05-29T13:19:32.264Z" }, - { url = "https://files.pythonhosted.org/packages/70/35/df3c74a2967bdf86edea58b265feeec181d693432faed1c3b688b7c231e3/mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92", size = 10084422, upload-time = "2025-05-29T13:18:01.437Z" }, - { url = "https://files.pythonhosted.org/packages/b3/07/145ffe29f4b577219943b7b1dc0a71df7ead3c5bed4898686bd87c5b5cc2/mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436", size = 11879670, upload-time = "2025-05-29T13:17:45.971Z" }, - { url = "https://files.pythonhosted.org/packages/c6/94/0421562d6b046e22986758c9ae31865d10ea0ba607ae99b32c9d18b16f66/mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2", size = 12610528, upload-time = "2025-05-29T13:34:36.983Z" }, - { url = "https://files.pythonhosted.org/packages/1a/f1/39a22985b78c766a594ae1e0bbb6f8bdf5f31ea8d0c52291a3c211fd3cd5/mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20", size = 12871923, upload-time = "2025-05-29T13:32:21.823Z" }, - { url = "https://files.pythonhosted.org/packages/f3/8e/84db4fb0d01f43d2c82fa9072ca72a42c49e52d58f44307bbd747c977bc2/mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21", size = 9482931, upload-time = "2025-05-29T13:21:32.326Z" }, - { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773, upload-time = "2025-05-29T13:35:18.762Z" }, + { url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416 }, + { url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654 }, + { url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192 }, + { url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939 }, + { url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719 }, + { url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053 }, + { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498 }, + { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755 }, + { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138 }, + { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156 }, + { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426 }, + { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319 }, + { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927 }, + { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082 }, + { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306 }, + { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764 }, + { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233 }, + { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547 }, + { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753 }, + { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338 }, + { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764 }, + { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356 }, + { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745 }, + { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200 }, + { url = "https://files.pythonhosted.org/packages/bd/eb/c0759617fe2159aee7a653f13cceafbf7f0b6323b4197403f2e587ca947d/mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3", size = 10956081 }, + { url = "https://files.pythonhosted.org/packages/70/35/df3c74a2967bdf86edea58b265feeec181d693432faed1c3b688b7c231e3/mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92", size = 10084422 }, + { url = "https://files.pythonhosted.org/packages/b3/07/145ffe29f4b577219943b7b1dc0a71df7ead3c5bed4898686bd87c5b5cc2/mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436", size = 11879670 }, + { url = "https://files.pythonhosted.org/packages/c6/94/0421562d6b046e22986758c9ae31865d10ea0ba607ae99b32c9d18b16f66/mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2", size = 12610528 }, + { url = "https://files.pythonhosted.org/packages/1a/f1/39a22985b78c766a594ae1e0bbb6f8bdf5f31ea8d0c52291a3c211fd3cd5/mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20", size = 12871923 }, + { url = "https://files.pythonhosted.org/packages/f3/8e/84db4fb0d01f43d2c82fa9072ca72a42c49e52d58f44307bbd747c977bc2/mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21", size = 9482931 }, + { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773 }, ] [[package]] name = "mypy-extensions" version = "1.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343 } wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 }, ] [[package]] name = "packaging" version = "25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, ] [[package]] name = "pathspec" version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, ] [[package]] name = "platformdirs" version = "4.3.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567 }, ] [[package]] name = "pluggy" version = "1.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 }, ] [[package]] name = "py-ballisticcalc" -version = "2.1.0b6" +version = "2.1.1b1" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "pytest" }, { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/07/52edb6f138f60a6fe29566d809a5e8886cabe3872909252f2a39d2dfc672/py_ballisticcalc-2.1.0b6.tar.gz", hash = "sha256:8e1c4844d84880da02b9c683df54595b86fd22982ff5030b8702103e1792a23e", size = 264475, upload-time = "2025-02-18T15:27:02.379Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/18/1f811017d43bf10ea446fb4563aa32b97e5e9f200a8c8b0e13fd5f023656/py_ballisticcalc-2.1.1b1.tar.gz", hash = "sha256:4b43cc6c80328e18e6b4ba7c267694114dd92f442606615e4185ed2794464a44", size = 261596 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ae/d2/aef4f6b01aba140dc7a4f7bdac79052e623136ff68f28414e7cc952a6d51/py_ballisticcalc-2.1.0b6-py3-none-any.whl", hash = "sha256:70f02f62e570836d23353b1d702324f3c8cbbb122515eaca5a620eb5e6ab24eb", size = 64783, upload-time = "2025-02-18T15:25:15.649Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ba/373ccd96ed4b900879c66e6cf62f98215af01dbb6a8680c8192e65195584/py_ballisticcalc-2.1.1b1-py3-none-any.whl", hash = "sha256:0dadf43ae2a422c7d8fd8dde0fc094ba0361df0d3dc157617f8be6f1cef09fd3", size = 68517 }, ] [[package]] @@ -382,18 +383,18 @@ dependencies = [ { name = "tomlkit" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1c/e4/83e487d3ddd64ab27749b66137b26dc0c5b5c161be680e6beffdc99070b3/pylint-3.3.7.tar.gz", hash = "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", size = 1520709, upload-time = "2025-05-04T17:07:51.089Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/e4/83e487d3ddd64ab27749b66137b26dc0c5b5c161be680e6beffdc99070b3/pylint-3.3.7.tar.gz", hash = "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", size = 1520709 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/83/bff755d09e31b5d25cc7fdc4bf3915d1a404e181f1abf0359af376845c24/pylint-3.3.7-py3-none-any.whl", hash = "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d", size = 522565, upload-time = "2025-05-04T17:07:48.714Z" }, + { url = "https://files.pythonhosted.org/packages/e8/83/bff755d09e31b5d25cc7fdc4bf3915d1a404e181f1abf0359af376845c24/pylint-3.3.7-py3-none-any.whl", hash = "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d", size = 522565 }, ] [[package]] name = "pyproject-hooks" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228, upload-time = "2024-09-29T09:24:13.293Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216, upload-time = "2024-09-29T09:24:11.978Z" }, + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216 }, ] [[package]] @@ -408,82 +409,82 @@ dependencies = [ { name = "pluggy" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, ] [[package]] name = "setuptools" version = "80.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486 }, ] [[package]] name = "tomli" version = "2.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, ] [[package]] name = "tomlkit" version = "0.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885, upload-time = "2024-08-14T08:19:41.488Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955, upload-time = "2024-08-14T08:19:40.05Z" }, + { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, ] [[package]] name = "typing-extensions" version = "4.13.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967 } wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806 }, ] [[package]] name = "zipp" version = "3.22.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257, upload-time = "2025-05-26T14:46:32.217Z" } +sdist = { url = "https://files.pythonhosted.org/packages/12/b6/7b3d16792fdf94f146bed92be90b4eb4563569eca91513c8609aebf0c167/zipp-3.22.0.tar.gz", hash = "sha256:dd2f28c3ce4bc67507bfd3781d21b7bb2be31103b51a4553ad7d90b84e57ace5", size = 25257 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796, upload-time = "2025-05-26T14:46:30.775Z" }, + { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796 }, ] From 3fede1ac843b61c32383687d7d58233aced5f5c3 Mon Sep 17 00:00:00 2001 From: o-murphy Date: Tue, 3 Jun 2025 23:29:03 +0300 Subject: [PATCH 11/18] trying new test ci --- .../package-test-cython-as-entry.yml | 71 ------------------- .github/workflows/package-test-cython.yml | 51 +++++++------ py-ballisticcalc | 1 - 3 files changed, 31 insertions(+), 92 deletions(-) delete mode 100644 .github/workflows/package-test-cython-as-entry.yml delete mode 160000 py-ballisticcalc diff --git a/.github/workflows/package-test-cython-as-entry.yml b/.github/workflows/package-test-cython-as-entry.yml deleted file mode 100644 index 0bd3f27..0000000 --- a/.github/workflows/package-test-cython-as-entry.yml +++ /dev/null @@ -1,71 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python - -name: Python cythonized package tests (uv) - -on: - pull_request: - branches: - - '*' - workflow_dispatch: - - -jobs: - test: - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, windows-latest, macos-13, macos-14 ] - python-version: ["3.9", "3.10", "3.11", "3.12"] - - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - - name: Install uv and set the python version ${{ matrix.python-version }} - uses: astral-sh/setup-uv@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - uv sync --dev - - - name: Build cython modules - run: | - uv pip install -e .[dev] - - - name: Get py-ballisticcalc installed version - id: get_installed_version # This ID allows referencing its output - run: | - # Run the Python command to get the version - # The output is captured and set as a step output named 'pybc_version' - # This syntax works universally with 'bash' shell on Linux and Windows - echo "pybc_version=$(python -c 'from importlib.metadata import metadata; print(metadata("py-ballisticcalc")["Version"])')" >> "$GITHUB_OUTPUT" - shell: bash # Explicitly use bash for cross-platform compatibility - - - name: Install from specific tag based on installed version - run: | - # Access the version obtained from the previous step's output - # The 'steps.get_installed_version.outputs.pybc_version' syntax is universal - PYBC_VERSION="${{ steps.get_installed_version.outputs.pybc_version }}" - echo "Cloning py-ballisticcalc with tag: $PYBC_VERSION" - - # Clone the specific tag (version) using the obtained version - git clone --branch "$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc - - # Change into the cloned directory - cd py-ballisticcalc - - # Install in editable mode with dev dependencies using uv - uv pip install -e .[dev] - - # Go back to the original directory and clean up - cd ../ - shell: bash # Ensure bash is used for the shell commands - - - name: Run pytest - run: | - pytest tests -v --engine CyEulerBallistic - shell: bash - if: runner.os != 'Windows' diff --git a/.github/workflows/package-test-cython.yml b/.github/workflows/package-test-cython.yml index 9cf2a42..0bd3f27 100644 --- a/.github/workflows/package-test-cython.yml +++ b/.github/workflows/package-test-cython.yml @@ -35,26 +35,37 @@ jobs: run: | uv pip install -e .[dev] - - name: Run unittest tests in binary mode + - name: Get py-ballisticcalc installed version + id: get_installed_version # This ID allows referencing its output run: | - uv run pytest tests --no-header --no-summary -v - if [ $? -ne 0 ]; then - echo "Pytest failed, running without capture" - uv run pytest tests -v - else - echo "Pytest succeeded." - fi - shell: bash - if: runner.os != 'Windows' + # Run the Python command to get the version + # The output is captured and set as a step output named 'pybc_version' + # This syntax works universally with 'bash' shell on Linux and Windows + echo "pybc_version=$(python -c 'from importlib.metadata import metadata; print(metadata("py-ballisticcalc")["Version"])')" >> "$GITHUB_OUTPUT" + shell: bash # Explicitly use bash for cross-platform compatibility - - name: Run unittest tests in binary mode on Windows + - name: Install from specific tag based on installed version run: | - uv run pytest tests --no-header --no-summary -v - if %ERRORLEVEL% neq 0 ( - echo Pytest failed, running without capture - uv run pytest tests -v - ) else ( - echo Pytest succeeded. - ) - shell: cmd - if: runner.os == 'Windows' + # Access the version obtained from the previous step's output + # The 'steps.get_installed_version.outputs.pybc_version' syntax is universal + PYBC_VERSION="${{ steps.get_installed_version.outputs.pybc_version }}" + echo "Cloning py-ballisticcalc with tag: $PYBC_VERSION" + + # Clone the specific tag (version) using the obtained version + git clone --branch "$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc + + # Change into the cloned directory + cd py-ballisticcalc + + # Install in editable mode with dev dependencies using uv + uv pip install -e .[dev] + + # Go back to the original directory and clean up + cd ../ + shell: bash # Ensure bash is used for the shell commands + + - name: Run pytest + run: | + pytest tests -v --engine CyEulerBallistic + shell: bash + if: runner.os != 'Windows' diff --git a/py-ballisticcalc b/py-ballisticcalc deleted file mode 160000 index a18059e..0000000 --- a/py-ballisticcalc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a18059ee5226ede2b5a1f6427b64e8f720cc4ec9 From 1872aab16bcbb30b8520d2b28b57e8a32ae11eec Mon Sep 17 00:00:00 2001 From: o-murphy Date: Tue, 3 Jun 2025 23:30:41 +0300 Subject: [PATCH 12/18] trying new test ci --- .github/workflows/package-test-cython.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package-test-cython.yml b/.github/workflows/package-test-cython.yml index 0bd3f27..52400a5 100644 --- a/.github/workflows/package-test-cython.yml +++ b/.github/workflows/package-test-cython.yml @@ -52,7 +52,7 @@ jobs: echo "Cloning py-ballisticcalc with tag: $PYBC_VERSION" # Clone the specific tag (version) using the obtained version - git clone --branch "$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc + git clone --branch "v$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc # Change into the cloned directory cd py-ballisticcalc From 65de6cfa4ce7943dfd97ebfe6826f4ab0f8a76c3 Mon Sep 17 00:00:00 2001 From: o-murphy Date: Tue, 3 Jun 2025 23:49:31 +0300 Subject: [PATCH 13/18] trying new test ci --- .github/workflows/package-test-cython.yml | 28 +--- .gitignore | 3 + .python-version | 1 + pyproject.toml | 12 +- uv.lock | 153 +++------------------- 5 files changed, 39 insertions(+), 158 deletions(-) create mode 100644 .python-version diff --git a/.github/workflows/package-test-cython.yml b/.github/workflows/package-test-cython.yml index 52400a5..310f066 100644 --- a/.github/workflows/package-test-cython.yml +++ b/.github/workflows/package-test-cython.yml @@ -27,45 +27,29 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install project run: | uv sync --dev - - name: Build cython modules - run: | - uv pip install -e .[dev] - - name: Get py-ballisticcalc installed version - id: get_installed_version # This ID allows referencing its output + id: get_installed_version run: | - # Run the Python command to get the version - # The output is captured and set as a step output named 'pybc_version' - # This syntax works universally with 'bash' shell on Linux and Windows echo "pybc_version=$(python -c 'from importlib.metadata import metadata; print(metadata("py-ballisticcalc")["Version"])')" >> "$GITHUB_OUTPUT" shell: bash # Explicitly use bash for cross-platform compatibility - - name: Install from specific tag based on installed version + - name: Clone from specific tag based on installed version run: | # Access the version obtained from the previous step's output # The 'steps.get_installed_version.outputs.pybc_version' syntax is universal PYBC_VERSION="${{ steps.get_installed_version.outputs.pybc_version }}" echo "Cloning py-ballisticcalc with tag: $PYBC_VERSION" - - # Clone the specific tag (version) using the obtained version git clone --branch "v$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc - - # Change into the cloned directory - cd py-ballisticcalc - - # Install in editable mode with dev dependencies using uv - uv pip install -e .[dev] - - # Go back to the original directory and clean up - cd ../ shell: bash # Ensure bash is used for the shell commands - - name: Run pytest + - name: Run py-ballisticcalc tests with --engine CyEulerBallistic run: | + cd py-ballisticcalc pytest tests -v --engine CyEulerBallistic + cd ../ shell: bash if: runner.os != 'Windows' diff --git a/.gitignore b/.gitignore index 191fd83..0ff2d03 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ **/*.egg-info **/.venv .vscode/settings.json + +# project specific +**/py-ballisticcalc \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..bd28b9c --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9 diff --git a/pyproject.toml b/pyproject.toml index 466b0ae..466c2b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,9 +51,19 @@ py-modules = ["CyEulerBallistic"] where = ["."] include = ["CyEulerBallistic*"] +# deprecated, use `uv sync` with `dev` dependency group [project.optional-dependencies] -dev = ['cython', 'build', 'setuptools', 'cibuildwheel', 'pytest', 'mypy', 'pylint'] +dev = ['cython', 'build', 'setuptools', 'cibuildwheel', 'pytest'] [tool.cibuildwheel] # Use uv and build build-frontend = "build[uv]" + +[dependency-groups] +dev = [ + "build>=1.2.2.post1", + "cibuildwheel>=2.23.3", + "cython>=3.1.1", + "pytest>=8.3.5", + "setuptools>=80.9.0", +] diff --git a/uv.lock b/uv.lock index 3d91f04..f95c11d 100644 --- a/uv.lock +++ b/uv.lock @@ -7,18 +7,6 @@ resolution-markers = [ "python_full_version < '3.11'", ] -[[package]] -name = "astroid" -version = "3.3.10" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/00/c2/9b2de9ed027f9fe5734a6c0c0a601289d796b3caaf1e372e23fa88a73047/astroid-3.3.10.tar.gz", hash = "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce", size = 398941 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/58/5260205b9968c20b6457ed82f48f9e3d6edf2f1f95103161798b73aeccf0/astroid-3.3.10-py3-none-any.whl", hash = "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", size = 275388 }, -] - [[package]] name = "bashlex" version = "0.18" @@ -104,8 +92,15 @@ dev = [ { name = "build" }, { name = "cibuildwheel" }, { name = "cython" }, - { name = "mypy" }, - { name = "pylint" }, + { name = "pytest" }, + { name = "setuptools" }, +] + +[package.dev-dependencies] +dev = [ + { name = "build" }, + { name = "cibuildwheel" }, + { name = "cython" }, { name = "pytest" }, { name = "setuptools" }, ] @@ -115,14 +110,21 @@ requires-dist = [ { name = "build", marker = "extra == 'dev'" }, { name = "cibuildwheel", marker = "extra == 'dev'" }, { name = "cython", marker = "extra == 'dev'" }, - { name = "mypy", marker = "extra == 'dev'" }, { name = "py-ballisticcalc", specifier = "==2.1.1b1" }, - { name = "pylint", marker = "extra == 'dev'" }, { name = "pytest", marker = "extra == 'dev'" }, { name = "setuptools", marker = "extra == 'dev'" }, ] provides-extras = ["dev"] +[package.metadata.requires-dev] +dev = [ + { name = "build", specifier = ">=1.2.2.post1" }, + { name = "cibuildwheel", specifier = ">=2.23.3" }, + { name = "cython", specifier = ">=3.1.1" }, + { name = "pytest", specifier = ">=8.3.5" }, + { name = "setuptools", specifier = ">=80.9.0" }, +] + [[package]] name = "cython" version = "3.1.1" @@ -195,15 +197,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/c7/d1ec24fb280caa5a79b6b950db565dab30210a66259d17d5bb2b3a9f878d/dependency_groups-1.3.1-py3-none-any.whl", hash = "sha256:51aeaa0dfad72430fcfb7bcdbefbd75f3792e5919563077f30bc0d73f4493030", size = 8664 }, ] -[[package]] -name = "dill" -version = "0.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/12/80/630b4b88364e9a8c8c5797f4602d0f76ef820909ee32f0bacb9f90654042/dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", size = 186976 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/50/3d/9373ad9c56321fdab5b41197068e1d8c25883b3fea29dd361f9b55116869/dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049", size = 119668 }, -] - [[package]] name = "exceptiongroup" version = "1.3.0" @@ -246,78 +239,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 }, ] -[[package]] -name = "isort" -version = "6.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186 }, -] - -[[package]] -name = "mccabe" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, -] - -[[package]] -name = "mypy" -version = "1.16.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mypy-extensions" }, - { name = "pathspec" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d4/38/13c2f1abae94d5ea0354e146b95a1be9b2137a0d506728e0da037c4276f6/mypy-1.16.0.tar.gz", hash = "sha256:84b94283f817e2aa6350a14b4a8fb2a35a53c286f97c9d30f53b63620e7af8ab", size = 3323139 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/64/5e/a0485f0608a3d67029d3d73cec209278b025e3493a3acfda3ef3a88540fd/mypy-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7909541fef256527e5ee9c0a7e2aeed78b6cda72ba44298d1334fe7881b05c5c", size = 10967416 }, - { url = "https://files.pythonhosted.org/packages/4b/53/5837c221f74c0d53a4bfc3003296f8179c3a2a7f336d7de7bbafbe96b688/mypy-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e71d6f0090c2256c713ed3d52711d01859c82608b5d68d4fa01a3fe30df95571", size = 10087654 }, - { url = "https://files.pythonhosted.org/packages/29/59/5fd2400352c3093bed4c09017fe671d26bc5bb7e6ef2d4bf85f2a2488104/mypy-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:936ccfdd749af4766be824268bfe22d1db9eb2f34a3ea1d00ffbe5b5265f5491", size = 11875192 }, - { url = "https://files.pythonhosted.org/packages/ad/3e/4bfec74663a64c2012f3e278dbc29ffe82b121bc551758590d1b6449ec0c/mypy-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4086883a73166631307fdd330c4a9080ce24913d4f4c5ec596c601b3a4bdd777", size = 12612939 }, - { url = "https://files.pythonhosted.org/packages/88/1f/fecbe3dcba4bf2ca34c26ca016383a9676711907f8db4da8354925cbb08f/mypy-1.16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:feec38097f71797da0231997e0de3a58108c51845399669ebc532c815f93866b", size = 12874719 }, - { url = "https://files.pythonhosted.org/packages/f3/51/c2d280601cd816c43dfa512a759270d5a5ef638d7ac9bea9134c8305a12f/mypy-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:09a8da6a0ee9a9770b8ff61b39c0bb07971cda90e7297f4213741b48a0cc8d93", size = 9487053 }, - { url = "https://files.pythonhosted.org/packages/24/c4/ff2f79db7075c274fe85b5fff8797d29c6b61b8854c39e3b7feb556aa377/mypy-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9f826aaa7ff8443bac6a494cf743f591488ea940dd360e7dd330e30dd772a5ab", size = 10884498 }, - { url = "https://files.pythonhosted.org/packages/02/07/12198e83006235f10f6a7808917376b5d6240a2fd5dce740fe5d2ebf3247/mypy-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82d056e6faa508501af333a6af192c700b33e15865bda49611e3d7d8358ebea2", size = 10011755 }, - { url = "https://files.pythonhosted.org/packages/f1/9b/5fd5801a72b5d6fb6ec0105ea1d0e01ab2d4971893076e558d4b6d6b5f80/mypy-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:089bedc02307c2548eb51f426e085546db1fa7dd87fbb7c9fa561575cf6eb1ff", size = 11800138 }, - { url = "https://files.pythonhosted.org/packages/2e/81/a117441ea5dfc3746431e51d78a4aca569c677aa225bca2cc05a7c239b61/mypy-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6a2322896003ba66bbd1318c10d3afdfe24e78ef12ea10e2acd985e9d684a666", size = 12533156 }, - { url = "https://files.pythonhosted.org/packages/3f/38/88ec57c6c86014d3f06251e00f397b5a7daa6888884d0abf187e4f5f587f/mypy-1.16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:021a68568082c5b36e977d54e8f1de978baf401a33884ffcea09bd8e88a98f4c", size = 12742426 }, - { url = "https://files.pythonhosted.org/packages/bd/53/7e9d528433d56e6f6f77ccf24af6ce570986c2d98a5839e4c2009ef47283/mypy-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:54066fed302d83bf5128632d05b4ec68412e1f03ef2c300434057d66866cea4b", size = 9478319 }, - { url = "https://files.pythonhosted.org/packages/70/cf/158e5055e60ca2be23aec54a3010f89dcffd788732634b344fc9cb1e85a0/mypy-1.16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c5436d11e89a3ad16ce8afe752f0f373ae9620841c50883dc96f8b8805620b13", size = 11062927 }, - { url = "https://files.pythonhosted.org/packages/94/34/cfff7a56be1609f5d10ef386342ce3494158e4d506516890142007e6472c/mypy-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f2622af30bf01d8fc36466231bdd203d120d7a599a6d88fb22bdcb9dbff84090", size = 10083082 }, - { url = "https://files.pythonhosted.org/packages/b3/7f/7242062ec6288c33d8ad89574df87c3903d394870e5e6ba1699317a65075/mypy-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d045d33c284e10a038f5e29faca055b90eee87da3fc63b8889085744ebabb5a1", size = 11828306 }, - { url = "https://files.pythonhosted.org/packages/6f/5f/b392f7b4f659f5b619ce5994c5c43caab3d80df2296ae54fa888b3d17f5a/mypy-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b4968f14f44c62e2ec4a038c8797a87315be8df7740dc3ee8d3bfe1c6bf5dba8", size = 12702764 }, - { url = "https://files.pythonhosted.org/packages/9b/c0/7646ef3a00fa39ac9bc0938626d9ff29d19d733011be929cfea59d82d136/mypy-1.16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:eb14a4a871bb8efb1e4a50360d4e3c8d6c601e7a31028a2c79f9bb659b63d730", size = 12896233 }, - { url = "https://files.pythonhosted.org/packages/6d/38/52f4b808b3fef7f0ef840ee8ff6ce5b5d77381e65425758d515cdd4f5bb5/mypy-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:bd4e1ebe126152a7bbaa4daedd781c90c8f9643c79b9748caa270ad542f12bec", size = 9565547 }, - { url = "https://files.pythonhosted.org/packages/97/9c/ca03bdbefbaa03b264b9318a98950a9c683e06472226b55472f96ebbc53d/mypy-1.16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a9e056237c89f1587a3be1a3a70a06a698d25e2479b9a2f57325ddaaffc3567b", size = 11059753 }, - { url = "https://files.pythonhosted.org/packages/36/92/79a969b8302cfe316027c88f7dc6fee70129490a370b3f6eb11d777749d0/mypy-1.16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b07e107affb9ee6ce1f342c07f51552d126c32cd62955f59a7db94a51ad12c0", size = 10073338 }, - { url = "https://files.pythonhosted.org/packages/14/9b/a943f09319167da0552d5cd722104096a9c99270719b1afeea60d11610aa/mypy-1.16.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c6fb60cbd85dc65d4d63d37cb5c86f4e3a301ec605f606ae3a9173e5cf34997b", size = 11827764 }, - { url = "https://files.pythonhosted.org/packages/ec/64/ff75e71c65a0cb6ee737287c7913ea155845a556c64144c65b811afdb9c7/mypy-1.16.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7e32297a437cc915599e0578fa6bc68ae6a8dc059c9e009c628e1c47f91495d", size = 12701356 }, - { url = "https://files.pythonhosted.org/packages/0a/ad/0e93c18987a1182c350f7a5fab70550852f9fabe30ecb63bfbe51b602074/mypy-1.16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:afe420c9380ccec31e744e8baff0d406c846683681025db3531b32db56962d52", size = 12900745 }, - { url = "https://files.pythonhosted.org/packages/28/5d/036c278d7a013e97e33f08c047fe5583ab4f1fc47c9a49f985f1cdd2a2d7/mypy-1.16.0-cp313-cp313-win_amd64.whl", hash = "sha256:55f9076c6ce55dd3f8cd0c6fff26a008ca8e5131b89d5ba6d86bd3f47e736eeb", size = 9572200 }, - { url = "https://files.pythonhosted.org/packages/bd/eb/c0759617fe2159aee7a653f13cceafbf7f0b6323b4197403f2e587ca947d/mypy-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f56236114c425620875c7cf71700e3d60004858da856c6fc78998ffe767b73d3", size = 10956081 }, - { url = "https://files.pythonhosted.org/packages/70/35/df3c74a2967bdf86edea58b265feeec181d693432faed1c3b688b7c231e3/mypy-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:15486beea80be24ff067d7d0ede673b001d0d684d0095803b3e6e17a886a2a92", size = 10084422 }, - { url = "https://files.pythonhosted.org/packages/b3/07/145ffe29f4b577219943b7b1dc0a71df7ead3c5bed4898686bd87c5b5cc2/mypy-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f2ed0e0847a80655afa2c121835b848ed101cc7b8d8d6ecc5205aedc732b1436", size = 11879670 }, - { url = "https://files.pythonhosted.org/packages/c6/94/0421562d6b046e22986758c9ae31865d10ea0ba607ae99b32c9d18b16f66/mypy-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb5fbc8063cb4fde7787e4c0406aa63094a34a2daf4673f359a1fb64050e9cb2", size = 12610528 }, - { url = "https://files.pythonhosted.org/packages/1a/f1/39a22985b78c766a594ae1e0bbb6f8bdf5f31ea8d0c52291a3c211fd3cd5/mypy-1.16.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a5fcfdb7318c6a8dd127b14b1052743b83e97a970f0edb6c913211507a255e20", size = 12871923 }, - { url = "https://files.pythonhosted.org/packages/f3/8e/84db4fb0d01f43d2c82fa9072ca72a42c49e52d58f44307bbd747c977bc2/mypy-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:2e7e0ad35275e02797323a5aa1be0b14a4d03ffdb2e5f2b0489fa07b89c67b21", size = 9482931 }, - { url = "https://files.pythonhosted.org/packages/99/a3/6ed10530dec8e0fdc890d81361260c9ef1f5e5c217ad8c9b21ecb2b8366b/mypy-1.16.0-py3-none-any.whl", hash = "sha256:29e1499864a3888bca5c1542f2d7232c6e586295183320caa95758fc84034031", size = 2265773 }, -] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963 }, -] - [[package]] name = "packaging" version = "25.0" @@ -327,15 +248,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, ] -[[package]] -name = "pathspec" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, -] - [[package]] name = "platformdirs" version = "4.3.8" @@ -368,26 +280,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/ba/373ccd96ed4b900879c66e6cf62f98215af01dbb6a8680c8192e65195584/py_ballisticcalc-2.1.1b1-py3-none-any.whl", hash = "sha256:0dadf43ae2a422c7d8fd8dde0fc094ba0361df0d3dc157617f8be6f1cef09fd3", size = 68517 }, ] -[[package]] -name = "pylint" -version = "3.3.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "astroid" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "dill" }, - { name = "isort" }, - { name = "mccabe" }, - { name = "platformdirs" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "tomlkit" }, - { name = "typing-extensions", marker = "python_full_version < '3.10'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1c/e4/83e487d3ddd64ab27749b66137b26dc0c5b5c161be680e6beffdc99070b3/pylint-3.3.7.tar.gz", hash = "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", size = 1520709 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/83/bff755d09e31b5d25cc7fdc4bf3915d1a404e181f1abf0359af376845c24/pylint-3.3.7-py3-none-any.whl", hash = "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d", size = 522565 }, -] - [[package]] name = "pyproject-hooks" version = "1.2.0" @@ -462,15 +354,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, ] -[[package]] -name = "tomlkit" -version = "0.13.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, -] - [[package]] name = "typing-extensions" version = "4.13.2" From 2ad1fd500a0a13b4f92d37e8ad2810001b761c42 Mon Sep 17 00:00:00 2001 From: o-murphy Date: Tue, 3 Jun 2025 23:52:09 +0300 Subject: [PATCH 14/18] dependabot update --- .github/dependabot.yml | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d5af07c..13e85da 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,7 +10,32 @@ updates: schedule: interval: "weekly" - groups : - python-packages : - patterns : - - " * " + # Define a group for general Python packages + groups: + python-packages: + patterns: + - "*" # This pattern should match all packages by default + + # New entry specifically for py-ballisticcalc to track patch versions + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" # You can adjust this if you want different schedules + + # Target only py-ballisticcalc + allow: + - dependency-name: "py-ballisticcalc" + + # Specify patch versioning strategy + versioning-strategy: "lockfile-only" # This tells Dependabot to only respect changes in the lockfile (e.g., Poetry.lock, Pipfile.lock) for versioning. + # For strict patch updates without a lockfile, you'd combine with 'ignore' or filter. + + # To specifically target patch updates, you'll generally use 'ignore' + # or ensure your project uses a lockfile (like poetry.lock or Pipfile.lock). + # Dependabot's 'versioning-strategy' typically works with the lockfile. + # If not using a lockfile, 'ignore' rules are more explicit for patch-only updates. + + ignore: + # Ignore minor and major version updates for py-ballisticcalc + - dependency-name: "py-ballisticcalc" + update-types: ["major", "minor"] \ No newline at end of file From 508e078f1f40199f84afc8438788b54a60c3b46f Mon Sep 17 00:00:00 2001 From: o-murphy Date: Wed, 4 Jun 2025 00:29:37 +0300 Subject: [PATCH 15/18] interface.py update --- CyEulerBallistic/interface.py | 75 +++++------------------------------ README.md | 41 ++++++++++++++++++- pyproject.toml | 2 +- 3 files changed, 50 insertions(+), 68 deletions(-) diff --git a/CyEulerBallistic/interface.py b/CyEulerBallistic/interface.py index b583c0b..8b37986 100644 --- a/CyEulerBallistic/interface.py +++ b/CyEulerBallistic/interface.py @@ -1,78 +1,21 @@ +"""Helper""" +from typing import Optional, Union + +from py_ballisticcalc.generics.engine import EngineProtocol + # type: ignore """Implements basic interface for the ballistics calculator""" from dataclasses import dataclass, field -from typing_extensions import Union, List, Optional - -# pylint: disable=import-error,no-name-in-module,wildcard-import -from CyEulerBallistic.trajectory_calc import EulerTrajectoryCalc -from py_ballisticcalc.conditions import Shot -from py_ballisticcalc.drag_model import DragDataPoint -from py_ballisticcalc.trajectory_data import HitResult -from py_ballisticcalc.unit import Angular, Distance, PreferredUnits -from py_ballisticcalc.interface_config import InterfaceConfigDict, create_interface_config +from py_ballisticcalc.interface import Calculator, InterfaceConfigDict @dataclass -class EulerCalculator: +class EulerCalculator(Calculator): """Basic interface for the ballistics calculator""" - _config: Optional[InterfaceConfigDict] = field(default=None) - _calc: EulerTrajectoryCalc = field(init=False, repr=False, compare=False) - - def __post_init__(self): - self._calc = EulerTrajectoryCalc(create_interface_config(self._config)) - - @property - def cdm(self) -> List[DragDataPoint]: - """returns custom drag function based on input data""" - return self._calc.table_data - - def barrel_elevation_for_target(self, shot: Shot, target_distance: Union[float, Distance]) -> Angular: - """Calculates barrel elevation to hit target at zero_distance. - :param shot: Shot instance for which calculate barrel elevation is - :param target_distance: Look-distance to "zero," which is point we want to hit. - This is the distance that a rangefinder would return with no ballistic adjustment. - NB: Some rangefinders offer an adjusted distance based on inclinometer measurement. - However, without a complete ballistic model these can only approximate the effects - on ballistic trajectory of shooting uphill or downhill. Therefore: - For maximum accuracy, use the raw sight distance and look_angle as inputs here. - """ - target_distance = PreferredUnits.distance(target_distance) - total_elevation = self._calc.zero_angle(shot, target_distance) - return Angular.Radian( - (total_elevation >> Angular.Radian) - (shot.look_angle >> Angular.Radian) - ) - - def set_weapon_zero(self, shot: Shot, zero_distance: Union[float, Distance]) -> Angular: - """Sets shot.weapon.zero_elevation so that it hits a target at zero_distance. - :param shot: Shot instance from which we take a zero - :param zero_distance: Look-distance to "zero," which is point we want to hit. - """ - shot.weapon.zero_elevation = self.barrel_elevation_for_target(shot, zero_distance) - return shot.weapon.zero_elevation - - def fire(self, shot: Shot, trajectory_range: Union[float, Distance], - trajectory_step: Union[float, Distance] = 0, - extra_data: bool = False, - time_step: float = 0.0) -> HitResult: - """Calculates trajectory - :param shot: shot parameters (initial position and barrel angle) - :param trajectory_range: Downrange distance at which to stop computing trajectory - :param trajectory_step: step between trajectory points to record - :param extra_data: True => store TrajectoryData for every calculation step; - False => store TrajectoryData only for each trajectory_step - :param time_step: (seconds) If > 0 then record TrajectoryData at least this frequently - """ - step: Distance - trajectory_range = PreferredUnits.distance(trajectory_range) - if not trajectory_step: - trajectory_step = trajectory_range.raw_value / 10.0 - step = Distance.Inch(trajectory_step) - else: - step = PreferredUnits.distance(trajectory_step) - data = self._calc.trajectory(shot, trajectory_range, step, extra_data, time_step) - return HitResult(shot, data, extra_data) + _engine: Union[str, EngineProtocol] = field(default='CyEulerBallistic') + _calc: EngineProtocol = field(init=False, repr=False, compare=False) __all__ = ('EulerCalculator',) diff --git a/README.md b/README.md index 9536fc6..ca81858 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,38 @@ LGPL library for small arms ballistic calculations based on point-mass (3 DoF) plus spin drift. The fork of py_ballisticcalc.exts that can be used as side-package +[![license]][LGPL-3] +[![pypi]][PyPiUrl] +[![downloads]][pepy] +[![downloads/month]][pepy] +[![versions]][sources] +[![Made in Ukraine]][SWUBadge] + +[sources]: +https://github.com/o-murphy/CyEulerBallistic +[license]: +https://img.shields.io/github/license/o-murphy/CyEulerBallistic?style=flat-square +[LGPL-3]: +https://opensource.org/licenses/LGPL-3.0-only +[pypi]: +https://img.shields.io/pypi/v/CyEulerBallistic?style=flat-square&logo=pypi +[PyPiUrl]: +https://pypi.org/project/CyEulerBallistic/ +[coverage]: +coverage.svg +[downloads]: +https://img.shields.io/pepy/dt/CyEulerBallistic?style=flat-square +[downloads/month]: +https://static.pepy.tech/personalized-badge/CyEulerBallistic?style=flat-square&period=month&units=abbreviation&left_color=grey&right_color=blue&left_text=downloads%2Fmonth +[pepy]: +https://pepy.tech/project/CyEulerBallistic +[versions]: +https://img.shields.io/pypi/pyversions/CyEulerBallistic?style=flat-square +[Made in Ukraine]: +https://img.shields.io/badge/made_in-Ukraine-ffd700.svg?labelColor=0057b7&style=flat-square +[SWUBadge]: +https://stand-with-ukraine.pp.ua + ### Table of contents * **[Installation](#installation)** * [Latest stable](#latest-stable-release-from-pypi) @@ -15,10 +47,17 @@ The fork of py_ballisticcalc.exts that can be used as side-package ```shell pip install CyEulerBallistic +# or +uv add CyEulerBallistic ``` # Usage -**See [Original README](Example.ipynb) for detailed illustrations of all features and usage.** +Initialize CyEulerBallistic engine +```shell +from py_ballisticcalc import Calculator +calc = Calculator(_engine="CyEulerBallistic") +``` +**Follow [Original README](Example.ipynb) for detailed illustrations of all features and usage.** # About project diff --git a/pyproject.toml b/pyproject.toml index 466c2b1..a20688e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" [project] name = "CyEulerBallistic" -version = "2.1.0b6" +version = "2.1.1b1" authors = [ { name="o-murphy", email="thehelixpg@gmail.com" }, From 41e569b4ded03ad60ea527fa462233a77e16047e Mon Sep 17 00:00:00 2001 From: o-murphy Date: Wed, 4 Jun 2025 00:41:24 +0300 Subject: [PATCH 16/18] update CI --- .github/workflows/cibuildwheel_test.yml | 2 +- .github/workflows/pypi-publish.yml | 12 +++++------- .github/workflows/pypi-test-publish.yml | 11 +++++------ 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cibuildwheel_test.yml b/.github/workflows/cibuildwheel_test.yml index e450fe6..76ae801 100644 --- a/.github/workflows/cibuildwheel_test.yml +++ b/.github/workflows/cibuildwheel_test.yml @@ -26,7 +26,7 @@ jobs: - name: Install dependencies run: | - uv pip install cibuildwheel + uv sync --dev - name: Build binary python package run: | diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml index 33a52f4..0881e0b 100644 --- a/.github/workflows/pypi-publish.yml +++ b/.github/workflows/pypi-publish.yml @@ -18,19 +18,18 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Install uv and set the python version "3.12" + uses: astral-sh/setup-uv@v5 with: python-version: "3.12" - - name: Install dependencies + - name: Install project run: | - python -m pip install --upgrade pip - python -m pip install build cibuildwheel + uv sync --dev - name: Build binary Python package run: | - python -m build --sdist --outdir ./dist + uv build --sdist --out-dir ./dist cibuildwheel --output-dir ./dist - name: Upload artifacts @@ -78,7 +77,6 @@ jobs: cp ./dist-macos-13/* dist/ || true cp ./dist-macos-14/* dist/ || true - - name: List ./dist run: ls ./dist diff --git a/.github/workflows/pypi-test-publish.yml b/.github/workflows/pypi-test-publish.yml index 7aa416a..518b417 100644 --- a/.github/workflows/pypi-test-publish.yml +++ b/.github/workflows/pypi-test-publish.yml @@ -17,19 +17,18 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Install uv and set the python version "3.12" + uses: astral-sh/setup-uv@v5 with: python-version: "3.12" - - name: Install dependencies + - name: Install project run: | - python -m pip install --upgrade pip - python -m pip install build cibuildwheel + uv sync --dev - name: Build binary Python package run: | - python -m build --sdist --outdir ./dist + uv build --sdist --out-dir ./dist cibuildwheel --output-dir ./dist - name: Upload artifacts From a41fdf0063b2b92bc5badb5660bcf05eadc0dbcc Mon Sep 17 00:00:00 2001 From: o-murphy Date: Wed, 4 Jun 2025 01:03:19 +0300 Subject: [PATCH 17/18] update CI --- .github/workflows/{package-test-cython.yml => pytest.yml} | 0 README.md | 4 ++++ 2 files changed, 4 insertions(+) rename .github/workflows/{package-test-cython.yml => pytest.yml} (100%) diff --git a/.github/workflows/package-test-cython.yml b/.github/workflows/pytest.yml similarity index 100% rename from .github/workflows/package-test-cython.yml rename to .github/workflows/pytest.yml diff --git a/README.md b/README.md index ca81858..757110c 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ The fork of py_ballisticcalc.exts that can be used as side-package [![versions]][sources] [![Made in Ukraine]][SWUBadge] +[![pytest]][pytest] + [sources]: https://github.com/o-murphy/CyEulerBallistic [license]: @@ -21,6 +23,8 @@ https://img.shields.io/pypi/v/CyEulerBallistic?style=flat-square&logo=pypi https://pypi.org/project/CyEulerBallistic/ [coverage]: coverage.svg +[pytest]: +https://github.com/o-murphy/CyEulerBallistic/actions/workflows/pytest.yml [downloads]: https://img.shields.io/pepy/dt/CyEulerBallistic?style=flat-square [downloads/month]: From 5d46989b37428e54451ba0544cc5dae75ae9c0db Mon Sep 17 00:00:00 2001 From: o-murphy Date: Wed, 4 Jun 2025 01:05:59 +0300 Subject: [PATCH 18/18] update CI --- .github/workflows/pytest.yml | 3 ++- README.md | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 310f066..73486aa 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -1,7 +1,8 @@ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python -name: Python cythonized package tests (uv) +# Python cythonized package tests (uv) +name: Pytest on: pull_request: diff --git a/README.md b/README.md index 757110c..53f6b5f 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The fork of py_ballisticcalc.exts that can be used as side-package [![versions]][sources] [![Made in Ukraine]][SWUBadge] -[![pytest]][pytest] +[![Python cythonized package tests (uv)](https://github.com/o-murphy/CyEulerBallistic/actions/workflows/pytest.yml/badge.svg)](https://github.com/o-murphy/CyEulerBallistic/actions/workflows/pytest.yml) [sources]: https://github.com/o-murphy/CyEulerBallistic @@ -23,8 +23,6 @@ https://img.shields.io/pypi/v/CyEulerBallistic?style=flat-square&logo=pypi https://pypi.org/project/CyEulerBallistic/ [coverage]: coverage.svg -[pytest]: -https://github.com/o-murphy/CyEulerBallistic/actions/workflows/pytest.yml [downloads]: https://img.shields.io/pepy/dt/CyEulerBallistic?style=flat-square [downloads/month]: