rgsl/
legendre.rs

1//
2// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
3//
4
5//! The Legendre Functions and Legendre Polynomials are described in Abramowitz & Stegun, Chapter 8.
6
7pub mod polynomials {
8    use crate::{types, Value};
9    use std::mem::MaybeUninit;
10
11    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
12    #[doc(alias = "gsl_sf_legendre_P1")]
13    pub fn legendre_P1(x: f64) -> f64 {
14        unsafe { sys::gsl_sf_legendre_P1(x) }
15    }
16
17    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
18    #[doc(alias = "gsl_sf_legendre_P2")]
19    pub fn legendre_P2(x: f64) -> f64 {
20        unsafe { sys::gsl_sf_legendre_P2(x) }
21    }
22
23    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
24    #[doc(alias = "gsl_sf_legendre_P3")]
25    pub fn legendre_P3(x: f64) -> f64 {
26        unsafe { sys::gsl_sf_legendre_P3(x) }
27    }
28
29    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
30    #[doc(alias = "gsl_sf_legendre_P1_e")]
31    pub fn legendre_P1_e(x: f64) -> Result<types::Result, Value> {
32        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
33        let ret = unsafe { sys::gsl_sf_legendre_P1_e(x, result.as_mut_ptr()) };
34
35        result_handler!(ret, unsafe { result.assume_init() }.into())
36    }
37
38    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
39    #[doc(alias = "gsl_sf_legendre_P2_e")]
40    pub fn legendre_P2_e(x: f64) -> Result<types::Result, Value> {
41        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
42        let ret = unsafe { sys::gsl_sf_legendre_P2_e(x, result.as_mut_ptr()) };
43
44        result_handler!(ret, unsafe { result.assume_init() }.into())
45    }
46
47    /// This function evaluates the Legendre polynomials P_l(x) using explicit representations for l=1, 2, 3.
48    #[doc(alias = "gsl_sf_legendre_P3_e")]
49    pub fn legendre_P3_e(x: f64) -> Result<types::Result, Value> {
50        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
51        let ret = unsafe { sys::gsl_sf_legendre_P3_e(x, result.as_mut_ptr()) };
52
53        result_handler!(ret, unsafe { result.assume_init() }.into())
54    }
55
56    /// This function evaluates the Legendre polynomial P_l(x) for a specific value of l, x subject to l >= 0, |x| <= 1
57    #[doc(alias = "gsl_sf_legendre_Pl")]
58    pub fn legendre_Pl(l: i32, x: f64) -> f64 {
59        unsafe { sys::gsl_sf_legendre_Pl(l, x) }
60    }
61
62    /// This function evaluates the Legendre polynomial P_l(x) for a specific value of l, x subject to l >= 0, |x| <= 1
63    #[doc(alias = "gsl_sf_legendre_Pl_e")]
64    pub fn legendre_Pl_e(l: i32, x: f64) -> Result<types::Result, Value> {
65        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
66        let ret = unsafe { sys::gsl_sf_legendre_Pl_e(l, x, result.as_mut_ptr()) };
67
68        result_handler!(ret, unsafe { result.assume_init() }.into())
69    }
70
71    /// This function computes arrays of Legendre polynomials P_l(x) and derivatives dP_l(x)/dx, for l = 0, \dots, lmax, |x| <= 1
72    #[doc(alias = "gsl_sf_legendre_Pl_array")]
73    pub fn legendre_Pl_array(lmax: usize, x: f64, result_array: &mut [f64]) -> Result<(), Value> {
74        let ret = unsafe { sys::gsl_sf_legendre_Pl_array(lmax as _, x, result_array.as_mut_ptr()) };
75        result_handler!(ret, ())
76    }
77
78    /// This function computes arrays of Legendre polynomials P_l(x) and derivatives dP_l(x)/dx, for l = 0, \dots, lmax, |x| <= 1
79    #[doc(alias = "gsl_sf_legendre_Pl_deriv_array")]
80    pub fn legendre_Pl_deriv_array(
81        x: f64,
82        result_array: &mut [f64],
83        result_deriv_array: &mut [f64],
84    ) -> Result<(), Value> {
85        let ret = unsafe {
86            sys::gsl_sf_legendre_Pl_deriv_array(
87                result_array.len() as _,
88                x,
89                result_array.as_mut_ptr(),
90                result_deriv_array.as_mut_ptr(),
91            )
92        };
93        result_handler!(ret, ())
94    }
95
96    /// This function computes the Legendre function Q_0(x) for x > -1, x != 1
97    #[doc(alias = "gsl_sf_legendre_Q0")]
98    pub fn legendre_Q0(x: f64) -> f64 {
99        unsafe { sys::gsl_sf_legendre_Q0(x) }
100    }
101
102    /// This function computes the Legendre function Q_0(x) for x > -1, x != 1
103    #[doc(alias = "gsl_sf_legendre_Q0_e")]
104    pub fn legendre_Q0_e(x: f64) -> Result<types::Result, Value> {
105        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
106        let ret = unsafe { sys::gsl_sf_legendre_Q0_e(x, result.as_mut_ptr()) };
107
108        result_handler!(ret, unsafe { result.assume_init() }.into())
109    }
110
111    /// This function computes the Legendre function Q_0(x) for x > -1, x != 1.
112    #[doc(alias = "gsl_sf_legendre_Q1")]
113    pub fn legendre_Q1(x: f64) -> f64 {
114        unsafe { sys::gsl_sf_legendre_Q1(x) }
115    }
116
117    /// This function computes the Legendre function Q_0(x) for x > -1, x != 1.
118    #[doc(alias = "gsl_sf_legendre_Q1_e")]
119    pub fn legendre_Q1_e(x: f64) -> Result<types::Result, Value> {
120        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
121        let ret = unsafe { sys::gsl_sf_legendre_Q1_e(x, result.as_mut_ptr()) };
122
123        result_handler!(ret, unsafe { result.assume_init() }.into())
124    }
125
126    /// This function computes the Legendre function Q_l(x) for x > -1, x != 1 and l >= 0.
127    #[doc(alias = "gsl_sf_legendre_Ql")]
128    pub fn legendre_Ql(l: i32, x: f64) -> f64 {
129        unsafe { sys::gsl_sf_legendre_Ql(l, x) }
130    }
131
132    /// This function computes the Legendre function Q_l(x) for x > -1, x != 1 and l >= 0.
133    #[doc(alias = "gsl_sf_legendre_Ql_e")]
134    pub fn legendre_Ql_e(l: i32, x: f64) -> Result<types::Result, Value> {
135        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
136        let ret = unsafe { sys::gsl_sf_legendre_Ql_e(l, x, result.as_mut_ptr()) };
137
138        result_handler!(ret, unsafe { result.assume_init() }.into())
139    }
140}
141
142/// The following functions compute the associated Legendre Polynomials P_l^m(x).
143/// Note that this function grows combinatorially with l and can overflow for l larger than about 150.
144/// There is no trouble for small m, but overflow occurs when m and l are both large.
145/// Rather than allow overflows, these functions refuse to calculate P_l^m(x) and return [`OvrFlw`](enums/type.Value.html) when they can sense that l and m are too big.
146///
147/// If you want to calculate a spherical harmonic, then do not use these functions. Instead use [`legendre_sphPlm`](fn.legendre_sphPlm.html) below, which uses a similar recursion, but with the normalized functions.
148pub mod associated_polynomials {
149    use crate::{enums, types, Value};
150    use std::mem::MaybeUninit;
151
152    /// This routine computes the associated Legendre polynomial P_l^m(x) for m >= 0, l >= m, |x| <= 1.
153    #[doc(alias = "gsl_sf_legendre_Plm")]
154    pub fn legendre_Plm(l: i32, m: i32, x: f64) -> f64 {
155        unsafe { sys::gsl_sf_legendre_Plm(l, m, x) }
156    }
157
158    /// This routine computes the associated Legendre polynomial P_l^m(x) for m >= 0, l >= m, |x| <= 1.
159    #[doc(alias = "gsl_sf_legendre_Plm_e")]
160    pub fn legendre_Plm_e(l: i32, m: i32, x: f64) -> Result<types::Result, Value> {
161        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
162        let ret = unsafe { sys::gsl_sf_legendre_Plm_e(l, m, x, result.as_mut_ptr()) };
163
164        result_handler!(ret, unsafe { result.assume_init() }.into())
165    }
166
167    /// This routine computes the normalized associated Legendre polynomial \sqrt{(2l+1)/(4\pi)} \sqrt{(l-m)!/(l+m)!} P_l^m(x) suitable for use in spherical harmonics.
168    /// The parameters must satisfy m >= 0, l >= m, |x| <= 1.
169    /// This routine avoids the overflows that occur for the standard normalization of P_l^m(x).
170    #[doc(alias = "gsl_sf_legendre_sphPlm")]
171    pub fn legendre_sphPlm(l: i32, m: i32, x: f64) -> f64 {
172        unsafe { sys::gsl_sf_legendre_sphPlm(l, m, x) }
173    }
174
175    /// This routine computes the normalized associated Legendre polynomial \sqrt{(2l+1)/(4\pi)} \sqrt{(l-m)!/(l+m)!} P_l^m(x) suitable for use in spherical harmonics.
176    /// The parameters must satisfy m >= 0, l >= m, |x| <= 1.
177    /// This routine avoids the overflows that occur for the standard normalization of P_l^m(x).
178    #[doc(alias = "gsl_sf_legendre_sphPlm_e")]
179    pub fn legendre_sphPlm_e(l: i32, m: i32, x: f64) -> Result<types::Result, Value> {
180        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
181        let ret = unsafe { sys::gsl_sf_legendre_sphPlm_e(l, m, x, result.as_mut_ptr()) };
182
183        result_handler!(ret, unsafe { result.assume_init() }.into())
184    }
185
186    /// Returns the size of the array needed for these functions, including GSL workspace.
187    #[doc(alias = "gsl_sf_legendre_array_n")]
188    pub fn legendre_array_n(lmax: usize) -> usize {
189        unsafe { sys::gsl_sf_legendre_array_n(lmax as _) }
190    }
191
192    #[doc(alias = "gsl_sf_legendre_array_index")]
193    pub fn legendre_array_index(l: usize, m: usize) -> usize {
194        unsafe { sys::gsl_sf_legendre_array_index(l as _, m as _) }
195    }
196
197    #[doc(alias = "gsl_sf_legendre_array")]
198    pub fn legendre_array(
199        norm: enums::SfLegendreNorm,
200        lmax: usize,
201        x: f64,
202        result: &mut [f64],
203    ) -> Result<(), Value> {
204        let ret = unsafe { sys::gsl_sf_legendre_array(norm.into(), lmax, x, result.as_mut_ptr()) };
205        result_handler!(ret, ())
206    }
207
208    #[doc(alias = "gsl_sf_legendre_deriv_array")]
209    pub fn legendre_deriv_array(
210        norm: enums::SfLegendreNorm,
211        lmax: usize,
212        x: f64,
213        result: &mut [f64],
214        deriv: &mut [f64],
215    ) -> Result<(), Value> {
216        let ret = unsafe {
217            sys::gsl_sf_legendre_deriv_array(
218                norm.into(),
219                lmax,
220                x,
221                result.as_mut_ptr(),
222                deriv.as_mut_ptr(),
223            )
224        };
225        result_handler!(ret, ())
226    }
227}
228
229/// The Conical Functions P^\mu_{-(1/2)+i\lambda}(x) and Q^\mu_{-(1/2)+i\lambda} are described in Abramowitz & Stegun, Section 8.12.
230pub mod conical {
231    use crate::{types, Value};
232    use std::mem::MaybeUninit;
233
234    /// This routine computes the irregular Spherical Conical Function P^{1/2}_{-1/2 + i \lambda}(x) for x > -1.
235    #[doc(alias = "gsl_sf_conicalP_half")]
236    pub fn half(lambda: f64, x: f64) -> f64 {
237        unsafe { sys::gsl_sf_conicalP_half(lambda, x) }
238    }
239
240    /// This routine computes the irregular Spherical Conical Function P^{1/2}_{-1/2 + i \lambda}(x) for x > -1.
241    #[doc(alias = "gsl_sf_conicalP_half_e")]
242    pub fn half_e(lambda: f64, x: f64) -> Result<types::Result, Value> {
243        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
244        let ret = unsafe { sys::gsl_sf_conicalP_half_e(lambda, x, result.as_mut_ptr()) };
245
246        result_handler!(ret, unsafe { result.assume_init() }.into())
247    }
248
249    /// This routine computes the regular Spherical Conical Function P^{-1/2}_{-1/2 + i \lambda}(x) for x > -1.
250    #[doc(alias = "gsl_sf_conicalP_mhalf")]
251    pub fn mhalf(lambda: f64, x: f64) -> f64 {
252        unsafe { sys::gsl_sf_conicalP_mhalf(lambda, x) }
253    }
254
255    /// This routine computes the regular Spherical Conical Function P^{-1/2}_{-1/2 + i \lambda}(x) for x > -1.
256    #[doc(alias = "gsl_sf_conicalP_mhalf_e")]
257    pub fn mhalf_e(lambda: f64, x: f64) -> Result<types::Result, Value> {
258        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
259        let ret = unsafe { sys::gsl_sf_conicalP_mhalf_e(lambda, x, result.as_mut_ptr()) };
260
261        result_handler!(ret, unsafe { result.assume_init() }.into())
262    }
263
264    /// This routine computes the conical function P^0_{-1/2 + i \lambda}(x) for x > -1.
265    #[doc(alias = "gsl_sf_conicalP_0")]
266    pub fn _0(lambda: f64, x: f64) -> f64 {
267        unsafe { sys::gsl_sf_conicalP_0(lambda, x) }
268    }
269
270    /// This routine computes the conical function P^0_{-1/2 + i \lambda}(x) for x > -1.
271    #[doc(alias = "gsl_sf_conicalP_0_e")]
272    pub fn _0_e(lambda: f64, x: f64) -> Result<types::Result, Value> {
273        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
274        let ret = unsafe { sys::gsl_sf_conicalP_0_e(lambda, x, result.as_mut_ptr()) };
275
276        result_handler!(ret, unsafe { result.assume_init() }.into())
277    }
278
279    /// This routine computes the conical function P^1_{-1/2 + i \lambda}(x) for x > -1.
280    #[doc(alias = "gsl_sf_conicalP_1")]
281    pub fn _1(lambda: f64, x: f64) -> f64 {
282        unsafe { sys::gsl_sf_conicalP_1(lambda, x) }
283    }
284
285    /// This routine computes the conical function P^1_{-1/2 + i \lambda}(x) for x > -1.
286    #[doc(alias = "gsl_sf_conicalP_1_e")]
287    pub fn _1_e(lambda: f64, x: f64) -> Result<types::Result, Value> {
288        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
289        let ret = unsafe { sys::gsl_sf_conicalP_1_e(lambda, x, result.as_mut_ptr()) };
290
291        result_handler!(ret, unsafe { result.assume_init() }.into())
292    }
293
294    /// This routine computes the Regular Spherical Conical Function P^{-1/2-l}_{-1/2 + i \lambda}(x) for x > -1, l >= -1.
295    #[doc(alias = "gsl_sf_conicalP_sph_reg")]
296    pub fn sph_reg(l: i32, lambda: f64, x: f64) -> f64 {
297        unsafe { sys::gsl_sf_conicalP_sph_reg(l, lambda, x) }
298    }
299
300    /// This routine computes the Regular Spherical Conical Function P^{-1/2-l}_{-1/2 + i \lambda}(x) for x > -1, l >= -1.
301    #[doc(alias = "gsl_sf_conicalP_sph_reg_e")]
302    pub fn sph_reg_e(l: i32, lambda: f64, x: f64) -> Result<types::Result, Value> {
303        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
304        let ret = unsafe { sys::gsl_sf_conicalP_sph_reg_e(l, lambda, x, result.as_mut_ptr()) };
305
306        result_handler!(ret, unsafe { result.assume_init() }.into())
307    }
308
309    /// This routine computes the Regular Cylindrical Conical Function P^{-m}_{-1/2 + i \lambda}(x) for x > -1, m >= -1.
310    #[doc(alias = "gsl_sf_conicalP_cyl_reg")]
311    pub fn cyl_reg(m: i32, lambda: f64, x: f64) -> f64 {
312        unsafe { sys::gsl_sf_conicalP_cyl_reg(m, lambda, x) }
313    }
314
315    /// This routine computes the Regular Cylindrical Conical Function P^{-m}_{-1/2 + i \lambda}(x) for x > -1, m >= -1.
316    #[doc(alias = "gsl_sf_conicalP_cyl_reg_e")]
317    pub fn cyl_reg_e(m: i32, lambda: f64, x: f64) -> Result<types::Result, Value> {
318        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
319        let ret = unsafe { sys::gsl_sf_conicalP_cyl_reg_e(m, lambda, x, result.as_mut_ptr()) };
320
321        result_handler!(ret, unsafe { result.assume_init() }.into())
322    }
323}
324
325/// The following spherical functions are specializations of Legendre functions which give the regular eigenfunctions of the Laplacian on a 3-dimensional hyperbolic space H3d.
326/// Of particular interest is the flat limit, \lambda \to \infty, \eta \to 0, \lambda\eta fixed.
327pub mod radial {
328    use crate::{types, Value};
329    use std::mem::MaybeUninit;
330
331    /// This routine computes the zeroth radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space, L^{H3d}_0(\lambda,\eta) := \sin(\lambda\eta)/(\lambda\sinh(\eta)) for \eta >= 0.
332    /// In the flat limit this takes the form L^{H3d}_0(\lambda,\eta) = j_0(\lambda\eta).
333    #[doc(alias = "gsl_sf_legendre_H3d_0")]
334    pub fn legendre_H3d_0(lambda: f64, eta: f64) -> f64 {
335        unsafe { sys::gsl_sf_legendre_H3d_0(lambda, eta) }
336    }
337
338    /// This routine computes the zeroth radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space, L^{H3d}_0(\lambda,\eta) := \sin(\lambda\eta)/(\lambda\sinh(\eta)) for \eta >= 0.
339    /// In the flat limit this takes the form L^{H3d}_0(\lambda,\eta) = j_0(\lambda\eta).
340    #[doc(alias = "gsl_sf_legendre_H3d_0_e")]
341    pub fn legendre_H3d_0_e(lambda: f64, eta: f64) -> Result<types::Result, Value> {
342        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
343        let ret = unsafe { sys::gsl_sf_legendre_H3d_0_e(lambda, eta, result.as_mut_ptr()) };
344
345        result_handler!(ret, unsafe { result.assume_init() }.into())
346    }
347
348    /// This routine computes the first radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space, L^{H3d}_1(\lambda,\eta) := 1/\sqrt{\lambda^2 + 1} \sin(\lambda \eta)/(\lambda \sinh(\eta))
349    /// (\coth(\eta) - \lambda \cot(\lambda\eta)) for \eta >= 0.
350    /// In the flat limit this takes the form L^{H3d}_1(\lambda,\eta) = j_1(\lambda\eta).
351    #[doc(alias = "gsl_sf_legendre_H3d_1")]
352    pub fn legendre_H3d_1(lambda: f64, eta: f64) -> f64 {
353        unsafe { sys::gsl_sf_legendre_H3d_1(lambda, eta) }
354    }
355
356    /// This routine computes the first radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space, L^{H3d}_1(\lambda,\eta) := 1/\sqrt{\lambda^2 + 1} \sin(\lambda \eta)/(\lambda \sinh(\eta))
357    /// (\coth(\eta) - \lambda \cot(\lambda\eta)) for \eta >= 0.
358    /// In the flat limit this takes the form L^{H3d}_1(\lambda,\eta) = j_1(\lambda\eta).
359    #[doc(alias = "gsl_sf_legendre_H3d_1_e")]
360    pub fn legendre_H3d_1_e(lambda: f64, eta: f64) -> Result<types::Result, Value> {
361        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
362        let ret = unsafe { sys::gsl_sf_legendre_H3d_1_e(lambda, eta, result.as_mut_ptr()) };
363
364        result_handler!(ret, unsafe { result.assume_init() }.into())
365    }
366
367    /// This routine computes the l-th radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space \eta >= 0, l >= 0. In the flat limit this takes the form L^{H3d}_l(\lambda,\eta) = j_l(\lambda\eta).
368    #[doc(alias = "gsl_sf_legendre_H3d")]
369    pub fn legendre_H3d(l: i32, lambda: f64, eta: f64) -> f64 {
370        unsafe { sys::gsl_sf_legendre_H3d(l, lambda, eta) }
371    }
372
373    /// This routine computes the l-th radial eigenfunction of the Laplacian on the 3-dimensional hyperbolic space \eta >= 0, l >= 0. In the flat limit this takes the form L^{H3d}_l(\lambda,\eta) = j_l(\lambda\eta).
374    #[doc(alias = "gsl_sf_legendre_H3d_e")]
375    pub fn legendre_H3d_e(l: i32, lambda: f64, eta: f64) -> Result<types::Result, Value> {
376        let mut result = MaybeUninit::<sys::gsl_sf_result>::uninit();
377        let ret = unsafe { sys::gsl_sf_legendre_H3d_e(l, lambda, eta, result.as_mut_ptr()) };
378
379        result_handler!(ret, unsafe { result.assume_init() }.into())
380    }
381
382    /// This function computes an array of radial eigenfunctions L^{H3d}_l(\lambda, \eta) for 0 <= l <= lmax.
383    #[doc(alias = "gsl_sf_legendre_H3d_array")]
384    pub fn legendre_H3d_array(
385        lambda: f64,
386        eta: f64,
387        result_array: &mut [f64],
388    ) -> Result<(), Value> {
389        let ret = unsafe {
390            sys::gsl_sf_legendre_H3d_array(
391                result_array.len() as _,
392                lambda,
393                eta,
394                result_array.as_mut_ptr(),
395            )
396        };
397        result_handler!(ret, ())
398    }
399}