Developer documentation
Version 3.0.3-105-gd3941f44
legendre.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __math_legendre_h__
18#define __math_legendre_h__
19
20#include "math/math.h"
21
22namespace MR
23{
24 namespace Math
25 {
26 namespace Legendre
27 {
28
29 template <typename ValueType>
30 inline ValueType factorial (const ValueType n)
31 {
32 return (n < 2.0 ? 1.0 : n*factorial (n-1.0));
33 }
34
35 template <typename ValueType>
36 inline ValueType double_factorial (const ValueType n)
37 {
38 return (n < 2.0 ? 1.0 : n*double_factorial (n-2.0));
39 }
40
41 template <typename ValueType>
42 inline ValueType Plm (const int l, const int m, const ValueType x)
43 {
44 if (m && abs (x) >= 1.0) return (0.0);
45 ValueType v0 = 1.0;
46 if (m > 0) v0 = double_factorial (ValueType (2*m-1)) * pow (1.0-pow2 (x), m/2.0);
47 if (m & 1) v0 = -v0; // (-1)^m
48 if (l == m) return (v0);
49
50 ValueType v1 = x * (2*m+1) * v0;
51 if (l == m+1) return (v1);
52
53 for (int n = m+2; n <= l; n++) {
54 ValueType v2 = ( (2.0*n-1.0) *x*v1 - (n+m-1) *v0) / (n-m);
55 v0 = v1;
56 v1 = v2;
57 }
58
59 return (v1);
60 }
61
62
63 namespace
64 {
65 template <typename ValueType>
66 inline ValueType Plm_sph_helper (const ValueType x, const ValueType m)
67 {
68 return (m < 1.0 ? 1.0 : x * (m-1.0) / m * Plm_sph_helper (x, m-2.0));
69 }
70 }
71
72 template <typename ValueType>
73 inline ValueType Plm_sph (const int l, const int m, const ValueType x)
74 {
75 ValueType x2 = pow2 (x);
76 if (m && x2 >= 1.0) return (0.0);
77 ValueType v0 = 0.282094791773878;
78 if (m) v0 *= std::sqrt ((2*m+1) * Plm_sph_helper (1.0-x2, 2.0*m));
79 if (m & 1) v0 = -v0;
80 if (l == m) return (v0);
81
82 ValueType f = std::sqrt (ValueType (2*m+3));
83 ValueType v1 = x * f * v0;
84
85 for (int n = m+2; n <= l; n++) {
86 ValueType v2 = x*v1 - v0/f;
87 f = std::sqrt (ValueType (4*pow2 (n)-1) / ValueType (pow2 (n)-pow2 (m)));
88 v0 = v1;
89 v1 = f*v2;
90 }
91
92 return (v1);
93 }
94
95
96
97
98 //* compute array of normalised associated Legendre functions
100 template <typename VectorType>
101 inline void Plm_sph (VectorType& array, const int lmax, const int m, const typename VectorType::Scalar x)
102 {
103 using value_type = typename VectorType::Scalar;
104 value_type x2 = pow2 (x);
105 if (m && x2 >= 1.0) {
106 for (int n = m; n <= lmax; ++n)
107 array[n] = 0.0;
108 return;
109 }
110 array[m] = 0.282094791773878;
111 if (m) array[m] *= std::sqrt (value_type (2*m+1) * Plm_sph_helper (1.0-x2, 2.0*m));
112 if (m & 1) array[m] = -array[m];
113 if (lmax == m) return;
114
115 value_type f = std::sqrt (value_type (2*m+3));
116 array[m+1] = x * f * array[m];
117
118 for (int n = m+2; n <= lmax; n++) {
119 array[n] = x*array[n-1] - array[n-2]/f;
120 f = std::sqrt (value_type (4*pow2 (n)-1) / value_type (pow2 (n)-pow2 (m)));
121 array[n] *= f;
122 }
123 }
124
125
126
127 //* compute derivatives of normalised associated Legendre functions
131 template <typename VectorType>
132 inline void Plm_sph_deriv (VectorType& array, const int lmax, const int m, const typename VectorType::Scalar x)
133 {
134 using value_type = typename VectorType::Scalar;
135 value_type x2 = pow2 (x);
136 if (x2 >= 1.0) {
137 for (int n = m; n <= lmax; n++)
138 array[n] = NaN;
139 return;
140 }
141 x2 = 1.0 / (x2-1.0);
142 for (int n = lmax; n > m; n--)
143 array[n] = x2 * (n*x*array[n] - (n+m) * std::sqrt ( (2.0*n+1.0) * (n-m) / ( (2.0*n-1.0) * (n+m))) *array[n-1]);
144 array[m] *= x2*m*x;
145 }
146
147
148 }
149 }
150}
151
152#endif
constexpr T pow2(const T &v)
Definition: math.h:53
ValueType double_factorial(const ValueType n)
Definition: legendre.h:36
void Plm_sph_deriv(VectorType &array, const int lmax, const int m, const typename VectorType::Scalar x)
Definition: legendre.h:132
ValueType factorial(const ValueType n)
Definition: legendre.h:30
ValueType Plm(const int l, const int m, const ValueType x)
Definition: legendre.h:42
ValueType Plm_sph(const int l, const int m, const ValueType x)
Definition: legendre.h:73
MR::default_type value_type
Definition: typedefs.h:33
Definition: base.h:24
constexpr std::enable_if< std::is_arithmetic< X >::value &&std::is_unsigned< X >::value, X >::type abs(X x)
Definition: types.h:297
constexpr default_type NaN
Definition: types.h:230