Skip to content

Ordinary and associated Legendre functions

Import Legendre from gem.legendre. Source, independent Rodrigues references through degree 12.

Supported degree/order are integers 0≤m≤l. Associated values require x in [-1,1]; ordinary m=0 polynomials also evaluate outside that interval. Functions are unnormalized, with Condon–Shortley phase:

Pmm(x)=(−1)m(2m−1)!!(1−x2)m/2,Pm+1m(x)=x(2m+1)Pmm(x),
Plm(x)=(2l−1)xPl−1m(x)−(l+m−1)Pl−2m(x)l−m.

SH applies its own normalization; do not substitute a different phase convention. No module constants exist.

See the ordinary-function plot and notation to connect degree, parity and endpoint behavior.

Exact source declaration Parameters, result and behavior
Legendre Mutable degree/order/argument and scratch container; construction does not evaluate.
Legendre.__init__(self, l, m, x) Store numeric l,m,x directly; initialize P=1.0, PM1=PML=0.0; return None. No generalized domain validation.
Legendre.mGreaterThan0(self) Rebuild scratch P=P_m^m from current m/x; even m=0 resets P to 1; return None. Deterministic repeated initialization.
Legendre.calculatePM1(self) Reset P seed, set PM1=x(2m+1)P; return None; mutates P and PM1.
Legendre.calculatePML(self, i) i: target integer degree ≥m; reset P/PM1 and set PML from recurrence; return None; explicit scratch mutation. Wider invalid-degree behavior is historical.
Legendre.run(self) Numeric P_l^m result from local recurrence; preserve P/PM1/PML and l/m/x. Historical l<m returns stored PML rather than raising a new validation exception.

Fields .l, .m, .x, .P, .PM1, .PML are mutable and not copied from another polynomial. run() does not use helper-mutated state for valid degrees. Noninteger orders can produce TypeError from range; associated x outside [-1,1] can raise ValueError from sqrt. Negative orders/degrees, nonfinite inputs, high-order overflow and generalized invalid-input behavior remain unsupported rather than covered by a new validation policy.

Ordinary builtin int/float extrapolation retries overflowing recurrence steps with power-of-two scaling when the preceding values are finite. Finite ordinary steps keep their existing rounding; associated phase and normalization are unchanged. A genuinely unrepresentable result can still be infinity, and high-order range/conditioning limits remain. See the numerical repair evidence.

import math
from gem.legendre import Legendre

p = Legendre(2, 0, 0.5)
assert p.run() == -0.125            # (3*x*x-1)/2
assert (p.P, p.PM1, p.PML) == (1.0, 0.0, 0.0)
assert p.run() == p.run()
a = Legendre(2, 1, 0.5)
assert abs(a.run() + 3 * 0.5 * math.sqrt(0.75)) < 1e-14
assert Legendre(12, 0, 1).run() == 1.0
assert a.calculatePML(2) is None
assert abs(a.PML - a.run()) < 1e-14

See SH normalization, shims, decisions and index.