ppapp 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ppapp/__init__.py +58 -0
- ppapp/__main__.py +6 -0
- ppapp/cheb_coeffs.py +231 -0
- ppapp/demo_functions/__init__.py +20 -0
- ppapp/demo_functions/erfcx.py +47 -0
- ppapp/demo_functions/imwofx.py +47 -0
- ppapp/demo_functions/polynomial.py +51 -0
- ppapp/demo_functions/voigt_hwhm.py +139 -0
- ppapp/docs/userManual.pdf +0 -0
- ppapp/ppapp.py +704 -0
- ppapp/target_algorithm.py +90 -0
- ppapp-1.0.0.dist-info/METADATA +171 -0
- ppapp-1.0.0.dist-info/RECORD +21 -0
- ppapp-1.0.0.dist-info/WHEEL +5 -0
- ppapp-1.0.0.dist-info/entry_points.txt +2 -0
- ppapp-1.0.0.dist-info/licenses/LICENSE +674 -0
- ppapp-1.0.0.dist-info/top_level.txt +3 -0
- tests/__init__.py +1 -0
- tests/test_app.py +374 -0
- userManual/userManual.pdf +0 -0
- userManual/userManual.tex +368 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Target algorithm for piecewise polynomial evaluation.
|
|
5
|
+
|
|
6
|
+
This script demonstrates the algorithm that evaluates a piecewise polynomial
|
|
7
|
+
approximation using Horner's method. It shows how to:
|
|
8
|
+
- Find the subdomain containing a given x
|
|
9
|
+
- Transform x to the local coordinate t in [-1, 1]
|
|
10
|
+
- Evaluate the polynomial using Horner's method
|
|
11
|
+
|
|
12
|
+
IMPORTANT: This plain Python implementation is for illustration only.
|
|
13
|
+
Project ppapp is designed to generate C code for optimized high-throughput
|
|
14
|
+
computation. For production use from Python, the evaluation code should be
|
|
15
|
+
implemented as a C extension module or at least use NumPy for vectorized
|
|
16
|
+
operations. Do not use this script as a template for production code.
|
|
17
|
+
|
|
18
|
+
Run with:
|
|
19
|
+
python -m ppapp.target_algorithm
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from ppapp import cheb_pm, compute_subdomains, ref_f, set_reference_function
|
|
23
|
+
from ppapp.demo_functions.imwofx import my_arb_f, my_domain
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def find_subdomain(x: float, subdomains) -> int:
|
|
27
|
+
"""Find the subdomain index containing x."""
|
|
28
|
+
for i, d in enumerate(subdomains):
|
|
29
|
+
if d.a <= x < d.b:
|
|
30
|
+
return i
|
|
31
|
+
# x might equal the last boundary
|
|
32
|
+
if subdomains and x == subdomains[-1].b:
|
|
33
|
+
return len(subdomains) - 1
|
|
34
|
+
raise ValueError(f"x={x} not in any subdomain")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def horner_eval(coeffs: list[float], t: float) -> float:
|
|
38
|
+
"""Evaluate polynomial using Horner's method."""
|
|
39
|
+
result = coeffs[-1]
|
|
40
|
+
for c in reversed(coeffs[:-1]):
|
|
41
|
+
result = result * t + c
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def main():
|
|
46
|
+
# Set up
|
|
47
|
+
set_reference_function(my_arb_f)
|
|
48
|
+
a, b = my_domain
|
|
49
|
+
M = 5
|
|
50
|
+
N = 10
|
|
51
|
+
|
|
52
|
+
# Compute subdomains and their coefficients
|
|
53
|
+
j0, l0, subdomains = compute_subdomains(a, b, M)
|
|
54
|
+
for d in subdomains:
|
|
55
|
+
d.coeffs = cheb_pm(d.a, d.b, N)
|
|
56
|
+
|
|
57
|
+
# Test points
|
|
58
|
+
test_x = [0.5, 1.0, 2.0, 5.0, 10.0, 11.9]
|
|
59
|
+
|
|
60
|
+
print("Comparing approximation vs reference:")
|
|
61
|
+
print("-" * 70)
|
|
62
|
+
print(f"{'x':>10} {'f_approx':>20} {'f_ref':>20} {'rel_error':>15}")
|
|
63
|
+
print("-" * 70)
|
|
64
|
+
|
|
65
|
+
eps = 2.0 ** -53 # Machine epsilon
|
|
66
|
+
|
|
67
|
+
for x in test_x:
|
|
68
|
+
# Find subdomain
|
|
69
|
+
idx = find_subdomain(x, subdomains)
|
|
70
|
+
d = subdomains[idx]
|
|
71
|
+
|
|
72
|
+
# Transform x to [-1, 1]
|
|
73
|
+
mid = (d.a + d.b) / 2
|
|
74
|
+
half = (d.b - d.a) / 2
|
|
75
|
+
t = (x - mid) / half
|
|
76
|
+
|
|
77
|
+
# Evaluate approximation
|
|
78
|
+
f_approx = horner_eval(d.coeffs, t)
|
|
79
|
+
|
|
80
|
+
# Evaluate reference
|
|
81
|
+
f_ref = ref_f(x)
|
|
82
|
+
|
|
83
|
+
# Relative error in units of epsilon
|
|
84
|
+
rel_err = abs(f_approx - f_ref) / abs(f_ref) / eps
|
|
85
|
+
|
|
86
|
+
print(f"{x:10.4f} {f_approx:20.15f} {f_ref:20.15f} {rel_err:12.2f} eps")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == "__main__":
|
|
90
|
+
main()
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ppapp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Piecewise polynomial approximation: code generator for Chebyshev approximation
|
|
5
|
+
Author-email: Joachim Wuttke <j.wuttke@fz-juelich.de>, Alexander Kleinsorge <alkl9873@th-wildau.de>
|
|
6
|
+
License: GPL-3.0-or-later
|
|
7
|
+
Project-URL: Repository, https://jugit.fz-juelich.de/mlz/ppapp
|
|
8
|
+
Project-URL: Documentation, https://jugit.fz-juelich.de/mlz/ppapp/-/blob/main/py/R/userManual/userManual.pdf
|
|
9
|
+
Keywords: chebyshev,approximation,polynomial,code-generation,numerical
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: python-flint>=0.4.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
27
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# ppapp - Piecewise Polynomial Approximation
|
|
31
|
+
|
|
32
|
+
Code generator for piecewise Chebyshev approximation of mathematical functions.
|
|
33
|
+
|
|
34
|
+
## Overview
|
|
35
|
+
|
|
36
|
+
This package generates C source code containing polynomial coefficients that approximate
|
|
37
|
+
a given function f(x) over a specified domain. The approximation uses piecewise Chebyshev
|
|
38
|
+
polynomials with octave-based domain subdivision for optimal accuracy.
|
|
39
|
+
|
|
40
|
+
**Reference:** Joachim Wuttke and Alexander Kleinsorge,
|
|
41
|
+
"Algorithm 1XXX: Code generation for piecewise Chebyshev approximation"
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install ppapp
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Requirements
|
|
50
|
+
|
|
51
|
+
- Python 3.9+
|
|
52
|
+
- python-flint (for arbitrary-precision arithmetic)
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### Command Line
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Compute a function value
|
|
60
|
+
ppapp v ppapp.demo_functions.imwofx 1.0
|
|
61
|
+
|
|
62
|
+
# Compute error bound for given M and N
|
|
63
|
+
ppapp e ppapp.demo_functions.imwofx 5 10
|
|
64
|
+
|
|
65
|
+
# Generate C source code
|
|
66
|
+
ppapp s ppapp.demo_functions.imwofx 5 10 > coefficients.c
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Using Demo Functions
|
|
70
|
+
|
|
71
|
+
The package includes several demo functions:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Im w(x) = exp(-x^2) * erfi(x)
|
|
75
|
+
ppapp e ppapp.demo_functions.imwofx 5 10
|
|
76
|
+
|
|
77
|
+
# erfcx(x) = exp(x^2) * erfc(x)
|
|
78
|
+
ppapp e ppapp.demo_functions.erfcx 5 10
|
|
79
|
+
|
|
80
|
+
# Polynomial x^3 - x^2 + x - 1
|
|
81
|
+
ppapp e ppapp.demo_functions.polynomial 8 15
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Python API
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
from ppapp import (
|
|
88
|
+
set_reference_function,
|
|
89
|
+
compute_subdomains,
|
|
90
|
+
cheb_pm,
|
|
91
|
+
analyse_row,
|
|
92
|
+
error_bound,
|
|
93
|
+
)
|
|
94
|
+
from ppapp.demo_functions.imwofx import my_arb_f, my_domain
|
|
95
|
+
|
|
96
|
+
# Set the reference function
|
|
97
|
+
set_reference_function(my_arb_f)
|
|
98
|
+
|
|
99
|
+
# Compute subdomains
|
|
100
|
+
a, b = my_domain
|
|
101
|
+
j0, l0, D = compute_subdomains(a, b, M=5)
|
|
102
|
+
|
|
103
|
+
# Compute coefficients for each subdomain
|
|
104
|
+
for d in D:
|
|
105
|
+
d.coeffs = cheb_pm(d.a, d.b, N=10)
|
|
106
|
+
d.s, d.r = analyse_row(d.coeffs)
|
|
107
|
+
err = error_bound(d, N=10)
|
|
108
|
+
print(f"Subdomain [{d.a}, {d.b}): error = {err:.2f} epsilon")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Creating Custom Functions
|
|
112
|
+
|
|
113
|
+
Create a Python module with:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
from flint import arb
|
|
117
|
+
|
|
118
|
+
# Domain [a, b)
|
|
119
|
+
my_domain: tuple[float, float] = (0.5, 12.0)
|
|
120
|
+
|
|
121
|
+
def my_arb_f(X: arb, prec: int) -> arb:
|
|
122
|
+
"""Evaluate f(x) with given precision."""
|
|
123
|
+
# Your implementation here
|
|
124
|
+
return result
|
|
125
|
+
|
|
126
|
+
# Test cases: (x, expected_value, tolerance)
|
|
127
|
+
my_testcases: list[tuple[float, float, float]] = [
|
|
128
|
+
(1.0, 0.123456, 1e-5),
|
|
129
|
+
]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then use it:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
ppapp s path/to/my_function.py 5 10 > output.c
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Modes
|
|
139
|
+
|
|
140
|
+
| Mode | Command | Description |
|
|
141
|
+
|------|---------|-------------|
|
|
142
|
+
| v | `ppapp v <f> <x>` | Compute f(x) |
|
|
143
|
+
| n | `ppapp n <f> <M> <Nmax> <E>` | Find minimal N for error ≤ E |
|
|
144
|
+
| e | `ppapp e <f> <M> <N>` | Compute error bound |
|
|
145
|
+
| c | `ppapp c <f> <M> <N> [E]` | Print Chebyshev coefficients |
|
|
146
|
+
| p | `ppapp p <f> <M> <N> [E]` | Print monomial coefficients |
|
|
147
|
+
| s | `ppapp s <f> <M> <N> [E]` | Generate C source code |
|
|
148
|
+
| t | `ppapp t <f> <M> <Nxo> <E>` | Generate test cases |
|
|
149
|
+
|
|
150
|
+
## Documentation
|
|
151
|
+
|
|
152
|
+
The user manual is included in the package:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from ppapp import get_user_manual_path
|
|
156
|
+
print(get_user_manual_path()) # Path to userManual.pdf
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
GNU General Public License v3 or later (GPLv3+)
|
|
162
|
+
|
|
163
|
+
## Authors
|
|
164
|
+
|
|
165
|
+
- Joachim Wuttke (Forschungszentrum Jülich GmbH)
|
|
166
|
+
- Alexander Kleinsorge (Technische Hochschule Wildau)
|
|
167
|
+
|
|
168
|
+
## Links
|
|
169
|
+
|
|
170
|
+
- [Repository](https://jugit.fz-juelich.de/mlz/ppapp)
|
|
171
|
+
- [Documentation (PDF)](https://jugit.fz-juelich.de/mlz/ppapp/-/blob/main/py/R/userManual/userManual.pdf)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
ppapp/__init__.py,sha256=T7WZdoCZI-ljRhojl-LCU_fmZ_6RJYr0zmSrg95XEB4,1280
|
|
2
|
+
ppapp/__main__.py,sha256=sptjNoySx17mJRZRJ_XBm0vX33DSTZRP4ogZFs-hYx4,140
|
|
3
|
+
ppapp/cheb_coeffs.py,sha256=PztuebJNdy4fQ4GKQou5I71zf73L98m_nfAglNK7ZhM,8699
|
|
4
|
+
ppapp/ppapp.py,sha256=02AzT_fpwF5t0ieEs4SryzmrCXtmytP1dnu8H8QdeqI,23293
|
|
5
|
+
ppapp/target_algorithm.py,sha256=msgZuKdsQgj0cKKaV9RhtYVn274c5KdVsw7LA3TlLAY,2635
|
|
6
|
+
ppapp/demo_functions/__init__.py,sha256=M0EiyXtb05zYNFB6YQJlANJyE0AcBrILhqpddExM2aI,666
|
|
7
|
+
ppapp/demo_functions/erfcx.py,sha256=cZbLzJBMGBmNDOtspsdHKX8qrLrtvAYpYg8KUzfY37w,1305
|
|
8
|
+
ppapp/demo_functions/imwofx.py,sha256=_0ApFx5P189URwEHb1lLrk19sh1gL24iJFEPDUvO8V4,1298
|
|
9
|
+
ppapp/demo_functions/polynomial.py,sha256=UOEZ-y4r_No9epyppHmjBzZA_x4THBdaxp_lf6b_-Z8,1496
|
|
10
|
+
ppapp/demo_functions/voigt_hwhm.py,sha256=ulJimr32u8ZvUH_b_ROt9VUPZwbFQFJ7WHF1F3fCM0Y,3727
|
|
11
|
+
ppapp/docs/userManual.pdf,sha256=wxD14KR37Wuff8IBHc7WfHouHfr2A6fhdfKFqq3QHaA,91907
|
|
12
|
+
ppapp-1.0.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
13
|
+
tests/__init__.py,sha256=I4m6tknsJyCzmLgbzdxpLwvJYdddqPAMZ0erGxkVfX8,31
|
|
14
|
+
tests/test_app.py,sha256=p-itnDWkWPo97OAZCxCdryJcjExEZjJXuWPIHI3FsEo,13084
|
|
15
|
+
userManual/userManual.pdf,sha256=wxD14KR37Wuff8IBHc7WfHouHfr2A6fhdfKFqq3QHaA,91907
|
|
16
|
+
userManual/userManual.tex,sha256=1ntNVjg7mSfFnciEmVIavW7xNQ1Lb1JyZBldTEwdaaY,15397
|
|
17
|
+
ppapp-1.0.0.dist-info/METADATA,sha256=1_-7bLeEPNfpYnU9M_mPknHjC-7rgT_Mmh7P4C4jlEs,4673
|
|
18
|
+
ppapp-1.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
19
|
+
ppapp-1.0.0.dist-info/entry_points.txt,sha256=xlSmZvp-e8xavDq6PRnOv_YMpbyjM0XUSaWL-pzttO4,43
|
|
20
|
+
ppapp-1.0.0.dist-info/top_level.txt,sha256=F1MZGl78sIGn8l3Ykfs6ruNnYQPiC4_vJkgkif90aTI,23
|
|
21
|
+
ppapp-1.0.0.dist-info/RECORD,,
|