// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // anger_weber.hpp // Anger function J_ν and Weber function E_ν // // Definitions (DLMF 11.10.1, 11.10.2): // J_ν(z) = (1/π) ∫₀^π cos(νt - z sin t) dt [Anger] // E_ν(z) = (1/π) ∫₀^π sin(νt - z sin t) dt [Weber] // // Functions provided: // angerJ(nu, z) — Anger function J_ν(z) // weberE(nu, z) — Weber function E_ν(z) // // Properties: // When ν is an integer n: J_n^Anger(z) = J_n^Bessel(z) (matches Bessel) // For non-integer ν it is a distinct, independent function family differing from Bessel // Both are entire functions for any finite z // // Implementation: // Evaluate the defining integral directly via Simpson's rule (N=512). // The ν series representation is not used, as the integer-ν limit handling is complex. // The integrand is analytic and smooth; with N=512, accuracy is about 1e-13 for |z|≲50, |ν|≲30. // // Uses: // Bessel variants, special integral evaluations, diffraction theory, non-integer-order oscillation problems // // References: DLMF §11.10, A&S §12.3, Watson "Bessel Functions" §10.1 #ifndef SANGI_SPECIAL_ANGER_WEBER_HPP #define SANGI_SPECIAL_ANGER_WEBER_HPP #include #include #include #include namespace sangi { namespace special { namespace detail_aw { // Evaluate ∫₀^π cos(νt - z sin t) dt or ∫₀^π sin(νt - z sin t) dt via // the composite Simpson's rule. is_sine=false selects cos, true selects sin. template [[nodiscard]] T simpson_integrate(T nu, T z, bool is_sine, int N = 1024) { // Force N to be even if (N % 2) N++; constexpr T PI = std::numbers::pi_v; T h = PI / T(N); auto integrand = [&](T t) -> T { T arg = nu * t - z * std::sin(t); return is_sine ? std::sin(arg) : std::cos(arg); }; T sum = integrand(T(0)) + integrand(PI); // endpoints // Odd indices (coefficient 4) for (int k = 1; k < N; k += 2) { sum += T(4) * integrand(T(k) * h); } // Even indices (coefficient 2) for (int k = 2; k < N; k += 2) { sum += T(2) * integrand(T(k) * h); } return sum * h / T(3); } } // namespace detail_aw // ================================================================ // Anger function J_ν(z) = (1/π) ∫₀^π cos(νt - z sin t) dt // ================================================================ template [[nodiscard]] T angerJ(T nu, T z) { if (std::isnan(nu) || std::isnan(z)) return std::numeric_limits::quiet_NaN(); constexpr T PI = std::numbers::pi_v; return detail_aw::simpson_integrate(nu, z, /*is_sine=*/false) / PI; } // ================================================================ // Weber function E_ν(z) = (1/π) ∫₀^π sin(νt - z sin t) dt // ================================================================ template [[nodiscard]] T weberE(T nu, T z) { if (std::isnan(nu) || std::isnan(z)) return std::numeric_limits::quiet_NaN(); constexpr T PI = std::numbers::pi_v; return detail_aw::simpson_integrate(nu, z, /*is_sine=*/true) / PI; } } // namespace special } // namespace sangi #endif // SANGI_SPECIAL_ANGER_WEBER_HPP