#include




    
 <boost/math/special_functions/legendre.hpp>
namespace boost{ namespace math{
template <class T>
calculated-result-type legendre_p(int n, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int n, T x, const Policy&);
template <class T>
calculated-result-type legendre_p_prime(int n, T x);
template <class T, class Policy>
calculated-result-type legendre_p_prime(int n, T x, const Policy&);
template <class T, class Policy>
std::vector<T> legendre_p_zeros(int l, const Policy&);
template <class T>
std::vector<T> legendre_p_zeros(int l);
template <class T>
calculated-result-type legendre_p(int n, int m, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int n, int m, T x, const Policy&);
template <class T>
calculated-result-type legendre_q(unsigned n, T x);
template <class T, class Policy>
calculated-result-type legendre_q(unsigned n, T x, const Policy&);
template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1);
template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1);
}} // namespaces

这些函数的返回类型是使用结果类型计算规则计算的:请注意,当只有一个模板参数时,结果类型与该参数类型相同;如果模板参数是整数类型,则结果类型为 double

最后的 Policy 参数是可选的,可用于控制函数的行为:如何处理错误、使用什么精度级别等。有关更多详细信息,请参阅 policy 文档

template <class T>
calculated-result-type legendre_p(int l, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int l, T x, const Policy&);

返回第一类勒让德多项式

calculated-result-type legendre_p_prime(int n, T x); template <class T, class Policy> calculated-result-type legendre_p_prime(int n, T x, const Policy&);

返回勒让德多项式的导数。

template <class T, class Policy>
std::vector<T> legendre_p_zeros(int l, const Policy&);
template <class T>
std::vector<T> legendre_p_zeros(int l);

勒让德多项式的零点是通过牛顿法计算的,初始猜测由 Tricomi 给出,根的括弧由 Szego 提供。

由于勒让德多项式是交替的偶函数和奇函数,因此仅返回非负零点。对于奇勒让德多项式,第一个零点始终为零。其余零点按递增顺序返回。

请注意,该例程的参数是整数,而输出是浮点类型。因此,模板参数是强制性的。提取单个根的时间与 l 成线性关系(这是评估勒让德多项式的缩放比例),因此恢复所有根的时间复杂度为 𝑶(l2)。存在具有线性缩放的算法可以恢复所有根,但这需要当前 boost.math 中未构建的工具。此实现是在假设计算这些函数的零点不会成为任何工作流程的瓶颈的情况下进行的。

template <class T>
calculated-result-type legendre_p(int l, int m, T x);
template <class T, class Policy>
calculated-result-type legendre_p(int l, int m, T x, const Policy&);

返回第一类连带勒让德多项式

此处使用的连带勒让德多项式的定义包括一个前导 Condon-Shortley 相位项 (-1)m。这与 Abramowitz 和 Stegun (8.6.6) 给出的定义以及 MathworldMathematica 的 LegendreP 函数使用的定义相匹配。然而,文献中的用法并不总是包含这个相位项,奇怪的是,尽管 C++ TR1 (assoc_legendre) 中连带勒让德函数的规范也省略了它,尽管它声明它使用 Abramowitz 和 Stegun 作为这些问题的最终仲裁者。

Weisstein, Eric W. “勒让德多项式。” 来自 MathWorld——Wolfram Web 资源.

Abramowitz, M. 和 Stegun, I. A. (编辑)。 “勒让德函数”和“正交多项式”。 《数学函数手册(含公式、图表和数学表格)》第 9 版,第 8 章和第 22 章中的第 22 章。纽约:Dover,第 331-339 页和第 771-802 页,1972 年。

template <class T>
calculated-result-type legendre_q(unsigned n, T x);
template <class T, class Policy>
calculated-result-type legendre_q(unsigned n, T x, const Policy&);

返回勒让德多项式的值,该值是勒让德微分方程的第二个解,例如

template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, T1 x, T2 Pl, T3 Plm1);

实现了勒让德多项式的三项递推关系,此函数可用于创建在相同的 x 值处评估以及对于递增的 l 值的序列。此递推关系适用于第一类和第二类勒让德多项式。

double x = 0.5;  // Abscissa value
vector<double> v;
v.push_back(legendre_p(0, x));
v.push_back(legendre_p(1, x));
for(unsigned l = 1; l < 10; ++l)
   v.push_back(legendre_next(l, x, v[l], v[l-1]));
// Double check values:
for(unsigned l = 1; l < 10; ++l)
   assert(v[l] == legendre_p(l, x));

正式参数为

最后计算的多项式的次数。

在次数 l 处评估的多项式的值。

在次数 l-1 处评估的多项式的值。

template <class T1, class T2, class T3>
calculated-result-type legendre_next(unsigned l, unsigned m, T1 x, T2 Pl, T3 Plm1);

实现了连带勒让德多项式的三项递推关系,此函数可用于创建在相同的 x 值处评估以及对于递增的 l 值的序列。

例如,我们可以使用以下方法生成前 m+10 个多项式值的向量

double x = 0.5;  // Abscissa value
int m = 10;      // order
vector<double> v;
v.push_back(legendre_p(m, m, x));
v.push_back(legendre_p(1 + m, m, x));
for(unsigned l = 1; l < 10; ++l)
   v.push_back(legendre_next(l + 10, m, x, v[l], v[l-1]));
// Double check values:
for(unsigned l = 1; l < 10; ++l)
   assert(v[l] == legendre_p(10 + l, m, x));

正式参数为

最后计算的多项式的次数。

连带多项式的阶数。

在次数 l 处评估的多项式的值。

在次数 l-1 处评估的多项式的值。

下表显示了各种输入参数域的峰值误差(以 epsilon 为单位)。请注意,仅给出了系统上最宽浮点类型的结果,因为较窄的类型具有实际上为零的误差

表 8.32. legendre_p 的错误率


请注意,最坏的错误发生在阶数增加时,大于 ~120 的值不太可能产生合理的结果,尤其是在连带多项式情况下,当次数也很大时。此外,当函数非常接近根时,相对误差可能会变得任意大。

使用了混合的点测试(使用 functions.wolfram.com 计算的值)和随机生成的测试数据:测试数据是使用 1000 位精度的 NTL::RR 计算的。

这些函数是使用稳定的三项递推关系实现的。这些关系保证了较低的绝对误差,但不能保证在多项式根附近具有较低的相对误差。