NumCpp  2.10.1
A Templatized Header Only C++ Implementation of the Python NumPy Library
legendre_p.hpp
Go to the documentation of this file.
1 #pragma once
29 
30 #include <cmath>
31 
32 #if defined(__cpp_lib_math_special_functions) || !defined(NUMCPP_NO_USE_BOOST)
33 
37 #include "NumCpp/NdArray.hpp"
38 
39 #ifndef __cpp_lib_math_special_functions
40 #include "boost/math/special_functions/legendre.hpp"
41 #endif
42 
43 namespace nc::polynomial
44 {
45  //============================================================================
46  // Method Description:
55  template<typename dtype>
56  double legendre_p(uint32 n, dtype x)
57  {
59 
60  if (x < -1. || x > 1.)
61  {
62  THROW_INVALID_ARGUMENT_ERROR("input x must be of the range [-1, 1].");
63  }
64 
65 #ifdef __cpp_lib_math_special_functions
66  return std::legendre(n, static_cast<double>(x));
67 #else
68  return boost::math::legendre_p(n, static_cast<double>(x));
69 #endif
70  }
71 
72  //============================================================================
73  // Method Description:
83  template<typename dtype>
84  double legendre_p(uint32 m, uint32 n, dtype x)
85  {
87 
88  if (x < -1. || x > 1.)
89  {
90  THROW_INVALID_ARGUMENT_ERROR("input x must be of the range [-1, 1].");
91  }
92 
93 #ifdef __cpp_lib_math_special_functions
94 
95  auto value = std::assoc_legendre(n, m, static_cast<double>(x));
96 
97 #ifdef __GNUC__
98 #if __GNUC__ != 7 && __GNUC__ != 8
99 
100  // gcc std::assoc_legendre is not standard compliant
101  value *= n % 2 == 0 ? 1 : -1;
102 
103 #endif // #if __GNUC__ != 7 && __GNUC__ != 8
104 #endif // #ifdef __GNUC__
105 
106 #ifdef __clang__
107 #if __clang_major__ != 7 && __clang_major__ != 8
108 
109  // clang uses gcc headers where std::assoc_legendre is not standard compliant
110  value *= n % 2 == 0 ? 1 : -1;
111 
112 #endif // #if __clang_major__ != 6 && __clang_major__ != 7 && __clang_major__ != 8
113 #endif // #ifdef __clang__
114 
115 #ifdef _MSC_VER
116 
117  value *= n % 2 == 0 ? 1 : -1;
118 
119 #endif // #ifdef _MSC_VER
120 
121  return value;
122 
123 #else // #ifdef __cpp_lib_math_special_functions
124 
125  return boost::math::legendre_p(n, m, static_cast<double>(x));
126 
127 #endif // #ifdef __cpp_lib_math_special_functions
128  }
129 
130  //============================================================================
131  // Method Description:
140  template<typename dtype>
142  {
143  NdArray<double> returnArray(inArrayX.shape());
144 
145  const auto function = [n](dtype x) -> double { return legendre_p(n, x); };
146 
147  stl_algorithms::transform(inArrayX.cbegin(), inArrayX.cend(), returnArray.begin(), function);
148 
149  return returnArray;
150  }
151 
152  //============================================================================
153  // Method Description:
163  template<typename dtype>
165  {
166  NdArray<double> returnArray(inArrayX.shape());
167 
168  const auto function = [m, n](dtype x) -> double { return legendre_p(m, n, x); };
169 
170  stl_algorithms::transform(inArrayX.cbegin(), inArrayX.cend(), returnArray.begin(), function);
171 
172  return returnArray;
173  }
174 } // namespace nc::polynomial
175 
176 #endif // #if defined(__cpp_lib_math_special_functions) || !defined(NUMCPP_NO_USE_BOOST)
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:39
const_iterator cbegin() const noexcept
Definition: NdArrayCore.hpp:1308
Shape shape() const noexcept
Definition: NdArrayCore.hpp:4402
const_iterator cend() const noexcept
Definition: NdArrayCore.hpp:1616
iterator begin() noexcept
Definition: NdArrayCore.hpp:1258
Definition: chebyshev_t.hpp:39
double legendre_p(uint32 n, dtype x)
Definition: legendre_p.hpp:56
NdArray< double > legendre_p(uint32 m, uint32 n, const NdArray< dtype > &inArrayX)
Definition: legendre_p.hpp:164
OutputIt transform(InputIt first, InputIt last, OutputIt destination, UnaryOperation unaryFunction)
Definition: StlAlgorithms.hpp:775
std::uint32_t uint32
Definition: Types.hpp:40