Skip to content

Port GSSVMDistribution and fix bessel_ratio normalization bug#1609

Open
Copilot wants to merge 4 commits intomainfrom
copilot/port-gssvm-distribution
Open

Port GSSVMDistribution and fix bessel_ratio normalization bug#1609
Copilot wants to merge 4 commits intomainfrom
copilot/port-gssvm-distribution

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

Adds GSSVMDistribution (Generalized Skew-Symmetric Von Mises) to match the libDirectional API, and fixes a pre-existing bug in bessel_ratio that made the PDF produce NaN for all orders m > 1.

Bug fix: bessel_ratio

The function was computing I_p(z) / I_p(0), but I_p(0) = 0 for all p > 0, causing division by zero. The normalization constants for m=2,3,4 require I_p(κ) / I_0(κ):

# Before (always NaN/inf for p > 0)
return ive(p, z) / ive(p, 0)

# After
return ive(p, z) / ive(0, z)

New class: GSSVMDistribution

  • Subclass of GeneralizedKSineSkewedVonMisesDistribution with k=1 fixed
  • Exposes n (order) instead of m, matching libDirectional naming
  • shift() returns a GSSVMDistribution rather than the base type
  • Exported from pyrecest/distributions/__init__.py
dist = GSSVMDistribution(mu=0.5, kappa=2.0, lambda_=0.3, n=2)
dist.pdf(xs)      # works correctly for all supported orders 1–4
dist.shift(pi/4)  # returns GSSVMDistribution

Tests

New test file test_gssvm_distribution.py covers initialization, parameter validation, n↔m mapping, non-negative PDFs for n=1..4, PDF parity with the parent class, shift() type/value, mu wrapping, and NotImplementedError for n > 4.

Copilot AI and others added 2 commits April 1, 2026 09:50
Agent-Logs-Url: https://github.com/FlorianPfaff/PyRecEst/sessions/0e13025c-e4bf-4408-9fd4-8926ad29cc95

Co-authored-by: FlorianPfaff <6773539+FlorianPfaff@users.noreply.github.com>
…istribution tests

Agent-Logs-Url: https://github.com/FlorianPfaff/PyRecEst/sessions/09bda777-60e4-4bfb-a88e-992398738c5d

Co-authored-by: FlorianPfaff <6773539+FlorianPfaff@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

MegaLinter analysis: Success

Descriptor Linter Files Fixed Errors Warnings Elapsed time
✅ COPYPASTE jscpd yes no no 9.33s
✅ JSON prettier 2 0 0 0 0.56s
✅ JSON v8r 2 0 0 2.44s
✅ MARKDOWN markdownlint 1 0 0 0 0.68s
✅ MARKDOWN markdown-table-formatter 1 0 0 0 0.23s
✅ PYTHON bandit 251 0 0 3.14s
✅ PYTHON black 251 1 0 0 4.44s
✅ PYTHON flake8 251 0 0 1.77s
✅ PYTHON isort 251 1 0 0 0.49s
✅ PYTHON mypy 251 0 0 4.16s
✅ PYTHON pylint 251 0 0 71.78s
✅ PYTHON ruff 251 1 0 0 0.05s
✅ REPOSITORY checkov yes no no 23.93s
✅ REPOSITORY gitleaks yes no no 4.45s
✅ REPOSITORY git_diff yes no no 0.02s
✅ REPOSITORY secretlint yes no no 5.89s
✅ REPOSITORY syft yes no no 3.35s
✅ REPOSITORY trivy-sbom yes no no 2.53s
✅ REPOSITORY trufflehog yes no no 16.52s
✅ YAML prettier 4 0 0 0 0.5s
✅ YAML v8r 4 0 0 5.03s
✅ YAML yamllint 4 0 0 0.44s

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@9.4.0 --custom-flavor-setup --custom-flavor-linters PYTHON_PYLINT,PYTHON_BLACK,PYTHON_FLAKE8,PYTHON_ISORT,PYTHON_BANDIT,PYTHON_MYPY,PYTHON_RUFF,COPYPASTE_JSCPD,JSON_V8R,JSON_PRETTIER,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,REPOSITORY_CHECKOV,REPOSITORY_GIT_DIFF,REPOSITORY_GITLEAKS,REPOSITORY_SECRETLINT,REPOSITORY_SYFT,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG,YAML_PRETTIER,YAML_YAMLLINT,YAML_V8R

MegaLinter is graciously provided by OX Security
Show us your support by starring ⭐ the repository

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

Test Results

   12 files  ±  0     12 suites  ±0   3h 18m 24s ⏱️ + 4m 29s
  606 tests +  9    606 ✅ +  9      0 💤 ±0  0 ❌ ±0 
7 484 runs  +108  6 236 ✅ +108  1 248 💤 ±0  0 ❌ ±0 

Results for commit 7670a61. ± Comparison against base commit 96e327d.

♻️ This comment has been updated with latest results.

@FlorianPfaff
Copy link
Copy Markdown
Owner

FlorianPfaff commented Apr 2, 2026

@copilot Somewhere, pyrecest.backend is not used and some numpy object is created although it shouldn't be.
=========================== short test summary info ============================
FAILED pyrecest/tests/distributions/test_gssvm_distribution.py::TestGSSVMDistribution::test_pdf_matches_generalized_parent - TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'Tensor'
FAILED pyrecest/tests/distributions/test_gssvm_distribution.py::TestGSSVMDistribution::test_pdf_non_negative - TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'Tensor'
= 2 failed, 512 passed, 66 skipped, 5559611 warnings, 11 subtests passed in 801.23s (0:13:21) =

@FlorianPfaff
Copy link
Copy Markdown
Owner

@copilot Somewhere, pyrecest.backend is not used and some numpy object is created although it shouldn't be.
=========================== short test summary info ============================
FAILED pyrecest/tests/distributions/test_gssvm_distribution.py::TestGSSVMDistribution::test_pdf_matches_generalized_parent - TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'Tensor'
FAILED pyrecest/tests/distributions/test_gssvm_distribution.py::TestGSSVMDistribution::test_pdf_non_negative - TypeError: unsupported operand type(s) for *: 'numpy.ndarray' and 'Tensor'
= 2 failed, 512 passed, 66 skipped, 5559611 warnings, 11 subtests passed in 801.23s (0:13:21) =

…tats.vonmises.pdf

Agent-Logs-Url: https://github.com/FlorianPfaff/PyRecEst/sessions/7c9c6cf0-3c05-4a8b-b788-b7ad856dee70

Co-authored-by: FlorianPfaff <6773539+FlorianPfaff@users.noreply.github.com>
auto-merge was automatically disabled April 2, 2026 13:44

Head branch was pushed to by a user without write access

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 2, 2026

@copilot Somewhere, pyrecest.backend is not used and some numpy object is created although it shouldn't be.
=========================== short test summary info ============================
FAILED py...

Fixed in 65cb132. scipy.stats.vonmises.pdf was the culprit — it always returns a NumPy array regardless of the active backend. Replaced it with VonMisesDistribution(self.mu, self.kappa).pdf(xs), which uses the pyrecest backend operations (exp, cos) and returns the correct tensor type.

@FlorianPfaff FlorianPfaff force-pushed the copilot/port-gssvm-distribution branch from ea2fae9 to 7670a61 Compare April 3, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants