symplex 0.43.0

Exact symbolic mathematics for Rust: calculus, summation, solving, linear algebra, transforms, compile-time dimensional analysis, and Rust/C code generation
Documentation
# Third-party notices

symplex is an independent project.  It is **not affiliated with, sponsored
by or endorsed by** the SymPy project, the mpmath, SciPy or statsmodels
projects, or any of their contributors; their names appear in this
repository only to identify them.

## How other projects are used

**As test oracles (no code).**  SymPy, mpmath, SciPy and statsmodels are
*run* — from `scripts/` and by hand, in a local virtualenv — to produce
reference values that tests compare against, each cited next to the value
with the call that produced it.  These are numbers and expressions
(mathematical facts), not code; no part of those projects is included in, or
linked into, symplex.  All four are BSD-3-Clause licensed.

**As references for conventions.**  Where a mathematical choice is
conventional — a branch cut, the ordering of a polynomial's terms, the
parametrisation of a distribution, which identities `expand_log` applies —
symplex usually makes SymPy's choice, so that the two agree and SymPy can
serve as an oracle.  Behaviour is not copyrightable, but the choice is
acknowledged in the doc comment where it is made.

**Implementations that follow SymPy's.**  A few modules follow the
structure of SymPy's implementation of a published algorithm, and say so in
their documentation:

| symplex | follows | algorithm published in |
|---|---|---|
| `src/calculus/gruntz.rs` (`SubsSet`, the sign and MRV routines) | `sympy/series/gruntz.py` | D. Gruntz, *On Computing Limits in a Symbolic Manipulation System*, PhD thesis, ETH Zürich, 1996 |
| `src/calculus/risch/hermite.rs` | `hermite_reduce` in `sympy/integrals/risch.py` | M. Bronstein, *Symbolic Integration I*, §2.3 |
| `src/domains/ntheory.rs` (`EcmStage2`, ECM stage 2 in `ecm_curve_ring`) | stage 2 of `_ecm_one_factor` in `sympy/ntheory/ecm.py` | P. L. Montgomery, *Math. Comp.* 48 (1987); R. Crandall, C. Pomerance, *Prime Numbers*, 2nd ed., §7.4.2 |
| `src/domains/exact_matrix.rs` (LLL reduction order and rounding) | `DomainMatrix.lll` / `_ddm_lll` | A. K. Lenstra, H. W. Lenstra, L. Lovász, *Math. Ann.* 261 (1982) |
| `src/plotting/textplot.rs` | `sympy/plotting/textplot.py` | — |
| `src/api/expr_algebraic_ext.rs` (`multipoly_resultant`: the subresultant PRS over `ℚ[params][x]`) | `dup_inner_subresultants`, `dup_prs_resultant` in `sympy/polys/euclidtools.py` | W. S. Brown, "The subresultant PRS algorithm", *ACM TOMS* 4 (1978) 237–249 |
| `src/poly/zpoly.rs` (`z_subresultant_prs`: the signed subresultant chain of the Sturm sequences and `z_gcd`) | `dup_inner_subresultants` in `sympy/polys/euclidtools.py` | W. S. Brown, "The subresultant PRS algorithm", *ACM TOMS* 4 (1978) 237–249 |
| `src/transforms/solve.rs` (the Lambert-form equations and their real branches) | `_solve_lambert` / `_lambert` in `sympy/solvers/bivariate.py` | R. M. Corless et al., "On the Lambert W function", *Adv. Comput. Math.* 5 (1996) 329–359 |
| `src/poly/modgcd.rs` (`heu_gcd`, `heu_attempt`: the evaluation-point bound and the three candidates per point, on integer coefficients) | `dmp_zz_heu_gcd` in `sympy/polys/euclidtools.py` | B. W. Char, K. O. Geddes, G. H. Gonnet, "GCDHEU: Heuristic polynomial GCD algorithm based on integer GCD computation", *J. Symbolic Comput.* 7 (1989) 31–48 |
| `src/transforms/evalf/hypsum.rs` (convergence classification, the direct hypergeometric summation) | `check_convergence` and `hypsum` in `sympy/core/evalf.py` | the term-ratio test for hypergeometric series |
| `src/transforms/pattern.rs` (`condition_pow_pow`) | the branch condition of `Pow._eval_power` | the principal branch of `z^a` |
| `src/base/assumptions.rs` (`compute_mul`: a real factor that may vanish keeps `real · imaginary` undecided) | `Mul._eval_real_imag` / `Mul._eval_is_imaginary` in `sympy/core/mul.py` | — |
| `src/base/assumptions.rs` (`may_be_infinite`: `abs z`, `re z`, `im z` real and `sinh`, `cosh`, `asinh`, `acosh`, `asin`, … finite only for a finite operand; `polygamma(n, x)` real only for a real order) | `Abs._eval_is_real`, `re`/`im` `_eval_is_finite`, `sinh._eval_is_finite` and its siblings in `sympy/functions/elementary/`, `polygamma._eval_is_real` in `sympy/functions/special/gamma_functions.py` | — |
| `src/simplify/log_expand.rs` (`expand_ln_node_guarded`: a known-negative factor becomes the finished term `ln(−f)`) | the `is_negative` branch of `log._eval_expand_log` in `sympy/functions/elementary/exponential.py` | — |
| `src/calculus/gruntz.rs` (`asymptotic_rewrite`: `erf`, `erfc`, `Ei`, `li` at ±∞ with their exponential factor explicit, `Γ` at ∞ as `exp(ln Γ)`, `ln ω` as a leading-term coefficient) | `_eval_rewrite_as_tractable` of `erf`, `erfc`, `Ei`, `gamma`, the helpers `_erfs`, `_eis` in `sympy/functions/special/error_functions.py` and `gamma_functions.py`; `logx` in `sympy/series/gruntz.py` | D. Gruntz, PhD thesis, ETH Zürich 1996; DLMF 7.12.1, 6.12.2, 5.11.1 |
| `src/domains/linalg.rs` (`rref_solve_algebraic`: fraction-free Gauss–Jordan elimination) | `ddm_irref_den` in `sympy/polys/matrices/dense.py` | G. C. Nakos, P. R. Turner, R. M. Williams, "Fraction-free algorithms for linear and polynomial equations", *ACM SIGSAM Bull.* 31 (1997) |
| `src/domains/matrix.rs` (`eigen_pairs`: eigenvalues block by block of a block-triangular matrix) | `_eigenvals_dict` in `sympy/matrices/eigen.py` | — |
| `src/base/canon.rs` (`infinity_plus_terms`: `±∞` absorbs only the real finite terms of a sum, `∞ + i` stays) | the `coeff is S.Infinity` / `S.NegativeInfinity` branch of `Add.flatten` in `sympy/core/add.py` | — |
| `src/base/canon.rs` (`assumed_value`, `assumed_power`, `shifted_by_periods`, `exp_shifted_by_periods`, `drop_dominated`, `known_sign_by_bounds`: applications and powers whose value follows from the assumptions on their symbols, folded when built) | the integer and parity cases of `sin.eval`, `cos.eval`, `tan.eval` (`_pi_coeff`, `_peeloff_pi`) and `sinh.eval` in `sympy/functions/elementary/trigonometric.py`, `hyperbolic.py`; `exp.eval`, `log.eval` in `exponential.py`; `(-1)**e` in `Pow.__new__` and the nonnegative-base rule of `Pow._eval_power` in `sympy/core/power.py`; `Abs.eval`, `Abs._eval_power`, `sign.eval` in `complexes.py`; `floor.eval` in `integers.py`; `Heaviside.eval`, `DiracDelta.eval` in `sympy/functions/special/delta_functions.py`; `MinMaxBase._collapse_arguments` in `miscellaneous.py`; `_monotonic_sign` in `sympy/core/exprtools.py` | the periodicity and parity of the trigonometric and exponential functions at multiples of `π`; the principal branch of `z^a` |
| `src/transforms/eval.rs` (`equal_by_difference`, `algebraic_rational_value`: an equality or order of constants decided by the minimal polynomial of their difference) | the `minimal_polynomial` step of `Expr.equals` in `sympy/core/expr.py` | an algebraic number is 0 exactly when its minimal polynomial over ℚ is `t` |
| `src/transforms/eval.rs` (`cos_pi_radical`, `sin_pi_radical`, `tan_pi_radical`, `cot_pi_radical`: `sin`, `cos`, `tan`, `cot` at `kπ/n` in square roots, the denominators `n` and the formulas — quadrant reductions, Chebyshev polynomials of `cos(π/5)`, half angles, `cos(x − y)` over the pairs of `_table2`, `table10` for `tan`; `inverse_of_trig_at_pi_multiple`: `asin(sin x)`, `acos(cos x)`, `atan(tan x)` reduced to the principal range) | `cos.eval`, `tan.eval`, `cot.eval`, `_table2`, and the trigonometric-argument cases of `asin.eval`, `acos.eval`, `atan.eval` in `sympy/functions/elementary/trigonometric.py` | the addition and half-angle formulas; `cos(π/5) = (1 + √5)/4` |
| `src/domains/linalg.rs` (`kp_radical_roots`: Cardano's formulas over ℚ(√p…, i)) | the case analysis of `roots_cubic` in `sympy/polys/polyroots.py` | G. Cardano, *Ars Magna* (1545) |
| `src/calculus/series.rs` (`inverse_at_branch_point`: the expansions of `asin`, `acos`, `acosh`, `atanh`, `asinh`, `atan` at their branch points) | the branch-point cases of `asin._eval_nseries`, `acos._eval_nseries` (`1 ∓ u = t²`) and `atanh`/`acosh._eval_nseries` (`rewrite(log)`) in `sympy/functions/elementary/trigonometric.py` and `hyperbolic.py` | `asin √z = √z·₂F₁(½, ½; 3/2; z)` (DLMF 15.4.4) |
| `src/simplify/radsimp.rs` (`try_rationalize`: a conjugate that makes the denominator 0 is not used) | the `d.has(S.Zero, nan, zoo)` guard of `radsimp` in `sympy/simplify/radsimp.py` | — |
| `src/domains/matrix.rs` (`norm_frobenius`: squared moduli of the entries, `Abs(a)**2` for entries not known to be real) | `MatrixBase.norm` in `sympy/matrices/matrixbase.py` | G. H. Golub, C. F. Van Loan, *Matrix Computations*, §2.3 (Frobenius norm) |
| `src/simplify/identically_zero.rs` (`vanishes_by_identity`: a numeric test at sample points, then an exact proof) | `Expr.equals` in `sympy/core/expr.py` | J. T. Schwartz (1980), R. Zippel (1979): zero testing at random points |
| `src/poly/polybridge.rs` (`generator_residue`: `exp(Σ cⱼ·mⱼ)` as `Π exp(mⱼ)^cⱼ`; rational powers of a generator) | `decompose_power` / `decompose_power_rat` in `sympy/core/exprtools.py` | J. T. Schwartz (1980), R. Zippel (1979): zero testing at random points |
| `src/transforms/evalf/extended.rs` (`add_terms`/`part_sum`: sums of terms at unbounded binary scales, terms more than the working precision below the largest moved into the error) | `add_terms` in `sympy/core/evalf.py`; `mpf` with unbounded exponents in `mpmath/libmp/libmpf.py` | — |
| `src/transforms/evalf/bessel_order.rs` (Bessel functions of large order: `(z/2)^ν/Γ(ν + 1)·₀F₁(; ν + 1; ∓z²/4)` in log space, with unbounded exponents) | `besselj` / `besseli` in `mpmath/functions/bessel.py` | DLMF 10.2.2, 10.14.4, 10.25.2 |
| `src/domains/linalg.rs` (`kp_quartic_roots`: the quartic in radicals and its case split) | `roots_quartic`, `_roots_quartic_euler` in `sympy/polys/polyroots.py` | Ferrari's method; the Descartes–Euler resolvent; quasi-symmetric quartics |
| `src/calculus/series.rs` (`compose_at_constant`: `f(u₀ + w)` from the Taylor coefficients of `f` at the constant term of its argument, also when `w` carries `ln x`) | the generic and logarithmic-argument cases of `Function._eval_nseries` in `sympy/core/function.py` | Taylor's theorem |
| `src/domains/matrix_decomp.rs` (`cholesky`, `ldl` of a Hermitian matrix: `A = L·Lᴴ`, `A = L·D·Lᴴ`) | `_cholesky`, `_LDLdecomposition` with `hermitian=True` in `sympy/matrices/decompositions.py` | the Cholesky and LDLᴴ factorisations (G. H. Golub, C. F. Van Loan, *Matrix Computations*, 4th ed., §4.2) |
| `src/base/numeric.rs` (`q_add`, `q_mul`: no gcd for an integer operand in a sum, cross-cancellation in a product) | `Rational.__add__` / `Rational.__mul__` in `sympy/core/numbers.py` | D. E. Knuth, *The Art of Computer Programming*, vol. 2, §4.5.1 (Henrici's sum) |
| `src/poly/modgcd.rs` (`zx_gcd`: the degree bound, the Chinese remainder theorem with early termination, trial division) | `modgcd_univariate` in `sympy/polys/modulargcd.py` | W. S. Brown, "On Euclid's algorithm and the computation of polynomial greatest common divisors", *J. ACM* 18 (1971) 478–504 |
| `src/poly/factor_zassenhaus.rs` (`hensel_lift`, `lift_tree`, `hensel_step`: quadratic multifactor Hensel lifting) | `dup_zz_hensel_lift`, `dup_zz_hensel_step` in `sympy/polys/factortools.py` | J. von zur Gathen, J. Gerhard, *Modern Computer Algebra*, Algorithms 15.10 and 15.17 |
| `src/poly/modgcd.rs` (`rat_add`, `rat_mul`: no gcd for an integer operand in a sum, cross-cancellation in a product) | `Rational.__add__` / `Rational.__mul__` in `sympy/core/numbers.py` | D. E. Knuth, *The Art of Computer Programming*, vol. 2, §4.5.1 (Henrici's sum) |
| `src/calculus/limit.rs` (`continuation_across_cut`), `src/calculus/gruntz.rs` (`resolve_branch_cut`, `cut_side`), `src/calculus/series.rs` (`series_cut_side`, `cut_jump`; the side of the cut in `apply_ln`, `pow_rational`): a branch function whose argument tends to its cut, continued from the side the argument approaches from | the side test of `log._eval_nseries` (the first non-real term of the argument's series, `−2πi` below the negative axis) and the branch-cut cases of `asin`, `acos`, `atanh`, `acosh`, `asinh`, `atan._eval_nseries` (`dir`, `π − asin`, …) in `sympy/functions/elementary/exponential.py`, `trigonometric.py`, `hyperbolic.py` | the principal branches of the elementary functions (DLMF 4.2, 4.23, 4.37) |
| `src/calculus/gruntz.rs` (`special_asymptotic_rewrite`: `Chi`, `Shi`, `erfi`, `Iν`, `Kν`, `Eₙ`, `Γ(s, ·)`, `γ(s, ·)`, `ζ` at ±∞), `src/calculus/series.rs` (`power_asymptotic_series`) | `_eval_aseries` of `erfi`, `expint`, `besseli`, `besselk` and the `Ei` forms of `Chi`, `Shi` in `sympy/functions/special/error_functions.py` and `bessel.py` | DLMF 6.2.15–16, 6.12.2, 7.12.1, 8.11.2, 8.20.2, 10.40.1–2, 25.2.1 |
| `src/transforms/integrate.rs` (`try_mobius_radical_substitution`, `mobius_core`: `t = ((a·x + b)/(c·x + d))^{1/q}` for the radicals of one Möbius base, `x` and `dx` as rational functions of `t`) | `sqrt_fractional_linear_rule` in `sympy/integrals/manualintegrate.py` | Chebyshev's theorem on binomial differentials (Gradshteyn–Ryzhik 2.202); the substitution `t = B₁^{1/q}·B₂^{−1/q}` for a pair, the power substitution `w = xⁿ`, the split of a quadratic radical into linear factors times a locally constant coefficient and `e^{k·atanh u} = (1 + u)^{k/2}(1 − u)^{−k/2}` (DLMF 4.37.24) are symplex's, after the mathematics of Rubi's reduction rules (MIT; rules not included) |
| `src/calculus/summation.rs` (`residue_sum_infinite`: an even rational series summed by the residues of `π·cot(πz)·f(z)`) | `eval_sum_residue` in `sympy/concrete/summations.py` | the residue theorem for series (e.g. Mitrinović, Kečkić, *The Cauchy Method of Residues*, §5.2) |
| `src/transforms/trig_integ.rs` (`continuous_through_tan`, `add_tan_floor`, `infinity_jump`, `end_value`: `G(tan w) + J·⌊w/π + 1/2⌋`, `J = G(+∞) − G(−∞)`) | the `floor` correction of `atan(c·tan(w) + d)` in `Integral.doit`, `sympy/integrals/integrals.py` | D. J. Jeffrey, A. D. Rich, "The evaluation of trigonometric integrals avoiding spurious discontinuities", *ACM Trans. Math. Softw.* 20 (1994) 124–135 |
| `src/transforms/integrate.rs` (`try_trig_rational_substitution`, `trig_rational_in_u`, `tan_algebraic_in_u`, `odd_algebraic_in_u`, `trig_polynomial_substitution`: `u = c + d·x`, multiple angles, Bioche's choice of `t = cos u`, `sin u`, `tan u` or `tan(u/2)`), `src/transforms/trig_integ.rs` (`infinity_jump_real_parameters`, `polynomial_root_sums`) | the mathematics of Rubi's integration rules 4.1–4.7 for the choice of substitution (MIT; rules not included; the implementation is symplex's, no SymPy code) | the substitutions for rational functions of `sin`, `cos` (Bioche's rules; Gradshteyn–Ryzhik 2.5); Chebyshev polynomials for multiple angles (DLMF 18.5.1–18.5.2); Newton's identities for power sums of roots |
| `src/domains/matrix_decomp.rs` (`qr` of a rank-deficient matrix: `Q` from the independent columns, `R = QᴴA` in echelon form) | `_QRdecomposition_optional` in `sympy/matrices/decompositions.py` | G. H. Golub, C. F. Van Loan, *Matrix Computations*, 4th ed., §5.2 |
| `src/domains/matrix_decomp.rs` (`jordan_function`: powers and square roots of defective matrices by Jordan blocks) | `_matrix_pow_by_jordan_blocks` in `sympy/matrices/matrixbase.py` | N. J. Higham, *Functions of Matrices* (SIAM 2008), §1.2 |
| `src/domains/matrix.rs` (`symbolic_factor_roots`: eigenvalues from the factorisation over ℚ[symbols]; `pinv` with conjugate transposes) | `roots` (`factor_list` branch) in `sympy/polys/polyroots.py`; `_pinv_full_rank`, `_pinv_rank_decomposition` in `sympy/matrices/inverse.py` | — |
| `src/domains/ntheory.rs` (`totient_with_factors`, `order_with_factors`: `φ(n)` factored from the factorisations of the `p − 1`, for `n_order`, `is_primitive_root`, `primitive_root`, `discrete_log`) | `n_order` in `sympy/ntheory/residue_ntheory.py` | Lagrange's theorem: the order divides `φ(n) = ∏ p^{k−1}(p − 1)` |
| `src/domains/ntheory.rs` (`prime` beyond `10⁷`, `nth_prime_by_counting`: `π(x)` at an estimate `x` of the `n`-th prime, then the primes counted from `x`) | `prime` in `sympy/ntheory/generate.py` | M. Cipolla, "La determinazione assintotica dell'n-imo numero primo", *Rend. Accad. Sci. Fis. Mat. Napoli* (3) 8 (1902) 132–166 |
| `src/domains/ntheory.rs` (`is_mersenne_prime`: the known exponents, and every exponent below `6.5·10⁷` settled) | `MERSENNE_PRIME_EXPONENTS`, `is_mersenne_prime` in `sympy/ntheory/primetest.py` | GIMPS (mersenne.org) milestones; the Lucas–Lehmer test |
| `src/transforms/sets.rs` (`image_set`: a family `a·n + b` over the integers with its offset reduced modulo the step; `image_set_contains`: membership by solving `f(n) = x` for an integer `n`; `intersect_image_parts`: the members of a family in an interval), `src/transforms/inequalities.rs` (`general_solution_set`: the zeros of denominators removed from the families) | `_set_function` for `Integers` in `sympy/sets/handlers/functions.py`; `ImageSet._contains` in `sympy/sets/fancysets.py`; the `ImageSet`–`Interval` handler in `sympy/sets/handlers/intersection.py`; the denominator check of `_solveset` in `sympy/solvers/solveset.py` | the lattice `{a·n + b : n ∈ ℤ}` and the general solutions of the trigonometric and exponential equations |
| `src/transforms/solve.rs` (`assumptions_hold`, `retain_admissible`: a candidate that certainly violates an assumption of the unknown is dropped, an undecided one kept), `src/poly/polysys.rs` (`solve_system_ex`: each unknown's assumptions), `src/transforms/sets.rs` (`restrict_set_to_domain`: the solution set intersected with the declared domain) | the assumption check (`check_assumptions`) at the end of `solve` in `sympy/solvers/solvers.py`; the domain intersection of `solveset` in `sympy/solvers/solveset.py` | the solutions of an equation in a domain |
| `src/domains/exact_matrix.rs` (`hnf_columns_modulo`, `hnf_gcdex`: the Hermite normal form computed modulo a multiple `D` of the lattice determinant, for `hermite_normal_form`, `column_hermite_normal_form`, `smith_normal_form`, `integer_nullspace`, `lattice_determinant`) | `_hermite_normal_form_modulo_D` and `_gcdex` in `sympy/polys/matrices/normalforms.py` | H. Cohen, *A Course in Computational Algebraic Number Theory*, Algorithm 2.4.8 (Domich, Kannan, Trotter, *Math. Oper. Res.* 12 (1987)) |
| `src/poly/numfield.rs` (`NumberField::factor_squarefree`, `NumberField::factor`: the shift `f(x − sα)` with a square-free norm, the norm factored over ℤ, `gcd(f(x − sα), gᵢ)` over the field, shifted back; square-free parts first) | `dup_sqf_norm` in `sympy/polys/sqfreetools.py` and `dup_ext_factor` in `sympy/polys/factortools.py` | B. M. Trager, "Algebraic factoring and rational function integration", *Proc. SYMSAC '76*, 219–226 (`alg_factor`) |
| `src/transforms/apart.rs` (`apart_params`, `apart_algebraic`: the expression combined, cancelled, divided, and its denominator factored over the ring of the parameters `ℤ[x, y₁, …]`, algebraic numbers other than `i` taken as generators), `src/poly/paramfield.rs` (`cancel_full`: cancellation over the fraction field of the other generators) | `apart` in `sympy/polys/partfrac.py`; `cancel` in `sympy/polys/polytools.py` | partial fractions over a field (the numerators here by the extended Euclidean algorithm, not SymPy's undetermined coefficients); Gauss's lemma |

To the extent any of these is a derivative of SymPy, SymPy's licence
applies to that part, and its notice is reproduced here as clause (a)
requires:

```text
Copyright (c) 2006-2023 SymPy Development Team

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

  a. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
  b. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
  c. Neither the name of SymPy nor the names of its contributors
     may be used to endorse or promote products derived from this software
     without specific prior written permission.


THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
```

**Implementations that follow mpmath's.**

| symplex | follows | algorithm published in |
|---|---|---|
| `src/transforms/evalf/lambertw.rs` (every branch over ℂ: branch-point and asymptotic starting values, Halley iteration), and the `lambert_wm1` start values of the `f64` runtime | `lambertw`, `_lambertw_series`, `_lambertw_approx_hybrid` in `mpmath/functions/functions.py` | R. M. Corless, G. H. Gonnet, D. E. G. Hare, D. J. Jeffrey, D. E. Knuth, "On the Lambert W function", *Adv. Comput. Math.* 5 (1996) 329–359 |
| `src/transforms/evalf/factorials.rs` (`gamma_ratio`: a quotient of Γ values with poles cancelled in the limit) | `gammaprod` in `mpmath/functions/factorials.py` | — |
| `src/transforms/evalf/polylog.rs` (`polylog` of a real order off `[−1, 1]`: the series, the `ln z` expansion, the inversion formula with the Hurwitz argument `½ + ln(−z)/(2πi)`) | `polylog`, `polylog_series`, `polylog_general` in `mpmath/functions/zeta.py` | DLMF 25.12.12, 25.12.13; the Euler–Maclaurin remainder as in F. Johansson, "Rigorous high-precision computation of the Hurwitz zeta function and its derivatives", *Numer. Algorithms* 69 (2015) |
| `src/transforms/evalf/loggamma.rs` (complex `loggamma`: reflection left of `Re z = ½`, the shifted Stirling series, the branch of the shifted product fixed by an `f64` estimate of its imaginary part) | `mpc_loggamma` / `mpc_gamma` in `mpmath/libmp/gammazeta.py` | DLMF 5.11(ii) (Stirling remainder bound) |
| `src/transforms/evalf/polylog.rs` (`nonpositive_poles`: `Li_{−n}(z) = n!·Σ_k (2πik − Log z)^(−n−1)` for `n > 1000`, the two-Hurwitz form summed term by term) | `polylog_general` in `mpmath/functions/zeta.py` | DLMF 25.12.13 (Jonquière's formula) |
| `src/transforms/evalf/extended.rs` (`bessel_scaled`: `J_ν`, `I_ν` below the exponent range as `e^L·₀F₁(; ν + 1; ∓x²/4)`, `L = ν·ln(x/2) − ln Γ(ν + 1)`) | `besselj` / `besseli` (`hypercomb` with unbounded exponents) in `mpmath/functions/bessel.py` | DLMF 10.2.2, 10.25.2 |
| `src/transforms/evalf.rs` (`arb_jacobi`: the cancellation of the explicit sum measured, the largest term over the value, and made up with more bits) | the cancellation check of `hypsum` in `mpmath/ctx_mp.py` (for the `₂F₁` of `jacobi` in `mpmath/functions/orthogonal.py`) | DLMF 18.5.8 |
| `src/transforms/evalf/polylog.rs` (`polylog_complex_order`: a complex order inside the unit disc by the defining series; a large order off the unit disc by the `ln z` expansion while `abs(ln z)` is small) | `polylog_series` (complex `s`) and the `abs(ln z) < 5` branch of `polylog_general` in `mpmath/functions/zeta.py` | DLMF 25.12.10, 25.12.12 |
| `src/transforms/evalf/quad.rs` (arbitrary-precision quadrature of a definite integral: tanh-sinh levels of step `2⁻ᵏ` reusing the previous level's sum, the change of variables of infinite ranges, Gauss–Legendre of degree `3·2^(m−1)` by Newton's iteration from the asymptotic roots, agreement of successive levels, bisection of a piece that does not converge) | `TanhSinh.calc_nodes` / `sum_next`, `QuadratureRule.transform_nodes` / `summation` / `estimate_error`, `GaussLegendre.calc_nodes`, `quadsubdiv` in `mpmath/calculus/quadrature.py` | H. Takahasi, M. Mori, "Double exponential formulas for numerical integration", *Publ. RIMS Kyoto Univ.* 9 (1974) 721–741; J. M. Borwein, D. H. Bailey, R. Girgensohn, *Experimentation in Mathematics: Computational Paths to Discovery*, A K Peters (2004) 312–313 |

To the extent these are derivatives of mpmath, mpmath's licence applies
to those parts, and its notice is reproduced here:

```text
Copyright (c) 2005-2021 Fredrik Johansson and mpmath contributors

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

  a. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
  b. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
  c. Neither the name of the copyright holder nor the names of its
     contributors may be used to endorse or promote products derived
     from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
```

**Implementations that follow statsmodels'.**

| symplex | follows | algorithm published in |
|---|---|---|
| `src/domains/stats/estimation.rs` (`proportion_interval`: the Clopper–Pearson and Jeffreys ends as Beta quantiles) | `proportion_confint(method='beta'/'jeffreys')` in `statsmodels/stats/proportion.py` | C. J. Clopper, E. S. Pearson, *Biometrika* 26 (1934) 404–413; L. D. Brown, T. T. Cai, A. DasGupta, *Statist. Sci.* 16 (2001) 101–133 |

To the extent it is a derivative of statsmodels, statsmodels' licence
applies to that part, and its notice is reproduced here:

```text
Copyright (C) 2006, Jonathan E. Taylor
All rights reserved.

Copyright (c) 2006-2008 Scipy Developers.
All rights reserved.

Copyright (c) 2009-2018 statsmodels Developers.
All rights reserved.


Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

  a. Redistributions of source code must retain the above copyright notice,
     this list of conditions and the following disclaimer.
  b. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
  c. Neither the name of statsmodels nor the names of its contributors
     may be used to endorse or promote products derived from this software
     without specific prior written permission.


THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL STATSMODELS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
```

**Vendored test data.**  `rubi-harness/suite/` is an unmodified copy of the
Rubi integration test suite in Maxima syntax
(<https://github.com/RuleBasedIntegration/MaximaSyntaxTestSuite>, commit
`60295e21`), MIT licensed, "Copyright (c) 2018 Rule-based Integration"; its
`LICENSE` file is kept next to it.  It is used as test input only (no Rubi
rules or code are part of symplex) and is excluded from the published crate.

Everything else in symplex is original work under the crate's licence
(MIT OR Apache-2.0, see `LICENSE-MIT` and `LICENSE-APACHE`), implemented
from the mathematical literature cited in the source.