numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
legendre.h
Go to the documentation of this file.
1/*
2 * Copyright 2021 MusicScience37 (Kenta Kabashima)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
20#pragma once
21
22#include <limits>
23#include <utility>
24
27#include "num_collect/constants/half.h" // IWYU pragma: keep
28#include "num_collect/constants/one.h" // IWYU pragma: keep
29#include "num_collect/constants/two.h" // IWYU pragma: keep
30#include "num_collect/constants/zero.h" // IWYU pragma: keep
31
32namespace num_collect::functions {
33
43template <base::concepts::real_scalar F, base::concepts::integral I>
44constexpr auto legendre(F x, I n) -> F {
45 if constexpr (std::is_signed_v<I>) {
46 if (n < constants::zero<I>) {
47 return std::numeric_limits<F>::quiet_NaN();
48 }
49 }
50 if (n == constants::zero<I>) {
51 return constants::one<F>;
52 }
53 if (n == constants::one<I>) {
54 return x;
55 }
56 F y_p = constants::zero<F>;
57 F y = x;
58 F y_m = constants::one<F>;
59 for (I i = constants::one<I>; i < n; ++i) {
60 y_p =
61 (static_cast<F>(constants::two<I> * i + constants::one<I>) * x * y -
62 static_cast<F>(i) * y_m) /
63 static_cast<F>(i + constants::one<I>);
64 y_m = y;
65 y = y_p;
66 }
67 return y;
68}
69
79template <base::concepts::real_scalar F, base::concepts::integral I>
80constexpr auto legendre_with_diff(F x, I n) -> std::pair<F, F> {
81 if constexpr (std::is_signed_v<I>) {
82 if (n < constants::zero<I>) {
83 return {std::numeric_limits<F>::quiet_NaN(),
84 std::numeric_limits<F>::quiet_NaN()};
85 }
86 }
87 if (n == constants::zero<I>) {
89 }
90 if (n == constants::one<I>) {
91 return {x, constants::one<F>};
92 }
93
94 if (x == constants::one<F>) {
95 return {constants::one<F>,
96 constants::half<F> * static_cast<F>(n) *
97 static_cast<F>(n + constants::one<I>)};
98 }
99 if (x == -constants::one<F>) {
101 return {constants::one<F>,
102 -constants::half<F> * static_cast<F>(n) *
103 static_cast<F>(n + constants::one<I>)};
104 }
105 return {-constants::one<F>,
106 constants::half<F> * static_cast<F>(n) *
107 static_cast<F>(n + constants::one<I>)};
108 }
109
110 F y_p = constants::zero<F>;
111 F y = x;
112 F y_m = constants::one<F>;
113 for (I i = constants::one<I>; i < n; ++i) {
114 y_p =
115 (static_cast<F>(constants::two<I> * i + constants::one<I>) * x * y -
116 static_cast<F>(i) * y_m) /
117 static_cast<F>(i + constants::one<I>);
118 y_m = y;
119 y = y_p;
120 }
121
122 F dif = static_cast<F>(n) * (y_m - x * y) / (constants::one<F> - x * x);
123
124 return {y, dif};
125}
126
127} // namespace num_collect::functions
Definition of half.
Definition of integral concept.
constexpr T two
Value 2.
Definition two.h:30
constexpr T zero
Value 0.
Definition zero.h:30
constexpr T half
Value 0.5.
Definition half.h:30
constexpr T one
Value 1.
Definition one.h:30
Namespace of special functions.
Definition gamma.h:27
constexpr auto legendre(F x, I n) -> F
Calculate Legendre function.
Definition legendre.h:44
constexpr auto legendre_with_diff(F x, I n) -> std::pair< F, F >
Calculate Legendre function and its differential coefficient.
Definition legendre.h:80
Definition of one.
Definition of real_scalar concept.
Definition of two.
Definition of zero.