polybench 0.2.0__tar.gz → 0.3.0__tar.gz

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.
Files changed (43) hide show
  1. {polybench-0.2.0 → polybench-0.3.0}/LICENSE +1 -1
  2. polybench-0.3.0/PKG-INFO +210 -0
  3. {polybench-0.2.0 → polybench-0.3.0}/README.md +59 -22
  4. {polybench-0.2.0 → polybench-0.3.0}/polybench/main.py +69 -12
  5. {polybench-0.2.0 → polybench-0.3.0}/polybench/plot.py +1 -1
  6. {polybench-0.2.0 → polybench-0.3.0}/polybench/poly.py +21 -6
  7. {polybench-0.2.0 → polybench-0.3.0}/polybench/solver.py +16 -4
  8. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/__init__.py +3 -1
  9. polybench-0.3.0/polybench/solvers/flint/CMakeLists.txt +27 -0
  10. polybench-0.3.0/polybench/solvers/flint/cmake/init-vcpkg.cmake +32 -0
  11. polybench-0.3.0/polybench/solvers/flint/main.c +267 -0
  12. polybench-0.3.0/polybench/solvers/flint/vcpkg.json +12 -0
  13. polybench-0.3.0/polybench/solvers/flint/version.h.in +6 -0
  14. polybench-0.3.0/polybench/solvers/flint.py +61 -0
  15. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/form.py +3 -3
  16. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/reform/Cargo.toml +1 -1
  17. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/reform.py +1 -1
  18. polybench-0.3.0/polybench/solvers/symbolica/Cargo.lock +629 -0
  19. polybench-0.3.0/polybench/solvers/symbolica/Cargo.toml +8 -0
  20. polybench-0.3.0/polybench/solvers/symbolica/src/main.rs +104 -0
  21. polybench-0.3.0/polybench/solvers/symbolica.py +53 -0
  22. {polybench-0.2.0 → polybench-0.3.0}/pyproject.toml +36 -17
  23. polybench-0.2.0/PKG-INFO +0 -165
  24. polybench-0.2.0/setup.py +0 -59
  25. {polybench-0.2.0 → polybench-0.3.0}/polybench/__init__.py +0 -0
  26. {polybench-0.2.0 → polybench-0.3.0}/polybench/__main__.py +0 -0
  27. {polybench-0.2.0 → polybench-0.3.0}/polybench/prob.py +0 -0
  28. {polybench-0.2.0 → polybench-0.3.0}/polybench/py.typed +0 -0
  29. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/fer.py +0 -0
  30. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/mma.py +0 -0
  31. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/reform/Cargo.lock +0 -0
  32. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/reform/src/main.rs +0 -0
  33. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/build.gradle +0 -0
  34. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/config/greclipse.properties +0 -0
  35. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/gradle/wrapper/gradle-wrapper.jar +0 -0
  36. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/gradle/wrapper/gradle-wrapper.properties +0 -0
  37. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/gradlew +0 -0
  38. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/gradlew.bat +0 -0
  39. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings/src/main/java/com/github/tueda/polybench/rings/App.java +0 -0
  40. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/rings.py +0 -0
  41. {polybench-0.2.0 → polybench-0.3.0}/polybench/solvers/singular.py +0 -0
  42. {polybench-0.2.0 → polybench-0.3.0}/polybench/util.py +0 -0
  43. {polybench-0.2.0 → polybench-0.3.0}/polybench/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020-2021 Takahiro Ueda
3
+ Copyright (c) 2020-2024 Takahiro Ueda
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.1
2
+ Name: polybench
3
+ Version: 0.3.0
4
+ Summary: Multivariate polynomial arithmetic benchmark tests.
5
+ Home-page: https://github.com/tueda/polybench
6
+ License: MIT
7
+ Keywords: benchmark,mathematics,multivariate-polynomials
8
+ Author: Takahiro Ueda
9
+ Author-email: t.ueda.od@juntendo.ac.jp
10
+ Requires-Python: >=3.6.1,<4.0.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
23
+ Classifier: Topic :: System :: Benchmark
24
+ Requires-Dist: colorama (>=0.4.5,<0.5.0)
25
+ Requires-Dist: colorlog (>=6.8.2,<7.0.0)
26
+ Requires-Dist: importlib-metadata (>=4.8.3,<5.0.0)
27
+ Requires-Dist: importlib-resources (>=5.4.0,<6.0.0)
28
+ Requires-Dist: kiwisolver (>=1.3.1,<1.4.0) ; python_full_version >= "3.6.1" and python_full_version < "3.7.0"
29
+ Requires-Dist: kiwisolver (>=1.4.5,<2.0.0) ; python_version >= "3.7" and python_version < "3.13"
30
+ Requires-Dist: matplotlib (>=3.3.4,<3.4.0) ; python_full_version >= "3.6.1" and python_full_version < "3.7.0"
31
+ Requires-Dist: matplotlib (>=3.5.3,<3.6.0) ; python_version >= "3.7" and python_version < "3.11"
32
+ Requires-Dist: matplotlib (>=3.9.0,<4.0.0) ; python_version >= "3.11" and python_version < "3.13"
33
+ Requires-Dist: numpy (>=1.19.5,<1.20.0) ; python_full_version >= "3.6.1" and python_full_version < "3.7.0"
34
+ Requires-Dist: numpy (>=1.21.6,<1.22.0) ; python_version >= "3.7" and python_version < "3.11"
35
+ Requires-Dist: numpy (>=2.0.0,<3.0.0) ; python_version >= "3.11" and python_version < "3.13"
36
+ Requires-Dist: pandas (>=1.1.5,<1.2.0) ; python_full_version >= "3.6.1" and python_full_version < "3.7.1"
37
+ Requires-Dist: pandas (>=1.3.5,<1.4.0) ; python_full_version >= "3.7.1" and python_version < "3.11"
38
+ Requires-Dist: pandas (>=2.2.2,<3.0.0) ; python_version >= "3.11" and python_version < "3.13"
39
+ Requires-Dist: pretty-errors (>=1.2.25,<2.0.0)
40
+ Requires-Dist: psutil (>=6.0.0,<7.0.0)
41
+ Requires-Dist: py-cpuinfo (>=9.0.0,<10.0.0)
42
+ Requires-Dist: symengine (>=0.10.0,<0.11.0) ; python_version >= "3.7" and python_version < "3.8"
43
+ Requires-Dist: symengine (>=0.11.0,<0.12.0) ; python_version >= "3.8" and python_version < "3.13"
44
+ Requires-Dist: symengine (>=0.8.1,<0.9.0) ; python_full_version >= "3.6.1" and python_full_version < "3.7.0"
45
+ Requires-Dist: toml (>=0.10.2,<0.11.0)
46
+ Requires-Dist: typing-extensions (>=4.1.1,<5.0.0)
47
+ Project-URL: Repository, https://github.com/tueda/polybench
48
+ Description-Content-Type: text/markdown
49
+
50
+ polybench
51
+ =========
52
+
53
+ [![Test](https://github.com/tueda/polybench/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/tueda/polybench/actions?query=branch:master)
54
+ [![PyPI version](https://badge.fury.io/py/polybench.svg)](https://pypi.org/project/polybench/)
55
+
56
+ Multivariate polynomial arithmetic benchmark tests.
57
+
58
+ Many scientific and engineering applications utilise multivariate polynomial
59
+ arithmetic in their algorithms and solutions. Here we provide a set of
60
+ benchmark tests for often-used operations in multivariate polynomial
61
+ arithmetic:
62
+
63
+ - Greatest common divisor
64
+ - Factorisation
65
+
66
+
67
+ Requirements
68
+ ------------
69
+
70
+ - [Python](https://www.python.org/) >= 3.6.1
71
+
72
+ You also need at least one or more tools to be benchmarked.
73
+ They are (in alphabetical order):
74
+
75
+ - [Fermat](https://home.bway.net/lewis/)
76
+ - [FLINT](https://flintlib.org/): automatically downloaded via [vcpkg](https://vcpkg.io/)
77
+ (requires [CMake](https://cmake.org/) >= 3.15, a C compiler and the Make utility).
78
+ - [FORM](https://www.nikhef.nl/~form/):
79
+ if not available in the system, then
80
+ a [release binary](https://github.com/vermaseren/form/releases)
81
+ will be automatically downloaded.
82
+ - [Mathematica](https://www.wolfram.com/mathematica/):
83
+ indeed, [Free Wolfram Engine for Developers](https://www.wolfram.com/engine/) is sufficient to run.
84
+ - [reFORM](https://reform.readthedocs.io/en/latest/):
85
+ automatically downloaded
86
+ (requires [Rust](https://www.rust-lang.org/) >= 1.36).
87
+ - [Rings](https://rings.readthedocs.io/en/latest/):
88
+ automatically downloaded
89
+ (requires [JDK](https://www.oracle.com/technetwork/java/) >= 8).
90
+ - [Singular](https://www.singular.uni-kl.de/)
91
+ - [Symbolica](https://symbolica.io/):
92
+ automatically downloaded
93
+ (requires [Rust](https://www.rust-lang.org/) >= 1.73),
94
+ running in [restricted mode](https://symbolica.io/docs/get_started.html#license).
95
+
96
+
97
+ Getting started
98
+ ---------------
99
+
100
+ Clone this repository and try to run the `run.sh` script:
101
+
102
+ ```sh
103
+ git clone https://github.com/tueda/polybench.git
104
+ cd polybench
105
+ ./run.sh --all
106
+ ```
107
+
108
+ When starting the script for the first time, it automatically sets up
109
+ a virtual environment for required Python packages so that it will not dirty
110
+ your environment. Some of the tools are provided as libraries registered in
111
+ public package registries, so the first run takes some time to download,
112
+ compile and link them with test binaries. After testing, a CSV file and
113
+ comparison plots will be generated.
114
+
115
+ For practical benchmarking, configuration parameters should be set
116
+ adequately. See the help message shown by
117
+
118
+ ```sh
119
+ ./run.sh --help
120
+ ```
121
+
122
+ You can also use [pip](https://pip.pypa.io/en/stable/),
123
+ [pipx](https://pipxproject.github.io/pipx/),
124
+ [Poetry](https://python-poetry.org/)
125
+ or [Docker](https://www.docker.com/) with this repository.
126
+ Installation with `pip(x) install` or `poetry install` makes a command
127
+ `polybench` available, which acts as the `run.sh` script described above.
128
+ ```sh
129
+ pip install polybench
130
+ polybench --all
131
+ python -m polybench --all # alternative way to launch
132
+ ```
133
+ ```sh
134
+ pipx install polybench
135
+ polybench --all
136
+ ```
137
+ ```sh
138
+ git clone https://github.com/tueda/polybench.git
139
+ cd polybench
140
+ poetry install
141
+ poetry run polybench --all
142
+ ```
143
+ ```sh
144
+ docker build -t polybench:latest https://github.com/tueda/polybench.git
145
+ docker run -it --rm polybench:latest
146
+ ./run.sh --all
147
+ ```
148
+
149
+
150
+ Example
151
+ -------
152
+
153
+ | | |
154
+ |----------------|------------------------------------------------------------------------------|
155
+ | platform | Linux-5.15.0-84-generic-x86_64-with-glibc2.29 |
156
+ | python_version | 3.8.10.final.0 (64 bit) |
157
+ | cpu_brand | 12th Gen Intel(R) Core(TM) i9-12900 |
158
+ | cpu_count | 16 (logical: 24) |
159
+ | total_memory | 62.6GB |
160
+ | FLINT | flint 2.9.0, cc (GNU) 10.5.0 |
161
+ | FORM | FORM 4.3.1 (Apr 11 2023, v4.3.1) 64-bits |
162
+ | Mathematica | 14.1.0 for Linux x86 (64-bit) (July 22, 2024) |
163
+ | reFORM | 0.1.0-fix-serialize, rustc 1.81.0 (eeb90cda1 2024-09-04) |
164
+ | Rings | 2.5.8, JVM: 11.0.20.1 (Ubuntu 11.0.20.1+1-post-Ubuntu-0ubuntu120.04) |
165
+ | Singular | Singular for x86_64-Linux version 4.4.0 (44002, 64 bit) May 29 2024 14:14:10 |
166
+ | Symbolica | 0.11.0, rustc 1.81.0 (eeb90cda1 2024-09-04) |
167
+
168
+ ![nontrivial-gcd](https://raw.githubusercontent.com/tueda/polybench-result/refs/heads/main/0.3.0/05/0002.figures/summary.png)
169
+
170
+ ![nontrivial-factor](https://raw.githubusercontent.com/tueda/polybench-result/refs/heads/main/0.3.0/05/0004.figures/summary.png)
171
+
172
+ Additional benchmark results are available [here](https://github.com/tueda/polybench-result/tree/main).
173
+
174
+
175
+ Development
176
+ -----------
177
+
178
+ ```bash
179
+ # Initialisation
180
+ poetry install
181
+ pre-commit install
182
+
183
+ # Linting and testing
184
+ pre-commit run --all-files
185
+ poetry run pytest
186
+
187
+ # Linting and testing for Cargo subproject
188
+ cd path/to/project
189
+ cargo fmt
190
+ cargo clippy
191
+ cargo test
192
+
193
+ # Linting and testing for Gradle subproject
194
+ cd path/to/project
195
+ ./gradlew spotlessApply
196
+ ./gradlew check
197
+
198
+ # Test run
199
+ ./run.sh <options> # for example, --all
200
+
201
+ # Release a new version
202
+ ./scripts/make-release.sh <new_version> # for example, 0.3.0rc1
203
+ ```
204
+
205
+
206
+ License
207
+ -------
208
+
209
+ [MIT](https://github.com/tueda/polybench/blob/master/LICENSE)
210
+
@@ -1,9 +1,8 @@
1
1
  polybench
2
2
  =========
3
3
 
4
- [![Test](https://github.com/tueda/polybench/workflows/Test/badge.svg?branch=master)](https://github.com/tueda/polybench/actions?query=branch:master)
4
+ [![Test](https://github.com/tueda/polybench/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/tueda/polybench/actions?query=branch:master)
5
5
  [![PyPI version](https://badge.fury.io/py/polybench.svg)](https://pypi.org/project/polybench/)
6
- [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/tueda/polybench.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/tueda/polybench/context:python)
7
6
 
8
7
  Multivariate polynomial arithmetic benchmark tests.
9
8
 
@@ -25,6 +24,8 @@ You also need at least one or more tools to be benchmarked.
25
24
  They are (in alphabetical order):
26
25
 
27
26
  - [Fermat](https://home.bway.net/lewis/)
27
+ - [FLINT](https://flintlib.org/): automatically downloaded via [vcpkg](https://vcpkg.io/)
28
+ (requires [CMake](https://cmake.org/) >= 3.15, a C compiler and the Make utility).
28
29
  - [FORM](https://www.nikhef.nl/~form/):
29
30
  if not available in the system, then
30
31
  a [release binary](https://github.com/vermaseren/form/releases)
@@ -34,10 +35,14 @@ They are (in alphabetical order):
34
35
  - [reFORM](https://reform.readthedocs.io/en/latest/):
35
36
  automatically downloaded
36
37
  (requires [Rust](https://www.rust-lang.org/) >= 1.36).
37
- - [Rings](https://ringsalgebra.io/):
38
+ - [Rings](https://rings.readthedocs.io/en/latest/):
38
39
  automatically downloaded
39
40
  (requires [JDK](https://www.oracle.com/technetwork/java/) >= 8).
40
41
  - [Singular](https://www.singular.uni-kl.de/)
42
+ - [Symbolica](https://symbolica.io/):
43
+ automatically downloaded
44
+ (requires [Rust](https://www.rust-lang.org/) >= 1.73),
45
+ running in [restricted mode](https://symbolica.io/docs/get_started.html#license).
41
46
 
42
47
 
43
48
  Getting started
@@ -96,25 +101,57 @@ docker run -it --rm polybench:latest
96
101
  Example
97
102
  -------
98
103
 
99
- | | |
100
- |----------------|-----------------------------------------------------------------|
101
- | platform | Linux-3.10.0-957.21.3.el7.x86_64-x86_64-with-glibc2.23 |
102
- | python_version | 3.9.9.final.0 (64 bit) |
103
- | cpu_brand | Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz |
104
- | cpu_count | 40 |
105
- | total_memory | 754.6GB |
106
- | FORM | FORM 4.2.1 (Nov 21 2018, v4.2.1) 64-bits |
107
- | Mathematica | 13.0.0 for Linux x86 (64-bit) (December 10, 2021) |
108
- | reFORM | 0.1.0-fix-serialize, rustc 1.56.1 |
109
- | Rings | 2.5.8, JVM: 17.0.1 (Homebrew 17.0.1+1) |
110
- | Singular | Singular for x86_64-Linux version 4.2.1 (4210, 64 bit) May 2021 |
111
-
112
- ![nontrivial-gcd](https://github.com/tueda/polybench-result/raw/b31989da7eef19faf127bac177ad8d89a7e51e2c/0.2.0/0002.figures/summary.png)
113
-
114
- ![nontrivial-gcd](https://github.com/tueda/polybench-result/raw/b31989da7eef19faf127bac177ad8d89a7e51e2c/0.2.0/0004.figures/summary.png)
115
-
116
- ReFORM has no factorization functionality.
117
- Mathematica exceeded the timeout of 60 minutes for the "nontrivial-factor" test.
104
+ | | |
105
+ |----------------|------------------------------------------------------------------------------|
106
+ | platform | Linux-5.15.0-84-generic-x86_64-with-glibc2.29 |
107
+ | python_version | 3.8.10.final.0 (64 bit) |
108
+ | cpu_brand | 12th Gen Intel(R) Core(TM) i9-12900 |
109
+ | cpu_count | 16 (logical: 24) |
110
+ | total_memory | 62.6GB |
111
+ | FLINT | flint 2.9.0, cc (GNU) 10.5.0 |
112
+ | FORM | FORM 4.3.1 (Apr 11 2023, v4.3.1) 64-bits |
113
+ | Mathematica | 14.1.0 for Linux x86 (64-bit) (July 22, 2024) |
114
+ | reFORM | 0.1.0-fix-serialize, rustc 1.81.0 (eeb90cda1 2024-09-04) |
115
+ | Rings | 2.5.8, JVM: 11.0.20.1 (Ubuntu 11.0.20.1+1-post-Ubuntu-0ubuntu120.04) |
116
+ | Singular | Singular for x86_64-Linux version 4.4.0 (44002, 64 bit) May 29 2024 14:14:10 |
117
+ | Symbolica | 0.11.0, rustc 1.81.0 (eeb90cda1 2024-09-04) |
118
+
119
+ ![nontrivial-gcd](https://raw.githubusercontent.com/tueda/polybench-result/refs/heads/main/0.3.0/05/0002.figures/summary.png)
120
+
121
+ ![nontrivial-factor](https://raw.githubusercontent.com/tueda/polybench-result/refs/heads/main/0.3.0/05/0004.figures/summary.png)
122
+
123
+ Additional benchmark results are available [here](https://github.com/tueda/polybench-result/tree/main).
124
+
125
+
126
+ Development
127
+ -----------
128
+
129
+ ```bash
130
+ # Initialisation
131
+ poetry install
132
+ pre-commit install
133
+
134
+ # Linting and testing
135
+ pre-commit run --all-files
136
+ poetry run pytest
137
+
138
+ # Linting and testing for Cargo subproject
139
+ cd path/to/project
140
+ cargo fmt
141
+ cargo clippy
142
+ cargo test
143
+
144
+ # Linting and testing for Gradle subproject
145
+ cd path/to/project
146
+ ./gradlew spotlessApply
147
+ ./gradlew check
148
+
149
+ # Test run
150
+ ./run.sh <options> # for example, --all
151
+
152
+ # Release a new version
153
+ ./scripts/make-release.sh <new_version> # for example, 0.3.0rc1
154
+ ```
118
155
 
119
156
 
120
157
  License
@@ -12,7 +12,7 @@ import sys
12
12
  import time
13
13
  from collections import OrderedDict
14
14
  from pathlib import Path
15
- from typing import Any, Callable, List, Optional, Sequence, Set, Tuple, cast
15
+ from typing import Any, Callable, List, NamedTuple, Optional, Sequence, Set, cast
16
16
 
17
17
  import colorama
18
18
  import cpuinfo
@@ -110,6 +110,14 @@ def prepare_solvers(
110
110
  return tuple(available_solvers)
111
111
 
112
112
 
113
+ class SolverResult(NamedTuple):
114
+ """Result from a solver."""
115
+
116
+ name: str
117
+ res: Sequence[Result]
118
+ output_dir: Path
119
+
120
+
113
121
  def run_solvers(
114
122
  solvers: Sequence[Solver],
115
123
  problems: ProblemSet,
@@ -140,14 +148,15 @@ def run_solvers(
140
148
  if len(times) == 1:
141
149
  return f" ({times[0]:.3f} sec)"
142
150
  mean = statistics.mean(times)
143
- stdev = statistics.stdev(times)
151
+ stdev = statistics.stdev(times, mean)
144
152
  max_t, max_i = max((t, i) for i, t in enumerate(times))
145
153
  return (
146
- f" (average: {mean:.3f} +- {stdev:.3f} sec,"
147
- f" slowest: {max_t:.3f} sec on {max_i + 1 + n_warmups})"
154
+ f" (mean: {mean:.3f} sec,"
155
+ f" SD: {stdev:.3f} sec,"
156
+ f" slowest: {max_t:.3f} sec on Prob. {max_i + 1 + n_warmups})"
148
157
  )
149
158
 
150
- results: List[Tuple[str, Sequence[Result], Path]] = []
159
+ results: List[SolverResult] = []
151
160
 
152
161
  for s in solvers:
153
162
  s._problem_file = problem_file # Yes, this is ugly.
@@ -155,40 +164,87 @@ def run_solvers(
155
164
  r = s.solve(problems)
156
165
  t2 = time.time()
157
166
  if r and len(r) == len(problems):
158
- results.append((s.name, r, s._output_dir))
167
+ results.append(SolverResult(s.name, r, s._output_dir))
159
168
  s.logger.info(
160
169
  f"{t2 - t1:.3f} sec{get_timing_information(r, problems.n_warmups)}"
161
170
  )
162
171
  else:
163
172
  s.logger.error("failed")
164
173
 
165
- # Check the consistency.
174
+ # Check the consistency of the obtained results.
166
175
 
167
176
  check_logger = logger.getChild("Check")
168
177
 
169
178
  wrong: Set[str] = set()
170
179
 
180
+ def count_factors(pp: Sequence[Polynomial]) -> int:
181
+ n = 0
182
+ m = 0
183
+ for p in pp:
184
+ n_terms = len(p)
185
+ if n_terms == 0:
186
+ return 0
187
+ elif n_terms == 1:
188
+ if not p.is_unit:
189
+ m += 1
190
+ else:
191
+ n += 1
192
+ if m >= 1:
193
+ n += 1
194
+ return n
195
+
171
196
  if problems.problem_type == "gcd":
197
+ # The GCD must be given as a single polynomial.
198
+ for name, res, _ in results:
199
+ for i, ri in enumerate(res):
200
+ if len(ri.answer) != 1:
201
+ check_logger.error(f"{name}:{i + 1}: wrong answer")
202
+ wrong.add(name)
203
+ # The GCD must be the same up to a multiplicative unit.
172
204
  if len(results) >= 2:
173
205
  for i in range(len(problems)):
174
- p0 = results[0][1][i].answer[0]
206
+ pp0 = results[0].res[i].answer
207
+ if len(pp0) != 1:
208
+ continue
209
+ p0 = pp0[0]
175
210
  for j in range(1, len(results)):
176
- pj = results[j][1][i].answer[0]
211
+ ppj = results[j].res[i].answer
212
+ if len(ppj) != 1:
213
+ continue
214
+ pj = ppj[0]
177
215
  if not p0.equals_without_unit(pj):
178
- name0 = results[0][0]
179
- namej = results[j][0]
216
+ name0 = results[0].name
217
+ namej = results[j].name
180
218
  check_logger.error(
181
219
  f"{name0}:{namej}:{i + 1}: inconsistent answers"
182
220
  )
183
221
  wrong.add(name0)
184
222
  wrong.add(namej)
185
223
  elif problems.problem_type == "factor":
224
+ # The product of the factorized polynomials must equal the original polynomial.
186
225
  for name, res, _ in results:
187
226
  for i, ri in enumerate(res):
188
227
  product = functools.reduce(operator.mul, ri.answer, Polynomial(1))
189
228
  if problems[i].p != product:
190
229
  check_logger.error(f"{name}:{i + 1}: wrong answer")
191
230
  wrong.add(name)
231
+ # The number of factorized polynomials must match,
232
+ # excluding any single-term polynomials.
233
+ if len(results) >= 2:
234
+ for i in range(len(problems)):
235
+ pp0 = results[0].res[i].answer
236
+ n0 = count_factors(pp0)
237
+ for j in range(1, len(results)):
238
+ ppj = results[j].res[i].answer
239
+ nj = count_factors(ppj)
240
+ if n0 != nj:
241
+ name0 = results[0].name
242
+ namej = results[j].name
243
+ check_logger.error(
244
+ f"{name0}:{namej}:{i + 1}: inconsistent answers"
245
+ )
246
+ wrong.add(name0)
247
+ wrong.add(namej)
192
248
 
193
249
  # Remove the solver's output directory only if succeeded.
194
250
 
@@ -316,7 +372,7 @@ def main(
316
372
  )
317
373
  parser.add_argument(
318
374
  "--max-coeff",
319
- default=2 ** 14,
375
+ default=2**14,
320
376
  type=int,
321
377
  help="set the maximum coefficient (default: 2^14)",
322
378
  metavar="N",
@@ -502,6 +558,7 @@ def main(
502
558
 
503
559
  if debug:
504
560
  logger.setLevel(logging.DEBUG)
561
+ Solver.debug = True
505
562
  else:
506
563
  logger.setLevel(logging.INFO)
507
564
 
@@ -1,4 +1,4 @@
1
- """Routines for making comaprsion plots."""
1
+ """Routines for making comparison plots."""
2
2
 
3
3
  import itertools
4
4
  from pathlib import Path
@@ -13,7 +13,7 @@ class Polynomial:
13
13
  def __init__(self, expr: Union[str, int, "Polynomial"] = 0) -> None:
14
14
  """Construct a polynomial."""
15
15
  if isinstance(expr, str):
16
- p = symengine.sympify(expr.lstrip("+")) # symengine/symengine.py#331
16
+ p = symengine.sympify(expr)
17
17
  self._raw = symengine.expand(p)
18
18
  elif isinstance(expr, int):
19
19
  self._raw = symengine.sympify(expr)
@@ -28,7 +28,17 @@ class Polynomial:
28
28
 
29
29
  def __bool__(self) -> bool:
30
30
  """Return ``bool(self)``."""
31
- return self._raw != 0 # type: ignore
31
+ return not self._raw.is_zero
32
+
33
+ def __len__(self) -> int:
34
+ """Return the number of terms in the polynomial."""
35
+ raw = self._raw
36
+ if raw.is_Add:
37
+ return len(raw.args)
38
+ elif raw.is_zero:
39
+ return 0
40
+ else:
41
+ return 1
32
42
 
33
43
  def __eq__(self, other: object) -> bool:
34
44
  """Return ``self == other``."""
@@ -46,26 +56,31 @@ class Polynomial:
46
56
  """Return ``- self``."""
47
57
  result = super().__new__(Polynomial)
48
58
  result._raw = symengine.expand(-self._raw)
49
- return result # type: ignore
59
+ return result
50
60
 
51
61
  def __add__(self, other: "Polynomial") -> "Polynomial":
52
62
  """Return ``self + other``."""
53
63
  result = super().__new__(Polynomial)
54
64
  result._raw = symengine.expand(self._raw + other._raw)
55
- return result # type: ignore
65
+ return result
56
66
 
57
67
  def __sub__(self, other: "Polynomial") -> "Polynomial":
58
68
  """Return ``self - other``."""
59
69
  result = super().__new__(Polynomial)
60
70
  result._raw = symengine.expand(self._raw - other._raw)
61
- return result # type: ignore
71
+ return result
62
72
 
63
73
  def __mul__(self, other: "Polynomial") -> "Polynomial":
64
74
  """Return ``self * other``."""
65
75
  result = super().__new__(Polynomial)
66
76
  result._raw = symengine.expand(self._raw * other._raw)
67
- return result # type: ignore
77
+ return result
68
78
 
69
79
  def equals_without_unit(self, other: "Polynomial") -> bool:
70
80
  """Return `True` if ``self == other`` up to a unit."""
71
81
  return self == other or self == -other
82
+
83
+ @property
84
+ def is_unit(self) -> bool:
85
+ """True if the polynomial is 1 or -1."""
86
+ return len(self) == 1 and (self == 1 or self == -1)
@@ -30,6 +30,8 @@ class Result(NamedTuple):
30
30
  class Solver:
31
31
  """Abstract solver."""
32
32
 
33
+ debug = False
34
+
33
35
  # Things that must be overridden in subclasses.
34
36
 
35
37
  _name = "None" # Must be a unique name (without spaces).
@@ -44,8 +46,8 @@ class Solver:
44
46
 
45
47
  def _solve(self, problems: ProblemSet) -> Optional[Sequence[Result]]:
46
48
  # Solve the given problems and return the results. If the underlying executable
47
- # has a programming langauge that is versatile enough, then the easiest way is
48
- # to generate a program in the langauge that creates a CSV file for the results
49
+ # has a programming language that is versatile enough, then the easiest way is
50
+ # to generate a program in the language that creates a CSV file for the results
49
51
  # and use `parse_csv_log` (example: `MathematicaSolver`). When this method is
50
52
  # called, the current working directory is set to `output_dir` and
51
53
  # `problem_file` is accessible. One can also use files in `build_dir`.
@@ -170,11 +172,16 @@ class Solver:
170
172
  new_args = [str(args)]
171
173
 
172
174
  try:
175
+ if self.debug:
176
+ redirect = None
177
+ else:
178
+ redirect = subprocess.DEVNULL
179
+
173
180
  p = subprocess.run( # noqa: S603
174
181
  new_args,
175
182
  input=input,
176
- stdout=subprocess.PIPE if capture_output else subprocess.DEVNULL,
177
- stderr=subprocess.DEVNULL,
183
+ stdout=subprocess.PIPE if capture_output else redirect,
184
+ stderr=redirect,
178
185
  universal_newlines=True,
179
186
  timeout=timeout,
180
187
  )
@@ -297,6 +304,11 @@ class Solver:
297
304
  dest_dir.mkdir(parents=True, exist_ok=True)
298
305
  shutil.copy2(p, q)
299
306
 
307
+ @property
308
+ def cmake_command(self) -> Sequence[str]:
309
+ """Return the CMake command."""
310
+ return [shutil.which("cmake") or "cmake"]
311
+
300
312
  @property
301
313
  def gradlew_command(self) -> Sequence[str]:
302
314
  """Return the gradlew command."""
@@ -6,5 +6,7 @@ from pkgutil import iter_modules
6
6
 
7
7
  # Load all modules.
8
8
 
9
- for (_, module_name, _) in iter_modules([str(Path(__file__).resolve().parent)]):
9
+ for _, module_name, _ in iter_modules( # type: ignore[assignment]
10
+ [str(Path(__file__).resolve().parent)]
11
+ ):
10
12
  import_module(f"{__name__}.{module_name}")
@@ -0,0 +1,27 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ include(cmake/init-vcpkg.cmake)
3
+ project(
4
+ polybench-flint
5
+ VERSION 0.1.0
6
+ LANGUAGES C)
7
+
8
+ get_filename_component(COMPILER_NAME ${CMAKE_C_COMPILER} NAME_WE)
9
+ set(COMPILER_VERSION
10
+ "${COMPILER_NAME} (${CMAKE_C_COMPILER_ID}) ${CMAKE_C_COMPILER_VERSION}")
11
+
12
+ configure_file(${CMAKE_SOURCE_DIR}/version.h.in ${CMAKE_BINARY_DIR}/version.h
13
+ @ONLY)
14
+
15
+ find_package(PkgConfig REQUIRED)
16
+ pkg_check_modules(gmp REQUIRED IMPORTED_TARGET gmp)
17
+ pkg_check_modules(mpfr REQUIRED IMPORTED_TARGET mpfr)
18
+
19
+ find_path(FLINT_INCLUDE_DIR flint/flint.h)
20
+ find_library(FLINT_LIBRARY flint)
21
+
22
+ add_executable(polybench-flint main.c)
23
+
24
+ target_include_directories(polybench-flint PRIVATE ${FLINT_INCLUDE_DIR}
25
+ ${CMAKE_BINARY_DIR})
26
+ target_link_libraries(polybench-flint PRIVATE m PkgConfig::gmp PkgConfig::mpfr
27
+ ${FLINT_LIBRARY})