Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
0adc5a6
Update mathieu.h with improved docstrings and comments.
brorson Sep 6, 2025
9f62cf0
Add new directory of Mathieu fcn impls.
brorson Sep 6, 2025
204e09d
Make sure we return nan when error is encountered.
brorson Sep 6, 2025
b09c280
Remove non-standard d in double constant literals.
brorson Sep 7, 2025
41c1f28
Merge branch 'scipy:main' into main
brorson Sep 10, 2025
93a41df
Remove license file and place code under whatever license xsf uses.
brorson Sep 10, 2025
b8911c1
Merge branch 'main' of https://github.com/brorson/xsf_mathieu
brorson Sep 10, 2025
5cbf45c
I removed my Makefile since it's not used in the Scipy CI tool. I moved
brorson Sep 11, 2025
cdf598b
Run clang-format on test_mathieu.cpp so it passes CI.
brorson Sep 11, 2025
cec5ca1
Merge branch 'scipy:main' into main
brorson Sep 24, 2025
9c850da
Replaced malloc/free with std::vector, updated some comments, added
brorson Sep 26, 2025
72a5146
Merge branch 'main' of https://github.com/brorson/xsf_mathieu
brorson Sep 26, 2025
b25ba42
Merge branch 'scipy:main' into main
brorson Sep 26, 2025
e32d63c
Remove mathieu.h since it doesn't belong in this dir.
brorson Sep 27, 2025
7614c4e
run clang-format on all .h files.
brorson Sep 27, 2025
f96e616
Change dsyev -> dsyevd to speed up calc.
brorson Nov 13, 2025
5ddc975
Change dsyevd to dstevd since dstevd is for tridiagonal matrices,
brorson Nov 13, 2025
67314ef
Revert back to dsyevd. Use correct calling sig this time.
brorson Nov 15, 2025
c5e098b
Clean up files using clang-format before checking in.
brorson Nov 16, 2025
7873a34
Merge branch 'scipy:main' into main
brorson Nov 16, 2025
78ce632
I used a more recent version of clang-format. Hopefully this will
brorson Nov 16, 2025
f3074d5
Modify meson.build so it includes Lapack as a dependency.
brorson Dec 24, 2025
536959f
Don't use _Float128 if not defined on this platform.
brorson Dec 25, 2025
eac37fe
Make _Float128 directive obey clang-format.
brorson Dec 25, 2025
1d0ec45
Fix some constant doubles -- don't use d suffix since Mac doesn't lik…
brorson Dec 25, 2025
7eb1c86
Run clang-format on mathieu_fcns to satisfy Scipy ci thing.
brorson Dec 25, 2025
d200bd4
Merge branch 'scipy:main' into main
brorson Dec 25, 2025
eb44cb3
Remove d suffix from constant doubles in test fcn to appease the CI t…
brorson Dec 25, 2025
8a401b3
Fix meson build problem where standalone build of xsf doesn't find blas
brorson Dec 26, 2025
678e532
Updates to the build files again so I can build both stand-alone xsf
brorson Dec 26, 2025
2c0710f
Updates to mathieu.h and make_matrix.h based on reviewer comments.
brorson Dec 26, 2025
ce4baf2
Change impl to use dstevd instead of dsyevd. The old dsyevd did an
brorson Jan 3, 2026
cb4b6d6
This creates the tridiagonal recursion matrix suitable for dstevd.
brorson Jan 3, 2026
f08887b
Udpate the tests to match the new API for the dstevd impl.
brorson Jan 3, 2026
caab938
I ran clang-format on the .h files since I forgot to do this last time.
brorson Jan 4, 2026
3c17ce4
Big changes including fixing row/col confusion in the eigenvector
brorson Jan 16, 2026
36f71c9
Run clang-format on *.h files.
brorson Jan 16, 2026
80d930d
Old s=0 code removed from mathieu_fcns. Also added s-max aproach to
brorson Jan 17, 2026
d1da899
Fix bug in se_2m+2 by changing coeff generation -- ask for matrix
brorson Jan 18, 2026
d6b2c3f
Add get_partial_sum_N to mathieu_fcns. The goal is to make the matrix
brorson Jan 18, 2026
bfd8ba5
Must update the mathieu test using clang-format.
brorson Jan 18, 2026
78c3ef9
Fix bugs found by Ho-Chul Shin.
brorson Jan 27, 2026
b9df532
Merge branch 'main' into Brorson-Mathieu-impl
brorson Feb 23, 2026
a8cacdd
Merge branch 'main' into Brorson-Mathieu-impl
steppi Apr 30, 2026
f656268
TST: delete soon to be unnecessary mathieu tests
steppi Apr 30, 2026
5b98901
MAINT: remove duplicate file
steppi Apr 30, 2026
a36e379
MAINT: Update make_matrix_tridiagonal to use mdspan
steppi Apr 30, 2026
49ce54a
Move test_mathieu.cpp out of tests
steppi Apr 30, 2026
9e5ec75
Get rid of include of now removed header
steppi Apr 30, 2026
38650ea
TST: Add test for mathieu tridiagonal
steppi Apr 30, 2026
666904a
Update docstring style comments
steppi Apr 30, 2026
a0cce79
keep old mathieu.h header and create new one so scipy still builds
steppi Apr 30, 2026
abfe40f
Use mathieu_new.h in debug program
steppi Apr 30, 2026
4f6ac4c
Make type of q generic
steppi May 1, 2026
08cc326
Merge branch 'main' into Brorson-Mathieu-impl-test-updates
steppi May 6, 2026
319ccae
Add as_mdspan helper
steppi May 6, 2026
6616001
Start reorganizing mathieu code
steppi May 6, 2026
adb3795
Use templates to reduce duplication in mathieu rr matrix
steppi May 8, 2026
3dc49c7
Some fixes for mathieu stuff
steppi May 8, 2026
f0bc516
Add comment explaining what get_partial_sum_N does
steppi May 8, 2026
0ceb45e
Add fourier series summing for mathieu + simplifications
steppi May 8, 2026
de819ac
Adding missing semicolons
steppi May 8, 2026
75fff8a
Remove now unnecessary using statement
steppi May 8, 2026
d1df6fc
Fix some small mistakes
steppi May 8, 2026
bdbbe5c
Remove unused variable
steppi May 8, 2026
765369c
Fix sign bug
steppi May 8, 2026
af53522
Add missing type
steppi May 8, 2026
553d7ae
Compute fourier sum in degrees internally
steppi May 8, 2026
2546fb8
Fix namespace for sinpi and cospi
steppi May 8, 2026
ede3b68
Add more comments on new mathieu implementations
steppi May 9, 2026
e60356a
Add AngleUnitPolicy
steppi May 9, 2026
ef6ac22
Add docstring like comment for sum_fourier_series
steppi May 9, 2026
51fcdb8
Remove pre-(refactored + isolated) mathieu implementations
steppi May 10, 2026
15e0022
Rename mathieu headers
steppi May 10, 2026
005737b
Add comment explaining mathieu_legacy.h
steppi May 10, 2026
e82b4b9
Fix typo and minor error
steppi May 10, 2026
a447f5b
Mark wrap_PyUFunc_getfperr inline to work around ODR
steppi May 10, 2026
2b8ddbb
Revert making wrap_PUFunc_getfperr inline
steppi May 10, 2026
cd6a277
Drop as_mdspan from numpy.h
steppi May 10, 2026
ffb73ce
Run clang format on numpy.h
steppi May 10, 2026
117d9e5
Update mathieu tests
steppi May 10, 2026
0ce474e
Add first sum_fourier_series test for mathieu
steppi May 10, 2026
ec7fb0c
Add another sum_fourier_series test
steppi May 10, 2026
2d8cbd8
Add more sum_fourier_series tests
steppi May 10, 2026
fcc8b53
Add more fourier series mathieu tests
steppi May 11, 2026
eed6bf4
Add a header comment about mathieu tests in xsf
steppi May 11, 2026
2829f04
Clean up some unnecessary things from #99
steppi May 11, 2026
f40b80b
Remove solve-group default for CuPy
steppi May 11, 2026
203e303
Update pixi.lock
steppi May 11, 2026
1d24a1b
Fix ufunc bug
steppi May 12, 2026
f4f416b
Run clang format
steppi May 12, 2026
eac5808
Merge branch 'ufunc-loop-bug' into brorson-mathieu-part1
steppi May 12, 2026
9b8b852
Merge branch 'main' into brorson-mathieu-part1
steppi May 14, 2026
9fdf040
Merge branch 'main' into brorson-mathieu-part1
steppi May 14, 2026
fa6756c
Merge branch 'main' into brorson-mathieu-part1
steppi May 18, 2026
95e1000
Apply suggestions from code review
steppi May 22, 2026
6ff3839
make capitalization consistent throughout
steppi May 22, 2026
b35edb8
use |q| in calculation of num Fourier terms
steppi May 22, 2026
7faa939
fix normalization condition for sem and add comments
steppi May 22, 2026
27f87a9
update comments on sign for mathieu
steppi May 22, 2026
a7e21f7
Apply suggestions from code review
steppi May 22, 2026
64b52cb
fix more typos
steppi May 22, 2026
652d508
rung clang format
steppi May 22, 2026
b51b24b
Apply suggestions from code review
steppi May 23, 2026
788adeb
Merge branch 'main' into brorson-mathieu-part1
steppi Jun 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
437 changes: 239 additions & 198 deletions include/xsf/mathieu.h

Large diffs are not rendered by default.

230 changes: 230 additions & 0 deletions include/xsf/mathieu_legacy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/* Less accurate (but faster) legacy versions of Mathieu functions. */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the plan for this file? what about backward-compatibility?

should we not keep old tests for smoke coverage?

@steppi steppi Jun 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file remains for now because it's still being used for the modified (radial) mathieu functions, and as a large order fallback for mathieu_cv. Once the modified mathieu functions are refactored like this, and we figure out something else for the fallback, then we can get rid of the file. We can't really keep the old tests because they rely on computing the functions from end to end and xsf doesn't offer that capability. The full implementations for CPU live in SciPy and rely on kernels from here that the CuPy implementations will also use. All of those old test cases (using degrees as angular unit) remain in SciPy.


#pragma once

#include "error.h"
#include "specfun/specfun.h"

namespace xsf {

template <typename T>
T sem_cva(T m, T q);

template <typename T>
void sem(T m, T q, T x, T &csf, T &csd);

/* Mathieu functions */
/* Characteristic values */
template <typename T>
T cem_cva(T m, T q) {
int int_m, kd = 1;

if ((m < 0) || (m != floor(m))) {
set_error("mathieu_a", SF_ERROR_DOMAIN, NULL);
return std::numeric_limits<T>::quiet_NaN();
}
int_m = (int)m;
if (q < 0) {
/* https://dlmf.nist.gov/28.2#E26 */
if (int_m % 2 == 0) {
return cem_cva(m, -q);
} else {
return sem_cva(m, -q);
}
}

if (int_m % 2) {
kd = 2;
}
return specfun::cva2(kd, int_m, q);
}

template <typename T>
T sem_cva(T m, T q) {
int int_m, kd = 4;

if ((m <= 0) || (m != floor(m))) {
set_error("mathieu_b", SF_ERROR_DOMAIN, NULL);
return std::numeric_limits<T>::quiet_NaN();
}
int_m = (int)m;
if (q < 0) {
/* https://dlmf.nist.gov/28.2#E26 */
if (int_m % 2 == 0) {
return sem_cva(m, -q);
} else {
return cem_cva(m, -q);
}
}
if (int_m % 2) {
kd = 3;
}
return specfun::cva2(kd, int_m, q);
}

/* Mathieu functions */
template <typename T>
void cem(T m, T q, T x, T &csf, T &csd) {
int int_m, kf = 1, sgn;
T f = 0.0, d = 0.0;
if ((m < 0) || (m != floor(m))) {
csf = std::numeric_limits<T>::quiet_NaN();
csd = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_cem", SF_ERROR_DOMAIN, NULL);
} else {
int_m = (int)m;
if (q < 0) {
/* https://dlmf.nist.gov/28.2#E34 */
if (int_m % 2 == 0) {
sgn = ((int_m / 2) % 2 == 0) ? 1 : -1;
cem(m, -q, 90 - x, f, d);
csf = sgn * f;
csd = -sgn * d;

} else {
sgn = ((int_m / 2) % 2 == 0) ? 1 : -1;
sem(m, -q, 90 - x, f, d);
csf = sgn * f;
csd = -sgn * d;
}
} else {
using specfun::Status;
Status status = specfun::mtu0(kf, int_m, q, x, &csf, &csd);
if (status != Status::OK) {
csf = std::numeric_limits<T>::quiet_NaN();
csd = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_cem", sf_error, NULL);
}
}
}
}

template <typename T>
void sem(T m, T q, T x, T &csf, T &csd) {
int int_m, kf = 2, sgn;
T f = 0.0, d = 0.0;
if ((m < 0) || (m != floor(m))) {
csf = std::numeric_limits<T>::quiet_NaN();
csd = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_sem", SF_ERROR_DOMAIN, NULL);
} else {
int_m = (int)m;
if (int_m == 0) {
csf = 0;
csd = 0;
} else if (q < 0) {
/* https://dlmf.nist.gov/28.2#E34 */
if (int_m % 2 == 0) {
sgn = ((int_m / 2) % 2 == 0) ? -1 : 1;
sem(m, -q, 90 - x, f, d);
csf = sgn * f;
csd = -sgn * d;
} else {
sgn = ((int_m / 2) % 2 == 0) ? 1 : -1;
cem(m, -q, 90 - x, f, d);
csf = sgn * f;
csd = -sgn * d;
}
} else {
using specfun::Status;
Status status = specfun::mtu0(kf, int_m, q, x, &csf, &csd);
if (status != Status::OK) {
csf = std::numeric_limits<T>::quiet_NaN();
csd = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_sem", sf_error, NULL);
}
}
}
}

template <typename T>
void mcm1(T m, T q, T x, T &f1r, T &d1r) {
int int_m, kf = 1, kc = 1;
T f2r = 0.0, d2r = 0.0;

if ((m < 0) || (m != floor(m)) || (q < 0)) {
f1r = std::numeric_limits<T>::quiet_NaN();
d1r = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_modcem1", SF_ERROR_DOMAIN, NULL);
} else {
using specfun::Status;
int_m = (int)m;
Status status = specfun::mtu12(kf, kc, int_m, q, x, &f1r, &d1r, &f2r, &d2r);
if (status != Status::OK) {
f1r = std::numeric_limits<T>::quiet_NaN();
d1r = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_modcem1", sf_error, NULL);
}
}
}

template <typename T>
void msm1(T m, T q, T x, T &f1r, T &d1r) {
int int_m, kf = 2, kc = 1;
T f2r = 0.0, d2r = 0.0;

if ((m < 1) || (m != floor(m)) || (q < 0)) {
f1r = std::numeric_limits<T>::quiet_NaN();
d1r = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_modsem1", SF_ERROR_DOMAIN, NULL);
} else {
using specfun::Status;
int_m = (int)m;
Status status = specfun::mtu12(kf, kc, int_m, q, x, &f1r, &d1r, &f2r, &d2r);
if (status != Status::OK) {
f1r = std::numeric_limits<T>::quiet_NaN();
d1r = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_modsem1", sf_error, NULL);
}
}
}

template <typename T>
void mcm2(T m, T q, T x, T &f2r, T &d2r) {
int int_m, kf = 1, kc = 2;
T f1r = 0.0, d1r = 0.0;

if ((m < 0) || (m != floor(m)) || (q < 0)) {
f2r = std::numeric_limits<T>::quiet_NaN();
d2r = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_modcem2", SF_ERROR_DOMAIN, NULL);
} else {
using specfun::Status;
int_m = (int)m;
Status status = specfun::mtu12(kf, kc, int_m, q, x, &f1r, &d1r, &f2r, &d2r);
if (status != Status::OK) {
f2r = std::numeric_limits<T>::quiet_NaN();
d2r = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_modcem2", sf_error, NULL);
}
}
}

template <typename T>
void msm2(T m, T q, T x, T &f2r, T &d2r) {
int int_m, kf = 2, kc = 2;
T f1r = 0.0, d1r = 0.0;

if ((m < 1) || (m != floor(m)) || (q < 0)) {
f2r = std::numeric_limits<T>::quiet_NaN();
d2r = std::numeric_limits<T>::quiet_NaN();
set_error("mathieu_modsem2", SF_ERROR_DOMAIN, NULL);
} else {
using specfun::Status;
int_m = (int)m;
Status status = specfun::mtu12(kf, kc, int_m, q, x, &f1r, &d1r, &f2r, &d2r);
if (status != Status::OK) {
f2r = std::numeric_limits<T>::quiet_NaN();
d2r = std::numeric_limits<T>::quiet_NaN();
sf_error_t sf_error = status == Status::NoMemory ? SF_ERROR_MEMORY : SF_ERROR_OTHER;
set_error("mathieu_modsem2", sf_error, NULL);
}
}
}

} // namespace xsf
37 changes: 0 additions & 37 deletions tests/scipy_special_tests/test_cem.cpp

This file was deleted.

25 changes: 0 additions & 25 deletions tests/scipy_special_tests/test_cem_cva.cpp

This file was deleted.

37 changes: 0 additions & 37 deletions tests/scipy_special_tests/test_mcm1.cpp

This file was deleted.

37 changes: 0 additions & 37 deletions tests/scipy_special_tests/test_mcm2.cpp

This file was deleted.

Loading
Loading