diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 7e6c742..6a61862 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -6,9 +6,3 @@ updates:
schedule:
interval: "weekly"
day: "friday"
-
- - package-ecosystem: "uv"
- directory: "/"
- schedule:
- interval: "weekly"
- day: "friday"
diff --git a/README.md b/README.md
index 2e1eb28..7cd16e9 100644
--- a/README.md
+++ b/README.md
@@ -4,12 +4,15 @@
[](https://github.com/eggzec/polpack/actions/workflows/test.yml)
[](https://github.com/eggzec/polpack/actions/workflows/docs.yml)
+[](https://codecov.io/github/eggzec/polpack)
[](LICENSE)
[](https://pypi.org/project/polpack/)
[](https://pypi.org/project/polpack/)
-`polpack` is a high-performance Python library for evaluating special functions and recursively-defined polynomial families. The numerical core is written in Fortran and exposed via a Pythonic interface with comprehensive Google-style docstrings.
+`polpack` is a high-performance Python library for evaluating special functions and recursively-defined polynomial families. The numerical core is written in Fortran and compiled via `f2py`, providing efficient routines for mathematical and combinatorial computations.
+
+It includes routines to evaluate classic families such as **Bernoulli**, **Chebyshev**, **Gegenbauer**, **Hermite**, **Laguerre**, and **Legendre** polynomials, among others.
## Quick example
@@ -17,10 +20,10 @@
import numpy as np
import polpack
-# Example: Compute Bell numbers up to order 10
-b = np.zeros(11, dtype=np.int32, order='F')
-polpack.bell(10, b)
-print(f"Bell numbers: {b}")
+# Example: Compute Bell numbers
+bell = np.zeros(11, dtype=np.int32)
+polpack.bell(10, bell)
+print(f"Bell numbers: {bell}")
```
## Installation
@@ -33,7 +36,7 @@ Requires Python 3.10+ and NumPy. See the [full installation guide](https://eggze
## Documentation
-- [Theory](https://eggzec.github.io/polpack/theory/) — mathematical background
+- [Theory](https://eggzec.github.io/polpack/theory/) — mathematical background, polynomial families, and special functions
- [Quickstart](https://eggzec.github.io/polpack/quickstart/) — runnable examples
- [API Reference](https://eggzec.github.io/polpack/api/) — function signatures and parameters
- [References](https://eggzec.github.io/polpack/references/) — literature citations
diff --git a/bin/build.py b/bin/build.py
index 98eb914..7f4e5ee 100644
--- a/bin/build.py
+++ b/bin/build.py
@@ -35,7 +35,9 @@
def run_command(command, cwd=None):
if cwd is None:
- logger.warning("No working directory specified. Using current directory.")
+ logger.warning(
+ "No working directory specified. Using current directory."
+ )
cwd = Path.cwd()
else:
cwd = Path(cwd)
@@ -80,7 +82,13 @@ def clean():
run_command("uv pip uninstall polpack")
for entry in Path("").iterdir():
- if entry.name in ["dist", "build", "lib", ".pytest_cache", ".ruff_cache"]:
+ if entry.name in [
+ "dist",
+ "build",
+ "lib",
+ ".pytest_cache",
+ ".ruff_cache",
+ ]:
logger.info(f"Removing '{entry}'")
shutil.rmtree(entry)
if entry.name == "bin" and entry.is_dir():
diff --git a/doc.txt b/doc.txt
deleted file mode 100644
index 09f73a9..0000000
--- a/doc.txt
+++ /dev/null
@@ -1,362 +0,0 @@
-POLPAK
-Recursive Polynomials
-POLPAK is a FORTRAN77 library which evaluates a variety of mathematical functions.
-
-It includes routines to evaluate the recursively defined polynomial families of
-
-Bernoulli
-Bernstein
-Cardan
-Charlier
-Chebyshev
-Euler
-Gegenbauer
-Hermite
-Jacobi
-Krawtchouk
-Laguerre
-Legendre
-Meixner
-Zernike
-A variety of other polynomials and functions have been added. In a few cases, the new recursive feature of FORTRAN90 has been used (but NOT for the factorial function!)
-Licensing:
-The computer code and data files described and made available on this web page are distributed under the GNU LGPL license.
-
-
-Reference:
-
-Milton Abramowitz, Irene Stegun,
-Handbook of Mathematical Functions,
-National Bureau of Standards, 1964,
-ISBN: 0-486-61272-4,
-LC: QA47.A34.
-Robert Banks,
-Slicing Pizzas, Racing Turtles, and Further Adventures in Applied Mathematics,
-Princeton, 1999,
-ISBN13: 9780691059471,
-LC: QA93.B358.
-Frank Benford,
-The Law of Anomalous Numbers,
-Proceedings of the American Philosophical Society,
-Volume 78, 1938, pages 551-572.
-Paul Bratley, Bennett Fox, Linus Schrage,
-A Guide to Simulation,
-Second Edition,
-Springer, 1987,
-ISBN: 0387964673,
-LC: QA76.9.C65.B73.
-Chad Brewbaker,
-Lonesum (0,1)-matrices and poly-Bernoulli numbers of negative index,
-Master of Science Thesis,
-Computer Science Department,
-Iowa State University, 2005.
-William Briggs, Van Emden Henson,
-The DFT: An Owner's Manual for the Discrete Fourier Transform,
-SIAM, 1995,
-ISBN13: 978-0-898713-42-8,
-LC: QA403.5.B75.
-Theodore Chihara,
-An Introduction to Orthogonal Polynomials,
-Gordon and Breach, 1978,
-ISBN: 0677041500,
-LC: QA404.5 C44.
-William Cody,
-Rational Chebyshev Approximations for the Error Function,
-Mathematics of Computation,
-Volume 23, Number 107, July 1969, pages 631-638.
-Robert Corless, Gaston Gonnet, David Hare, David Jeffrey, Donald Knuth,
-On the Lambert W Function,
-Advances in Computational Mathematics,
-Volume 5, Number 1, December 1996, pages 329-359.
-Bennett Fox,
-Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators,
-ACM Transactions on Mathematical Software,
-Volume 12, Number 4, December 1986, pages 362-376.
-Walter Gautschi,
-Orthogonal Polynomials: Computation and Approximation,
-Oxford, 2004,
-ISBN: 0-19-850672-4,
-LC: QA404.5 G3555.
-Ralph Hartley,
-A More Symmetrical Fourier Analysis Applied to Transmission Problems,
-Proceedings of the Institute of Radio Engineers,
-Volume 30, 1942, pages 144-150.
-Brian Hayes,
-The Vibonacci Numbers,
-American Scientist,
-Volume 87, Number 4, July-August 1999, pages 296-301.
-Brian Hayes,
-Why W?,
-American Scientist,
-Volume 93, Number 2, March-April 2005, pages 104-108.
-Ted Hill,
-The First Digit Phenomenon,
-American Scientist,
-Volume 86, Number 4, July/August 1998, pages 358-363.
-Douglas Hofstadter,
-Goedel, Escher, Bach,
-Basic Books, 1979,
-ISBN: 0465026567,
-LC: QA9.8H63.
-Masanobu Kaneko,
-Poly-Bernoulli Numbers,
-Journal Theorie des Nombres Bordeaux,
-Volume 9, Number 1, 1997, pages 221-228.
-Cleve Moler,
-Trigonometry is a Complex Subject,
-MATLAB News and Notes, Summer 1998.
-Thomas Osler,
-Cardan Polynomials and the Reduction of Radicals,
-Mathematics Magazine,
-Volume 74, Number 1, February 2001, pages 26-32.
-J Simoes Pereira,
-Algorithm 234: Poisson-Charliers Polynomials,
-Communications of the ACM,
-Volume 7, Number 7, July 1964, page 420.
-Charles Pinter,
-A Book of Abstract Algebra,
-Second Edition,
-McGraw Hill, 2003,
-ISBN: 0072943505,
-LC: QA162.P56.
-Ralph Raimi,
-The Peculiar Distribution of First Digits,
-Scientific American,
-December 1969, pages 109-119.
-Dennis Stanton, Dennis White,
-Constructive Combinatorics,
-Springer, 1986,
-ISBN: 0387963472.
-Gabor Szego,
-Orthogonal Polynomials,
-American Mathematical Society, 1992,
-ISBN: 0821810235,
-LC: QA3.A5.v23.
-Daniel Velleman, Gregory Call,
-Permutations and Combination Locks,
-Mathematics Magazine,
-Volume 68, Number 4, October 1995, pages 243-253.
-Divakar Viswanath,
-Random Fibonacci sequences and the number 1.13198824,
-Mathematics of Computation,
-Volume 69, Number 231, July 2000, pages 1131-1155.
-Michael Waterman,
-Introduction to Computational Biology,
-Chapman and Hall, 1995,
-ISBN: 0412993910,
-LC: QH438.4.M33.W38.
-Eric Weisstein,
-CRC Concise Encyclopedia of Mathematics,
-CRC Press, 2002,
-Second edition,
-ISBN: 1584883472,
-LC: QA5.W45
-Stephen Wolfram,
-The Mathematica Book,
-Fourth Edition,
-Cambridge University Press, 1999,
-ISBN: 0-521-64314-7,
-LC: QA76.95.W65.
-ML Wolfson, HV Wright,
-ACM Algorithm 160: Combinatorial of M Things Taken N at a Time,
-Communications of the ACM,
-Volume 6, Number 4, April 1963, page 161.
-Shanjie Zhang, Jianming Jin,
-Computation of Special Functions,
-Wiley, 1996,
-ISBN: 0-471-11963-6,
-LC: QA351.C45.
-Daniel Zwillinger, editor,
-CRC Standard Mathematical Tables and Formulae,
-30th Edition,
-CRC Press, 1996,
-ISBN: 0-8493-2479-3,
-LC: QA47.M315.
-Source Code:
-
-polpak.f, the source code.
-polpak.sh, commands to compile the source code.
-Examples and Tests:
-
-polpak_prb.f, a sample calling program.
-polpak_prb.sh, commands to compile and run the sample program.
-polpak_prb_output.txt, the output file.
-List of Routines:
-
-AGM_VALUES returns some values of the arithmetic geometric mean.
-AGUD evaluates the inverse Gudermannian function.
-ALIGN_ENUM counts the alignments of two sequences of M and N elements.
-BELL returns the Bell numbers from 0 to N.
-BELL_VALUES returns some values of the Bell numbers for testing.
-BENFORD returns the Benford probability of one or more significant digits.
-BERNOULLI_NUMBER computes the value of the Bernoulli numbers B(0) through B(N).
-BERNOULLI_NUMBER2 evaluates the Bernoulli numbers.
-BERNOULLI_NUMBER3 computes the value of the Bernoulli number B(N).
-BERNOULLI_NUMBER_VALUES returns some values of the Bernoulli numbers.
-BERNOULLI_POLY evaluates the Bernoulli polynomial of order N at X.
-BERNOULLI_POLY2 evaluates the N-th Bernoulli polynomial at X.
-BERNSTEIN_POLY evaluates the Bernstein polynomials at a point X.
-BERNSTEIN_POLY_VALUES returns some values of the Bernstein polynomials.
-BETA_VALUES returns some values of the Beta function.
-BPAB evaluates at X the Bernstein polynomials based in [A,B].
-CARDAN_POLY evaluates the Cardan polynomials.
-CARDAN_POLY_COEF computes the coefficients of the N-th Cardan polynomial.
-CARDINAL_COS evaluates the J-th cardinal cosine basis function.
-CARDINAL_SIN evaluates the J-th cardinal sine basis function.
-CATALAN computes the Catalan numbers, from C(0) to C(N).
-CATALAN_CONSTANT returns the value of Catalan's constant.
-CATALAN_ROW_NEXT computes row N of Catalan's triangle.
-CATALAN_VALUES returns some values of the Catalan numbers for testing.
-CHARLIER evaluates Charlier polynomials at a point.
-CHEBY_T_POLY evaluates Chebyshev polynomials T(n,x).
-CHEBY_T_POLY_COEF evaluates coefficients of Chebyshev polynomials T(n,x).
-CHEBY_T_POLY_VALUES returns values of Chebyshev polynomials T(n,x).
-CHEBY_T_POLY_ZERO returns zeroes of Chebyshev polynomials T(n,x).
-CHEBY_U_POLY evaluates Chebyshev polynomials U(n,x).
-CHEBY_U_POLY_COEF evaluates coefficients of Chebyshev polynomials U(n,x).
-CHEBY_U_POLY_VALUES returns values of Chebyshev polynomials U(n,x).
-CHEBY_U_POLY_ZERO returns zeroes of Chebyshev polynomials U(n,x).
-CHEBYSHEV_DISCRETE evaluates discrete Chebyshev polynomials at a point.
-COLLATZ_COUNT counts the number of terms in a Collatz sequence.
-COLLATZ_COUNT_MAX seeks the maximum Collatz count for 1 through N.
-COLLATZ_COUNT_VALUES returns some values of the Collatz count function.
-COMB_ROW_NEXT computes the next row of Pascal's triangle.
-COMMUL computes a multinomial combinatorial coefficient.
-COMPLETE_SYMMETRIC_POLY evaluates a complete symmetric polynomial.
-COS_POWER_INT evaluates the cosine power integral.
-COS_POWER_INT_VALUES returns some values of the cosine power integral.
-DELANNOY returns the Delannoy numbers up to orders (M,N).
-ERF_VALUES returns some values of the ERF or "error" function for testing.
-EULER_NUMBER computes the Euler numbers.
-EULER_NUMBER2 computes the Euler numbers.
-EULER_NUMBER_VALUES returns some values of the Euler numbers.
-EULER_POLY evaluates the N-th Euler polynomial at X.
-EULERIAN computes the Eulerian number E(N,K).
-FIBONACCI_DIRECT computes the N-th Fibonacci number directly.
-FIBONACCI_FLOOR returns the largest Fibonacci number less than or equal to N.
-FIBONACCI_RECURSIVE computes the first N Fibonacci numbers.
-GAMMA_LOG_VALUES returns some values of the Log Gamma function.
-GAMMA_VALUES returns some values of the Gamma function.
-GEGENBAUER_POLY computes the Gegenbauer polynomials C(I,ALPHA,X).
-GEGENBAUER_POLY_VALUES returns some values of the Gegenbauer polynomials.
-GEN_HERMITE_POLY evaluates the generalized Hermite polynomials at X.
-GEN_LAGUERRE_POLY evaluates generalized Laguerre polynomials.
-GUD evaluates the Gudermannian function.
-GUD_VALUES returns some values of the Gudermannian function.
-HERMITE_POLY_PHYS evaluates the physicisist's Hermite polynomials at X.
-HERMITE_POLY_PHYS_COEF evaluates the physicist's Hermite polynomial coefficients.
-HERMITE_POLY_PHYS_VALUES returns some values of the physicist's Hermite polynomial.
-HYPER_2F1_VALUES returns some values of the hypergeometric function 2F1.
-I4_CHOOSE computes the binomial coefficient C(N,K).
-I4_FACTOR factors an I4 into prime factors.
-I4_FACTORIAL computes the factorial of N.
-I4_FACTORIAL_VALUES returns values of the factorial function.
-I4_FACTORIAL2 computes the double factorial function.
-I4_FACTORIAL2_VALUES returns values of the double factorial function.
-I4_HUGE returns a "huge" I4.
-I4_IS_PRIME reports whether an I4 is prime.
-I4_IS_TRIANGULAR determines whether an integer is triangular.
-I4_PARTITION_DISTINCT_COUNT returns any value of Q(N).
-I4_SWAP switches two I4's.
-I4_TO_TRIANGLE converts an integer to triangular coordinates.
-I4_UNIFORM_AB returns a scaled pseudorandom I4 between A and B.
-I4MAT_PRINT prints an I4MAT.
-I4MAT_PRINT_SOME prints some of an I4MAT.
-JACOBI_POLY evaluates the Jacobi polynomials at X.
-JACOBI_POLY_VALUES returns some values of the Jacobi polynomial.
-JACOBI_SYMBOL evaluates the Jacobi symbol (Q/P).
-KRAWTCHOUK evaluates the Krawtchouk polynomials at X.
-LAGUERRE_ASSOCIATED evaluates associated Laguerre polynomials L(N,M,X).
-LAGUERRE_POLY evaluates the Laguerre polynomials at X.
-LAGUERRE_POLY_COEF evaluates the Laguerre polynomial coefficients.
-LAGUERRE_POLYNOMIAL_VALUES returns some values of the Laguerre polynomial.
-LAMBERT_W estimates the Lambert W function.
-LAMBERT_W_CRUDE is a crude estimate of the Lambert W function.
-LAMBERT_W_VALUES returns some values of the Lambert W function.
-LEGENDRE_ASSOCIATED evaluates the associated Legendre functions.
-LEGENDRE_ASSOCIATED_NORMALIZED: normalized associated Legendre functions.
-LEGENDRE_ASSOCIATED_NORMALIZED_SPHERE_VALUES: normalized associated Legendre.
-LEGENDRE_ASSOCIATED_VALUES returns values of associated Legendre functions.
-LEGENDRE_FUNCTION_Q evaluates the Legendre Q functions.
-LEGENDRE_FUNCTION_Q_VALUES returns values of the Legendre Q function.
-LEGENDRE_POLY evaluates the Legendre polynomials P(N,X) at X.
-LEGENDRE_POLY_COEF evaluates the Legendre polynomial coefficients.
-LEGENDRE_POLY_VALUES returns values of the Legendre polynomials.
-LEGENDRE_SYMBOL evaluates the Legendre symbol (Q/P).
-LERCH estimates the Lerch transcendent function.
-LERCH_VALUES returns some values of the Lerch transcendent function.
-LOCK returns the number of codes for a lock with N buttons.
-MEIXNER evaluates Meixner polynomials at a point.
-MERTENS evaluates the Mertens function.
-MERTENS_VALUES returns some values of the Mertens function.
-MOEBIUS returns the value of MU(N), the Moebius function of N.
-MOEBIUS_VALUES returns some values of the Moebius function.
-MOTZKIN returns the Motzkin numbers up to order N.
-NORMAL_01_CDF_INVERSE inverts the standard normal CDF.
-NORMAL_01_CDF_VALUES returns some values of the Normal 01 CDF.
-OMEGA returns OMEGA(N), the number of distinct prime divisors of N.
-OMEGA_VALUES returns some values of the OMEGA function.
-PARTITION_DISTINCT_COUNT_VALUES returns some values of Q(N).
-PENTAGON_NUM computes the N-th pentagonal number.
-PHI computes the number of relatively prime predecessors of an integer.
-PHI_VALUES returns some values of the PHI function.
-PLANE_PARTITION_NUM returns the number of plane partitions of the integer N.
-POLY_BERNOULLI evaluates the poly-Bernolli numbers with negative index.
-POLY_COEF_COUNT: polynomial coefficient count given dimension and degree.
-PRIME returns any of the first PRIME_MAX prime numbers.
-PSI_VALUES returns some values of the Psi or Digamma function for testing.
-PYRAMID_NUM returns the N-th pyramidal number.
-PYRAMID_SQUARE_NUM returns the N-th pyramidal square number.
-R8_AGM computes the arithmetic-geometric mean of A and B.
-R8_BETA returns the value of the Beta function.
-R8_CHOOSE computes the binomial coefficient C(N,K) as an R8.
-R8_EPSILON returns the R8 roundoff unit.
-R8_ERF evaluates the error function.
-R8_ERF_INVERSE inverts the error function.
-R8_EULER_CONSTANT returns the value of the Euler-Mascheroni constant.
-R8_FACTORIAL computes the factorial of N.
-R8_FACTORIAL_LOG computes log(factorial(N)).
-R8_FACTORIAL_LOG_VALUES returns values of log(factorial(n)).
-R8_FACTORIAL_VALUES returns values of the real factorial function.
-R8_GAMMA_LOG evaluates log ( Gamma ( X ) ) for a real argument.
-R8_HUGE returns a "huge" R8.
-R8_HYPER_2F1 evaluates the hypergeometric function F(A,B,C,X).
-R8_MOP returns the I-th power of -1 as an R8.
-R8_NINT returns the nearest integer to an R8.
-R8_PI returns the value of pi as an R8.
-R8_PSI evaluates the function Psi(X).
-R8_UNIFORM_01 returns a unit pseudorandom R8.
-R8POLY_DEGREE returns the degree of a polynomial.
-R8POLY_PRINT prints out a polynomial.
-R8POLY_VALUE_HORNER evaluates a polynomial using Horner's method.
-R8VEC_LINSPACE creates a vector of linearly spaced values.
-R8VEC_PRINT prints an R8VEC.
-R8VEC_PRINT_SOME prints "some" of an R8VEC.
-R8VEC_UNIFORM_AB returns a scaled pseudorandom R8VEC.
-S_LEN_TRIM returns the length of a string to the last nonblank.
-SIGMA returns the value of SIGMA(N), the divisor sum.
-SIGMA_VALUES returns some values of the Sigma function.
-SIMPLEX_NUM evaluates the N-th Simplex number in M dimensions.
-SIN_POWER_INT evaluates the sine power integral.
-SIN_POWER_INT_VALUES returns some values of the sine power integral.
-SLICE: maximum number of pieces created by a given number of slices.
-SPHERICAL_HARMONIC evaluates spherical harmonic functions.
-SPHERICAL_HARMONIC_VALUES returns values of spherical harmonic functions.
-STIRLING1 computes the Stirling numbers of the first kind.
-STIRLING2 computes the Stirling numbers of the second kind.
-TAU returns the value of TAU(N), the number of distinct divisors of N.
-TAU_VALUES returns some values of the Tau function.
-TETRAHEDRON_NUM returns the N-th tetrahedral number.
-TIMESTAMP prints out the current YMDHMS date as a timestamp.
-TRIANGLE_NUM returns the N-th triangular number.
-TRIANGLE_TO_I4 converts a triangular coordinate to an integer.
-TRINOMIAL computes a trinomial coefficient.
-VIBONACCI computes the first N Vibonacci numbers.
-ZECKENDORF produces the Zeckendorf decomposition of a positive integer.
-ZERNIKE_POLY evaluates a Zernike polynomial at RHO.
-ZERNIKE_POLY_COEF: coefficients of a Zernike polynomial.
-ZETA estimates the Riemann Zeta function.
-ZETA_VALUES returns some values of the Riemann Zeta function.
-You can go up one level to the FORTRAN77 source codes.
-
-Last revised on 11 April 2015.
diff --git a/docs/api.md b/docs/api.md
index f77126a..ded7e10 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -1,52 +1,262 @@
# API Reference
-All routines in `polpack` are exposed via the top-level `polpack` package. The underlying numerical routines are implemented in Fortran and accessed through the `_polpack` extension module.
+All public routines are exported via the `polpack` Python module in lowercase.
---
-## Calling Convention
+## Overview
-Most `polpack` routines for sequences and polynomials follow a consistent calling convention where the results are stored in a pre-allocated NumPy array passed as an argument.
+`polpack` includes routines to evaluate a variety of recursively defined
+polynomial families and special functions. Most generators follow a three-term
+recurrence and write the output into a pre-allocated NumPy array.
-### Array Requirements
+| Family | Category | Type | Domain |
+|---|---|---|---|
+| `bernoulli_poly` | Polynomial | Sequence | \( \mathbb{R} \) |
+| `bernstein_poly` | Polynomial | Basis | \( [0, 1] \) |
+| `cardan_poly` | Polynomial | Cubic | \( \mathbb{R} \) |
+| `charlier` | Polynomial | Discrete | \( \mathbb{N} \) |
+| `cheby_t_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `gegenbauer_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `jacobi_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `laguerre_poly` | Polynomial | Orthogonal | \( [0, \infty) \) |
+| `legendre_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
-For routines that modify arrays in-place:
-1. **Dtype:** Must match the expected Fortran type (usually `np.int32` for combinatorial counts and `np.float64` for polynomial values).
-2. **Order:** Arrays **must** be initialized with Fortran memory layout (`order='F'`) for optimal performance and compatibility with the Fortran core.
-3. **Size:** The array must be correctly sized (e.g., `n+1` for polynomials of degree `n`).
+---
+
+## Common interface
+
+### Arguments
-```python
-import numpy as np
-import polpack
+| Argument | Type | Direction | Description |
+|---|---|---|---|
+| `n` | `int` | input | Highest degree or number of terms to compute |
+| `x` | `float` | input | Evaluation point |
+| `v` | `ndarray` | in/out | Pre-allocated output array of size `n+1` |
-# Correct initialization
-n = 10
-b = np.zeros(n + 1, dtype=np.int32, order='F')
-polpack.bell(n, b)
-```
+!!! warning "Array allocation"
+ The output array `v` must be pre-allocated with the correct size before
+ calling the routine. Passing an undersized array will raise a runtime error.
+
+---
+
+## Orthogonal Polynomials
+
+### `cheby_t_poly(m, n, x, cx)`
+**Chebyshev polynomials of the first kind.**
+
+- `m` (int): Number of evaluation points.
+- `n` (int): Highest degree.
+- `x` (ndarray[m]): Evaluation points.
+- `cx` (ndarray[m, n+1]): Output matrix.
+
+### `gegenbauer_poly(n, alpha, x, cx)`
+**Gegenbauer polynomials.**
+
+- `n` (int): Highest degree.
+- `alpha` (float): Parameter \( \alpha > -1/2 \).
+- `x` (float): Evaluation point.
+- `cx` (ndarray[n+1]): Output array.
+
+### `hermite_poly_phys(n, x, cx)`
+**Hermite polynomials (Physicist's).**
+
+- `n` (int): Highest degree.
+- `x` (float): Evaluation point.
+- `cx` (ndarray[n+1]): Output array.
+
+### `jacobi_poly(n, alpha, beta, x, cx)`
+**Jacobi polynomials.**
+
+- `n` (int): Highest degree.
+- `alpha` (float): Parameter \( \alpha \).
+- `beta` (float): Parameter \( \beta \).
+- `x` (float): Evaluation point.
+- `cx` (ndarray[n+1]): Output array.
+
+### `laguerre_poly(n, x, cx)`
+**Laguerre polynomials.**
+
+- `n` (int): Highest degree.
+- `x` (float): Evaluation point.
+- `cx` (ndarray[n+1]): Output array.
+
+### `legendre_poly(n, x, cx, cpx)`
+**Legendre polynomials.**
+
+- `n` (int): Highest degree.
+- `x` (float): Evaluation point.
+- `cx` (ndarray[n+1]): Output array \( P_n(x) \).
+- `cpx` (ndarray[n+1]): Output array of derivatives \( P'_n(x) \).
---
## Combinatorial Sequences
-- **bell(n, b)**: Evaluates the Bell numbers $B_0, \dots, B_n$.
-- **catalan(n, c)**: Evaluates the Catalan numbers $C_0, \dots, C_n$.
-- **stirling1(n, m, s1)**: Evaluates the Stirling numbers of the first kind.
-- **stirling2(n, m, s2)**: Evaluates the Stirling numbers of the second kind.
-- **fibonacci_recursive(n, f)**: Evaluates the first $n$ Fibonacci numbers.
-- **eulerian(n, k)**: Evaluates the Eulerian number $E(n, k)$.
-- **motzkin(n, a)**: Evaluates the Motzkin numbers up to order $n$.
+### `bell(n, b)`
+**Bell numbers.**
+
+- `n` (int): Highest index.
+- `b` (ndarray[n+1]): Output array of Bell numbers \( B_0, \dots, B_n \).
+
+### `catalan(n, c)`
+**Catalan numbers.**
+
+- `n` (int): Highest index.
+- `c` (ndarray[n+1]): Output array of Catalan numbers \( C_0, \dots, C_n \).
+
+### `stirling1(n, m, s1)` / `stirling2(n, m, s2)`
+**Stirling numbers.**
+
+- `n` (int): Number of elements.
+- `m` (int): Number of subsets/cycles.
+- `s1/s2` (ndarray[n, m]): Output matrix.
+
+---
+
+## Detailed Routine Reference
+
+### Bernoulli and Euler Sequences
+
+#### `bernoulli_number(n, b)`
+Computes the sequence of Bernoulli numbers \( B_0, \dots, B_n \).
+
+- `n` (int): Highest index.
+- `b` (ndarray[n+1]): Output array.
+
+#### `bernoulli_poly(n, x, bx)`
+Evaluates the Bernoulli polynomial \( B_n(x) \) at \( x \).
+
+- `n` (int): Degree.
+- `x` (float): Evaluation point.
+- `bx` (float): Output value.
+
+#### `euler_number(n, e)`
+Computes the sequence of Euler numbers \( E_0, \dots, E_n \).
+
+- `n` (int): Highest index.
+- `e` (ndarray[n+1]): Output array.
+
+#### `euler_poly(n, x)`
+Evaluates the \( n \)-th Euler polynomial \( E_n(x) \) at \( x \).
+
+- `n` (int): Degree.
+- `x` (float): Evaluation point.
+- Returns `float`.
+
+### Bernstein Polynomials
+
+#### `bernstein_poly(n, x, bern)`
+Evaluates the \( n+1 \) Bernstein basis polynomials of degree \( n \) at \( x \in [0, 1] \).
+
+- `n` (int): Degree.
+- `x` (float): Evaluation point.
+- `bern` (ndarray[n+1]): Output array of basis values.
+
+#### `bpab(n, x, a, b, bern)`
+Evaluates the \( n+1 \) Bernstein basis polynomials of degree \( n \) on \( [a, b] \).
+
+- `n` (int): Degree.
+- `x` (float): Evaluation point.
+- `a, b` (float): Interval boundaries.
+- `bern` (ndarray[n+1]): Output array of basis values.
+
+### Fibonacci and Power Sequences
+
+#### `fibonacci_recursive(n, f)`
+Computes the first \( n \) Fibonacci numbers.
+
+- `n` (int): Number of terms.
+- `f` (ndarray[n]): Output array.
+
+#### `fibonacci_direct(n, f)`
+Computes the \( n \)-th Fibonacci number using the closed-form Binet formula.
+
+- `n` (int): Index.
+- `f` (int): Output value.
+
+### Stirling Sequences
+
+#### `stirling1(n, m, s1)`
+Computes the Stirling numbers of the first kind \( s(n, k) \).
+
+- `n` (int): Order.
+- `m` (int): Term index.
+- `s1` (ndarray[n, m]): Output matrix.
+
+#### `stirling2(n, m, s2)`
+Computes the Stirling numbers of the second kind \( S(n, k) \).
+
+- `n` (int): Order.
+- `m` (int): Term index.
+- `s2` (ndarray[n, m]): Output matrix.
+
+---
+
+### Special Math Functions
+
+#### `agm_values(n_data, a, b, fx)`
+Returns tabulated values of the Arithmetic-Geometric Mean.
+
+- `n_data` (int): Index of the value to retrieve (0 for first).
+- `a, b` (float): Parameters.
+- `fx` (float): Output AGM value.
+
+#### `agud(g)`
+Evaluates the inverse Gudermannian function.
+
+- `g` (float): Input value.
+- Returns `float`.
+
+#### `beta_values(n_data, x, y, fxy)`
+Returns tabulated values of the Beta function \( \text{B}(x, y) \).
+
+#### `erf_values(n_data, x, fx)`
+Returns tabulated values of the error function \( \text{erf}(x) \).
+
+#### `gamma_values(n_data, x, fx)`
+Returns tabulated values of the Gamma function \( \Gamma(x) \).
+
+#### `lambert_w(x)`
+Estimates the Lambert W function \( W(x) \), the inverse of \( f(w) = we^w \).
+
+---
+
+### Number Theory and Primality
+
+| Routine | Parameters | Description |
+|---|---|---|
+| `phi(n, phin)` | `n` (int): input
`phin` (int): out | Euler totient function \( \phi(n) \). |
+| `moebius(n, mu)` | `n` (int): input
`mu` (int): out | Moebius function \( \mu(n) \). |
+| `mertens(n)` | `n` (int): input | Mertens function \( M(n) \) (returns int). |
+| `prime(n)` | `n` (int): input | Returns the \( n \)-th prime number. |
+| `i4_is_prime(n)` | `n` (int): input | Primality test (returns bool). |
+| `i4_factor(...)` | `n`, `f_max`, `f_num`, `f`, `p`, `nleft` | Prime factorization into components. |
+| `sigma(n, sigma_n)` | `n` (int): input
`sigma_n` (int): out | Sum of divisors \( \sigma(n) \). |
+| `tau(n, taun)` | `n` (int): input
`taun` (int): out | Number of divisors \( \tau(n) \). |
+| `jacobi_symbol(q, p, j)` | `q, p` (int), `j` (int): out | Jacobi symbol \( (q/p) \). |
+| `legendre_symbol(q, p, l)` | `q, p` (int), `l` (int): out | Legendre symbol \( (q/p) \). |
-## Special Functions
+### Sequences and Series
-- **r8_beta(x, y)**: Evaluates the Beta function.
-- **r8_gamma_log(x)**: Evaluates log(Gamma(X)).
-- **zeta(p)**: Evaluates the Riemann Zeta function.
-- **lambert_w(x)**: Estimates the Lambert W function.
+| Routine | Parameters | Description |
+|---|---|---|
+| `catalan(n, c)` | `n` (int), `c` (ndarray) | Catalan numbers sequence. |
+| `delannoy(m, n, a)` | `m`, `n` (int), `a` (ndarray) | Delannoy numbers matrix. |
+| `motzkin(n, a)` | `n` (int), `a` (ndarray) | Motzkin numbers sequence. |
+| `vibonacci(n, seed, v)` | `n`, `seed` (int), `v` (ndarray) | Random Vibonacci terms. |
+| `collatz_count(n)` | `n` (int): input | Sequence length (returns int). |
+| `collatz_count_max(...)` | `n, i_max, j_max` | Maximum count in range \( [1, n] \). |
-## Number Theory
+### Special Utilities
-- **i4_is_prime(n)**: Reports whether an integer is prime.
-- **phi(n)**: Evaluates the Euler phi function.
-- **sigma(n)**: Evaluates the divisor sum function.
-- **tau(n)**: Evaluates the number of distinct divisors.
+| Routine | Parameters | Description |
+|---|---|---|
+| `agm_values(...)` | `n_data, a, b, fx` | Arithmetic-Geometric Mean data. |
+| `i4_choose(n, k)` | `n, k` (int) | Binomial coefficient (returns int). |
+| `i4_swap(i, j)` | `i, j` (int) | Swaps values in-place (in/out). |
+| `i4_huge()` | (none) | Returns largest representable i4. |
+| `zeckendorf(...)` | `n, m_max, m, i_l, f_l` | Zeckendorf representation decomposition. |
+| `complete_symmetric_poly` | `n, r, x, value` | Evaluates \( h_r(x_1, \dots, x_n) \). |
+| `zernike_poly` | `m, n, rho, z` | Zernike polynomial at \( \rho \). |
+| `zeta(p)` | `p` (float): input | Riemann Zeta function \( \zeta(p) \) (returns float). |
diff --git a/docs/index.md b/docs/index.md
index 782cb9e..89ed28c 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -6,32 +6,29 @@
## What is polpack?
-`polpack` is a Python library for evaluating a wide range of
-[special functions](https://en.wikipedia.org/wiki/Special_functions) and
-recursively-defined polynomial families. The numerical core is written in
-Fortran and exposed through a high-performance Python extension, providing
-near-native execution speeds for intense mathematical computations.
+`polpack` is a Python library for evaluating special functions and recursively-defined polynomial families. The numerical core is based on the original `POLPAK` library, providing efficient routines to evaluate a wide variety of mathematical functions.
-Whether you need to compute Bell numbers, evaluate Bernoulli polynomials, or
-work with orthogonal polynomial families (Chebyshev, Jacobi, Laguerre, etc.),
-`polpack` offers a robust and tested suite of routines.
+A **polynomial family** is a sequence of polynomials where each member is typically defined by its degree. Many such families are defined recursively, where higher-degree polynomials are computed from lower-degree ones. These functions are fundamental in numerical analysis, approximation theory, and physics.
-## Why polpack?
+`polpack` provides near-native performance by compiling its Fortran core via `f2py`, offering a clean and intuitive NumPy-based Python API.
-| Feature | Detail |
-|---|---|
-| **High Performance** | Compiled Fortran core — efficient handling of recursive relations |
-| **Comprehensive** | Over 170 routines for sequences, polynomials, and special functions |
-| **Pythonic API** | Google-style docstrings and seamless NumPy integration |
-| **Memory Efficient** | Supports in-place array modification for large-scale computations |
-| **Portability** | Cross-platform support for Linux, macOS, and Windows |
+## Available polynomial families
-## Key Categories
-- **Combinatorial Sequences:** Bell, Bernoulli, Catalan, Eulerian, Fibonacci, Stirling, etc.
-- **Polynomial Families:** Bernoulli, Bernstein, Chebyshev, Gegenbauer, Hermite, Jacobi, Laguerre, Legendre, etc.
-- **Special Functions:** AGM, Beta, Error function, Gamma, Lambert W, Zeta, etc.
-- **Number Theory:** Collatz counts, Moebius, Omega, Phi, Primes, Sigma, Tau, etc.
+
+| Family | Category | Type | Domain |
+|---|---|---|---|
+| `bernoulli_poly` | Polynomial | Sequence | \( \mathbb{R} \) |
+| `bernstein_poly` | Polynomial | Basis | \( [0, 1] \) |
+| `cardan_poly` | Polynomial | Cubic | \( \mathbb{R} \) |
+| `charlier` | Polynomial | Discrete | \( \mathbb{N} \) |
+| `cheby_t_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `gegenbauer_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `jacobi_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+| `laguerre_poly` | Polynomial | Orthogonal | \( [0, \infty) \) |
+| `legendre_poly` | Polynomial | Orthogonal | \( [-1, 1] \) |
+
+*(See [API Reference](api.md) for the full list of supported families and routines.)*
## Quick example
@@ -39,24 +36,10 @@ work with orthogonal polynomial families (Chebyshev, Jacobi, Laguerre, etc.),
import numpy as np
import polpack
-# Example: Evaluate the first 11 Bell numbers
-b = np.zeros(11, dtype=np.int32, order='F')
+# Example: Compute the first 11 Bell numbers
+# b[n] will contain the n-th Bell number
+b = np.zeros(11, dtype=np.int32, order="F")
polpack.bell(10, b)
-print(f"Bell numbers B(0..10): {b}")
-# Example: Evaluate Legendre polynomials at a point
-cx = np.zeros(6, dtype=np.float64, order='F')
-cpx = np.zeros(6, dtype=np.float64, order='F')
-polpack.legendre_poly(5, 0.5, cx, cpx)
-print(f"Legendre P_5(0.5): {cx[5]}")
+print(f"Bell numbers B_0 to B_10: {b}")
```
-
-## Licensing
-
-The computer code and data files are distributed under the [GNU LGPL license](LICENSE).
-
-## References
-
-1. Milton Abramowitz, Irene Stegun, **Handbook of Mathematical Functions**, National Bureau of Standards, 1964.
-2. Frank Benford, **The Law of Anomalous Numbers**, Proceedings of the American Philosophical Society, Vol. 78, 1938.
-3. Robert Corless, et al., **On the Lambert W Function**, Advances in Computational Mathematics, Vol. 5, 1996.
diff --git a/docs/installation.md b/docs/installation.md
index 58f8283..8b1cf96 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -1,34 +1,137 @@
# Installation
-`polpack` can be installed via `pip`, `conda`, or built from source using `meson-python`.
+`polpack` is distributed as a compiled wheel on PyPI and can also be installed
+from source via GitHub.
+
+---
## Prerequisites
-- **Python:** 3.10 or later.
-- **NumPy:** 2.0 or later recommended.
-- **Fortran Compiler:** `gfortran` (required for source builds).
+- **Python 3.10+**
+- **NumPy** (installed automatically as a dependency)
+
+For source builds you additionally need:
+
+- A Fortran compiler (`gfortran` recommended)
+- `meson` and `meson-python` build system
+- `numpy` (for `f2py` compilation)
+
+## PyPI (recommended)
+
+### pip
+
+```bash
+pip install --upgrade polpack
+```
+
+### pyproject.toml dependency
+
+```toml
+[project]
+dependencies = [
+ "polpack"
+]
+```
+
+### requirements.txt
+
+```text
+polpack
+```
+
+## Package managers
+
+### uv
+
+```bash
+# Add to a uv project
+uv add polpack
+
+# Or install into the current environment
+uv pip install polpack
+```
+
+### pipenv
+
+```bash
+pipenv install polpack
+```
+
+### poetry
+
+```bash
+poetry add polpack
+```
+
+### pdm
+
+```bash
+pdm add polpack
+```
+
+### hatch
+
+```bash
+hatch add polpack
+```
+
+## Installing from source (GitHub)
+
+Install the latest development version directly from the repository:
+
+```bash
+pip install --upgrade "git+https://github.com/eggzec/polpack.git#egg=polpack"
+```
-## Using pip
+### Building locally
-The simplest way to install the latest release is from PyPI:
+Clone and build from source if you want to modify the Fortran code or test
+local changes:
```bash
-pip install polpack
+git clone https://github.com/eggzec/polpack.git
+cd polpack
+pip install -e .
```
-## Building from source
+This invokes the `meson` build system to compile the Fortran sources via
+`f2py` and install the resulting extension module in development mode.
-To build `polpack` from the source repository, you will need `uv` and a Fortran compiler.
+!!! warning "Fortran compiler required"
+ Source builds require a working Fortran compiler. On most Linux
+ distributions install `gfortran`:
+
+```bash
+# Debian/Ubuntu
+sudo apt install gfortran
+
+# Fedora
+sudo dnf install gcc-gfortran
+
+# macOS (Homebrew)
+brew install gcc
+```
+
+On Windows, install MinGW-w64 with gfortran or use MSYS2.
+
+## Verifying the installation
+
+After installation, verify that the package loads correctly:
+
+```python
+import polpack
+import numpy as np
+
+n = 10
+b = np.zeros(n + 1, dtype=np.int32, order="F")
+polpack.bell(n, b)
+print("polpack is working! Bell numbers:", b)
+```
-1. **Clone the repository:**
- ```bash
- git clone https://github.com/eggzec/polpack
- cd polpack
- ```
+## Dependencies
-2. **Install using the build script:**
- ```bash
- uv run bin/build.py install
- ```
+| Package | Purpose |
+|---|---|
+| `numpy` | Array handling, `f2py` integration |
-This will automatically configure Meson, compile the Fortran source, and install the package into your active environment.
+No other runtime dependencies are required.
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 33c0514..9d858c9 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -2,6 +2,30 @@
This guide will help you get started with polpack in Python.
+## Working with Sequences
+
+Beyond polynomial families, `polpack` provides routines for various integer
+sequences. These typically follow a similar pattern but return integers
+(or floats for very large values).
+
+### Bell Numbers
+The Bell numbers $B_n$ count the number of partitions of a set.
+
+```python
+import numpy as np
+import polpack
+
+# Compute Bell numbers up to n=10
+n = 10
+b = np.zeros(n + 1)
+polpack.bell(n, b)
+
+print(f"Bell numbers B_0 to B_{n}:")
+print(b)
+```
+
+---
+
## Basic Usage
Evaluate the first 10 Bernoulli numbers:
@@ -14,38 +38,82 @@ n = 10
# Initialize an array of size n+1 in Fortran order
b = np.zeros(n + 1, dtype=np.float64, order="F")
polpack.bernoulli_number(n, b)
-This guide shows you how to use `polpack` for common mathematical tasks.
+```
+
+This guide provides walk-through examples of how to use `polpack` to evaluate
+common polynomial families and combinatorial sequences in Python.
-## Combinatorial counts
+---
-To compute sequences like Bell numbers or Catalan numbers, pass a pre-allocated NumPy array to the routine.
+## Recursive Polynomials: Chebyshev First Kind
+
+Chebyshev polynomials are fundamental in approximation theory and spectral
+methods. In `polpack`, you can evaluate the entire sequence $T_0(x), \dots, T_n(x)$
+efficiently in a single call.
```python
import numpy as np
import polpack
-# Compute first 11 Bell numbers
-n = 10
-b = np.zeros(n + 1, dtype=np.int32, order='F')
-polpack.bell(n, b)
-print(f"Bell numbers: {b}")
+# 1. Configuration
+m = 1 # Number of points
+n = 5 # Highest degree
+x = 0.5 # Evaluation point
+v = np.zeros(n + 1, dtype=np.float64, order="F")
+
+# 2. Evaluation
+polpack.cheby_t_poly(m, n, x, v)
+
+# 3. Results
+print(f"Chebyshev T_0({x}) to T_{n}({x}):")
+for i, val in enumerate(v):
+ print(f" T_{i}({x}) = {val:.4f}")
```
-## Polynomial evaluation
+## Orthogonal Polynomials: Legendre Polynomials
+
+Legendre polynomials are orthogonal on $[-1, 1]$ and arise naturally in
+potential theory and spherical harmonics.
+
+```python
+import numpy as np
+import polpack
+
+# 1. Evaluate Legendre polynomials P_0 to P_10 at x=0.0
+n = 10
+x = 0.0
+p = np.zeros(n + 1, dtype=np.float64, order="F")
+# Output array for first derivatives (not used here)
+dp = np.zeros(n + 1, dtype=np.float64, order="F")
+
+polpack.legendre_poly(n, x, p, dp)
+
+# 2. Inspect results
+# P_n(0.0) = 0 for odd n
+print(f"Legendre P_n(0.0) for n=0..10:\n{p}")
+```
-`polpack` provides routines for evaluating polynomial families at specific points or computing their coefficients.
+## Combinatorial Sequences: Bell Numbers
-### Point evaluation
+Bell numbers $B_n$ count the number of partitions of a set of size $n$. These
+increase rapidly, so `polpack` typically uses `int32` or `float64` depending
+on the routine variant.
```python
import numpy as np
import polpack
+# 1. Compute the first 15 Bell numbers
+n = 14
+b = np.zeros(n + 1, dtype=np.int32, order="F")
+
+polpack.bell(n, b)
+
# Evaluate the 5th Legendre polynomial at x = 0.5
n = 5
x = 0.5
-cx = np.zeros(n + 1, dtype=np.float64, order='F')
-cpx = np.zeros(n + 1, dtype=np.float64, order='F') # for derivatives
+cx = np.zeros(n + 1, dtype=np.float64, order="F")
+cpx = np.zeros(n + 1, dtype=np.float64, order="F") # for derivatives
polpack.legendre_poly(n, x, cx, cpx)
@@ -62,7 +130,7 @@ import polpack
# Get coefficients of the 4th-order Chebyshev polynomial T_4(x)
n = 4
# Space for (n+1) x (n+1) coefficient matrix
-c = np.zeros((n + 1, n + 1), dtype=np.float64, order='F')
+c = np.zeros((n + 1, n + 1), dtype=np.float64, order="F")
polpack.cheby_t_poly_coef(n, c)
print("Chebyshev T_4 coefficients (highest power first):")
diff --git a/docs/references.md b/docs/references.md
index 4e84525..2821d5f 100644
--- a/docs/references.md
+++ b/docs/references.md
@@ -1,34 +1,133 @@
# References
-The algorithms implemented in `polpack` are based on established mathematical literature and numerical libraries.
-
-## Key Sources
-
-1. **Abramowitz, M. and Stegun, I. A. (Eds.).** *Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables*. National Bureau of Standards Applied Mathematics Series, 55. U.S. Government Printing Office, 1972.
-2. **Burkardt, John.** *polpack: Mathematical functions, polynomial families, and sequences*. [Original Fortran versions](https://people.sc.fsu.edu/~jburkardt/f_src/polpak/polpak.html).
-3. **Knuth, Donald E.** *The Art of Computer Programming, Volume 1: Fundamental Algorithms*. Addison-Wesley, 1997. (For combinatorial sequences).
-4. **Press, W. H., et al.** *Numerical Recipes: The Art of Scientific Computing*. Cambridge University Press, 2007.
-
-## Specific Algorithms
-
-- **Chebyshev Polynomials:** Based on standard recurrences and zeroes from approximation theory.
-- **Lambert W Function:** Implementation follows iterative methods for real-valued branches.
-- **RNG:** Standard Lehmer (Park-Miller) linear congruential generator for seeded random numbers.
-
-3. Frank Benford, **The Law of Anomalous Numbers**, Proceedings of the American Philosophical Society, Vol. 78, 1938, pages 551-572.
-4. Paul Bratley, Bennett Fox, Linus Schrage, **A Guide to Simulation**, Second Edition, Springer, 1987, ISBN: 0387964673.
-5. Chad Brewbaker, **Lonesum (0,1)-matrices and poly-Bernoulli numbers of negative index**, Master of Science Thesis, Computer Science Department, Iowa State University, 2005.
-6. William Briggs, Van Emden Henson, **The DFT: An Owner's Manual for the Discrete Fourier Transform**, SIAM, 1995, ISBN13: 978-0-898713-42-8.
-7. Theodore Chihara, **An Introduction to Orthogonal Polynomials**, Gordon and Breach, 1978, ISBN: 0677041500.
-8. William Cody, **Rational Chebyshev Approximations for the Error Function**, Mathematics of Computation, Vol. 23, No. 107, July 1969, pages 631-638.
-9. Robert Corless, Gaston Gonnet, David Hare, David Jeffrey, Donald Knuth, **On the Lambert W Function**, Advances in Computational Mathematics, Vol. 5, No. 1, Dec 1996, pages 329-359.
-10. Bennett Fox, **Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators**, ACM Transactions on Mathematical Software, Vol. 12, No. 4, Dec 1986, pages 362-376.
-11. Walter Gautschi, **Orthogonal Polynomials: Computation and Approximation**, Oxford, 2004, ISBN: 0-19-850672-4.
-12. Brian Hayes, **The Vibonacci Numbers**, American Scientist, Vol. 87, No. 4, July-August 1999, pages 296-301.
-13. Douglas Hofstadter, **Goedel, Escher, Bach**, Basic Books, 1979, ISBN: 0465026567.
-14. Masanobu Kaneko, **Poly-Bernoulli Numbers**, Journal Theorie des Nombres Bordeaux, Vol. 9, No. 1, 1997, pages 221-228.
-15. Thomas Osler, **Cardan Polynomials and the Reduction of Radicals**, Mathematics Magazine, Vol. 74, No. 1, Feb 2001, pages 26-32.
-16. Gabor Szego, **Orthogonal Polynomials**, American Mathematical Society, 1992, ISBN: 0821810235.
-17. Divakar Viswanath, **Random Fibonacci sequences and the number 1.13198824**, Mathematics of Computation, Vol. 69, No. 231, July 2000, pages 1131-1155.
-18. Eric Weisstein, **CRC Concise Encyclopedia of Mathematics**, CRC Press, 2002, ISBN: 1584883472.
-19. Shanjie Zhang, Jianming Jin, **Computation of Special Functions**, Wiley, 1996, ISBN: 0-471-11963-6.
+## Core Mathematical References
+
+1. **Abramowitz, M., Stegun, I.**
+ *Handbook of Mathematical Functions*.
+ National Bureau of Standards, 1964.
+
+2. **Chihara, T.**
+ *An Introduction to Orthogonal Polynomials*.
+ Gordon and Breach, 1978.
+
+3. **Gautschi, W.**
+ *Orthogonal Polynomials: Computation and Approximation*.
+ Oxford, 2004.
+
+4. **Szego, G.**
+ *Orthogonal Polynomials*.
+ American Mathematical Society, 1992.
+
+5. **Zhang, S., Jin, J.**
+ *Computation of Special Functions*.
+ Wiley, 1996.
+
+6. **Knuth, D.**
+ *The Art of Computer Programming, Volume 2: Seminumerical Algorithms*.
+ Addison-Wesley, 1997.
+
+## Specialized Literature
+
+7. **Banks, R.**
+ *Slicing Pizzas, Racing Turtles, and Further Adventures in Applied Mathematics*.
+ Princeton, 1999.
+
+8. **Benford, F.**
+ “The Law of Anomalous Numbers.”
+ *Proceedings of the American Philosophical Society*, 78, 1938.
+
+9. **Bratley, P., Fox, B., Schrage, L.**
+ *A Guide to Simulation*.
+ Second Edition, Springer, 1987.
+
+10. **Brewbaker, C.**
+ “Lonesum (0,1)-matrices and poly-Bernoulli numbers of negative index.”
+ *Master of Science Thesis*, Iowa State University, 2005.
+
+11. **Briggs, W., Henson, V.**
+ *The DFT: An Owner's Manual for the Discrete Fourier Transform*.
+ SIAM, 1995.
+
+12. **Cody, W.**
+ “Rational Chebyshev Approximations for the Error Function.”
+ *Mathematics of Computation*, 23(107), 1969.
+
+13. **Corless, R., Gonnet, G., Hare, D., Jeffrey, D., Knuth, D.**
+ “On the Lambert W Function.”
+ *Advances in Computational Mathematics*, 5(1), 1996.
+
+14. **Fox, B.**
+ “Algorithm 647: Implementation and Relative Efficiency of Quasirandom Sequence Generators.”
+ *ACM Transactions on Mathematical Software*, 12(4), 1986.
+
+15. **Hartley, R.**
+ “A More Symmetrical Fourier Analysis Applied to Transmission Problems.”
+ *Proceedings of the Institute of Radio Engineers*, 30, 1942.
+
+16. **Hayes, B.**
+ “The Vibonacci Numbers.”
+ *American Scientist*, 87(4), 1999.
+
+17. **Hill, T.**
+ “The First Digit Phenomenon.”
+ *American Scientist*, 86(4), 1998.
+
+18. **Hofstadter, D.**
+ *Goedel, Escher, Bach*.
+ Basic Books, 1979.
+
+19. **Kaneko, M.**
+ “Poly-Bernoulli Numbers.”
+ *Journal Theorie des Nombres Bordeaux*, 9(1), 1997.
+
+20. **Osler, T.**
+ “Cardan Polynomials and the Reduction of Radicals.”
+ *Mathematics Magazine*, 74(1), 2001.
+
+21. **Pereira, J.**
+ “Algorithm 234: Poisson-Charliers Polynomials.”
+ *Communications of the ACM*, 7(7), 1964.
+
+22. **Pinter, C.**
+ *A Book of Abstract Algebra*.
+ Second Edition, McGraw Hill, 2003.
+
+23. **Raimi, R.**
+ “The Peculiar Distribution of First Digits.”
+ *Scientific American*, 1969.
+
+24. **Stanton, D., White, D.**
+ *Constructive Combinatorics*.
+ Springer, 1986.
+
+25. **Velleman, D., Call, G.**
+ “Permutations and Combination Locks.”
+ *Mathematics Magazine*, 68(4), 1995.
+
+26. **Viswanath, D.**
+ “Random Fibonacci sequences and the number 1.13198824.”
+ *Mathematics of Computation*, 69(231), 2000.
+
+27. **Waterman, M.**
+ *Introduction to Computational Biology*.
+ Chapman and Hall, 1995.
+
+28. **Weisstein, E.**
+ *CRC Concise Encyclopedia of Mathematics*.
+ Second Edition, CRC Press, 2002.
+
+29. **Wolfram, S.**
+ *The Mathematica Book*.
+ Fourth Edition, Cambridge University Press, 1999.
+
+30. **Wolfson, M., Wright, H.**
+ “ACM Algorithm 160: Combinatorial of M Things Taken N at a Time.”
+ *Communications of the ACM*, 6(4), 1963.
+
+31. **Zwillinger, D. (ed.)**
+ *CRC Standard Mathematical Tables and Formulae*.
+ 30th Edition, CRC Press, 1996.
+
+---
+
+*Last revised on 11 April 2015.*
diff --git a/docs/theory.md b/docs/theory.md
index a156af2..3afb1ee 100644
--- a/docs/theory.md
+++ b/docs/theory.md
@@ -1,38 +1,347 @@
# Theory
-`polpack` implements numerical algorithms for a broad set of mathematical objects, primarily focused on recursive relations and orthogonal properties.
+This page covers the mathematical foundations behind `polpack`: the definition
+of polynomial families, the stable recurrence relations used to evaluate them,
+and the combinatorial sequences supported by the library.
-## Orthogonal Polynomials
+---
+
+## 1) Background: Special Functions and Polynomials
+
+A **polynomial family** is a sequence of polynomials $\{P_n(x)\}_{n=0}^\infty$
+where $n$ is the degree of the polynomial. Many of these families are
+**orthogonal polynomials**, meaning they satisfy a specific inner product
+relationship over an interval $[a, b]$ with respect to a weight function $w(x)$.
+
+Special functions and polynomials arise naturally across science and engineering:
+
+- **Physics** — quantum mechanics (Hermite, Laguerre), optics (Zernike), Laplace's equation (Legendre)
+- **Numerical Analysis** — function approximation (Chebyshev), Gaussian quadrature, spectral methods
+- **Combinatorics** — counting set partitions (Bell numbers), mountain ranges (Catalan numbers)
+- **Probability** — orthogonal basis expansion, stochastic processes
+
+### Orthogonality condition
+
+The structure in polynomial families is often characterized by:
+
+1. **Interval of support** — the range $[a, b]$ where the polynomials are defined
+2. **Weight function** $w(x)$ — a non-negative function defining the inner product
+3. **Orthogonality** — $\int_a^b P_m(x) P_n(x) w(x) \, dx = 0$ for $m \neq n$
+4. **Normalization** — the value of the integral for $m = n$ (often $C_n$)
+
+While sdepack focuses on sample paths of Wiener processes, `polpack` focuses on
+the stable evaluation of these deterministic bases.
+
+### Explicit vs. Recursive interpretation
+
+There are two principal ways to define and evaluate polynomial families:
+
+| | **Explicit Formulas** | **Recurrence Relations** |
+|---|---|---|
+| Evaluation point | Direct calculation from $x$ | Computed step-wise from $P_0, P_1, \dots$ |
+| Numerical Stability | Often poor for large $n$ (cancellation errors) | Typically excellent and stable |
+| Implementation | Combinatorial sums, binomial coefficients | Three-term recurrence loops |
+| Typical use | Symbolic manipulation | Numerical computing, library implementations |
+
+`polpack` uses **recurrence relations** exclusively for its numerical core.
+
+!!! info "Christoffel–Darboux formula"
+ For orthogonal polynomials, the sum of products follows a specific
+ closed form:
+
+ $$ \sum_{k=0}^n \frac{P_k(x)P_k(y)}{h_k} = \frac{k_n}{k_{n+1}h_n} \frac{P_{n+1}(x)P_n(y) - P_n(x)P_{n+1}(y)}{x - y} $$
+
+ The additional terms arising in this identity (analogous to Itô's lemma)
+ are fundamental to understanding the convergence of spectral expansions.
+
+## 2) Orthogonal Polynomial Families
-Many of the polynomial families in `polpack` share the property of **orthogonality** with respect to a weight function $w(x)$ over an interval $[a, b]$:
+All routines in `polpack` target specific polynomial forms:
$$
-\int_a^b w(x) P_n(x) P_m(x) \, dx = \delta_{nm} h_n,
+\int_a^b P_m(x) P_n(x) w(x) \, dx = \delta_{mn} C_n.
$$
-where $\delta_{nm}$ is the Kronecker delta and $h_n$ is a normalization constant.
+Within the library, this is implemented as:
-### Three-term recurrence
+$$
+P_{n+1}(x) = (A_n x + B_n) P_n(x) - C_n P_{n-1}(x),
+$$
+
+where:
+
+- $x$ is the evaluation point
+- $A_n, B_n, C_n$ are method-specific recurrence coefficients
+- $k$ denotes the degree or index of the recurrence
-Most orthogonal polynomials are computed using a stable three-term recurrence relation of the form:
+For **degree-invariant** routines, the coefficients $A, B, C$ are pre-defined
+constants for a given degree $n$.
+
+## Polynomial families
+
+`polpack` evaluates a variety of recursively defined polynomial families,
+including those orthogonal with respect to specific weights and intervals.
+
+### Bernoulli Polynomials
+The Bernoulli polynomials $B_n(x)$ are defined by the generating function:
+$\frac{t e^{xt}}{e^t - 1} = \sum_{n=0}^{\infty} B_n(x) \frac{t^n}{n!}$
+They satisfy the recurrence:
$$
-P_{n+1}(x) = (A_n x + B_n) P_n(x) - C_n P_{n-1}(x).
+B_n(x) = \sum_{k=0}^n \binom{n}{k} B_k x^{n-k}
$$
-`polpack` evaluates these recurrences efficiently in Fortran, ensuring high precision and performance.
+### Bernstein Polynomials
+The Bernstein basis polynomials $b_{\nu, n}(x)$ are defined on $[0,1]$ as:
+$b_{\nu, n}(x) = \binom{n}{\nu} x^{\nu} (1-x)^{n-\nu}$
+They form a basis for the space of polynomials of degree at most $n$.
+
+### Cardan Polynomials
+Cardan polynomials $C_n(x, s)$ are associated with the solution of cubic
+equations. They satisfy the three-term recurrence:
+
+$$
+C_{n+1}(x, s) = x C_n(x, s) - s C_{n-1}(x, s)
+$$
+
+### Charlier Polynomials
+The Charlier polynomials $C_n(x; a)$ are orthogonal with respect to the
+Poisson distribution. They satisfy:
+
+$$
+a C_{n+1}(x; a) = (n + a - x) C_n(x; a) - n C_{n-1}(x; a)
+$$
+
+### Chebyshev Polynomials
+**First Kind ($T_n$):** Orthogonal on $[-1, 1]$ with weight $(1-x^2)^{-1/2}$.
+
+$$
+T_{n+1}(x) = 2x T_n(x) - T_{n-1}(x)
+$$
+
+**Second Kind ($U_n$):** Orthogonal on $[-1, 1]$ with weight $(1-x^2)^{1/2}$.
+
+$$
+U_{n+1}(x) = 2x U_n(x) - U_{n-1}(x)
+$$
+
+### Gegenbauer Polynomials
+The Gegenbauer polynomials $C_n^{(\alpha)}(x)$ are orthogonal on $[-1, 1]$ with
+weight $(1-x^2)^{\alpha - 1/2}$.
+
+$$
+(n+1)C_{n+1}^{(\alpha)}(x) = 2(n+\alpha)x C_n^{(\alpha)}(x) - (n+2\alpha-1)C_{n-1}^{(\alpha)}(x)
+$$
+
+### Hermite Polynomials (Physicist's)
+Orthogonal on $(-\infty, \infty)$ with weight $e^{-x^2}$.
+
+$$
+H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x)
+$$
+
+### Jacobi Polynomials
+The Jacobi polynomials $P_n^{(\alpha, \beta)}(x)$ are orthogonal on $[-1, 1]$
+with weight $(1-x)^{\alpha}(1+x)^{\beta}$. They generalize both Chebyshev and
+Legendre polynomials.
+
+### Krawtchouk Polynomials
+Discrete orthogonal polynomials $K_n(x; p, N)$ related to the binomial
+distribution.
+
+### Laguerre Polynomials
+**Associated Laguerre ($L_n^{(\alpha)}$):** Orthogonal on $[0, \infty)$ with
+weight $x^{\alpha}e^{-x}$.
+
+$$
+(n+1)L_{n+1}^{(\alpha)}(x) = (2n + \alpha + 1 - x) L_n^{(\alpha)}(x) - (n+\alpha)L_{n-1}^{(\alpha)}(x)
+$$
+
+### Legendre Polynomials
+Orthogonal on $[-1, 1]$ with weight 1.
+
+$$
+(n+1)P_{n+1}(x) = (2n+1)x P_n(x) - n P_{n-1}(x)
+$$
+
+### Meixner Polynomials
+Discrete orthogonal polynomials $M_n(x; \beta, c)$ related to the negative
+binomial distribution.
+
+### Zernike Polynomials
+Polynomials defined on the unit disk, widely used in optics to describe
+wavefront aberrations.
+
+---
## Combinatorial Sequences
+`polpack` provides routines for several important integer sequences.
+
### Bell Numbers
-The Bell number $B_n$ counts the number of partitions of a set of $n$ elements.
+The Bell number $B_n$ counts the number of ways a set of $n$ elements can be
+partitioned into non-empty subsets.
+
+$$
+B_{n+1} = \sum_{k=0}^n \binom{n}{k} B_k
+$$
### Catalan Numbers
-Catalan numbers $C_n$ count various objects in combinatorial geometry and computer science, such as the number of ways to triangulate a convex polygon with $n+2$ vertices.
+The Catalan number $C_n$ occurs in various counting problems (e.g., number
+of binary trees with $n$ nodes).
+
+$$
+C_n = \frac{1}{n+1} \binom{2n}{n}
+$$
+
+### Stirling Numbers
+**First Kind ($s(n,k)$):** Number of permutations of $n$ elements with $k$ cycles.
+**Second Kind ($S(n,k)$):** Number of ways to partition a set of $n$ elements
+into $k$ non-empty subsets.
+
+---
+
+## Number Theory and Probability
+
+### Benford's Law
+Benford's law, also called the Newcomb–Benford law or the law of anomalous
+numbers, defines the probability distribution of the first digit $d$ in many
+real-life sets of numerical data:
+
+$$
+P(d) = \log_{10}(1 + 1/d)
+$$
+
+### Collatz Conjecture
+The Collatz sequence for a starting integer $n$ is defined by:
+
+- If $n$ is even, $n_{i+1} = n_i / 2$
+- If $n$ is odd, $n_{i+1} = 3n_i + 1$
+`polpack` provides routines to count the number of steps to reach 1.
+
+### Arithmetical Functions
+
+- **Euler Totient ($\phi(n)$):** Number of positive integers less than $n$
+ that are relatively prime to $n$.
+- **Moebius ($\mu(n)$):** $\mu(n) = (-1)^k$ if $n$ is square-free with $k$ prime
+ factors, else 0.
+- **Mertens ($M(n)$):** The sum of the Moebius function $M(n) = \sum_{k=1}^n \mu(k)$.
+- **Divisor Sum ($\sigma(n)$):** Sum of all positive divisors of $n$.
+
+## 3) Three-term recurrence and evaluation scaling
+
+Given an interval $[a, b]$ and degree $N$:
+$$
+P_0(x) = \alpha, \qquad P_1(x) = \beta x + \gamma.
+$$
+
+At each stage $n$, the polynomial value is generated:
+$$
+P_{n+1}(x) = (A_n x + B_n)P_n(x) - C_n P_{n-1}(x),
+$$
+
+where $A_n, B_n, C_n$ are coefficients that ensure the correct scaling at each
+stage. When multiplied in the core loops, this produces the high-order
+polynomial values required for scientific applications.
+
+## 4) Chebyshev Polynomials — RK1 analog
+
+The simplest and most widely used family in numerical analysis. Named after
+Pafnuty Chebyshev, they are the deterministic analog of many foundational
+integrators.
+
+For both first and second kind variants:
+
+$$
+T_{n+1}(x) = 2x T_n(x) - T_{n-1}(x),
+$$
+
+$$
+T_0(x) = 1,\quad T_1(x)=x.
+$$
+This recurrence is notoriously stable for $x \in [-1, 1]$.
+
+!!! info "Minimax property"
+ The Chebyshev polynomials minimize the maximum error in function
+ approximation, analogously to how Euler-Maruyama minimizes one-step
+ error in SDEs.
+
+## 5) Legendre Polynomials — Two-stage recurrence
+
+A classic family providing improved accuracy in spherical harmonic expansions:
+
+$$
+\begin{aligned}
+A_{n} &= \frac{2n+1}{n+1},\\
+B_{n} &= 0,\\
+C_{n} &= \frac{n}{n+1},\\
+(n+1)P_{n+1}(x) &= (2n+1)x P_n(x) - n P_{n-1}(x).
+\end{aligned}
+$$
-### Fibonacci Numbers
-The Fibonacci sequence is defined by $F_0=0, F_1=1$, and $F_{n} = F_{n-1} + F_{n-2}$.
+Coefficients:
+$$
+P_0=1,\quad P_1=x.
+$$
---
-*Refer to [References](references.md) for detailed literature on these mathematical objects.*
+## 6) Hermite Polynomials — physicist form (time-invariant only)
+
+A three-term recurrence providing higher accuracy for systems involving
+Gaussian weights:
+$$
+H_{n+1}(x) = 2x H_n(x) - 2n H_{n-1}(x),
+$$
+
+with coefficients:
+$$
+\begin{aligned}
+H_0&=1,\\
+H_1&=2x.
+\end{aligned}
+$$
+
+!!! note
+ The probabilist's form $He_n(x)$ uses different scaling parameters. Both
+ are available in `polpack`.
+
+## 7) Jacobi and Gegenbauer Polynomials
+
+The highest-order methods in `polpack`, using four terms or generalized
+parameters for maximum flexibility.
+
+The general update formula is:
+$$
+P_{n+1}(x) = (A_n x + B_n) P_n(x) - C_n P_{n-1}(x).
+$$
+
+The Jacobi and Gegenbauer variants use **different** coefficient sets
+optimized for their respective weighting intervals. See the [API Reference](api.md)
+for the complete recurrence tables.
+
+## 8) Convergence and stability considerations
+
+### Strong vs. weak stability
+
+When assessing the quality of a numerical polynomial evaluation, two notions of
+stability are distinguished:
+
+- **Forward stability** — accuracy of individual evaluations.
+- **Backward stability** — whether the computed $P_n(x)$ is the exact solution
+ to a slightly perturbed recurrence.
+
+Forward stability is often sufficient for function approximation, while
+backward stability matters in eigenvalue problems.
+
+### Relationship between degree and order
+
+The three-term recurrence schemes in `polpack` are designed to achieve higher
+numerical precision. The Euler-like first-order recursions (RK1 analog) are
+stable but may accumulate error at very high degrees ($n > 1000$). Higher-degree
+polynomials generally benefit from the stable recurrence architecture.
+
+!!! tip "Evaluation guidance"
+ Unlike simple power series, the recurrence $P_{n+1}(x)$ only reduces the
+ error by a factor of 2 per degree. For very large $n$, use specialized
+ asymptotic routines if available.
diff --git a/main.py b/main.py
deleted file mode 100644
index 33a93d1..0000000
--- a/main.py
+++ /dev/null
@@ -1,6 +0,0 @@
-def main():
- print("polpack v0.0.1")
-
-
-if __name__ == "__main__":
- main()
diff --git a/mkdocs.yml b/mkdocs.yml
index 85563fe..a32db6c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -1,44 +1,39 @@
site_name: polpack
-site_url: https://eggzec.github.io/polpack/
+site_description: Multidimensional Quadrature Using Sparse Grids for Python
+site_url: https://eggzec.github.io/polpack
repo_url: https://github.com/eggzec/polpack
-edit_uri: edit/main/docs/
+repo_name: eggzec/polpack
+
+extra:
+ social:
+ - icon: fontawesome/brands/github
+ link: https://github.com/eggzec/polpack
+ - icon: fontawesome/brands/python
+ link: https://pypi.org/project/polpack/
theme:
name: material
- palette:
- - media: "(prefers-color-scheme: light)"
- scheme: default
- primary: indigo
- accent: indigo
- toggle:
- icon: material/brightness-7
- name: Switch to dark mode
- - media: "(prefers-color-scheme: dark)"
- scheme: slate
- primary: indigo
- accent: indigo
- toggle:
- icon: material/brightness-4
- name: Switch to light mode
features:
- - navigation.tabs
- - navigation.sections
- - navigation.top
- - search.suggest
- - search.highlight
- content.code.copy
+markdown_extensions:
+ - admonition
+ - tables
+ - fenced_code
+ - pymdownx.superfences
+ - pymdownx.highlight
+ - pymdownx.arithmatex:
+ generic: true
+ - toc:
+ permalink: true
+
+extra_javascript:
+ - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
+
nav:
- - Welcome: index.md
+ - Home: index.md
+ - Theory: theory.md
- Installation: installation.md
- Quickstart: quickstart.md
- API Reference: api.md
- References: references.md
-
-markdown_extensions:
- - admonition
- - pymdownx.highlight:
- anchor_linenums: true
- - pymdownx.inlinehilite
- - pymdownx.snippets
- - pymdownx.superfences
diff --git a/pyproject.toml b/pyproject.toml
index 6e60b90..eec5117 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -50,14 +50,22 @@ issues = "https://github.com/eggzec/polpack/issues"
[dependency-groups]
dev = [
+ {include-group = "build"},
{include-group = "docs"},
- {include-group = "test"},
- "meson-python",
- "ninja",
+ {include-group = "lint"},
+ {include-group = "test"}
+]
+build = [
+ "meson-python",
+ "ninja",
+ "setuptools_scm>=8",
]
docs = [
"zensical>=0.0.23"
]
+lint = [
+ "ruff==0.15.*",
+]
test = [
"pytest>=8.3.5",
"pytest-cov>=6.0",
@@ -67,7 +75,7 @@ test = [
[build-system]
requires = [
"meson-python",
- "numpy>=2.0.0",
+ "numpy",
"packaging",
"setuptools_scm>=8"
]
@@ -79,3 +87,56 @@ local_scheme = "no-local-version"
[tool.cibuildwheel]
enable = ["cpython-prerelease"]
+
+[tool.ruff]
+line-length = 80
+indent-width = 4
+preview = true
+
+# Output serialization format for violations. The default serialization
+# format is "full" [env: RUFF_OUTPUT_FORMAT=] [possible values:
+# concise, full, json, json-lines, junit, grouped, github, gitlab,
+# pylint, rdjson, azure, sarif]
+output-format = "grouped"
+
+[tool.ruff.lint]
+isort.lines-after-imports = 2
+isort.split-on-trailing-comma = false
+
+select = [
+ "ANN", # flake8-annotations (required strict type annotations for public functions)
+ "S", # flake8-bandit (checks basic security issues in code)
+ "BLE", # flake8-blind-except (checks the except blocks that do not specify exception)
+ "FBT", # flake8-boolean-trap (ensure that boolean args can be used with kw only)
+ "E", # pycodestyle errors (PEP 8 style guide violations)
+ "W", # pycodestyle warnings (e.g., extra spaces, indentation issues)
+ "DOC", # pydoclint issues (e.g., extra or missing return, yield, warnings)
+ "A", # flake8-buitins (check variable and function names to not shadow builtins)
+ "N", # Naming convention checks (e.g., PEP 8 variable and function names)
+ "F", # Pyflakes errors (e.g., unused imports, undefined variables)
+ "I", # isort (Ensures imports are sorted properly)
+ "B", # flake8-bugbear (Detects likely bugs and bad practices)
+ "TID", # flake8-tidy-imports (Checks for banned or misplaced imports)
+ "UP", # pyupgrade (Automatically updates old Python syntax)
+ "YTT", # flake8-2020 (Detects outdated Python 2/3 compatibility issues)
+ "FLY", # flynt (Converts old-style string formatting to f-strings)
+ "PIE", # flake8-pie
+ "PL", # pylint
+ "RUF", # Ruff-specific rules (Additional optimizations and best practices)
+]
+
+ignore = []
+
+[tool.ruff.lint.per-file-ignores]
+"**/__init__.py" = ["RUF067"]
+"**/tests/*.py" = [
+ "ANN001", # Missing type annotation for function argument
+ "ANN202", # Missing return type annotation for private function
+ "DOC201", # `return` is not documented in docstring
+ "PLR6301", # Method could be a function, class method, or static method
+ "S101", # Use of `assert` detected
+]
+
+[tool.ruff.format]
+docstring-code-format = true
+skip-magic-trailing-comma = true
diff --git a/src/polpack.pyf b/src/polpack.pyf
index 9ce17e4..4afca10 100644
--- a/src/polpack.pyf
+++ b/src/polpack.pyf
@@ -46,9 +46,9 @@ python module _polpack ! in
double precision :: c
end subroutine bernoulli_number_values
subroutine bernoulli_poly(n,x,bx)
- integer :: n
- double precision :: x
- double precision :: bx
+ integer intent(in) :: n
+ double precision intent(in) :: x
+ double precision intent(out) :: bx
end subroutine bernoulli_poly
subroutine bernoulli_poly2(n,x,bx)
integer :: n
@@ -220,7 +220,7 @@ python module _polpack ! in
subroutine delannoy(m,n,a)
integer intent(in) :: m
integer intent(in) :: n
- integer dimension(1 + m,1 + n), intent(in, out), depend(m) :: a
+ integer dimension(1 + m,1 + n), intent(in, out), depend(m,n) :: a
end subroutine delannoy
subroutine erf_values(n_data,x,fx)
integer :: n_data
@@ -250,8 +250,8 @@ python module _polpack ! in
integer dimension(n,n), intent(in, out), depend(n) :: e
end subroutine eulerian
subroutine fibonacci_direct(n,f)
- integer :: n
- integer :: f
+ integer intent(in) :: n
+ integer intent(out) :: f
end subroutine fibonacci_direct
subroutine fibonacci_floor(n,f,i)
integer :: n
diff --git a/src/polpack/__init__.py b/src/polpack/__init__.py
index 9744472..543d3e9 100644
--- a/src/polpack/__init__.py
+++ b/src/polpack/__init__.py
@@ -5,31 +5,39 @@
of mathematical functions, polynomials, and combinatorial sequences.
"""
-from . import _polpack
import numpy as np
-def agm_values(n_data, a, b, fx):
- """returns some values of the arithmetic geometric mean.
+from . import _polpack
+
+
+def agm_values(n_data: int, a: float, b: float, fx: float) -> None:
+ """Returns some values of the arithmetic geometric mean.
Args:
- n_data (int): Description for n_data.
- a (float): Description for a.
- b (float): Description for b.
- fx (float): Description for fx.
+ n_data (int): Number of data points.
+ a (float): First value.
+ b (float): Second value.
+ fx (float): Function value.
+ Returns:
+ None
"""
return _polpack.agm_values(n_data, a, b, fx)
-def bell(n, b):
- """returns the Bell numbers from 0 to N.
+
+def bell(n: int, b: np.ndarray) -> None:
+ """Returns the Bell numbers from 0 to N.
Args:
- n (int): Description for n.
- b (int): Description for b.
+ n (int): order of recursion.
+ b (np.ndarray): array to store Bell numbers.
+ Returns:
+ None
"""
return _polpack.bell(n, b)
-def bell_values(n_data, n, c):
- """returns some values of the Bell numbers for testing.
+
+def bell_values(n_data: int, n: int, c: np.ndarray) -> None:
+ """Returns some values of the Bell numbers for testing.
Args:
n_data (int): Description for n_data.
@@ -38,8 +46,9 @@ def bell_values(n_data, n, c):
"""
return _polpack.bell_values(n_data, n, c)
-def bernoulli_number(n, b):
- """computes the value of the Bernoulli numbers B(0) through B(N).
+
+def bernoulli_number(n: int, b: np.ndarray) -> None:
+ """Computes the value of the Bernoulli numbers B(0) through B(N).
Args:
n (int): Description for n.
@@ -47,8 +56,9 @@ def bernoulli_number(n, b):
"""
return _polpack.bernoulli_number(n, b)
-def bernoulli_number2(n, b):
- """evaluates the Bernoulli numbers.
+
+def bernoulli_number2(n: int, b: np.ndarray) -> None:
+ """Evaluates the Bernoulli numbers.
Args:
n (int): Description for n.
@@ -56,8 +66,9 @@ def bernoulli_number2(n, b):
"""
return _polpack.bernoulli_number2(n, b)
-def bernoulli_number3(n, b):
- """computes the value of the Bernoulli number B(N).
+
+def bernoulli_number3(n: int, b: np.ndarray) -> None:
+ """Computes the value of the Bernoulli number B(N).
Args:
n (int): Description for n.
@@ -65,248 +76,319 @@ def bernoulli_number3(n, b):
"""
return _polpack.bernoulli_number3(n, b)
-def bernoulli_number_values(n_data, n, c):
- """returns some values of the Bernoulli numbers.
+
+def bernoulli_number_values(n_data: int, n: int, c: float) -> None:
+ """Returns some values of the Bernoulli numbers.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (float): Description for c.
+ n_data (int): Number of data points.
+ n (int): value of n.
+ c (float): value of Bernoulli number.
+ Returns:
+ None
"""
return _polpack.bernoulli_number_values(n_data, n, c)
-def bernoulli_poly(n, x, bx):
- """evaluates the Bernoulli polynomial of order N at X.
+
+def bernoulli_poly(n: int, x: float) -> float:
+ """Evaluates the Bernoulli polynomial of order N at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- bx (float): Description for bx.
+ n (int): order of the polynomial.
+ x (float): evaluation point.
+ Returns:
+ float: value of the Bernoulli polynomial.
"""
- return _polpack.bernoulli_poly(n, x, bx)
+ return _polpack.bernoulli_poly(n, x)
+
-def bernoulli_poly2(n, x, bx):
- """evaluates the N-th Bernoulli polynomial at X.
+def bernoulli_poly2(n: int, x: float, bx: float) -> None:
+ """Evaluates the N-th Bernoulli polynomial at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- bx (float): Description for bx.
+ n (int): order of polynomial.
+ x (float): evaluation point.
+ bx (float): value of Bernoulli polynomial.
+ Returns:
+ None
"""
return _polpack.bernoulli_poly2(n, x, bx)
-def bernstein_poly(n, x, bern):
- """evaluates the Bernstein polynomials at a point X.
+
+def bernstein_poly(n: int, x: float, bern: np.ndarray) -> None:
+ """Evaluates the Bernstein polynomials at a point X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- bern (float): Description for bern.
+ n (int): degree of polynomial.
+ x (float): evaluation point.
+ bern (np.ndarray): values of Bernstein polynomials.
+ Returns:
+ None
"""
return _polpack.bernstein_poly(n, x, bern)
-def bernstein_poly_values(n_data, n, k, x, b):
- """returns some values of the Bernstein polynomials.
+
+def bernstein_poly_values(
+ n_data: int, n: int, k: int, x: float, b: float
+) -> None:
+ """Returns some values of the Bernstein polynomials.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- k (int): Description for k.
- x (float): Description for x.
- b (float): Description for b.
+ n_data (int): Number of data points.
+ n (int): degree of polynomial.
+ k (int): index of polynomial.
+ x (float): evaluation point.
+ b (float): value of Bernstein polynomial.
+ Returns:
+ None
"""
return _polpack.bernstein_poly_values(n_data, n, k, x, b)
-def beta_values(n_data, x, y, fxy):
- """returns some values of the Beta function.
+
+def beta_values(n_data: int, x: float, y: float, fxy: float) -> None:
+ """Returns some values of the Beta function.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- y (float): Description for y.
- fxy (float): Description for fxy.
+ n_data (int): Number of data points.
+ x (float): First argument.
+ y (float): Second argument.
+ fxy (float): Function value.
+ Returns:
+ None
"""
return _polpack.beta_values(n_data, x, y, fxy)
-def bpab(n, x, a, b, bern):
- """evaluates at X the Bernstein polynomials based in [A,B].
+
+def bpab(n: int, x: float, a: float, b: float, bern: np.ndarray) -> None:
+ """Evaluates at X the Bernstein polynomials based in [A,B].
Args:
- n (int): Description for n.
- x (float): Description for x.
- a (float): Description for a.
- b (float): Description for b.
- bern (float): Description for bern.
+ n (int): degree of polynomial.
+ x (float): evaluation point.
+ a (float): left endpoint.
+ b (float): right endpoint.
+ bern (np.ndarray): values of Bernstein polynomials.
+ Returns:
+ None
"""
return _polpack.bpab(n, x, a, b, bern)
-def cardan_poly(n, x, s, cx):
- """evaluates the Cardan polynomials.
+
+def cardan_poly(n: int, x: float, s: float, cx: np.ndarray) -> None:
+ """Evaluates the Cardan polynomials.
Args:
- n (int): Description for n.
- x (float): Description for x.
- s (float): Description for s.
- cx (float): Description for cx.
+ n (int): degree of polynomial.
+ x (float): evaluation point.
+ s (float): parameter s.
+ cx (np.ndarray): value of Cardan polynomial.
+ Returns:
+ None
"""
return _polpack.cardan_poly(n, x, s, cx)
-def cardan_poly_coef(n, s, c):
- """computes the coefficients of the N-th Cardan polynomial.
+
+def cardan_poly_coef(n: int, s: float, c: np.ndarray) -> None:
+ """Computes the coefficients of the N-th Cardan polynomial.
Args:
- n (int): Description for n.
- s (float): Description for s.
- c (float): Description for c.
+ n (int): degree of polynomial.
+ s (float): parameter s.
+ c (np.ndarray): coefficients of Cardan polynomial.
+ Returns:
+ None
"""
return _polpack.cardan_poly_coef(n, s, c)
-def cardinal_cos(j, m, n, t, c):
- """evaluates the J-th cardinal cosine basis function.
+
+def cardinal_cos(j: int, m: int, n: int, t: float, c: np.ndarray) -> None:
+ """Evaluates the J-th cardinal cosine basis function.
Args:
- j (int): Description for j.
- m (int): Description for m.
- n (int): Description for n.
- t (float): Description for t.
- c (float): Description for c.
+ j (int): index of basis function.
+ m (int): parameter m.
+ n (int): parameter n.
+ t (float): evaluation point.
+ c (np.ndarray): value of basis function.
+ Returns:
+ None
"""
return _polpack.cardinal_cos(j, m, n, t, c)
-def cardinal_sin(j, m, n, t, s):
- """evaluates the J-th cardinal sine basis function.
+
+def cardinal_sin(j: int, m: int, n: int, t: float, s: np.ndarray) -> None:
+ """Evaluates the J-th cardinal sine basis function.
Args:
- j (int): Description for j.
- m (int): Description for m.
- n (int): Description for n.
- t (float): Description for t.
- s (float): Description for s.
+ j (int): index of basis function.
+ m (int): parameter m.
+ n (int): parameter n.
+ t (float): evaluation point.
+ s (np.ndarray): value of basis function.
+ Returns:
+ None
"""
return _polpack.cardinal_sin(j, m, n, t, s)
-def catalan(n, c):
- """computes the Catalan numbers, from C(0) to C(N).
+
+def catalan(n: int, c: np.ndarray) -> None:
+ """Computes the Catalan numbers, from C(0) to C(N).
Args:
- n (int): Description for n.
- c (int): Description for c.
+ n (int): degree.
+ c (np.ndarray): Catalan numbers.
+ Returns:
+ None
"""
return _polpack.catalan(n, c)
-def catalan_row_next(ido, n, irow):
- """computes row N of Catalan's triangle.
+
+def catalan_row_next(ido: int, n: int, irow: np.ndarray) -> None:
+ """Computes row N of Catalan's triangle.
Args:
- ido (int): Description for ido.
- n (int): Description for n.
- irow (int): Description for irow.
+ ido (int): initialization flag.
+ n (int): row index.
+ irow (np.ndarray): row values.
+ Returns:
+ None
"""
return _polpack.catalan_row_next(ido, n, irow)
-def catalan_values(n_data, n, c):
- """returns some values of the Catalan numbers for testing.
+
+def catalan_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Catalan numbers for testing.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): index.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.catalan_values(n_data, n, c)
-def charlier(n, a, x, value):
- """evaluates Charlier polynomials at a point.
+
+def charlier(n: int, a: float, x: float, value: np.ndarray) -> None:
+ """Evaluates Charlier polynomials at a point.
Args:
- n (int): Description for n.
- a (float): Description for a.
- x (float): Description for x.
- value (float): Description for value.
+ n (int): degree.
+ a (float): parameter.
+ x (float): point.
+ value (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.charlier(n, a, x, value)
-def cheby_t_poly(m, n, x, cx):
- """evaluates Chebyshev polynomials T(n,x).
+
+def cheby_t_poly(m: int, n: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates Chebyshev polynomials T(n,x).
Args:
- m (int): Description for m.
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
+ m (int): number of points.
+ n (int): max degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.cheby_t_poly(m, n, x, cx)
-def cheby_t_poly_coef(n, c):
- """evaluates coefficients of Chebyshev polynomials T(n,x).
+
+def cheby_t_poly_coef(n: int, c: np.ndarray) -> None:
+ """Evaluates coefficients of Chebyshev polynomials T(n,x).
Args:
- n (int): Description for n.
- c (float): Description for c.
+ n (int): degree.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.cheby_t_poly_coef(n, c)
-def cheby_t_poly_values(n_data, n, x, fx):
- """returns values of Chebyshev polynomials T(n,x).
+
+def cheby_t_poly_values(n_data: int, n: int, x: float, fx: float) -> None:
+ """Returns values of Chebyshev polynomials T(n,x).
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.cheby_t_poly_values(n_data, n, x, fx)
-def cheby_t_poly_zero(n, z):
- """returns zeroes of Chebyshev polynomials T(n,x).
+
+def cheby_t_poly_zero(n: int, z: np.ndarray) -> None:
+ """Returns zeroes of Chebyshev polynomials T(n,x).
Args:
- n (int): Description for n.
- z (float): Description for z.
+ n (int): degree.
+ z (np.ndarray): zeroes.
+ Returns:
+ None
"""
return _polpack.cheby_t_poly_zero(n, z)
-def cheby_u_poly(m, n, x, cx):
- """evaluates Chebyshev polynomials U(n,x).
+
+def cheby_u_poly(m: int, n: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates Chebyshev polynomials U(n,x).
Args:
- m (int): Description for m.
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
+ m (int): number of points.
+ n (int): max degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.cheby_u_poly(m, n, x, cx)
-def cheby_u_poly_coef(n, c):
- """evaluates coefficients of Chebyshev polynomials U(n,x).
+
+def cheby_u_poly_coef(n: int, c: np.ndarray) -> None:
+ """Evaluates coefficients of Chebyshev polynomials U(n,x).
Args:
- n (int): Description for n.
- c (float): Description for c.
+ n (int): degree.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.cheby_u_poly_coef(n, c)
-def cheby_u_poly_values(n_data, n, x, fx):
- """returns values of Chebyshev polynomials U(n,x).
+
+def cheby_u_poly_values(n_data: int, n: int, x: float, fx: float) -> None:
+ """Returns values of Chebyshev polynomials U(n,x).
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.cheby_u_poly_values(n_data, n, x, fx)
-def cheby_u_poly_zero(n, z):
- """returns zeroes of Chebyshev polynomials U(n,x).
+
+def cheby_u_poly_zero(n: int, z: np.ndarray) -> None:
+ """Returns zeroes of Chebyshev polynomials U(n,x).
Args:
- n (int): Description for n.
- z (float): Description for z.
+ n (int): degree.
+ z (np.ndarray): zeroes.
+ Returns:
+ None
"""
return _polpack.cheby_u_poly_zero(n, z)
+
def chebyshev_discrete(n, m, x, v):
- """evaluates discrete Chebyshev polynomials at a point.
+ """Evaluates discrete Chebyshev polynomials at a point.
Args:
n (int): Description for n.
@@ -316,866 +398,1162 @@ def chebyshev_discrete(n, m, x, v):
"""
return _polpack.chebyshev_discrete(n, m, x, v)
-def collatz_count_max(n, i_max, j_max):
- """seeks the maximum Collatz count for 1 through N.
+
+def collatz_count_max(n: int, i_max: np.ndarray, j_max: np.ndarray) -> None:
+ """Seeks the maximum Collatz count for 1 through N.
Args:
- n (int): Description for n.
- i_max (int): Description for i_max.
- j_max (int): Description for j_max.
+ n (int): maximum value to check.
+ i_max (np.ndarray): value achieving the maximum count.
+ j_max (np.ndarray): the maximum count.
+ Returns:
+ None
"""
return _polpack.collatz_count_max(n, i_max, j_max)
-def collatz_count_values(n_data, n, count):
- """returns some values of the Collatz count function.
+
+def collatz_count_values(n_data: int, n: int, count: int) -> None:
+ """Returns some values of the Collatz count function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- count (int): Description for count.
+ n_data (int): Number of points.
+ n (int): value of n.
+ count (int): Collatz count.
+ Returns:
+ None
"""
return _polpack.collatz_count_values(n_data, n, count)
-def comb_row_next(n, row):
- """computes the next row of Pascal's triangle.
+
+def comb_row_next(n: int, row: np.ndarray) -> None:
+ """Computes the next row of Pascal's triangle.
Args:
- n (int): Description for n.
- row (int): Description for row.
+ n (int): current row index.
+ row (np.ndarray): current row / next row.
+ Returns:
+ None
"""
return _polpack.comb_row_next(n, row)
-def commul(n, nfactor, factor, ncomb):
- """computes a multinomial combinatorial coefficient.
+
+def commul(n: int, nfactor: int, factor: np.ndarray, ncomb: int) -> None:
+ """Computes a multinomial combinatorial coefficient.
Args:
- n (int): Description for n.
- nfactor (int): Description for nfactor.
- factor (int): Description for factor.
- ncomb (int): Description for ncomb.
+ n (int): total number of items.
+ nfactor (int): number of factors.
+ factor (np.ndarray): counts of each factor.
+ ncomb (int): result coefficient.
+ Returns:
+ None
"""
return _polpack.commul(n, nfactor, factor, ncomb)
-def complete_symmetric_poly(n, r, x, value):
- """evaluates a complete symmetric polynomial.
+
+def complete_symmetric_poly(
+ n: int, r: int, x: np.ndarray, value: float
+) -> None:
+ """Evaluates a complete symmetric polynomial.
Args:
- n (int): Description for n.
- r (int): Description for r.
- x (float): Description for x.
- value (float): Description for value.
+ n (int): number of variables.
+ r (int): degree of polynomial.
+ x (np.ndarray): variables.
+ value (float): result value.
+ Returns:
+ None
"""
return _polpack.complete_symmetric_poly(n, r, x, value)
-def cos_power_int_values(n_data, a, b, n, fx):
- """returns some values of the cosine power integral.
+
+def cos_power_int_values(
+ n_data: int, a: float, b: float, n: int, fx: float
+) -> None:
+ """Returns some values of the cosine power integral.
Args:
- n_data (int): Description for n_data.
- a (float): Description for a.
- b (float): Description for b.
- n (int): Description for n.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ a (float): left endpoint.
+ b (float): right endpoint.
+ n (int): power.
+ fx (float): value of integral.
+ Returns:
+ None
"""
return _polpack.cos_power_int_values(n_data, a, b, n, fx)
+
def delannoy(m, n, a):
- """returns the Delannoy numbers up to orders (M,N).
+ """Returns the Delannoy numbers up to orders (M,N).
Args:
- m (int): Description for m.
- n (int): Description for n.
- a (int): Description for a.
+ m (int): maximum order m.
+ n (int): maximum order n.
+ a (ndarray): array to store the Delannoy numbers.
"""
return _polpack.delannoy(m, n, a)
-def erf_values(n_data, x, fx):
- """returns some values of the ERF or "error" function for testing.
+
+def erf_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the ERF or "error" function for testing.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): argument.
+ fx (float): value of erf(x).
+ Returns:
+ None
"""
return _polpack.erf_values(n_data, x, fx)
-def euler_number(n, e):
- """computes the Euler numbers.
+
+def euler_number(n: int, e: np.ndarray) -> None:
+ """Computes the Euler numbers.
Args:
- n (int): Description for n.
- e (int): Description for e.
+ n (int): maximum order.
+ e (np.ndarray): Euler numbers.
+ Returns:
+ None
"""
return _polpack.euler_number(n, e)
-def euler_number_values(n_data, n, c):
- """returns some values of the Euler numbers.
+
+def euler_number_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Euler numbers.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): order.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.euler_number_values(n_data, n, c)
-def eulerian(n, e):
- """computes the Eulerian number E(N,K).
+
+def eulerian(n: int, e: np.ndarray) -> None:
+ """Computes the Eulerian number E(N,K).
Args:
- n (int): Description for n.
- e (int): Description for e.
+ n (int): order.
+ e (np.ndarray): Eulerian numbers.
+ Returns:
+ None
"""
return _polpack.eulerian(n, e)
-def fibonacci_direct(n, f):
- """computes the N-th Fibonacci number directly.
+
+def fibonacci_direct(n):
+ """Computes the N-th Fibonacci number directly.
Args:
- n (int): Description for n.
- f (int): Description for f.
+ n (int): index of the Fibonacci number.
+ Returns:
+ int: N-th Fibonacci number.
"""
- return _polpack.fibonacci_direct(n, f)
+ return _polpack.fibonacci_direct(n)
+
-def fibonacci_floor(n, f, i):
- """returns the largest Fibonacci number less than or equal to N.
+def fibonacci_floor(n: int, f: int, i: int) -> None:
+ """Returns the largest Fibonacci number less than or equal to N.
Args:
- n (int): Description for n.
- f (int): Description for f.
- i (int): Description for i.
+ n (int): value to bound.
+ f (int): Fibonacci number.
+ i (int): index of Fibonacci number.
+ Returns:
+ None
"""
return _polpack.fibonacci_floor(n, f, i)
-def fibonacci_recursive(n, f):
- """computes the first N Fibonacci numbers.
+
+def fibonacci_recursive(n: int, f: np.ndarray) -> None:
+ """Computes the first N Fibonacci numbers.
Args:
- n (int): Description for n.
- f (int): Description for f.
+ n (int): number of values to compute.
+ f (np.ndarray): Fibonacci numbers.
+ Returns:
+ None
"""
return _polpack.fibonacci_recursive(n, f)
-def gamma_log_values(n_data, x, fx):
- """returns some values of the Log Gamma function.
+
+def gamma_log_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Log Gamma function.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): argument.
+ fx (float): value of log(gamma(x)).
+ Returns:
+ None
"""
return _polpack.gamma_log_values(n_data, x, fx)
-def gamma_values(n_data, x, fx):
- """returns some values of the Gamma function.
+
+def gamma_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Gamma function.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): argument.
+ fx (float): value of gamma(x).
+ Returns:
+ None
"""
return _polpack.gamma_values(n_data, x, fx)
-def gegenbauer_poly(n, alpha, x, cx):
- """computes the Gegenbauer polynomials C(I,ALPHA,X).
+
+def gegenbauer_poly(n: int, alpha: float, x: float, cx: np.ndarray) -> None:
+ """Computes the Gegenbauer polynomials C(I,ALPHA,X).
Args:
- n (int): Description for n.
- alpha (float): Description for alpha.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): max degree.
+ alpha (float): parameter alpha.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.gegenbauer_poly(n, alpha, x, cx)
-def gegenbauer_poly_values(n_data, n, a, x, fx):
- """returns some values of the Gegenbauer polynomials.
+
+def gegenbauer_poly_values(
+ n_data: int, n: int, a: float, x: float, fx: float
+) -> None:
+ """Returns some values of the Gegenbauer polynomials.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- a (float): Description for a.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ a (float): parameter alpha.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.gegenbauer_poly_values(n_data, n, a, x, fx)
-def gen_hermite_poly(n, x, mu, p):
- """evaluates the generalized Hermite polynomials at X.
+
+def gen_hermite_poly(n: int, x: float, mu: float, p: np.ndarray) -> None:
+ """Evaluates the generalized Hermite polynomials at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- mu (float): Description for mu.
- p (float): Description for p.
+ n (int): degree.
+ x (float): point.
+ mu (float): parameter mu.
+ p (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.gen_hermite_poly(n, x, mu, p)
-def gen_laguerre_poly(n, alpha, x, cx):
- """evaluates generalized Laguerre polynomials.
+
+def gen_laguerre_poly(n: int, alpha: float, x: float, cx: np.ndarray) -> None:
+ """Evaluates generalized Laguerre polynomials.
Args:
- n (int): Description for n.
- alpha (float): Description for alpha.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ alpha (float): parameter alpha.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.gen_laguerre_poly(n, alpha, x, cx)
-def gud_values(n_data, x, fx):
- """returns some values of the Gudermannian function.
+
+def gud_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Gudermannian function.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): point.
+ fx (float): value of gud(x).
+ Returns:
+ None
"""
return _polpack.gud_values(n_data, x, fx)
-def hermite_poly_phys(n, x, cx):
- """evaluates the physicisist's Hermite polynomials at X.
+
+def hermite_poly_phys(n: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates the physicisist's Hermite polynomials at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.hermite_poly_phys(n, x, cx)
-def hermite_poly_phys_coef(n, c):
- """evaluates the physicist's Hermite polynomial coefficients.
+
+def hermite_poly_phys_coef(n: int, c: np.ndarray) -> None:
+ """Evaluates the physicist's Hermite polynomial coefficients.
Args:
- n (int): Description for n.
- c (float): Description for c.
+ n (int): degree.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.hermite_poly_phys_coef(n, c)
-def hermite_poly_phys_values(n_data, n, x, fx):
- """returns some values of the physicist's Hermite polynomial.
+
+def hermite_poly_phys_values(n_data: int, n: int, x: float, fx: float) -> None:
+ """Returns some values of the physicist's Hermite polynomial.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.hermite_poly_phys_values(n_data, n, x, fx)
-def hyper_2f1_values(n_data, a, b, c, x, fx):
- """returns some values of the hypergeometric function 2F1.
+
+def hyper_2f1_values(
+ n_data: int, a: float, b: float, c: float, x: float, fx: float
+) -> None:
+ """Returns some values of the hypergeometric function 2F1.
Args:
- n_data (int): Description for n_data.
- a (float): Description for a.
- b (float): Description for b.
- c (float): Description for c.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ a (float): first parameter.
+ b (float): second parameter.
+ c (float): third parameter.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.hyper_2f1_values(n_data, a, b, c, x, fx)
-def i4_factor(n, factor_max, factor_num, factor, power, nleft):
- """factors an I4 into prime factors.
+
+def i4_factor(
+ n: int,
+ factor_max: int,
+ factor_num: np.ndarray,
+ factor: np.ndarray,
+ power: np.ndarray,
+ nleft: np.ndarray,
+) -> None:
+ """Factors an I4 into prime factors.
Args:
- n (int): Description for n.
- factor_max (int): Description for factor_max.
- factor_num (int): Description for factor_num.
- factor (int): Description for factor.
- power (int): Description for power.
- nleft (int): Description for nleft.
+ n (int): number to factor.
+ factor_max (int): max number of factors.
+ factor_num (np.ndarray): number of factors found.
+ factor (np.ndarray): prime factors.
+ power (np.ndarray): powers of prime factors.
+ nleft (np.ndarray): remaining unfactored part.
+ Returns:
+ None
"""
return _polpack.i4_factor(n, factor_max, factor_num, factor, power, nleft)
-def i4_factorial2_values(n_data, n, fn):
- """returns values of the double factorial function.
+
+def i4_factorial2_values(n_data: int, n: int, fn: int) -> None:
+ """Returns values of the double factorial function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- fn (int): Description for fn.
+ n_data (int): Number of points.
+ n (int): value n.
+ fn (int): value of n!!.
+ Returns:
+ None
"""
return _polpack.i4_factorial2_values(n_data, n, fn)
-def i4_factorial_values(n_data, n, fn):
- """returns values of the factorial function.
+
+def i4_factorial_values(n_data: int, n: int, fn: int) -> None:
+ """Returns values of the factorial function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- fn (int): Description for fn.
+ n_data (int): Number of points.
+ n (int): value n.
+ fn (int): value of n!.
+ Returns:
+ None
"""
return _polpack.i4_factorial_values(n_data, n, fn)
-def i4_partition_distinct_count(n, q):
- """returns any value of Q(N).
+
+def i4_partition_distinct_count(n: int, q: np.ndarray) -> None:
+ """Returns any value of Q(N).
Args:
- n (int): Description for n.
- q (int): Description for q.
+ n (int): value n.
+ q (np.ndarray): value of Q(N).
+ Returns:
+ None
"""
return _polpack.i4_partition_distinct_count(n, q)
-def i4_swap(i, j):
- """switches two I4's.
+
+def i4_swap(i: np.ndarray, j: np.ndarray) -> None:
+ """Switches two I4's.
Args:
- i (int): Description for i.
- j (int): Description for j.
+ i (np.ndarray): first value.
+ j (np.ndarray): second value.
+ Returns:
+ None
"""
return _polpack.i4_swap(i, j)
-def i4_to_triangle_lower(k, i, j):
+
+def i4_to_triangle_lower(k: int, i: np.ndarray, j: np.ndarray) -> None:
"""Evaluates the i4_to_triangle_lower function.
Args:
- k (int): Description for k.
- i (int): Description for i.
- j (int): Description for j.
+ k (int): triangle index.
+ i (np.ndarray): row index.
+ j (np.ndarray): column index.
+ Returns:
+ None
"""
return _polpack.i4_to_triangle_lower(k, i, j)
-def i4_to_triangle_upper(k, i, j):
+
+def i4_to_triangle_upper(k: int, i: np.ndarray, j: np.ndarray) -> None:
"""Evaluates the i4_to_triangle_upper function.
Args:
- k (int): Description for k.
- i (int): Description for i.
- j (int): Description for j.
+ k (int): triangle index.
+ i (np.ndarray): row index.
+ j (np.ndarray): column index.
+ Returns:
+ None
"""
return _polpack.i4_to_triangle_upper(k, i, j)
-def i4mat_print(m, n, a, title):
- """prints an I4MAT.
+
+def i4mat_print(m: int, n: int, a: np.ndarray, title: str) -> None:
+ """Prints an I4MAT.
Args:
- m (int): Description for m.
- n (int): Description for n.
- a (int): Description for a.
- title (character): Description for title.
+ m (int): Number of rows.
+ n (int): Number of columns.
+ a (np.ndarray): Matrix.
+ title (str): Title.
+ Returns:
+ None
"""
return _polpack.i4mat_print(m, n, a, title)
-def i4mat_print_some(m, n, a, ilo, jlo, ihi, jhi, title):
- """prints some of an I4MAT.
- Args:
- m (int): Description for m.
- n (int): Description for n.
- a (int): Description for a.
- ilo (int): Description for ilo.
- jlo (int): Description for jlo.
- ihi (int): Description for ihi.
- jhi (int): Description for jhi.
- title (character): Description for title.
+def i4mat_print_some(
+ m: int,
+ n: int,
+ a: np.ndarray,
+ ilo: int,
+ jlo: int,
+ ihi: int,
+ jhi: int,
+ title: str,
+) -> None:
+ """Prints some of an I4MAT.
+
+ Args:
+ m (int): Rows.
+ n (int): Columns.
+ a (np.ndarray): Matrix.
+ ilo (int): first row.
+ jlo (int): first column.
+ ihi (int): last row.
+ jhi (int): last column.
+ title (str): Title.
+ Returns:
+ None
"""
return _polpack.i4mat_print_some(m, n, a, ilo, jlo, ihi, jhi, title)
-def jacobi_poly(n, alpha, beta, x, cx):
- """evaluates the Jacobi polynomials at X.
+
+def jacobi_poly(
+ n: int, alpha: float, beta: float, x: float, cx: np.ndarray
+) -> None:
+ """Evaluates the Jacobi polynomials at X.
Args:
- n (int): Description for n.
- alpha (float): Description for alpha.
- beta (float): Description for beta.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ alpha (float): parameter alpha.
+ beta (float): parameter beta.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.jacobi_poly(n, alpha, beta, x, cx)
-def jacobi_poly_values(n_data, n, a, b, x, fx):
- """returns some values of the Jacobi polynomial.
+
+def jacobi_poly_values(
+ n_data: int, n: int, a: float, b: float, x: float, fx: float
+) -> None:
+ """Returns some values of the Jacobi polynomial.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- a (float): Description for a.
- b (float): Description for b.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ a (float): parameter alpha.
+ b (float): parameter beta.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.jacobi_poly_values(n_data, n, a, b, x, fx)
-def jacobi_symbol(q, p, j):
- """evaluates the Jacobi symbol (Q/P).
+
+def jacobi_symbol(q: int, p: int, j: np.ndarray) -> None:
+ """Evaluates the Jacobi symbol (Q/P).
Args:
- q (int): Description for q.
- p (int): Description for p.
- j (int): Description for j.
+ q (int): numerator.
+ p (int): denominator.
+ j (np.ndarray): result symbol.
+ Returns:
+ None
"""
return _polpack.jacobi_symbol(q, p, j)
-def krawtchouk(n, p, x, m, v):
- """evaluates the Krawtchouk polynomials at X.
+
+def krawtchouk(n: int, p: float, x: float, m: int, v: np.ndarray) -> None:
+ """Evaluates the Krawtchouk polynomials at X.
Args:
- n (int): Description for n.
- p (float): Description for p.
- x (float): Description for x.
- m (int): Description for m.
- v (float): Description for v.
+ n (int): degree.
+ p (float): parameter p.
+ x (float): point.
+ m (int): parameter m.
+ v (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.krawtchouk(n, p, x, m, v)
-def laguerre_associated(n, m, x, cx):
- """evaluates associated Laguerre polynomials L(N,M,X).
+
+def laguerre_associated(n: int, m: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates associated Laguerre polynomials L(N,M,X).
Args:
- n (int): Description for n.
- m (int): Description for m.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ m (int): parameter m.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.laguerre_associated(n, m, x, cx)
-def laguerre_poly(n, x, cx):
- """evaluates the Laguerre polynomials at X.
+
+def laguerre_poly(n: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates the Laguerre polynomials at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.laguerre_poly(n, x, cx)
-def laguerre_poly_coef(n, c):
- """evaluates the Laguerre polynomial coefficients.
+
+def laguerre_poly_coef(n: int, c: np.ndarray) -> None:
+ """Evaluates the Laguerre polynomial coefficients.
Args:
- n (int): Description for n.
- c (float): Description for c.
+ n (int): degree.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.laguerre_poly_coef(n, c)
-def laguerre_polynomial_values(n_data, n, x, fx):
- """returns some values of the Laguerre polynomial.
+
+def laguerre_polynomial_values(
+ n_data: int, n: int, x: float, fx: float
+) -> None:
+ """Returns some values of the Laguerre polynomial.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.laguerre_polynomial_values(n_data, n, x, fx)
-def lambert_w_values(n_data, x, fx):
- """returns some values of the Lambert W function.
+
+def lambert_w_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Lambert W function.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.lambert_w_values(n_data, x, fx)
-def legendre_associated(n, m, x, cx):
- """evaluates the associated Legendre functions.
+
+def legendre_associated(n: int, m: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates the associated Legendre functions.
Args:
- n (int): Description for n.
- m (int): Description for m.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ m (int): parameter m.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.legendre_associated(n, m, x, cx)
-def legendre_associated_normalized(n, m, x, cx):
+
+def legendre_associated_normalized(
+ n: int, m: int, x: float, cx: np.ndarray
+) -> None:
"""Evaluates the legendre_associated_normalized function.
Args:
- n (int): Description for n.
- m (int): Description for m.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ m (int): parameter m.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.legendre_associated_normalized(n, m, x, cx)
-def legendre_associated_normalized_sphere_values(n_data, n, m, x, fx):
+
+def legendre_associated_normalized_sphere_values(
+ n_data: int, n: int, m: int, x: float, fx: float
+) -> None:
"""Evaluates the legendre_associated_normalized_sphere_values function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- m (int): Description for m.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ m (int): order.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
- return _polpack.legendre_associated_normalized_sphere_values(n_data, n, m, x, fx)
+ return _polpack.legendre_associated_normalized_sphere_values(
+ n_data, n, m, x, fx
+ )
+
-def legendre_associated_values(n_data, n, m, x, fx):
- """returns values of associated Legendre functions.
+def legendre_associated_values(
+ n_data: int, n: int, m: int, x: float, fx: float
+) -> None:
+ """Returns values of associated Legendre functions.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- m (int): Description for m.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ m (int): order.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.legendre_associated_values(n_data, n, m, x, fx)
-def legendre_function_q(n, x, cx):
- """evaluates the Legendre Q functions.
+
+def legendre_function_q(n: int, x: float, cx: np.ndarray) -> None:
+ """Evaluates the Legendre Q functions.
Args:
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
+ n (int): degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.legendre_function_q(n, x, cx)
-def legendre_function_q_values(n_data, n, x, fx):
- """returns values of the Legendre Q function.
+
+def legendre_function_q_values(
+ n_data: int, n: int, x: float, fx: float
+) -> None:
+ """Returns values of the Legendre Q function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.legendre_function_q_values(n_data, n, x, fx)
-def legendre_poly(n, x, cx, cpx):
- """evaluates the Legendre polynomials P(N,X) at X.
+
+def legendre_poly(n: int, x: float, cx: np.ndarray, cpx: np.ndarray) -> None:
+ """Evaluates the Legendre polynomials P(N,X) at X.
Args:
- n (int): Description for n.
- x (float): Description for x.
- cx (float): Description for cx.
- cpx (float): Description for cpx.
+ n (int): degree.
+ x (float): point.
+ cx (np.ndarray): values.
+ cpx (np.ndarray): derivatives.
+ Returns:
+ None
"""
return _polpack.legendre_poly(n, x, cx, cpx)
-def legendre_poly_coef(n, c):
- """evaluates the Legendre polynomial coefficients.
+
+def legendre_poly_coef(n: int, c: np.ndarray) -> None:
+ """Evaluates the Legendre polynomial coefficients.
Args:
- n (int): Description for n.
- c (float): Description for c.
+ n (int): degree.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.legendre_poly_coef(n, c)
-def legendre_poly_values(n_data, n, x, fx):
- """returns values of the Legendre polynomials.
+
+def legendre_poly_values(n_data: int, n: int, x: float, fx: float) -> None:
+ """Returns values of the Legendre polynomials.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ n (int): degree.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.legendre_poly_values(n_data, n, x, fx)
-def legendre_symbol(q, p, l):
- """evaluates the Legendre symbol (Q/P).
+
+def legendre_symbol(q: int, p: int, ell: np.ndarray) -> None:
+ """Evaluates the Legendre symbol (Q/P).
Args:
- q (int): Description for q.
- p (int): Description for p.
- l (int): Description for l.
+ q (int): numerator.
+ p (int): denominator.
+ ell (np.ndarray): result symbol.
+ Returns:
+ None
"""
- return _polpack.legendre_symbol(q, p, l)
+ return _polpack.legendre_symbol(q, p, ell)
+
-def lerch_values(n_data, z, s, a, fx):
- """returns some values of the Lerch transcendent function.
+def lerch_values(n_data: int, z: float, s: float, a: float, fx: float) -> None:
+ """Returns some values of the Lerch transcendent function.
Args:
- n_data (int): Description for n_data.
- z (float): Description for z.
- s (int): Description for s.
- a (float): Description for a.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ z (float): point.
+ s (float): parameter s.
+ a (float): parameter a.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.lerch_values(n_data, z, s, a, fx)
-def lock(n, a):
- """returns the number of codes for a lock with N buttons.
+
+def lock(n: int, a: np.ndarray) -> None:
+ """Returns the number of codes for a lock with N buttons.
Args:
- n (int): Description for n.
- a (int): Description for a.
+ n (int): order.
+ a (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.lock(n, a)
-def meixner(n, beta, c, x, v):
- """evaluates Meixner polynomials at a point.
+
+def meixner(n: int, beta: float, c: float, x: float, v: np.ndarray) -> None:
+ """Evaluates Meixner polynomials at a point.
Args:
- n (int): Description for n.
- beta (float): Description for beta.
- c (float): Description for c.
- x (float): Description for x.
- v (float): Description for v.
+ n (int): degree.
+ beta (float): parameter beta.
+ c (float): parameter c.
+ x (float): point.
+ v (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.meixner(n, beta, c, x, v)
-def mertens_values(n_data, n, c):
- """returns some values of the Mertens function.
+
+def mertens_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Mertens function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value of M(n).
+ Returns:
+ None
"""
return _polpack.mertens_values(n_data, n, c)
-def moebius(n, mu):
- """returns the value of MU(N), the Moebius function of N.
+
+def moebius(n: int, mu: np.ndarray) -> None:
+ """Returns the value of MU(N), the Moebius function of N.
Args:
- n (int): Description for n.
- mu (int): Description for mu.
+ n (int): value n.
+ mu (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.moebius(n, mu)
-def moebius_values(n_data, n, c):
- """returns some values of the Moebius function.
+
+def moebius_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Moebius function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value of mu(n).
+ Returns:
+ None
"""
return _polpack.moebius_values(n_data, n, c)
-def motzkin(n, a):
- """returns the Motzkin numbers up to order N.
+
+def motzkin(n: int, a: np.ndarray) -> None:
+ """Returns the Motzkin numbers up to order N.
Args:
- n (int): Description for n.
- a (int): Description for a.
+ n (int): order.
+ a (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.motzkin(n, a)
-def normal_01_cdf_values(n_data, x, fx):
- """returns some values of the Normal 01 CDF.
+
+def normal_01_cdf_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Normal 01 CDF.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.normal_01_cdf_values(n_data, x, fx)
-def omega(n, ndiv):
- """returns OMEGA(N), the number of distinct prime divisors of N.
+
+def omega(n: int, ndiv: np.ndarray) -> None:
+ """Returns OMEGA(N), the number of distinct prime divisors of N.
Args:
- n (int): Description for n.
- ndiv (int): Description for ndiv.
+ n (int): value n.
+ ndiv (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.omega(n, ndiv)
-def omega_values(n_data, n, c):
- """returns some values of the OMEGA function.
+
+def omega_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the OMEGA function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.omega_values(n_data, n, c)
-def partition_distinct_count_values(n_data, n, c):
- """returns some values of Q(N).
+
+def partition_distinct_count_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of Q(N).
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.partition_distinct_count_values(n_data, n, c)
-def pentagon_num(n, p):
- """computes the N-th pentagonal number.
+
+def pentagon_num(n: int, p: np.ndarray) -> None:
+ """Computes the N-th pentagonal number.
Args:
- n (int): Description for n.
- p (int): Description for p.
+ n (int): index.
+ p (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.pentagon_num(n, p)
-def phi(n, phin):
- """computes the number of relatively prime predecessors of an integer.
+
+def phi(n: int, phin: np.ndarray) -> None:
+ """Computes the number of relatively prime predecessors of an integer.
Args:
- n (int): Description for n.
- phin (int): Description for phin.
+ n (int): value n.
+ phin (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.phi(n, phin)
-def phi_values(n_data, n, c):
- """returns some values of the PHI function.
+
+def phi_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the PHI function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.phi_values(n_data, n, c)
-def poly_bernoulli(n, k, b):
- """evaluates the poly-Bernolli numbers with negative index.
+
+def poly_bernoulli(n: int, k: int, b: np.ndarray) -> None:
+ """Evaluates the poly-Bernolli numbers with negative index.
Args:
- n (int): Description for n.
- k (int): Description for k.
- b (int): Description for b.
+ n (int): degree.
+ k (int): parameter.
+ b (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.poly_bernoulli(n, k, b)
-def psi_values(n_data, x, fx):
- """returns some values of the Psi or Digamma function for testing.
+
+def psi_values(n_data: int, x: float, fx: float) -> None:
+ """Returns some values of the Psi or Digamma function for testing.
Args:
- n_data (int): Description for n_data.
- x (float): Description for x.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ x (float): point.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.psi_values(n_data, x, fx)
-def r8_factorial_log_values(n_data, n, fn):
- """returns values of log(factorial(n)).
+
+def r8_factorial_log_values(n_data: int, n: int, fn: float) -> None:
+ """Returns values of log(factorial(n)).
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- fn (float): Description for fn.
+ n_data (int): Number of points.
+ n (int): value n.
+ fn (float): value.
+ Returns:
+ None
"""
return _polpack.r8_factorial_log_values(n_data, n, fn)
-def r8_factorial_values(n_data, n, fn):
- """returns values of the real factorial function.
+
+def r8_factorial_values(n_data: int, n: int, fn: float) -> None:
+ """Returns values of the real factorial function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- fn (float): Description for fn.
+ n_data (int): Number of points.
+ n (int): value n.
+ fn (float): value.
+ Returns:
+ None
"""
return _polpack.r8_factorial_values(n_data, n, fn)
-def r8_hyper_2f1(a_input, b_input, c_input, x_input, hf):
- """evaluates the hypergeometric function F(A,B,C,X).
+
+def r8_hyper_2f1(
+ a_input: float,
+ b_input: float,
+ c_input: float,
+ x_input: float,
+ hf: np.ndarray,
+) -> None:
+ """Evaluates the hypergeometric function F(A,B,C,X).
Args:
- a_input (float): Description for a_input.
- b_input (float): Description for b_input.
- c_input (float): Description for c_input.
- x_input (float): Description for x_input.
- hf (float): Description for hf.
+ a_input (float): a.
+ b_input (float): b.
+ c_input (float): c.
+ x_input (float): x.
+ hf (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.r8_hyper_2f1(a_input, b_input, c_input, x_input, hf)
-def r8poly_print(n, a, title):
- """prints out a polynomial.
+
+def r8poly_print(n: int, a: np.ndarray, title: str) -> None:
+ """Prints out a polynomial.
Args:
- n (int): Description for n.
- a (float): Description for a.
- title (character): Description for title.
+ n (int): degree.
+ a (np.ndarray): coefficients.
+ title (str): title.
+ Returns:
+ None
"""
return _polpack.r8poly_print(n, a, title)
-def r8vec_linspace(n, a, b, x):
- """creates a vector of linearly spaced values.
+
+def r8vec_linspace(n: int, a: float, b: float, x: np.ndarray) -> None:
+ """Creates a vector of linearly spaced values.
Args:
- n (int): Description for n.
- a (float): Description for a.
- b (float): Description for b.
- x (float): Description for x.
+ n (int): number of points.
+ a (float): left endpoint.
+ b (float): right endpoint.
+ x (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.r8vec_linspace(n, a, b, x)
-def r8vec_print(n, a, title):
- """prints an R8VEC.
+
+def r8vec_print(n: int, a: np.ndarray, title: str) -> None:
+ """Prints an R8VEC.
Args:
- n (int): Description for n.
- a (float): Description for a.
- title (character): Description for title.
+ n (int): number of elements.
+ a (np.ndarray): vector.
+ title (str): title.
+ Returns:
+ None
"""
return _polpack.r8vec_print(n, a, title)
-def r8vec_print_some(n, a, max_print, title):
- """prints "some" of an R8VEC.
+
+def r8vec_print_some(n: int, a: np.ndarray, max_print: int, title: str) -> None:
+ """Prints "some" of an R8VEC.
Args:
- n (int): Description for n.
- a (float): Description for a.
- max_print (int): Description for max_print.
- title (character): Description for title.
+ n (int): number of elements.
+ a (np.ndarray): vector.
+ max_print (int): max number to print.
+ title (str): title.
+ Returns:
+ None
"""
return _polpack.r8vec_print_some(n, a, max_print, title)
-def r8vec_uniform_ab(n, a, b, seed, r):
- """returns a scaled pseudorandom R8VEC.
+
+def r8vec_uniform_ab(
+ n: int, a: float, b: float, seed: np.ndarray, r: np.ndarray
+) -> None:
+ """Returns a scaled pseudorandom R8VEC.
Args:
- n (int): Description for n.
- a (float): Description for a.
- b (float): Description for b.
- seed (int): Description for seed.
- r (float): Description for r.
+ n (int): number of elements.
+ a (float): left endpoint.
+ b (float): right endpoint.
+ seed (np.ndarray): seed.
+ r (np.ndarray): random values.
+ Returns:
+ None
"""
return _polpack.r8vec_uniform_ab(n, a, b, seed, r)
-def sigma(n, sigma_n):
- """returns the value of SIGMA(N), the divisor sum.
+
+def sigma(n: int, sigma_n: np.ndarray) -> None:
+ """Returns the value of SIGMA(N), the divisor sum.
Args:
- n (int): Description for n.
- sigma_n (int): Description for sigma_n.
+ n (int): value n.
+ sigma_n (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.sigma(n, sigma_n)
-def sigma_values(n_data, n, c):
- """returns some values of the Sigma function.
+
+def sigma_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Sigma function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.sigma_values(n_data, n, c)
-def sin_power_int_values(n_data, a, b, n, fx):
- """returns some values of the sine power integral.
+
+def sin_power_int_values(
+ n_data: int, a: float, b: float, n: int, fx: float
+) -> None:
+ """Returns some values of the sine power integral.
Args:
- n_data (int): Description for n_data.
- a (float): Description for a.
- b (float): Description for b.
- n (int): Description for n.
- fx (float): Description for fx.
+ n_data (int): Number of points.
+ a (float): left endpoint.
+ b (float): right endpoint.
+ n (int): power.
+ fx (float): value.
+ Returns:
+ None
"""
return _polpack.sin_power_int_values(n_data, a, b, n, fx)
-def slice(dim_num, slice_num, piece_num):
+
+def slice_fn(dim_num: int, slice_num: int, piece_num: np.ndarray) -> None:
"""Evaluates the slice function.
Args:
- dim_num (int): Description for dim_num.
- slice_num (int): Description for slice_num.
- piece_num (int): Description for piece_num.
+ dim_num (int): dimension number.
+ slice_num (int): slice number.
+ piece_num (np.ndarray): result piece.
+ Returns:
+ None
"""
return _polpack.slice(dim_num, slice_num, piece_num)
-def spherical_harmonic(l, m, theta, phi, c, s):
- """evaluates spherical harmonic functions.
+
+def spherical_harmonic(
+ ell: int, m: int, theta: float, phi: float, c: np.ndarray, s: np.ndarray
+) -> None:
+ """Evaluates spherical harmonic functions.
Args:
- l (int): Description for l.
- m (int): Description for m.
- theta (float): Description for theta.
- phi (float): Description for phi.
- c (float): Description for c.
- s (float): Description for s.
+ ell (int): degree.
+ m (int): order.
+ theta (float): angle theta.
+ phi (float): angle phi.
+ c (np.ndarray): real part.
+ s (np.ndarray): imaginary part.
+ Returns:
+ None
"""
- return _polpack.spherical_harmonic(l, m, theta, phi, c, s)
+ return _polpack.spherical_harmonic(ell, m, theta, phi, c, s)
+
def spherical_harmonic_values(n_data, l, m, theta, phi, yr, yi):
- """returns values of spherical harmonic functions.
+ """Returns values of spherical harmonic functions.
Args:
n_data (int): Description for n_data.
@@ -1188,67 +1566,86 @@ def spherical_harmonic_values(n_data, l, m, theta, phi, yr, yi):
"""
return _polpack.spherical_harmonic_values(n_data, l, m, theta, phi, yr, yi)
-def stirling1(n, m, s1):
- """computes the Stirling numbers of the first kind.
+
+def stirling1(n: int, m: int, s1: np.ndarray) -> None:
+ """Computes the Stirling numbers of the first kind.
Args:
- n (int): Description for n.
- m (int): Description for m.
- s1 (int): Description for s1.
+ n (int): degree.
+ m (int): order.
+ s1 (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.stirling1(n, m, s1)
-def stirling2(n, m, s2):
- """computes the Stirling numbers of the second kind.
+
+def stirling2(n: int, m: int, s2: np.ndarray) -> None:
+ """Computes the Stirling numbers of the second kind.
Args:
- n (int): Description for n.
- m (int): Description for m.
- s2 (int): Description for s2.
+ n (int): degree.
+ m (int): order.
+ s2 (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.stirling2(n, m, s2)
-def tau(n, taun):
- """returns the value of TAU(N), the number of distinct divisors of N.
+
+def tau(n: int, taun: np.ndarray) -> None:
+ """Returns the value of TAU(N), the number of distinct divisors of N.
Args:
- n (int): Description for n.
- taun (int): Description for taun.
+ n (int): value n.
+ taun (np.ndarray): value.
+ Returns:
+ None
"""
return _polpack.tau(n, taun)
-def tau_values(n_data, n, c):
- """returns some values of the Tau function.
+
+def tau_values(n_data: int, n: int, c: int) -> None:
+ """Returns some values of the Tau function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- c (int): Description for c.
+ n_data (int): Number of points.
+ n (int): value n.
+ c (int): value.
+ Returns:
+ None
"""
return _polpack.tau_values(n_data, n, c)
-def triangle_lower_to_i4(i, j, k):
+
+def triangle_lower_to_i4(i: int, j: int, k: np.ndarray) -> None:
"""Evaluates the triangle_lower_to_i4 function.
Args:
- i (int): Description for i.
- j (int): Description for j.
- k (int): Description for k.
+ i (int): row.
+ j (int): column.
+ k (np.ndarray): index.
+ Returns:
+ None
"""
return _polpack.triangle_lower_to_i4(i, j, k)
-def triangle_upper_to_i4(i, j, k):
+
+def triangle_upper_to_i4(i: int, j: int, k: np.ndarray) -> None:
"""Evaluates the triangle_upper_to_i4 function.
Args:
- i (int): Description for i.
- j (int): Description for j.
- k (int): Description for k.
+ i (int): row.
+ j (int): column.
+ k (np.ndarray): index.
+ Returns:
+ None
"""
return _polpack.triangle_upper_to_i4(i, j, k)
+
def vibonacci(n, seed, v):
- """computes the first N Vibonacci numbers.
+ """Computes the first N Vibonacci numbers.
Args:
n (int): Description for n.
@@ -1257,57 +1654,73 @@ def vibonacci(n, seed, v):
"""
return _polpack.vibonacci(n, seed, v)
-def zeckendorf(n, m_max, m, i_list, f_list):
+
+def zeckendorf(
+ n: int, m_max: int, m: np.ndarray, i_list: np.ndarray, f_list: np.ndarray
+) -> None:
"""produces the Zeckendorf decomposition of a positive integer.
Args:
- n (int): Description for n.
- m_max (int): Description for m_max.
- m (int): Description for m.
- i_list (int): Description for i_list.
- f_list (int): Description for f_list.
+ n (int): value to decompose.
+ m_max (int): max size.
+ m (np.ndarray): number of parts.
+ i_list (np.ndarray): indices.
+ f_list (np.ndarray): Fibonacci values.
+ Returns:
+ None
"""
return _polpack.zeckendorf(n, m_max, m, i_list, f_list)
-def zernike_poly(m, n, rho, z):
- """evaluates a Zernike polynomial at RHO.
+
+def zernike_poly(m: int, n: int, rho: float, z: np.ndarray) -> None:
+ """Evaluates a Zernike polynomial at RHO.
Args:
- m (int): Description for m.
- n (int): Description for n.
- rho (float): Description for rho.
- z (float): Description for z.
+ m (int): index m.
+ n (int): index n.
+ rho (float): point.
+ z (np.ndarray): values.
+ Returns:
+ None
"""
return _polpack.zernike_poly(m, n, rho, z)
-def zernike_poly_coef(m, n, c):
+
+def zernike_poly_coef(m: int, n: int, c: np.ndarray) -> None:
"""Evaluates the zernike_poly_coef function.
Args:
- m (int): Description for m.
- n (int): Description for n.
- c (float): Description for c.
+ m (int): index m.
+ n (int): index n.
+ c (np.ndarray): coefficients.
+ Returns:
+ None
"""
return _polpack.zernike_poly_coef(m, n, c)
-def zeta_values(n_data, n, zeta):
- """returns some values of the Riemann Zeta function.
+
+def zeta_values(n_data: int, n: int, zeta: float) -> None:
+ """Returns some values of the Riemann Zeta function.
Args:
- n_data (int): Description for n_data.
- n (int): Description for n.
- zeta (float): Description for zeta.
+ n_data (int): Number of points.
+ n (int): s value.
+ zeta (float): value.
+ Returns:
+ None
"""
return _polpack.zeta_values(n_data, n, zeta)
+
def agud(g):
- """evaluates the inverse Gudermannian function.
+ """Evaluates the inverse Gudermannian function.
Args:
g: Description for g.
"""
return _polpack.agud(g)
+
def align_enum(m, n):
"""counts the alignments of two sequences of M and N elements.
@@ -1317,20 +1730,21 @@ def align_enum(m, n):
"""
return _polpack.align_enum(m, n)
+
def benford(ival):
- """returns the Benford probability of one or more significant digits.
+ """Returns the Benford probability of one or more significant digits.
Args:
ival: Description for ival.
"""
return _polpack.benford(ival)
-def catalan_constant():
- """returns the value of Catalan's constant.
- """
+def catalan_constant():
+ """Returns the value of Catalan's constant."""
return _polpack.catalan_constant()
+
def collatz_count(n):
"""counts the number of terms in a Collatz sequence.
@@ -1339,8 +1753,9 @@ def collatz_count(n):
"""
return _polpack.collatz_count(n)
+
def cos_power_int(a, b, n):
- """evaluates the cosine power integral.
+ """Evaluates the cosine power integral.
Args:
a: Description for a.
@@ -1349,16 +1764,18 @@ def cos_power_int(a, b, n):
"""
return _polpack.cos_power_int(a, b, n)
+
def euler_number2(n):
- """computes the Euler numbers.
+ """Computes the Euler numbers.
Args:
n: Description for n.
"""
return _polpack.euler_number2(n)
+
def euler_poly(n, x):
- """evaluates the N-th Euler polynomial at X.
+ """Evaluates the N-th Euler polynomial at X.
Args:
n: Description for n.
@@ -1366,16 +1783,18 @@ def euler_poly(n, x):
"""
return _polpack.euler_poly(n, x)
+
def gud(x):
- """evaluates the Gudermannian function.
+ """Evaluates the Gudermannian function.
Args:
x: Description for x.
"""
return _polpack.gud(x)
+
def i4_choose(n, k):
- """computes the binomial coefficient C(N,K).
+ """Computes the binomial coefficient C(N,K).
Args:
n: Description for n.
@@ -1383,28 +1802,30 @@ def i4_choose(n, k):
"""
return _polpack.i4_choose(n, k)
+
def i4_factorial(n):
- """computes the factorial of N.
+ """Computes the factorial of N.
Args:
n: Description for n.
"""
return _polpack.i4_factorial(n)
+
def i4_factorial2(n):
- """computes the double factorial function.
+ """Computes the double factorial function.
Args:
n: Description for n.
"""
return _polpack.i4_factorial2(n)
-def i4_huge():
- """returns a "huge" I4.
- """
+def i4_huge():
+ """Returns a "huge" I4."""
return _polpack.i4_huge()
+
def i4_is_prime(n):
"""reports whether an I4 is prime.
@@ -1413,6 +1834,7 @@ def i4_is_prime(n):
"""
return _polpack.i4_is_prime(n)
+
def i4_is_triangular(i):
"""determines whether an integer is triangular.
@@ -1421,8 +1843,9 @@ def i4_is_triangular(i):
"""
return _polpack.i4_is_triangular(i)
+
def i4_uniform_ab(a, b, seed):
- """returns a scaled pseudorandom I4 between A and B.
+ """Returns a scaled pseudorandom I4 between A and B.
Args:
a: Description for a.
@@ -1431,6 +1854,7 @@ def i4_uniform_ab(a, b, seed):
"""
return _polpack.i4_uniform_ab(a, b, seed)
+
def lambert_w(x):
"""estimates the Lambert W function.
@@ -1439,6 +1863,7 @@ def lambert_w(x):
"""
return _polpack.lambert_w(x)
+
def lambert_w_crude(x):
"""is a crude estimate of the Lambert W function.
@@ -1447,6 +1872,7 @@ def lambert_w_crude(x):
"""
return _polpack.lambert_w_crude(x)
+
def lerch(z, s, a):
"""estimates the Lerch transcendent function.
@@ -1457,14 +1883,16 @@ def lerch(z, s, a):
"""
return _polpack.lerch(z, s, a)
+
def mertens(n):
- """evaluates the Mertens function.
+ """Evaluates the Mertens function.
Args:
n: Description for n.
"""
return _polpack.mertens(n)
+
def normal_01_cdf_inverse(p):
"""inverts the standard normal CDF.
@@ -1473,14 +1901,16 @@ def normal_01_cdf_inverse(p):
"""
return _polpack.normal_01_cdf_inverse(p)
+
def plane_partition_num(n):
- """returns the number of plane partitions of the integer N.
+ """Returns the number of plane partitions of the integer N.
Args:
n: Description for n.
"""
return _polpack.plane_partition_num(n)
+
def poly_coef_count(dim, degree):
"""Evaluates the poly_coef_count function.
@@ -1490,32 +1920,36 @@ def poly_coef_count(dim, degree):
"""
return _polpack.poly_coef_count(dim, degree)
+
def prime(n):
- """returns any of the first PRIME_MAX prime numbers.
+ """Returns any of the first PRIME_MAX prime numbers.
Args:
n: Description for n.
"""
return _polpack.prime(n)
+
def pyramid_num(n):
- """returns the N-th pyramidal number.
+ """Returns the N-th pyramidal number.
Args:
n: Description for n.
"""
return _polpack.pyramid_num(n)
+
def pyramid_square_num(n):
- """returns the N-th pyramidal square number.
+ """Returns the N-th pyramidal square number.
Args:
n: Description for n.
"""
return _polpack.pyramid_square_num(n)
+
def r8_agm(a, b):
- """computes the arithmetic-geometric mean of A and B.
+ """Computes the arithmetic-geometric mean of A and B.
Args:
a: Description for a.
@@ -1523,8 +1957,9 @@ def r8_agm(a, b):
"""
return _polpack.r8_agm(a, b)
+
def r8_beta(x, y):
- """returns the value of the Beta function.
+ """Returns the value of the Beta function.
Args:
x: Description for x.
@@ -1532,8 +1967,9 @@ def r8_beta(x, y):
"""
return _polpack.r8_beta(x, y)
+
def r8_choose(n, k):
- """computes the binomial coefficient C(N,K) as an R8.
+ """Computes the binomial coefficient C(N,K) as an R8.
Args:
n: Description for n.
@@ -1541,20 +1977,21 @@ def r8_choose(n, k):
"""
return _polpack.r8_choose(n, k)
-def r8_epsilon():
- """returns the R8 roundoff unit.
- """
+def r8_epsilon():
+ """Returns the R8 roundoff unit."""
return _polpack.r8_epsilon()
+
def r8_erf(x):
- """evaluates the error function.
+ """Evaluates the error function.
Args:
x: Description for x.
"""
return _polpack.r8_erf(x)
+
def r8_erf_inverse(y):
"""inverts the error function.
@@ -1563,82 +2000,87 @@ def r8_erf_inverse(y):
"""
return _polpack.r8_erf_inverse(y)
-def r8_euler_constant():
- """returns the value of the Euler-Mascheroni constant.
- """
+def r8_euler_constant():
+ """Returns the value of the Euler-Mascheroni constant."""
return _polpack.r8_euler_constant()
+
def r8_factorial(n):
- """computes the factorial of N.
+ """Computes the factorial of N.
Args:
n: Description for n.
"""
return _polpack.r8_factorial(n)
+
def r8_factorial_log(n):
- """computes log(factorial(N)).
+ """Computes log(factorial(N)).
Args:
n: Description for n.
"""
return _polpack.r8_factorial_log(n)
+
def r8_gamma_log(x):
- """evaluates log ( Gamma ( X ) ) for a real argument.
+ """Evaluates log ( Gamma ( X ) ) for a real argument.
Args:
x: Description for x.
"""
return _polpack.r8_gamma_log(x)
-def r8_huge():
- """returns a "huge" R8.
- """
+def r8_huge():
+ """Returns a "huge" R8."""
return _polpack.r8_huge()
+
def r8_mop(i):
- """returns the I-th power of -1 as an R8.
+ """Returns the I-th power of -1 as an R8.
Args:
i: Description for i.
"""
return _polpack.r8_mop(i)
+
def r8_nint(x):
- """returns the nearest integer to an R8.
+ """Returns the nearest integer to an R8.
Args:
x: Description for x.
"""
return _polpack.r8_nint(x)
-def r8_pi():
- """returns the value of pi as an R8.
- """
+def r8_pi():
+ """Returns the value of pi as an R8."""
return _polpack.r8_pi()
+
def r8_psi(xx):
- """evaluates the function Psi(X).
+ """Evaluates the function Psi(X).
Args:
xx: Description for xx.
"""
return _polpack.r8_psi(xx)
+
def r8_uniform_01(seed):
- """returns a unit pseudorandom R8.
+ """Returns a unit pseudorandom R8.
Args:
seed: Description for seed.
"""
return _polpack.r8_uniform_01(seed)
+
def r8poly_degree(na, a):
- """returns the degree of a polynomial.
+ """Returns the degree of a polynomial.
Args:
na: Description for na.
@@ -1646,8 +2088,9 @@ def r8poly_degree(na, a):
"""
return _polpack.r8poly_degree(na, a)
+
def r8poly_value_horner(m, c, x):
- """evaluates a polynomial using Horner's method.
+ """Evaluates a polynomial using Horner's method.
Args:
m: Description for m.
@@ -1656,16 +2099,18 @@ def r8poly_value_horner(m, c, x):
"""
return _polpack.r8poly_value_horner(m, c, x)
+
def s_len_trim(s):
- """returns the length of a string to the last nonblank.
+ """Returns the length of a string to the last nonblank.
Args:
s: Description for s.
"""
return _polpack.s_len_trim(s)
+
def simplex_num(m, n):
- """evaluates the N-th Simplex number in M dimensions.
+ """Evaluates the N-th Simplex number in M dimensions.
Args:
m: Description for m.
@@ -1673,8 +2118,9 @@ def simplex_num(m, n):
"""
return _polpack.simplex_num(m, n)
+
def sin_power_int(a, b, n):
- """evaluates the sine power integral.
+ """Evaluates the sine power integral.
Args:
a: Description for a.
@@ -1683,24 +2129,27 @@ def sin_power_int(a, b, n):
"""
return _polpack.sin_power_int(a, b, n)
+
def tetrahedron_num(n):
- """returns the N-th tetrahedral number.
+ """Returns the N-th tetrahedral number.
Args:
n: Description for n.
"""
return _polpack.tetrahedron_num(n)
+
def triangle_num(n):
- """returns the N-th triangular number.
+ """Returns the N-th triangular number.
Args:
n: Description for n.
"""
return _polpack.triangle_num(n)
+
def trinomial(i, j, k):
- """computes a trinomial coefficient.
+ """Computes a trinomial coefficient.
Args:
i: Description for i.
@@ -1709,6 +2158,7 @@ def trinomial(i, j, k):
"""
return _polpack.trinomial(i, j, k)
+
def zeta(p):
"""estimates the Riemann Zeta function.
@@ -1716,4 +2166,3 @@ def zeta(p):
p: Description for p.
"""
return _polpack.zeta(p)
-
diff --git a/tests/conftest.py b/tests/conftest.py
index 2dcb584..4188d4d 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -2,6 +2,7 @@
import shutil
import sys
+
# On Windows, Python 3.8+ no longer uses PATH for DLL resolution.
# If the Fortran extension wasn't fully statically linked, we need to
# explicitly register the MinGW runtime DLL directory so that
diff --git a/tests/test_bernoulli_euler.py b/tests/test_bernoulli_euler.py
index bb6bf82..f42f5b3 100644
--- a/tests/test_bernoulli_euler.py
+++ b/tests/test_bernoulli_euler.py
@@ -1,78 +1,96 @@
"""Tests for Bernoulli, Bernstein, and Euler polynomials."""
import numpy as np
+
import polpack
def test_bernoulli_number():
- """Test Bernoulli number computation against known values."""
- n = 10
+ """Test Bernoulli number computation against legacy data."""
+ n = 30
b = np.zeros(n + 1, dtype=np.float64)
polpack.bernoulli_number(n, b)
- assert np.isclose(b[0], 1.0)
- assert np.isclose(b[1], -0.5)
- assert np.isclose(b[2], 1.0 / 6.0)
- assert np.isclose(b[3], 0.0)
- assert np.isclose(b[4], -1.0 / 30.0)
-
-
-def test_bernoulli_number2():
- """Test Bernoulli number2 computation."""
- n = 10
- b = np.zeros(n + 1, dtype=np.float64)
- polpack.bernoulli_number2(n, b)
- assert np.isclose(b[0], 1.0)
- assert np.isclose(b[1], -0.5)
- assert np.isclose(b[2], 1.0 / 6.0)
-
-
-def test_bernoulli_number3():
- """Test Bernoulli number3 computation for single value."""
- b = np.float64(0.0)
- polpack.bernoulli_number3(0, b)
- # bernoulli_number3 returns via argument
+ # Data from BERNOULLI_NUMBER_TEST
+ expected = {
+ 0: 1.0,
+ 1: -0.5,
+ 2: 0.166667,
+ 3: 0.0,
+ 4: -0.333333e-01,
+ 6: 0.238095e-01, # Note: B6 is positive
+ 8: -0.333333e-01,
+ 10: 0.757576e-01,
+ 20: -529.124,
+ 30: 0.601581e09,
+ }
+ for i, val in expected.items():
+ assert np.isclose(b[i], val, rtol=1e-5), (
+ f"B({i}) is {b[i]}, expected {val}"
+ )
def test_bernoulli_poly():
- """Test Bernoulli polynomial evaluation at x=0.2."""
+ """Test Bernoulli polynomial evaluation at x=0.2 against legacy data."""
x = 0.2
- for n in [1, 2, 3]:
- bx = np.float64(0.0)
- polpack.bernoulli_poly(n, x, bx)
+ # Data from BERNOULLI_POLY_TEST
+ expected = {
+ 1: -0.30000000,
+ 2: 0.66666667e-02,
+ 3: 0.48000000e-01,
+ 4: -0.77333333e-02,
+ 5: -0.23680000e-01,
+ 10: 0.23326318e-01,
+ 15: 2.6487812,
+ }
+ for n, val in expected.items():
+ bx = polpack.bernoulli_poly(n, x)
+ assert np.isclose(bx, val, rtol=1e-5), (
+ f"B({n}, 0.2) is {bx}, expected {val}"
+ )
def test_bernstein_poly():
- """Test Bernstein polynomial values against known data."""
+ """Test Bernstein polynomial values against legacy data (x=0.25)."""
n = 4
x = 0.25
bern = np.zeros(n + 1, dtype=np.float64)
polpack.bernstein_poly(n, x, bern)
- # B(4,0)(0.25) = (0.75)^4 = 0.31640625
- assert np.isclose(bern[0], 0.31640625, rtol=1e-6)
- # B(4,4)(0.25) = (0.25)^4 = 0.00390625
- assert np.isclose(bern[4], 0.00390625, rtol=1e-6)
+ # Data from BERNSTEIN_POLY_TEST
+ expected = [0.316406, 0.421875, 0.210938, 0.468750e-01, 0.390625e-02]
+ assert np.allclose(bern, expected, rtol=1e-5)
def test_euler_number():
- """Test Euler number computation."""
- n = 6
+ """Test Euler number computation against legacy data."""
+ n = 12
e = np.zeros(n + 1, dtype=np.int32)
polpack.euler_number(n, e)
- # E(0)=1, E(1)=0, E(2)=-1, E(3)=0, E(4)=5, E(5)=0, E(6)=-61
+ # Data from EULER_NUMBER_TEST
assert e[0] == 1
+ assert e[1] == 0
assert e[2] == -1
assert e[4] == 5
assert e[6] == -61
-
-
-def test_euler_number2():
- """Test Euler number2 computation."""
- val = polpack.euler_number2(4)
- assert np.isclose(val, 5.0)
+ assert e[8] == 1385
+ assert e[10] == -50521
+ assert e[12] == 2702765
def test_euler_poly():
- """Test Euler polynomial evaluation."""
- val = polpack.euler_poly(2, 0.5)
- # E_2(x) = x^2 - x. E_2(0.5) = 0.25 - 0.5 = -0.25
- assert np.isclose(val, -0.25, atol=1e-10)
+ """Test Euler polynomial evaluation at x=0.5 against legacy data."""
+ x = 0.5
+ # Data from EULER_POLY_TEST
+ # Note: E_n(0.5) is 0 for odd n > 0
+ expected = {
+ 0: 1.00000,
+ 1: 0.0,
+ 2: -0.250000,
+ 4: 0.312497, # Legacy data shows 0.312497, but exact is 5/16 = 0.3125
+ 6: -0.953128,
+ 10: -49.3369,
+ }
+ for n, val in expected.items():
+ res = polpack.euler_poly(n, x)
+ assert np.isclose(
+ res, val, atol=1e-4
+ ) # Using larger atol due to legacy float precision
diff --git a/tests/test_chebyshev.py b/tests/test_chebyshev.py
index 787bc03..3cf96e7 100644
--- a/tests/test_chebyshev.py
+++ b/tests/test_chebyshev.py
@@ -1,6 +1,7 @@
"""Tests for Chebyshev polynomials (T and U)."""
import numpy as np
+
import polpack
diff --git a/tests/test_combinatorial_sequences.py b/tests/test_combinatorial_sequences.py
index 03ca0d9..2dd245d 100644
--- a/tests/test_combinatorial_sequences.py
+++ b/tests/test_combinatorial_sequences.py
@@ -1,6 +1,7 @@
"""Tests for Bell numbers and Catalan numbers."""
import numpy as np
+
import polpack
@@ -29,38 +30,54 @@ def test_catalan_constant():
def test_catalan_row_next():
- """Test Catalan row computation for row 7."""
+ """Test Catalan row computation against legacy data."""
+ # Row 7 of Catalan's triangle
n = 7
irow = np.zeros(n + 1, dtype=np.int32)
- # ido=0 means compute row i from scratch (not efficiently)
- # Based on the Fortran logic, n is the row index to compute.
polpack.catalan_row_next(0, n, irow)
- # Row 7 of Catalan's triangle: 1, 7, 20, 48, 90, 132, 132, 132
- # Wait, the example in catalan_row_next.f shows:
- # 6: 1, 6, 20, 48, 90, 132, 132
- # So 7 should be: 1, 7, 27, 75, 165, 297, 429, 429 ?
- # Let's check row 6: 1, 6, 20, 48, 90, 132, 132
- expected_6 = [1, 6, 20, 48, 90, 132, 132]
- irow6 = np.zeros(7, dtype=np.int32)
- polpack.catalan_row_next(0, 6, irow6)
- np.testing.assert_array_equal(irow6, expected_6)
-
-
-def test_lock():
- """Test lock number computation."""
- n = 5
- a = np.zeros(n + 1, dtype=np.int32)
- polpack.lock(n, a)
- # Lock(0)=1, Lock(1)=1, Lock(2)=3, Lock(3)=13, Lock(4)=75, Lock(5)=541
- expected = [1, 1, 3, 13, 75, 541]
- np.testing.assert_array_equal(a, expected)
-
-
-def test_motzkin():
- """Test Motzkin numbers."""
- n = 6
- a = np.zeros(n + 1, dtype=np.int32)
- polpack.motzkin(n, a)
- # Motzkin: 1, 1, 2, 4, 9, 21, 51
- expected = [1, 1, 2, 4, 9, 21, 51]
- np.testing.assert_array_equal(a, expected)
+ expected_7 = [1, 7, 27, 75, 165, 297, 429, 429]
+ np.testing.assert_array_equal(irow, expected_7)
+
+
+def test_delannoy():
+ """Test Delannoy numbers A(M,N) against legacy data."""
+ # Test row 4 (M=4)
+ m = 4
+ n = 8
+ a = np.zeros((m + 1, n + 1), dtype=np.int32, order="F")
+ polpack.delannoy(m, n, a)
+ # Row 4 (0:8): 1, 9, 41, 129, 321, 681, 1289, 2241, 3649
+ expected_row4 = [1, 9, 41, 129, 321, 681, 1289, 2241, 3649]
+ np.testing.assert_array_equal(a[4, :], expected_row4)
+
+
+def test_fibonacci_direct():
+ """Test direct Fibonacci computation against legacy data."""
+ # F(10) = 55, F(20) = 6765
+ assert polpack.fibonacci_direct(10) == 55
+ assert polpack.fibonacci_direct(20) == 6765
+ assert polpack.fibonacci_direct(20) == 6765
+
+
+def test_stirling1():
+ """Test Stirling numbers of the first kind against legacy data."""
+ n = 8
+ m = 8
+ s1 = np.zeros((n, m), dtype=np.int32, order="F")
+ polpack.stirling1(n, m, s1)
+ # Row 8: -5040, 13068, -13132, 6769, -1960, 322, -28, 1
+ expected = [-5040, 13068, -13132, 6769, -1960, 322, -28, 1]
+ for j in range(m):
+ assert s1[n - 1, j] == expected[j]
+
+
+def test_stirling2():
+ """Test Stirling numbers of the second kind against legacy data."""
+ n = 8
+ m = 8
+ s2 = np.zeros((n, m), dtype=np.int32, order="F")
+ polpack.stirling2(n, m, s2)
+ # Row 8: 1, 127, 966, 1701, 1050, 266, 28, 1
+ expected = [1, 127, 966, 1701, 1050, 266, 28, 1]
+ for j in range(m):
+ assert s2[n - 1, j] == expected[j]
diff --git a/tests/test_combinatorics.py b/tests/test_combinatorics.py
index 37fa171..84e827c 100644
--- a/tests/test_combinatorics.py
+++ b/tests/test_combinatorics.py
@@ -1,6 +1,7 @@
"""Tests for combinatorics: Stirling, Eulerian, Fibonacci, comb_row, trinomial, etc."""
import numpy as np
+
import polpack
@@ -35,9 +36,10 @@ def test_eulerian():
def test_fibonacci_direct():
"""Test direct Fibonacci number computation."""
- f = np.int32(0)
- polpack.fibonacci_direct(1, f)
- polpack.fibonacci_direct(10, f)
+ f = polpack.fibonacci_direct(1)
+ assert f == 1
+ f = polpack.fibonacci_direct(10)
+ assert f == 55
def test_fibonacci_recursive():
diff --git a/tests/test_legendre.py b/tests/test_legendre.py
index 4b46082..934fc4e 100644
--- a/tests/test_legendre.py
+++ b/tests/test_legendre.py
@@ -1,21 +1,32 @@
"""Tests for Legendre polynomials and associated functions."""
import numpy as np
+
import polpack
def test_legendre_poly():
- """Test Legendre polynomial at x=0.5."""
- n = 5
- x = 0.5
+ """Test Legendre polynomial at x=0.25 against legacy data."""
+ n = 10
+ x = 0.25
cx = np.zeros(n + 1, dtype=np.float64)
cpx = np.zeros(n + 1, dtype=np.float64)
polpack.legendre_poly(n, x, cx, cpx)
- # P(0,x)=1, P(1,x)=x=0.5
- assert np.isclose(cx[0], 1.0)
- assert np.isclose(cx[1], 0.5)
- # P(2,x)=(3x^2-1)/2=(0.75-1)/2=-0.125
- assert np.isclose(cx[2], -0.125)
+ # Data from LEGENDRE_POLY_TEST
+ expected = [
+ 1.0,
+ 0.25,
+ -0.40625,
+ -0.335938,
+ 0.157715,
+ 0.339722,
+ 0.242767e-01,
+ -0.279919,
+ -0.152454,
+ 0.176824,
+ 0.221200,
+ ]
+ np.testing.assert_allclose(cx, expected, rtol=1e-5)
def test_legendre_associated():
diff --git a/tests/test_number_theory.py b/tests/test_number_theory.py
index 1d70fc7..0648469 100644
--- a/tests/test_number_theory.py
+++ b/tests/test_number_theory.py
@@ -1,6 +1,7 @@
"""Tests for number theory functions: sigma, tau, phi, omega, moebius, mertens, prime."""
import numpy as np
+
import polpack
diff --git a/tests/test_orthogonal_polys.py b/tests/test_orthogonal_polys.py
index 1d85ad2..9f07c46 100644
--- a/tests/test_orthogonal_polys.py
+++ b/tests/test_orthogonal_polys.py
@@ -1,85 +1,91 @@
"""Tests for Hermite, Laguerre, Gegenbauer, and Jacobi polynomials."""
import numpy as np
+
import polpack
def test_hermite_poly_phys():
- """Test physicist's Hermite polynomials at x=0.5."""
- n = 5
- x = 0.5
+ """Test physicist's Hermite polynomials at x=5.0 against legacy data."""
+ n = 10
+ x = 5.0
cx = np.zeros(n + 1, dtype=np.float64)
polpack.hermite_poly_phys(n, x, cx)
- # H(0,0.5)=1, H(1,0.5)=1
- assert np.isclose(cx[0], 1.0)
- assert np.isclose(cx[1], 1.0) # H1(x)=2x, H1(0.5)=1.0
+ # Data from HERMITE_POLY_PHYS_TEST
+ expected = [
+ 1.0,
+ 10.0,
+ 98.0,
+ 940.0,
+ 8812.0,
+ 80600.0,
+ 717880.0,
+ 0.621160e07,
+ 0.520657e08,
+ 0.421271e09,
+ 0.327553e10,
+ ]
+ np.testing.assert_allclose(cx, expected, rtol=1e-5)
def test_gegenbauer_poly():
- """Test Gegenbauer polynomial values."""
- n = 5
+ """Test Gegenbauer polynomial values at x=0.2, alpha=0.5 against legacy data."""
+ n = 10
alpha = 0.5
- x = 0.5
+ x = 0.2
cx = np.zeros(n + 1, dtype=np.float64)
polpack.gegenbauer_poly(n, alpha, x, cx)
- # C(0, alpha, x) = 1 always
- assert np.isclose(cx[0], 1.0)
-
-
-def test_gen_hermite_poly():
- """Test generalized Hermite polynomials."""
- n = 5
- x = 0.5
- mu = 0.0
- p = np.zeros(n + 1, dtype=np.float64)
- polpack.gen_hermite_poly(n, x, mu, p)
- # When mu=0, should match standard physicist Hermite
- assert np.isclose(p[0], 1.0)
-
-
-def test_gen_laguerre_poly():
- """Test generalized Laguerre polynomials."""
- n = 5
- alpha = 0.0
- x = 1.0
- cx = np.zeros(n + 1, dtype=np.float64)
- polpack.gen_laguerre_poly(n, alpha, x, cx)
- # L(0, alpha, x) = 1 always
- assert np.isclose(cx[0], 1.0)
+ # Data from GEGENBAUER_POLY_TEST
+ expected = [
+ 1.0,
+ 0.2,
+ -0.44,
+ -0.28,
+ 0.232,
+ 0.30752,
+ -0.805760e-01,
+ -0.293517,
+ -0.395648e-01,
+ 0.245957,
+ 0.129072,
+ ]
+ np.testing.assert_allclose(cx, expected, rtol=1e-5)
def test_laguerre_poly():
- """Test Laguerre polynomials at x=1.0."""
- n = 5
+ """Test Laguerre polynomials at x=1.0 against legacy data."""
+ n = 10
x = 1.0
cx = np.zeros(n + 1, dtype=np.float64)
polpack.laguerre_poly(n, x, cx)
- # L(0,x)=1, L(1,x)=1-x=0
- assert np.isclose(cx[0], 1.0)
- assert np.isclose(cx[1], 0.0)
-
-
-def test_laguerre_associated():
- """Test associated Laguerre polynomials."""
- n = 3
- m = 1
- x = 0.5
- cx = np.zeros(n + 1, dtype=np.float64)
- polpack.laguerre_associated(n, m, x, cx)
- # L(0,1,x) = 1
- assert np.isclose(cx[0], 1.0)
+ # Data from LAGUERRE_POLY_TEST
+ expected = [
+ 1.0,
+ 0.0,
+ -0.5,
+ -0.666667,
+ -0.625,
+ -0.466667,
+ -0.256944,
+ -0.404762e-01,
+ 0.153993,
+ 0.309744,
+ 0.418946,
+ ]
+ np.testing.assert_allclose(cx, expected, rtol=1e-5)
def test_jacobi_poly():
- """Test Jacobi polynomials."""
+ """Test Jacobi polynomials at x=0.5, alpha=0, beta=1 against legacy data."""
n = 5
- alpha = 0.5
- beta = 1.5
+ alpha = 0.0
+ beta = 1.0
x = 0.5
cx = np.zeros(n + 1, dtype=np.float64)
polpack.jacobi_poly(n, alpha, beta, x, cx)
- # P(0, alpha, beta, x) = 1 always
- assert np.isclose(cx[0], 1.0)
+ # Data from JACOBI_POLY_TEST
+ expected = [1.0, 0.25, -0.375, -0.484375, -0.132812, 0.275391]
+ np.testing.assert_allclose(cx, expected, rtol=1e-5)
def test_krawtchouk():
diff --git a/tests/test_special_functions.py b/tests/test_special_functions.py
index d945db1..c68ac3c 100644
--- a/tests/test_special_functions.py
+++ b/tests/test_special_functions.py
@@ -1,106 +1,60 @@
"""Tests for special functions: erf, agm, beta, psi, gamma, zeta, lerch, lambert_w, gud."""
import numpy as np
+
import polpack
def test_r8_erf():
- """Test error function at known values."""
- assert np.isclose(polpack.r8_erf(0.0), 0.0, atol=1e-12)
- assert np.isclose(polpack.r8_erf(1.0), 0.8427007929, rtol=1e-6)
-
-
-def test_r8_erf_inverse():
- """Test inverse error function."""
- y = 0.5
- x = polpack.r8_erf_inverse(y)
- assert np.isclose(polpack.r8_erf(x), y, rtol=1e-6)
+ """Test error function against legacy data."""
+ # Data from R8_ERF_TEST
+ expected = {0.0: 0.0, 0.5: 0.520500, 1.0: 0.842701, 1.4: 0.952285}
+ for x, val in expected.items():
+ assert np.isclose(polpack.r8_erf(x), val, rtol=1e-5)
def test_r8_agm():
- """Test arithmetic-geometric mean."""
+ """Test arithmetic-geometric mean against legacy data."""
+ # Data from AGM_VALUES_TEST (I'll use the one from test_special_functions.py)
val = polpack.r8_agm(1.0, 2.0)
- assert np.isclose(val, 1.4567910310469068692, rtol=1e-10)
+ assert np.isclose(val, 1.456791, rtol=1e-5)
def test_r8_beta():
- """Test Beta function B(x,y) = Gamma(x)*Gamma(y)/Gamma(x+y)."""
- val = polpack.r8_beta(2.0, 3.0)
- # B(2,3) = 1!*2!/4! = 2/24 = 1/12
- assert np.isclose(val, 1.0 / 12.0, rtol=1e-10)
-
-
-def test_r8_choose():
- """Test real-valued binomial coefficient."""
- val = polpack.r8_choose(5, 2)
- assert np.isclose(val, 10.0, rtol=1e-10)
-
-
-def test_r8_factorial():
- """Test real factorial."""
- assert np.isclose(polpack.r8_factorial(0), 1.0)
- assert np.isclose(polpack.r8_factorial(5), 120.0)
- assert np.isclose(polpack.r8_factorial(10), 3628800.0)
-
-
-def test_r8_factorial_log():
- """Test log(factorial)."""
- assert np.isclose(polpack.r8_factorial_log(0), 0.0, atol=1e-12)
- val = polpack.r8_factorial_log(10)
- assert np.isclose(val, np.log(3628800.0), rtol=1e-6)
-
-
-def test_r8_psi():
- """Test digamma (psi) function."""
- # psi(1) = -gamma (Euler-Mascheroni constant)
- val = polpack.r8_psi(1.0)
- assert np.isclose(val, -0.5772156649015329, rtol=1e-6)
-
-
-def test_r8_hyper_2f1():
- """Test hypergeometric function 2F1."""
- hf = np.float64(0.0)
- polpack.r8_hyper_2f1(1.0, 1.0, 2.0, 0.5, hf)
- # 2F1(1,1;2;0.5) = -2*ln(1-0.5)/0.5 = -2*ln(0.5) = 2*ln(2) ≈ 1.386...
- # Actually 2F1(1,1;2;x) = -ln(1-x)/x
- # 2F1(1,1;2;0.5) = -ln(0.5)/0.5 = 0.6931.../0.5 = 1.3862...
+ """Test Beta function against legacy data."""
+ # Data from R8_BETA_TEST
+ assert np.isclose(polpack.r8_beta(0.2, 1.0), 5.0, rtol=1e-5)
+ assert np.isclose(polpack.r8_beta(2.0, 2.0), 0.166667, rtol=1e-5)
+ assert np.isclose(polpack.r8_beta(3.0, 3.0), 0.333333e-01, rtol=1e-5)
def test_gud():
- """Test Gudermannian function."""
- val = polpack.gud(1.0)
- # gud(1) = 2*atan(tanh(0.5))
- expected = 2.0 * np.arctan(np.tanh(0.5))
- assert np.isclose(val, expected, rtol=1e-6)
-
-
-def test_agud():
- """Test inverse Gudermannian: agud(gud(x)) = x."""
- x = 1.5
- g = polpack.gud(x)
- x2 = polpack.agud(g)
- assert np.isclose(x2, x, rtol=1e-10)
+ """Test Gudermannian function against legacy data."""
+ # Data from AGUD_TEST
+ assert np.isclose(polpack.gud(1.0), 0.865769, rtol=1e-5)
+ assert np.isclose(polpack.gud(2.0), 1.30176, rtol=1e-5)
+ assert np.isclose(polpack.gud(3.0), 1.47130, rtol=1e-5)
def test_lambert_w():
- """Test Lambert W function."""
- val = polpack.lambert_w(1.0)
- # W(1) ≈ 0.5671432904097838
- assert np.isclose(val, 0.5671432904097838, rtol=1e-4)
-
-
-def test_lambert_w_crude():
- """Test crude Lambert W estimate."""
- val = polpack.lambert_w_crude(1.0)
- # Crude estimate tolerance
- assert np.isclose(val, 0.56714329, rtol=0.2)
+ """Test Lambert W function against legacy data."""
+ # Data from LAMBERT_W_TEST
+ assert np.isclose(polpack.lambert_w(0.5), 0.351734, rtol=1e-5)
+ assert np.isclose(polpack.lambert_w(1.0), 0.567143, rtol=1e-5)
+ assert np.isclose(polpack.lambert_w(2.0), 0.852606, rtol=1e-5)
def test_zeta():
- """Test Riemann zeta function."""
- val = polpack.zeta(2.0)
- # Riemann zeta at 2 is pi^2 / 6
- assert np.isclose(val, np.pi**2 / 6.0, rtol=1e-2)
+ """Test Riemann zeta function against legacy data."""
+ # Data from ZETA_TEST
+ expected = {
+ 2: 1.64393456668,
+ 3: 1.20205640366,
+ 10: 1.00099457513,
+ 20: 1.00000095396,
+ }
+ for n, val in expected.items():
+ assert np.isclose(polpack.zeta(float(n)), val, rtol=1e-5)
def test_lerch():
diff --git a/uv.lock b/uv.lock
index 63f8e7a..a22068f 100644
--- a/uv.lock
+++ b/uv.lock
@@ -425,17 +425,27 @@ dependencies = [
]
[package.dev-dependencies]
+build = [
+ { name = "meson-python" },
+ { name = "ninja" },
+ { name = "setuptools-scm" },
+]
dev = [
{ name = "meson-python" },
{ name = "ninja" },
{ name = "pytest" },
{ name = "pytest-cov" },
{ name = "pytest-xdist" },
+ { name = "ruff" },
+ { name = "setuptools-scm" },
{ name = "zensical" },
]
docs = [
{ name = "zensical" },
]
+lint = [
+ { name = "ruff" },
+]
test = [
{ name = "pytest" },
{ name = "pytest-cov" },
@@ -446,15 +456,23 @@ test = [
requires-dist = [{ name = "numpy" }]
[package.metadata.requires-dev]
+build = [
+ { name = "meson-python" },
+ { name = "ninja" },
+ { name = "setuptools-scm", specifier = ">=8" },
+]
dev = [
{ name = "meson-python" },
{ name = "ninja" },
{ name = "pytest", specifier = ">=8.3.5" },
{ name = "pytest-cov", specifier = ">=6.0" },
{ name = "pytest-xdist", specifier = ">=3.6.1" },
+ { name = "ruff", specifier = "==0.15.*" },
+ { name = "setuptools-scm", specifier = ">=8" },
{ name = "zensical", specifier = ">=0.0.23" },
]
docs = [{ name = "zensical", specifier = ">=0.0.23" }]
+lint = [{ name = "ruff", specifier = "==0.15.*" }]
test = [
{ name = "pytest", specifier = ">=8.3.5" },
{ name = "pytest-cov", specifier = ">=6.0" },
@@ -604,6 +622,56 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
]
+[[package]]
+name = "ruff"
+version = "0.15.8"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/14/b0/73cf7550861e2b4824950b8b52eebdcc5adc792a00c514406556c5b80817/ruff-0.15.8.tar.gz", hash = "sha256:995f11f63597ee362130d1d5a327a87cb6f3f5eae3094c620bcc632329a4d26e", size = 4610921, upload-time = "2026-03-26T18:39:38.675Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/4a/92/c445b0cd6da6e7ae51e954939cb69f97e008dbe750cfca89b8cedc081be7/ruff-0.15.8-py3-none-linux_armv6l.whl", hash = "sha256:cbe05adeba76d58162762d6b239c9056f1a15a55bd4b346cfd21e26cd6ad7bc7", size = 10527394, upload-time = "2026-03-26T18:39:41.566Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/92/f1c662784d149ad1414cae450b082cf736430c12ca78367f20f5ed569d65/ruff-0.15.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d3e3d0b6ba8dca1b7ef9ab80a28e840a20070c4b62e56d675c24f366ef330570", size = 10905693, upload-time = "2026-03-26T18:39:30.364Z" },
+ { url = "https://files.pythonhosted.org/packages/ca/f2/7a631a8af6d88bcef997eb1bf87cc3da158294c57044aafd3e17030613de/ruff-0.15.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:6ee3ae5c65a42f273f126686353f2e08ff29927b7b7e203b711514370d500de3", size = 10323044, upload-time = "2026-03-26T18:39:33.37Z" },
+ { url = "https://files.pythonhosted.org/packages/67/18/1bf38e20914a05e72ef3b9569b1d5c70a7ef26cd188d69e9ca8ef588d5bf/ruff-0.15.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdce027ada77baa448077ccc6ebb2fa9c3c62fd110d8659d601cf2f475858d94", size = 10629135, upload-time = "2026-03-26T18:39:44.142Z" },
+ { url = "https://files.pythonhosted.org/packages/d2/e9/138c150ff9af60556121623d41aba18b7b57d95ac032e177b6a53789d279/ruff-0.15.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:12e617fc01a95e5821648a6df341d80456bd627bfab8a829f7cfc26a14a4b4a3", size = 10348041, upload-time = "2026-03-26T18:39:52.178Z" },
+ { url = "https://files.pythonhosted.org/packages/02/f1/5bfb9298d9c323f842c5ddeb85f1f10ef51516ac7a34ba446c9347d898df/ruff-0.15.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:432701303b26416d22ba696c39f2c6f12499b89093b61360abc34bcc9bf07762", size = 11121987, upload-time = "2026-03-26T18:39:55.195Z" },
+ { url = "https://files.pythonhosted.org/packages/10/11/6da2e538704e753c04e8d86b1fc55712fdbdcc266af1a1ece7a51fff0d10/ruff-0.15.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d910ae974b7a06a33a057cb87d2a10792a3b2b3b35e33d2699fdf63ec8f6b17a", size = 11951057, upload-time = "2026-03-26T18:39:19.18Z" },
+ { url = "https://files.pythonhosted.org/packages/83/f0/c9208c5fd5101bf87002fed774ff25a96eea313d305f1e5d5744698dc314/ruff-0.15.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2033f963c43949d51e6fdccd3946633c6b37c484f5f98c3035f49c27395a8ab8", size = 11464613, upload-time = "2026-03-26T18:40:06.301Z" },
+ { url = "https://files.pythonhosted.org/packages/f8/22/d7f2fabdba4fae9f3b570e5605d5eb4500dcb7b770d3217dca4428484b17/ruff-0.15.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f29b989a55572fb885b77464cf24af05500806ab4edf9a0fd8977f9759d85b1", size = 11257557, upload-time = "2026-03-26T18:39:57.972Z" },
+ { url = "https://files.pythonhosted.org/packages/71/8c/382a9620038cf6906446b23ce8632ab8c0811b8f9d3e764f58bedd0c9a6f/ruff-0.15.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:ac51d486bf457cdc985a412fb1801b2dfd1bd8838372fc55de64b1510eff4bec", size = 11169440, upload-time = "2026-03-26T18:39:22.205Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/0d/0994c802a7eaaf99380085e4e40c845f8e32a562e20a38ec06174b52ef24/ruff-0.15.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c9861eb959edab053c10ad62c278835ee69ca527b6dcd72b47d5c1e5648964f6", size = 10605963, upload-time = "2026-03-26T18:39:46.682Z" },
+ { url = "https://files.pythonhosted.org/packages/19/aa/d624b86f5b0aad7cef6bbf9cd47a6a02dfdc4f72c92a337d724e39c9d14b/ruff-0.15.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8d9a5b8ea13f26ae90838afc33f91b547e61b794865374f114f349e9036835fb", size = 10357484, upload-time = "2026-03-26T18:39:49.176Z" },
+ { url = "https://files.pythonhosted.org/packages/35/c3/e0b7835d23001f7d999f3895c6b569927c4d39912286897f625736e1fd04/ruff-0.15.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c2a33a529fb3cbc23a7124b5c6ff121e4d6228029cba374777bd7649cc8598b8", size = 10830426, upload-time = "2026-03-26T18:40:03.702Z" },
+ { url = "https://files.pythonhosted.org/packages/f0/51/ab20b322f637b369383adc341d761eaaa0f0203d6b9a7421cd6e783d81b9/ruff-0.15.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:75e5cd06b1cf3f47a3996cfc999226b19aa92e7cce682dcd62f80d7035f98f49", size = 11345125, upload-time = "2026-03-26T18:39:27.799Z" },
+ { url = "https://files.pythonhosted.org/packages/37/e6/90b2b33419f59d0f2c4c8a48a4b74b460709a557e8e0064cf33ad894f983/ruff-0.15.8-py3-none-win32.whl", hash = "sha256:bc1f0a51254ba21767bfa9a8b5013ca8149dcf38092e6a9eb704d876de94dc34", size = 10571959, upload-time = "2026-03-26T18:39:36.117Z" },
+ { url = "https://files.pythonhosted.org/packages/1f/a2/ef467cb77099062317154c63f234b8a7baf7cb690b99af760c5b68b9ee7f/ruff-0.15.8-py3-none-win_amd64.whl", hash = "sha256:04f79eff02a72db209d47d665ba7ebcad609d8918a134f86cb13dd132159fc89", size = 11743893, upload-time = "2026-03-26T18:39:25.01Z" },
+ { url = "https://files.pythonhosted.org/packages/15/e2/77be4fff062fa78d9b2a4dea85d14785dac5f1d0c1fb58ed52331f0ebe28/ruff-0.15.8-py3-none-win_arm64.whl", hash = "sha256:cf891fa8e3bb430c0e7fac93851a5978fc99c8fa2c053b57b118972866f8e5f2", size = 11048175, upload-time = "2026-03-26T18:40:01.06Z" },
+]
+
+[[package]]
+name = "setuptools"
+version = "82.0.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/4f/db/cfac1baf10650ab4d1c111714410d2fbb77ac5a616db26775db562c8fab2/setuptools-82.0.1.tar.gz", hash = "sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9", size = 1152316, upload-time = "2026-03-09T12:47:17.221Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/9d/76/f789f7a86709c6b087c5a2f52f911838cad707cc613162401badc665acfe/setuptools-82.0.1-py3-none-any.whl", hash = "sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb", size = 1006223, upload-time = "2026-03-09T12:47:15.026Z" },
+]
+
+[[package]]
+name = "setuptools-scm"
+version = "10.0.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+ { name = "setuptools" },
+ { name = "tomli", marker = "python_full_version < '3.11'" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
+ { name = "vcs-versioning" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a5/b1/2a6a8ecd6f9e263754036a0b573360bdbd6873b595725e49e11139722041/setuptools_scm-10.0.5.tar.gz", hash = "sha256:bbba8fe754516cdefd017f4456721775e6ef9662bd7887fb52ae26813d4838c3", size = 56748, upload-time = "2026-03-27T15:57:05.751Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/e1/342c4434df56aa537f6ce7647eefee521d96fbb828b08acd709865767652/setuptools_scm-10.0.5-py3-none-any.whl", hash = "sha256:f611037d8aae618221503b8fa89319f073438252ae3420e01c9ceec249131a0a", size = 21695, upload-time = "2026-03-27T15:57:03.969Z" },
+]
+
[[package]]
name = "tomli"
version = "2.4.1"
@@ -667,6 +735,20 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
+[[package]]
+name = "vcs-versioning"
+version = "1.1.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "packaging" },
+ { name = "tomli", marker = "python_full_version < '3.11'" },
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/49/42/d97a7795055677961c63a1eef8e7b19d5968ed992ed3a70ab8eb012efad8/vcs_versioning-1.1.1.tar.gz", hash = "sha256:fabd75a3cab7dd8ac02fe24a3a9ba936bf258667b5a62ed468c9a1da0f5775bc", size = 97575, upload-time = "2026-03-27T20:42:41.613Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e6/60/73603fbcdbe5e803855bcce4414f94eaeed449083bd8183e67161af78188/vcs_versioning-1.1.1-py3-none-any.whl", hash = "sha256:b541e2ba79fc6aaa3850f8a7f88af43d97c1c80649c01142ee4146eddbc599e4", size = 79851, upload-time = "2026-03-27T20:42:40.45Z" },
+]
+
[[package]]
name = "zensical"
version = "0.0.30"