77/// # Examples
88///
99/// ```
10- /// # use boost::math::{hermite, hermite_next };
10+ /// # use boost::math::{hermite_h, hermite_h_next };
1111/// let x = 0.42;
12- /// let h0 = hermite (0, x); // 1
13- /// let h1 = hermite (1, x); // 2x
14- /// let h2 = hermite (2, x); // 4x² - 2
15- /// let h3 = hermite (3, x); // 8x³ - 12x
16- /// assert_eq!(hermite_next (1, x, h1, h0 ), h2 );
17- /// assert_eq!(hermite_next (2, x, h2, h1 ), h3 );
12+ /// let p0 = hermite_h (0, x); // 1
13+ /// let p1 = hermite_h (1, x); // 2x
14+ /// let p2 = hermite_h (2, x); // 4x² - 2
15+ /// let p3 = hermite_h (3, x); // 8x³ - 12x
16+ /// assert_eq!(hermite_h_next (1, x, p1, p0 ), p2 );
17+ /// assert_eq!(hermite_h_next (2, x, p2, p1 ), p3 );
1818/// ```
19- #[ allow( non_snake_case) ]
2019#[ inline( always) ]
21- pub fn hermite_h_next ( n : u32 , x : f64 , Hn : f64 , Hn_prev : f64 ) -> f64 {
22- 2.0 * ( x * Hn - ( n as f64 ) * Hn_prev )
20+ pub fn hermite_h_next ( n : u32 , x : f64 , pn : f64 , pn_prev : f64 ) -> f64 {
21+ 2.0 * hermite_he_next ( n, x, pn, pn_prev)
22+ }
23+
24+ /// Recurrence relation for [`hermite_he`]
25+ ///
26+ /// *He<sub>n+1</sub>(x) = x He<sub>n</sub>(x) - n He<sub>n-1</sub>(x)*
27+ ///
28+ /// # Examples
29+ ///
30+ /// ```
31+ /// # use boost::math::{hermite_he, hermite_he_next};
32+ /// let x = 0.42;
33+ /// let p0 = hermite_he(0, x); // 1
34+ /// let p1 = hermite_he(1, x); // 2x
35+ /// let p2 = hermite_he(2, x); // 4x² - 2
36+ /// let p3 = hermite_he(3, x); // 8x³ - 12x
37+ /// assert_eq!(hermite_he_next(1, x, p1, p0), p2);
38+ /// assert_eq!(hermite_he_next(2, x, p2, p1), p3);
39+ /// ```
40+ #[ inline( always) ]
41+ pub fn hermite_he_next ( n : u32 , x : f64 , pn : f64 , pn_prev : f64 ) -> f64 {
42+ x * pn - ( n as f64 ) * pn_prev
2343}
2444
2545/// Hermite Polynomial *H<sub>n</sub>(x)*
@@ -41,22 +61,57 @@ pub fn hermite_h(n: u32, x: f64) -> f64 {
4161 }
4262}
4363
64+ /// Monic Hermite Polynomial *He<sub>n</sub>(x)*
65+ ///
66+ /// Note that this is the "probabilist's" Hermite polynomial, which is monic (leading coefficient
67+ /// is 1). It is related to the "physicist's" Hermite polynomial ([`hermite_h`]) by
68+ ///
69+ /// *He<sub>n</sub>(x) = 2<sup>-n/2</sup> H<sub>n</sub>(x / √2)*
70+ ///
71+ /// This function does not exist in the Boost Math C++ library.
72+ pub fn hermite_he ( n : u32 , x : f64 ) -> f64 {
73+ let ( mut p0, mut p1) = ( 1.0 , x) ;
74+ if n == 0 {
75+ p0
76+ } else {
77+ for c in 1 ..n {
78+ ( p0, p1) = ( p1, hermite_he_next ( c, x, p1, p0) ) ;
79+ }
80+ p1
81+ }
82+ }
83+
4484#[ cfg( test) ]
4585mod tests {
4686 use super :: * ;
87+ use core:: f64:: consts:: FRAC_1_SQRT_2 ;
4788
48- const RTOL : f64 = 1e-14 ;
89+ const ATOL : f64 = 1e-15 ;
90+ const RTOL : f64 = 1e-12 ;
4991
5092 fn hermite_h_ffi ( n : u32 , x : f64 ) -> f64 {
5193 unsafe { crate :: ffi:: math_hermite ( n as core:: ffi:: c_uint , x) }
5294 }
5395
5496 #[ test]
55- fn test_hermite ( ) {
97+ fn test_hermite_h ( ) {
98+ for n in 0 ..20 {
99+ for x in -10 ..=10 {
100+ let x = x as f64 * 0.1 ;
101+ let h = hermite_h_ffi ( n, x) ;
102+ assert_relative_eq ! ( hermite_h( n, x) , h, epsilon = ATOL , max_relative = RTOL ) ;
103+ }
104+ }
105+ }
106+
107+ #[ test]
108+ fn test_hermite_he ( ) {
56109 for n in 0 ..20 {
57- for x in -2 ..=2 {
110+ let c = FRAC_1_SQRT_2 . powi ( n as i32 ) ;
111+ for x in -10 ..=10 {
58112 let x = x as f64 * 0.1 ;
59- assert_relative_eq ! ( hermite_h( n, x) , hermite_h_ffi( n, x) , max_relative = RTOL ) ;
113+ let h = c * hermite_h ( n, FRAC_1_SQRT_2 * x) ;
114+ assert_relative_eq ! ( hermite_he( n, x) , h, epsilon = ATOL , max_relative = RTOL ) ;
60115 }
61116 }
62117 }
0 commit comments