|
@@ -56,11 +56,9 @@
|
|
#include "nmie-precision.hpp"
|
|
#include "nmie-precision.hpp"
|
|
|
|
|
|
namespace nmie {
|
|
namespace nmie {
|
|
-////helper functions
|
|
|
|
-//template<class T> inline T pow2(const T value) {return value*value;}
|
|
|
|
-
|
|
|
|
// Note, that Kapteyn seems to be too optimistic (at least by 3 digits
|
|
// Note, that Kapteyn seems to be too optimistic (at least by 3 digits
|
|
// in some cases) for forward recurrence, see D1test with WYang_data
|
|
// in some cases) for forward recurrence, see D1test with WYang_data
|
|
|
|
+template <typename FloatType>
|
|
int evalKapteynNumberOfLostSignificantDigits(const int ni,
|
|
int evalKapteynNumberOfLostSignificantDigits(const int ni,
|
|
const std::complex<FloatType> zz) {
|
|
const std::complex<FloatType> zz) {
|
|
using std::abs; using std::imag; using std::real; using std::log; using std::sqrt; using std::round;
|
|
using std::abs; using std::imag; using std::real; using std::log; using std::sqrt; using std::round;
|
|
@@ -74,6 +72,7 @@ int evalKapteynNumberOfLostSignificantDigits(const int ni,
|
|
)))/ log(10.));
|
|
)))/ log(10.));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+template <typename FloatType>
|
|
int getNStar(int nmax, std::complex<FloatType> z, const int valid_digits) {
|
|
int getNStar(int nmax, std::complex<FloatType> z, const int valid_digits) {
|
|
if (nmax == 0) nmax = 1;
|
|
if (nmax == 0) nmax = 1;
|
|
int nstar = nmax;
|
|
int nstar = nmax;
|
|
@@ -92,8 +91,8 @@ int getNStar(int nmax, std::complex<FloatType> z, const int valid_digits) {
|
|
|
|
|
|
// Custom implementation of complex cot function to avoid overflow
|
|
// Custom implementation of complex cot function to avoid overflow
|
|
// if Im(z) < 0, then it evaluates cot(z) as conj(cot(conj(z)))
|
|
// if Im(z) < 0, then it evaluates cot(z) as conj(cot(conj(z)))
|
|
-const std::complex<FloatType>
|
|
|
|
-complex_cot(const std::complex<FloatType> z) {
|
|
|
|
|
|
+template <typename FloatType>
|
|
|
|
+std::complex<FloatType> complex_cot(const std::complex<FloatType> z) {
|
|
auto Remx = z.real();
|
|
auto Remx = z.real();
|
|
auto Immx = z.imag();
|
|
auto Immx = z.imag();
|
|
int sign = (Immx>0) ? 1: -1; // use complex conj if needed for exp and return
|
|
int sign = (Immx>0) ? 1: -1; // use complex conj if needed for exp and return
|
|
@@ -109,6 +108,7 @@ complex_cot(const std::complex<FloatType> z) {
|
|
}
|
|
}
|
|
|
|
|
|
// Forward iteration for evaluation of ratio of the Riccati–Bessel functions
|
|
// Forward iteration for evaluation of ratio of the Riccati–Bessel functions
|
|
|
|
+template <typename FloatType>
|
|
void evalForwardR (const std::complex<FloatType> z,
|
|
void evalForwardR (const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& r) {
|
|
std::vector<std::complex<FloatType> >& r) {
|
|
if (r.size() < 1) throw std::invalid_argument(
|
|
if (r.size() < 1) throw std::invalid_argument(
|
|
@@ -123,6 +123,7 @@ void evalForwardR (const std::complex<FloatType> z,
|
|
|
|
|
|
|
|
|
|
// Backward iteration for evaluation of ratio of the Riccati–Bessel functions
|
|
// Backward iteration for evaluation of ratio of the Riccati–Bessel functions
|
|
|
|
+template <typename FloatType>
|
|
void evalBackwardR (const std::complex<FloatType> z,
|
|
void evalBackwardR (const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& r) {
|
|
std::vector<std::complex<FloatType> >& r) {
|
|
if (r.size() < 1) throw std::invalid_argument(
|
|
if (r.size() < 1) throw std::invalid_argument(
|
|
@@ -137,6 +138,7 @@ void evalBackwardR (const std::complex<FloatType> z,
|
|
// nmm::cout << "R0 = " << r[0] <<" at arg = "<<z<<'\n';
|
|
// nmm::cout << "R0 = " << r[0] <<" at arg = "<<z<<'\n';
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+template <typename FloatType>
|
|
void convertRtoD1(const std::complex<FloatType> z,
|
|
void convertRtoD1(const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& r,
|
|
std::vector<std::complex<FloatType> >& r,
|
|
std::vector<std::complex<FloatType> >& D1) {
|
|
std::vector<std::complex<FloatType> >& D1) {
|
|
@@ -151,6 +153,7 @@ void convertRtoD1(const std::complex<FloatType> z,
|
|
}
|
|
}
|
|
|
|
|
|
// ********************************************************************** //
|
|
// ********************************************************************** //
|
|
|
|
+template <typename FloatType>
|
|
void evalForwardD (const std::complex<FloatType> z,
|
|
void evalForwardD (const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& D) {
|
|
std::vector<std::complex<FloatType> >& D) {
|
|
int nmax = D.size();
|
|
int nmax = D.size();
|
|
@@ -162,6 +165,7 @@ void evalForwardD (const std::complex<FloatType> z,
|
|
}
|
|
}
|
|
|
|
|
|
// ********************************************************************** //
|
|
// ********************************************************************** //
|
|
|
|
+template <typename FloatType>
|
|
void evalForwardD1 (const std::complex<FloatType> z,
|
|
void evalForwardD1 (const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& D) {
|
|
std::vector<std::complex<FloatType> >& D) {
|
|
if (D.size()<1) throw std::invalid_argument("Should have a leas one element!\n");
|
|
if (D.size()<1) throw std::invalid_argument("Should have a leas one element!\n");
|
|
@@ -319,6 +323,7 @@ void evalForwardD1 (const std::complex<FloatType> z,
|
|
// Output parameters: //
|
|
// Output parameters: //
|
|
// D1, D3: Logarithmic derivatives of the Riccati-Bessel functions //
|
|
// D1, D3: Logarithmic derivatives of the Riccati-Bessel functions //
|
|
//**********************************************************************************//
|
|
//**********************************************************************************//
|
|
|
|
+template <typename FloatType>
|
|
void evalDownwardD1 (const std::complex<FloatType> z,
|
|
void evalDownwardD1 (const std::complex<FloatType> z,
|
|
std::vector<std::complex<FloatType> >& D1) {
|
|
std::vector<std::complex<FloatType> >& D1) {
|
|
int nmax = D1.size() - 1;
|
|
int nmax = D1.size() - 1;
|
|
@@ -344,6 +349,7 @@ void evalDownwardD1 (const std::complex<FloatType> z,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+template <typename FloatType>
|
|
void evalUpwardD3 (const std::complex<FloatType> z,
|
|
void evalUpwardD3 (const std::complex<FloatType> z,
|
|
const std::vector<std::complex<FloatType> >& D1,
|
|
const std::vector<std::complex<FloatType> >& D1,
|
|
std::vector<std::complex<FloatType> >& D3,
|
|
std::vector<std::complex<FloatType> >& D3,
|
|
@@ -362,6 +368,7 @@ void evalUpwardD3 (const std::complex<FloatType> z,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+template <typename FloatType>
|
|
void evalUpwardPsi (const std::complex<FloatType> z,
|
|
void evalUpwardPsi (const std::complex<FloatType> z,
|
|
const std::vector<std::complex<FloatType> > D1,
|
|
const std::vector<std::complex<FloatType> > D1,
|
|
std::vector<std::complex<FloatType> >& Psi) {
|
|
std::vector<std::complex<FloatType> >& Psi) {
|
|
@@ -374,6 +381,7 @@ void evalUpwardPsi (const std::complex<FloatType> z,
|
|
}
|
|
}
|
|
|
|
|
|
// Sometimes in literature Zeta is also denoted as Ksi, it is a Riccati-Bessel function of third kind.
|
|
// Sometimes in literature Zeta is also denoted as Ksi, it is a Riccati-Bessel function of third kind.
|
|
|
|
+template <typename FloatType>
|
|
void evalUpwardZeta (const std::complex<FloatType> z,
|
|
void evalUpwardZeta (const std::complex<FloatType> z,
|
|
const std::vector<std::complex<FloatType> > D3,
|
|
const std::vector<std::complex<FloatType> > D3,
|
|
std::vector<std::complex<FloatType> >& Zeta) {
|
|
std::vector<std::complex<FloatType> >& Zeta) {
|