Skip to content

Problem with scaling of derivative output of Mathieu functions. #68

@WarrenWeckesser

Description

@WarrenWeckesser

Over in scipy/scipy#14580, it was pointed out that the scaling for the derivative output of scipy.special.mathieu_cem and scipy.special.mathieu_sem was not correct. In those Python functions, the x argument is given in degrees. The problem is that the returned derivative behaves as if the input was in radians--it is missing the scaling factor of π/180.

I have created this issue here because the problem was brought over to xsf. This program (using C++20)

#include <iomanip>
#include <iostream>
#include <numbers>
#include <xsf/mathieu.h>

int main(int argc, char *argv[])
{
    using std::numbers::pi_v;
    double f, df;

    double m = 3.0;
    double q = 1.5;
    double theta = 1.0;                     // radians
    double angle = theta*180/pi_v<double>;  // degrees
    xsf::cem(m, q, angle, f, df);

    std::cout << std::setprecision(15);
    std::cout << "f = " << f << std::endl;
    std::cout << "df          = " << df << std::endl;

    double h = 1e-8;
    double fplus, fminus, tmp;
    xsf::cem(m, q, angle + h, fplus, tmp);
    xsf::cem(m, q, angle - h, fminus, tmp);
    double approx_diff = (fplus - fminus)/(2*h);
    std::cout << "finite diff = " << approx_diff << std::endl;
    std::cout << "df*π/180    = " << df * pi_v<double> / 180.0 << std::endl;

    return 0;
}

prints

f = -0.867785570960645
df          = -1.05398845039289
finite diff = -0.0183955628507704
df*π/180    = -0.0183955687373489

You can check with Wolfram Alpha (MathieuCPrime(MathieuCharacteristicA(3, 3/2), 3/2, 1)) that df is the value that would be correct if the implementation of xsf::cem accepted radians instead of degrees. With degrees, the values of df should be -0.018395568737348884.

The program computes a numerical approximation to the derivative to verify that df is off by a factor of π/180.

The straightforward fix is to multiply the derivative outputs by pi/180 before returning.

(Personally, I wouldn't mind if we changed all the Mathieu functions to accept radians instead of degrees. Over in SciPy, we would have to find a way to make the transition that is not too painful--may just create a new set of functions, and slowly deprecate (or at least doc-deprecate) the ones that accept degrees.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions