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 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/package-test-cython.yml b/.github/workflows/package-test-cython.yml deleted file mode 100644 index 9cf2a42..0000000 --- a/.github/workflows/package-test-cython.yml +++ /dev/null @@ -1,60 +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: Run unittest tests in binary mode - 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' - - - name: Run unittest tests in binary mode on Windows - 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' 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 diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..73486aa --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,56 @@ +# 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 + +# Python cythonized package tests (uv) +name: Pytest + +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 project + run: | + uv sync --dev + + - name: Get py-ballisticcalc installed version + id: get_installed_version + run: | + 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: 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" + git clone --branch "v$PYBC_VERSION" --single-branch https://github.com/o-murphy/py-ballisticcalc.git py-ballisticcalc + shell: bash # Ensure bash is used for the shell commands + + - 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/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/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/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/README.md b/README.md index 9536fc6..53f6b5f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,40 @@ 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] + +[![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 +[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 +49,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 da07dc0..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" }, @@ -33,7 +33,10 @@ 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" [project.urls] "Homepage" = "https://github.com/o-murphy/CyEulerBallistic" @@ -48,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/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 new file mode 100644 index 0000000..f95c11d --- /dev/null +++ b/uv.lock @@ -0,0 +1,373 @@ +version = 1 +revision = 1 +requires-python = ">=3.9" +resolution-markers = [ + "python_full_version >= '3.12'", + "python_full_version == '3.11.*'", + "python_full_version < '3.11'", +] + +[[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 } +wheels = [ + { 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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/02/8db98cdc1a58e0abd6716d5e63244658e6e63513c65f469f34b6f1053fd0/bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6", size = 11558 }, +] + +[[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 } +wheels = [ + { 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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618 }, +] + +[[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 } +wheels = [ + { 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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "cyeulerballistic" +version = "2.1.0b6" +source = { editable = "." } +dependencies = [ + { name = "py-ballisticcalc" }, +] + +[package.optional-dependencies] +dev = [ + { name = "build" }, + { name = "cibuildwheel" }, + { name = "cython" }, + { name = "pytest" }, + { name = "setuptools" }, +] + +[package.dev-dependencies] +dev = [ + { name = "build" }, + { name = "cibuildwheel" }, + { name = "cython" }, + { name = "pytest" }, + { name = "setuptools" }, +] + +[package.metadata] +requires-dist = [ + { name = "build", marker = "extra == 'dev'" }, + { name = "cibuildwheel", marker = "extra == 'dev'" }, + { name = "cython", marker = "extra == 'dev'" }, + { name = "py-ballisticcalc", specifier = "==2.1.1b1" }, + { 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" +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 } +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 }, + { 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]] +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 } +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 = "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 } +wheels = [ + { 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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { 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 } +wheels = [ + { 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 } +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 = "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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, +] + +[[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 } +wheels = [ + { 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 } +wheels = [ + { 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.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/7c/18/1f811017d43bf10ea446fb4563aa32b97e5e9f200a8c8b0e13fd5f023656/py_ballisticcalc-2.1.1b1.tar.gz", hash = "sha256:4b43cc6c80328e18e6b4ba7c267694114dd92f442606615e4185ed2794464a44", size = 261596 } +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 = "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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216 }, +] + +[[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 } +wheels = [ + { 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 } +wheels = [ + { 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 } +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 }, + { 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 = "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 } +wheels = [ + { 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 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/da/f64669af4cae46f17b90798a827519ce3737d31dbafad65d391e49643dc4/zipp-3.22.0-py3-none-any.whl", hash = "sha256:fe208f65f2aca48b81f9e6fd8cf7b8b32c26375266b009b413d45306b6148343", size = 9796 }, +]