2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00
Files
math/tools/Jamfile.v2
Evan Miller d7141cd353 Jacobi Theta functions (#394)
* Jacobi Theta functions

Implementations, tests, and ULP plotting programs are provided for the
four Jacobi Theta functions per #373. Twenty-four public C++ functions
are provided in all, covering various precision-preserving scenarios.

Documentation for collaborators is provided in the code comments. Proper
documentation for end users will be provided when the implementation and
APIs are finalized.

Some tests are failing; this implementation is meant to start a
conversation. The core dilemma faced by the author was that large values
of |q| resulted in slow convergence, and sometimes wildly inaccurate
results. Following the implementation note in DLMF 20.14, I added code
to switch over to the imaginary versions of the theta functions when |q|
> 0.85.  This restored accuracy such that all of the identity tests
passed for a loose-enough epsilon, but then lost precision to the point
that the Wolfram Alpha spot checks failed. It is the author's hope that
someone with floating-point experience can tame the exponential dragons
and squeeze the ULPs back down to a reasonable range when |q| is large.

When #392 is merged I will add more thorough value tests, although I
fully expect them to fail until the underlying precision issues are
resolved.

As a final note, the precision issues do not affect the z=0 case - the
ULP plots indicate these return values within 2 ULP across all valid
|q|. So that's a start.

* [CI SKIP] Jacobi theta: Add special-value tests and more

* Add tests covering z=0 special values from MathWorld

* Add missing real_concept header

* Replace M_PI and friends with constants::pi etc

* Use BOOST_MATH_STD_USING in more places

* Jacobi theta: Test two more of Watson's identities [CI SKIP]

See https://mathworld.wolfram.com/JacobiThetaFunctions.html

(Equations 48 and 49)

* Improve precision of Jacobi theta functions [CI SKIP]

Rewrite the private imaginary versions to use double-sided summations
following DLMF 20.13.4 and 20.13.5. This cuts down the worst of the
precision issues by a factor of 10, and gets more of the tests to pass.

I am confident enough in the code path to eliminate the compile-time
__JACOBI_THETA_USE_IMAGINARY flag. In fact the imaginary-z code paths
are now enabled for all |q| > 0.04, i.e. most legal values of q.

More extensive tests will be needed to illuminate any remaining
precision issues.

* Jacobi theta: Make changes suggested in #394 [CI SKIP]

* Add LICENSE notice to main file

* Document convergence criteria

* Eliminate eps*eps = 0 logic. This causes some disagreement with the
zero returned by Wolfram Alpha for z=0, q > 0.99 in the fourth function.
Mathematically, the fourth function is never exactly zero, so I don't
trust Wolfram here.

* Per code-review comments, remove multiplications by floating-point 2.

* Tweak the plotting programs to display their titles, and to uniformly
use `float` as their CoarseType and `long double` as their
`PreciseType`.

* Add quadrature tests to Jacobi theta functions [CI SKIP]

The quadrature tests revealed a problem in the m1 functions: they too
should switch to the _IMAGINARY logic for q > exp(-pi), or will suffer
from slow convergence. Fix them.

Also tighten tolerances for many tests from sqrt(eps) to 100 * eps.

* Test Jacobi thetas against elliptic functions and elliptic integrals [CI SKIP]

See:

* https://dlmf.nist.gov/22.2
* https://dlmf.nist.gov/20.9#i

* Test Jacobi Thetas against their Laplace transforms [CI SKIP]

See:

* https://dlmf.nist.gov/20.10#ii

I did find some disagreement, and dropped the negative sign from the
theta1 equation. DLMF's theta2 and theta3 Laplace transform equations do
not agree at all with the computed values - will need to investigate.

In the meantime, the two implemented equations agree to 4 EPS so I am
keeping them.

* Add a note on using log1p with Jacobi theta functions [CI SKIP]

See discussion:

* https://github.com/boostorg/math/pull/394#issuecomment-655871762

* Add random data tests to Jacobi Theta functions [CI SKIP]

Add a test data generator program for the Jacobi theta functions.
This program will produce data for the tau parameterization, so that
precision isn't lost during the log-transformation. This distinguishes
it from the Wolfram Alpha data, which is parameterized by q.

A few of these new random-data tests are failing, but not by obscene
margins (< 100 EPS). These failures will be addressed when the test
tolerances are finalized.

* Add small-tau tests and simplify Jacobi Theta code [CI SKIP]

Add tests for small tau (i.e. large q). The tests are failing with mean
~ 200 EPS and max ~ 800 EPS. These look like worst-case input, and
should be the focus of future accuracy improvements.

This commit also simplifies the _IMAGINARY code by abstracting all of
the loops into a single svelte function.

* Add user documentation for Jacobi Theta functions [CI SKIP]

* Add function graphs to Jacobi Theta docs [CI SKIP]

* Define Jacobi Theta test tolerances [CI SKIP]

* Add implementation note on Jacobi theta functions [CI SKIP]

* Consolidate Jacobi Theta ULPs plotting programs [CI SKIP]

* Fix q domain checking of jacobi_theta4 [CI SKIP]

* Add ULPs plots to Jacobi Theta docs [CI SKIP]

Also add the built HTML files for easy evaluation. A full rebuild is
needed for the new docs to appear in the indexes.

* Add missing Jacobi Theta ULPs plots [CI SKIP]

* Add LaTeX source for Jacobi Theta equations [CI SKIP]

* Remove unused Jacobi Theta PNG equations [CI SKIP]

* Add Jacobi Theta performance script [CI SKIP]

Provided by @NAThompson.

* Remove vestigial eps*eps check from jacobi_theta3 [CI SKIP]

* Update Jacobi Theta docs per code review comments [CI SKIP]

* Enable arg promotion for Jacobi Theta functions [CI SKIP]

Add Jacobi theta functions to the instantiation tests and fix up
everything needed to make them pass. This changes the function
signatures to use promote_args.

* Fix Jacobi Theta plotting script [CI SKIP]

This script broke when the promote_args API was added.

* Change Jacobi Theta convergence criterion [CI SKIP]

Compare the non-oscillating part of the delta to the previous one.
This avoids some headaches comparing the delta to the partial sum,
because the partial sum can be a small number due to the oscillating
component alternating signs.

Because successive terms involve either q^n^2 or exp(-(pi*n)^2),
convergence should still happen pretty quickly. Graphs have been updated
and tests still passs with no noticeable difference.
2020-08-15 18:51:47 -04:00

228 lines
10 KiB
Plaintext

# Copyright John Maddock 2010
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt.
# \math_toolkit\libs\math\test\jamfile.v2
# Runs all math toolkit tests, functions & distributions,
# and build math examples.
# bring in the rules for testing
import modules ;
import path ;
import ../../config/checks/config : requires ;
project
: requirements
<toolset>gcc:<cxxflags>-Wno-missing-braces
<toolset>darwin:<cxxflags>-Wno-missing-braces
<toolset>acc:<cxxflags>+W2068,2461,2236,4070,4069
<toolset>intel-win:<cxxflags>-nologo
<toolset>intel-win:<linkflags>-nologo
<toolset>msvc:<warnings>all
<toolset>msvc:<asynch-exceptions>on
<toolset>msvc:<cxxflags>/wd4996
<toolset>msvc:<cxxflags>/wd4512
<toolset>msvc:<cxxflags>/wd4610
<toolset>msvc:<cxxflags>/wd4510
<toolset>msvc:<cxxflags>/wd4127
<toolset>msvc:<cxxflags>/wd4701 # needed for lexical cast - temporary.
<link>static
<toolset>borland:<runtime-link>static
<include>../../..
<define>BOOST_ALL_NO_LIB=1
<define>BOOST_UBLAS_UNSUPPORTED_COMPILER=0
<include>.
<include>../include_private
;
lib gmp ;
lib mpfr ;
lib mpfi ;
lib quadmath ;
exe bessel_data : bessel_data.cpp ;
install bessel_data_install : bessel_data : <location>bin ;
exe ellint_f_data : ellint_f_data.cpp ;
install ellint_f_data_install : ellint_f_data : <location>bin ;
exe heuman_lambda_data : heuman_lambda_data.cpp ;
install heuman_lambda_data_install : heuman_lambda_data : <location>bin ;
exe hyp_2f2_data : hyp_2f2_data.cpp ;
install hyp_2f2_data_install : hyp_2f2_data : <location>bin ;
exe laguerre_data : laguerre_data.cpp ;
install laguerre_data_install : laguerre_data : <location>bin ;
exe bessel_derivative_data : bessel_derivative_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ] ;
install bessel_derivative_data_install : bessel_derivative_data : <location>bin ;
exe ellint_k_data : ellint_k_data.cpp ;
install ellint_k_data_install : ellint_k_data : <location>bin ;
exe hyp_0f2_data : hyp_0f2_data.cpp ;
install hyp_0f2_data_install : hyp_0f2_data : <location>bin ;
exe hypergeometric_dist_data : hypergeometric_dist_data.cpp : [ requires cxx11_hdr_random ] ;
install hypergeometric_dist_data_install : hypergeometric_dist_data : <location>bin ;
exe legendre_data : legendre_data.cpp ;
install legendre_data_install : legendre_data : <location>bin ;
exe beta_data : beta_data.cpp ;
install beta_data_install : beta_data : <location>bin ;
exe ellint_pi2_data : ellint_pi2_data.cpp ;
install ellint_pi2_data_install : ellint_pi2_data : <location>bin ;
exe hyp_1f1_big_data : hyp_1f1_big_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfi : <source>gmp <source>mpfr <source>mpfi : <build>no ]
[ requires cxx11_decltype ] ;
install hyp_1f1_big_data_install : hyp_1f1_big_data : <location>bin ;
exe ibeta_data : ibeta_data.cpp ;
install ibeta_data_install : ibeta_data : <location>bin ;
exe log1p_expm1_data : log1p_expm1_data.cpp ;
install log1p_expm1_data_install : log1p_expm1_data : <location>bin ;
exe carlson_ellint_data : carlson_ellint_data.cpp ;
install carlson_ellint_data_install : carlson_ellint_data : <location>bin ;
exe ellint_pi3_data : ellint_pi3_data.cpp ;
install ellint_pi3_data_install : ellint_pi3_data : <location>bin ;
exe hyp_1f1_data : hyp_1f1_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfi : <source>gmp <source>mpfr <source>mpfi : <build>no ]
[ requires cxx11_decltype ] ;
install hyp_1f1_data_install : hyp_1f1_data : <location>bin ;
exe ibeta_derivative_data : ibeta_derivative_data.cpp ;
install ibeta_derivative_data_install : ibeta_derivative_data : <location>bin ;
exe sinc_data : sinc_data.cpp ;
install sinc_data_install : sinc_data : <location>bin ;
exe cbrt_data : cbrt_data.cpp ;
install cbrt_data_install : cbrt_data : <location>bin ;
exe erf_data : erf_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install erf_data_install : erf_data : <location>bin ;
exe hyp_1f1_log_big_data : hyp_1f1_log_big_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfi : <source>gmp <source>mpfr <source>mpfi : <build>no ]
[ requires cxx11_decltype ] ;
install hyp_1f1_log_big_data_install : hyp_1f1_log_big_data : <location>bin ;
exe ibeta_inv_data : ibeta_inv_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install ibeta_inv_data_install : ibeta_inv_data : <location>bin ;
exe spherical_harmonic_data : spherical_harmonic_data.cpp ;
install spherical_harmonic_data_install : spherical_harmonic_data : <location>bin ;
exe digamma_data : digamma_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install digamma_data_install : digamma_data : <location>bin ;
exe expint_data : expint_data.cpp ;
install expint_data_install : expint_data : <location>bin ;
exe hyp_1f1_reg_big_data : hyp_1f1_reg_big_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfi : <source>gmp <source>mpfr <source>mpfi : <build>no ]
[ requires cxx11_decltype ] ;
install hyp_1f1_reg_big_data_install : hyp_1f1_reg_big_data : <location>bin ;
exe ibeta_invab_data : ibeta_invab_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install ibeta_invab_data_install : ibeta_invab_data : <location>bin ;
exe tgamma_large_data : tgamma_large_data.cpp :
[ check-target-builds ../../multiprecision/config//has_gmp : <source>gmp : <build>no ]
[ check-target-builds ../../multiprecision/config//has_mpfr : <source>mpfr : <build>no ] ;
install tgamma_large_data_install : tgamma_large_data : <location>bin ;
exe ellint_d_data : ellint_d_data.cpp ;
install ellint_d_data_install : ellint_d_data : <location>bin ;
exe expint_i_data : expint_i_data.cpp ;
install expint_i_data_install : expint_i_data : <location>bin ;
exe hyp_1f2_data : hyp_1f2_data.cpp ;
install hyp_1f2_data_install : hyp_1f2_data : <location>bin ;
exe igamma_data : igamma_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install igamma_data_install : igamma_data : <location>bin ;
exe tgamma_ratio_data : tgamma_ratio_data.cpp ;
install tgamma_ratio_data_install : tgamma_ratio_data : <location>bin ;
exe ellint_d2_data : ellint_d2_data.cpp ;
install ellint_d2_data_install : ellint_d2_data : <location>bin ;
exe gamma_P_inva_data : gamma_P_inva_data.cpp : [ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ] ;
install gamma_P_inva_data_install : gamma_P_inva_data : <location>bin ;
exe hyp_2f0_data : hyp_2f0_data.cpp ;
install hyp_2f0_data_install : hyp_2f0_data : <location>bin ;
exe inv_hyp_data : inv_hyp_data.cpp ;
install inv_hyp_data_install : inv_hyp_data : <location>bin ;
exe trig_data : trig_data.cpp ;
install trig_data_install : trig_data : <location>bin ;
exe ellint_e_data : ellint_e_data.cpp ;
install ellint_e_data_install : ellint_e_data : <location>bin ;
exe hermite_data : hermite_data.cpp ;
install hermite_data_install : hermite_data : <location>bin ;
exe hyp_2f1_data : hyp_2f1_data.cpp ;
install hyp_2f1_data_install : hyp_2f1_data : <location>bin ;
exe jacobi_theta_data : jacobi_theta_data.cpp ;
install jacobi_theta_data_install : jacobi_theta_data : <location>bin ;
exe jacobi_zeta_data : jacobi_zeta_data.cpp ;
install jacobi_zeta_data_install : jacobi_zeta_data : <location>bin ;
exe zeta_data : zeta_data.cpp ;
install zeta_data_install : zeta_data : <location>bin ;
exe generate_test_values : generate_test_values.cpp ;
install generate_test_values_install : generate_test_values : <location>bin ;
exe igamma_temme_large_coef : igamma_temme_large_coef.cpp ;
install igamma_temme_large_coef_install : igamma_temme_large_coef : <location>bin ;
exe lanczos_generator : lanczos_generator.cpp ../../chrono/build//boost_chrono ../../system/build//boost_system :
[ check-target-builds ../../multiprecision/config//has_float128 : <source>quadmath : <build>no ]
[ requires cxx11_nullptr ] ;
install lanczos_generator_install : lanczos_generator : <location>bin ;
exe factorial_tables : factorial_tables.cpp ;
install factorial_tables_install : factorial_tables : <location>bin ;
exe generate_rational_test : generate_rational_test.cpp ;
install generate_rational_test_install : generate_rational_test : <location>bin ;
#for local source in [ glob *_data.cpp ] generate_test_values.cpp igamma_temme_large_coef.cpp lanczos_generator.cpp factorial_tables.cpp generate_rational_test.cpp
#{
# exe $(source:B) : $(source) : [ check-target-builds ../../multiprecision/config//has_gmp : <define>HAS_GMP <source>gmp : <build>no ] [ check-target-builds ../../multiprecision/config//has_mpfr : <define>HAS_MPFR <source>mpfr : <build>no ] [ check-target-builds ../../multiprecision/config//has_mpfi : <define>HAS_MPFI <source>gmp <source>mpfr <source>mpfi ] ;
# install $(source:B)_bin : $(source:B) : <location>bin ;
#}
exe generate_rational_code : generate_rational_code.cpp ;
exe process_perf_results : process_perf_results.cpp ../../regex/build//boost_regex ;
install bin : generate_rational_code process_perf_results ;