# pyAdic
[![CI Lint](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_lint.yml/badge.svg)](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_lint.yml)
[![CI Test](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_test.yml/badge.svg)](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_test.yml)
[![Coverage](https://img.shields.io/badge/Coverage-91%25-green?labelColor=2a2f35)](https://github.com/GDeLaurentis/pyadic/actions)
[![Docs](https://github.com/GDeLaurentis/pyadic/actions/workflows/cd_docs.yml/badge.svg?label=Docs)](https://gdelaurentis.github.io/pyadic/)
[![PyPI](https://img.shields.io/pypi/v/pyadic?label=PyPI)](https://pypi.org/project/pyadic/)
[![PyPI Downloads](https://img.shields.io/pypi/dm/pyadic.svg?label=PyPI%20downloads)](https://pypistats.org/packages/pyadic)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/GDeLaurentis/pyadic/HEAD)
[![DOI](https://zenodo.org/badge/519290930.svg)](https://zenodo.org/doi/10.5281/zenodo.11114230)
[![Python](https://img.shields.io/pypi/pyversions/pyadic?label=Python)](https://pypi.org/project/pyadic/)
The `pyadic` library is Python 3 package that provides number types for finite fields $\mathbb{F}_p$ (`ModP`) and $p$-adic numbers $\mathbb{Q}_p$ (`PAdic`). The goal is to mimic the flexible behavior of built-in types, such as `int`, `float` and `complex`. Thus, one can mix-and-match the different number types, as long as the operations are consistent. In particular, `ModP` and `PAdic` are compatible with `fractions.Fraction`.
In addition to arithmetic operations, the pyadic library also provides the following functions:
- `rationalise` to perform rationalization ($\mathbb{F}_p\rightarrow \mathbb{Q}$ and $\mathbb{Q}_p \rightarrow \mathbb{Q}$);
- `finite_field_sqrt` and `padic_sqrt` to compute square roots (which may involve `FieldExtension`);
- `padic_log` to compute the $p$-adic logarithm.
- polynomial and rational function interpolation, see `interpolation.py` module.
A shout-out to [galois](https://github.com/mhostetter/galois) for a very nice tool. It is recommented for vectorized finite field operations, unless type compatibility is an issue. For scalar operation this repo is recommended. See performance comparison below.
## Installation
The package is available on the [Python Package Index](https://pypi.org/project/pyadic/)
```console
pip install pyadic
```
Alternativelty, it can be installed by cloning the repo
```console
git clone https://github.com/GDeLaurentis/pyadic.git path/to/repo
pip install -e path/to/repo
```
### Requirements
`pip` will automatically install the required packages, which are
```
numpy, sympy
```
Additionally, `pytest` is needed for testing.
### Testing
Extensive tests are implemented with [pytest](https://github.com/pytest-dev/pytest)
```console
pytest --cov pyadic/ --cov-report html tests/ --verbose
```
## Quick Start
```python
In [1]: from pyadic import PAdic, ModP
In [2]: from fractions import Fraction as Q
# 7/13 as a 12-digit 2147483647-adic number
In [3]: PAdic(Q(7, 13), 2147483647, 12)
Out [3]: 1817101548 + 825955248*2147483647 + 1156337348*2147483647^2 + 330382099*2147483647^3 + 1321528398*2147483647^4 + 991146298*2147483647^5 + 1817101547*2147483647^6 + 825955248*2147483647^7 + 1156337348*2147483647^8 + 330382099*2147483647^9 + 1321528398*2147483647^10 + 991146298*2147483647^11 + O(2147483647^12)
# 7/13 in F_2147483647
In [4]: ModP(Q(7, 13), 2147483647)
Out [4]: 1817101548 % 2147483647
# Mapping back to rational numbers
In [5]: from pyadic.finite_field import rationalise
In [6]: rationalise(ModP(Q(7, 13), 2147483647))
Out [6]: Fraction(7, 13)
In [7]: rationalise(PAdic(Q(7, 13), 2147483647, 12))
Out [7]: Fraction(7, 13)
```
## Perfomance comparison with [galois](https://github.com/mhostetter/galois) for finite fields
Scalar instantiation and operations are faster in pyadic
```python
import numpy
from galois import GF
from pyadic import ModP
from random import randint
GFp = GF(2 ** 31 - 1)
x = randint(0, 2 ** 31 - 1)
%timeit GFp(x)
2.84 µs ± 63.5 ns
%timeit ModP(x, 2 ** 31 - 1)
297 ns ± 0.876 ns
%timeit GFp(x) ** 2
30.1 µs ± 20.6 µs
%timeit ModP(x, 2 ** 31 - 1) ** 2
2.23 µs ± 91.8 ns
```
while galois is faster for vectorized operations (the bigger the array the bigger the gain)
```python
%timeit numpy.array([randint(0, 2 ** 31 - 1) for i in range(100)]).view(GFp) ** 2
65.6 µs ± 1.86 µs
%timeit numpy.array([ModP(randint(0, 2 ** 31 - 1), 2 ** 31 - 1) for i in range(100)]) ** 2
351 µs ± 9.28 µs
```
However, galois requires everything to be appropriately typed, while pyadic performs type-casting on-the-fly
```python
numpy.array([randint(0, 2 ** 31 - 1) for i in range(100)]).view(GFp) / 2
TypeError
numpy.array([ModP(randint(0, 2 ** 31 - 1), 2 ** 31 - 1) for i in range(100)]) / 2
array([...], dtype=object)
```
## Citation
If you found this library useful, please consider citing it
```bibtex
@inproceedings{DeLaurentis:2023qhd,
author = "De Laurentis, Giuseppe",
title = "{Lips: $p$-adic and singular phase space}",
booktitle = "{21th International Workshop on Advanced Computing and Analysis Techniques in Physics Research}: {AI meets Reality}",
eprint = "2305.14075",
archivePrefix = "arXiv",
primaryClass = "hep-th",
reportNumber = "PSI-PR-23-14",
month = "5",
year = "2023"
}
```
Raw data
{
"_id": null,
"home_page": "https://github.com/GDeLaurentis/pyadic",
"name": "pyadic",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "p-adic numbers, finite-fields, rational reconstruction",
"author": "Giuseppe De Laurentis",
"author_email": "g.dl@hotmail.it",
"download_url": "https://files.pythonhosted.org/packages/fb/cf/5218e0304979356ab42211a18ca8ec1237a176b78e43ddbd9e6d52d76f56/pyadic-0.2.2.tar.gz",
"platform": null,
"description": "# pyAdic\n\n[![CI Lint](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_lint.yml/badge.svg)](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_lint.yml)\n[![CI Test](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_test.yml/badge.svg)](https://github.com/GDeLaurentis/pyadic/actions/workflows/ci_test.yml)\n[![Coverage](https://img.shields.io/badge/Coverage-91%25-green?labelColor=2a2f35)](https://github.com/GDeLaurentis/pyadic/actions)\n[![Docs](https://github.com/GDeLaurentis/pyadic/actions/workflows/cd_docs.yml/badge.svg?label=Docs)](https://gdelaurentis.github.io/pyadic/)\n[![PyPI](https://img.shields.io/pypi/v/pyadic?label=PyPI)](https://pypi.org/project/pyadic/)\n[![PyPI Downloads](https://img.shields.io/pypi/dm/pyadic.svg?label=PyPI%20downloads)](https://pypistats.org/packages/pyadic)\n[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/GDeLaurentis/pyadic/HEAD)\n[![DOI](https://zenodo.org/badge/519290930.svg)](https://zenodo.org/doi/10.5281/zenodo.11114230)\n[![Python](https://img.shields.io/pypi/pyversions/pyadic?label=Python)](https://pypi.org/project/pyadic/)\n\n\nThe `pyadic` library is Python 3 package that provides number types for finite fields $\\mathbb{F}_p$ (`ModP`) and $p$-adic numbers $\\mathbb{Q}_p$ (`PAdic`). The goal is to mimic the flexible behavior of built-in types, such as `int`, `float` and `complex`. Thus, one can mix-and-match the different number types, as long as the operations are consistent. In particular, `ModP` and `PAdic` are compatible with `fractions.Fraction`.\n\nIn addition to arithmetic operations, the pyadic library also provides the following functions:\n\n- `rationalise` to perform rationalization ($\\mathbb{F}_p\\rightarrow \\mathbb{Q}$ and $\\mathbb{Q}_p \\rightarrow \\mathbb{Q}$);\n- `finite_field_sqrt` and `padic_sqrt` to compute square roots (which may involve `FieldExtension`);\n- `padic_log` to compute the $p$-adic logarithm.\n- polynomial and rational function interpolation, see `interpolation.py` module.\n\nA shout-out to [galois](https://github.com/mhostetter/galois) for a very nice tool. It is recommented for vectorized finite field operations, unless type compatibility is an issue. For scalar operation this repo is recommended. See performance comparison below.\n\n## Installation\nThe package is available on the [Python Package Index](https://pypi.org/project/pyadic/)\n```console\npip install pyadic\n```\nAlternativelty, it can be installed by cloning the repo\n```console\ngit clone https://github.com/GDeLaurentis/pyadic.git path/to/repo\npip install -e path/to/repo\n```\n\n### Requirements\n`pip` will automatically install the required packages, which are\n```\nnumpy, sympy\n```\nAdditionally, `pytest` is needed for testing.\n\n### Testing\nExtensive tests are implemented with [pytest](https://github.com/pytest-dev/pytest)\n\n```console\npytest --cov pyadic/ --cov-report html tests/ --verbose\n```\n\n## Quick Start\n\n```python\nIn [1]: from pyadic import PAdic, ModP\nIn [2]: from fractions import Fraction as Q\n\n# 7/13 as a 12-digit 2147483647-adic number\nIn [3]: PAdic(Q(7, 13), 2147483647, 12) \nOut [3]: 1817101548 + 825955248*2147483647 + 1156337348*2147483647^2 + 330382099*2147483647^3 + 1321528398*2147483647^4 + 991146298*2147483647^5 + 1817101547*2147483647^6 + 825955248*2147483647^7 + 1156337348*2147483647^8 + 330382099*2147483647^9 + 1321528398*2147483647^10 + 991146298*2147483647^11 + O(2147483647^12)\n\n# 7/13 in F_2147483647\nIn [4]: ModP(Q(7, 13), 2147483647)\nOut [4]: 1817101548 % 2147483647\n\n# Mapping back to rational numbers\nIn [5]: from pyadic.finite_field import rationalise\nIn [6]: rationalise(ModP(Q(7, 13), 2147483647))\nOut [6]: Fraction(7, 13)\nIn [7]: rationalise(PAdic(Q(7, 13), 2147483647, 12))\nOut [7]: Fraction(7, 13)\n```\n\n## Perfomance comparison with [galois](https://github.com/mhostetter/galois) for finite fields\n\nScalar instantiation and operations are faster in pyadic\n```python\nimport numpy\nfrom galois import GF\nfrom pyadic import ModP\nfrom random import randint\n\nGFp = GF(2 ** 31 - 1)\nx = randint(0, 2 ** 31 - 1)\n\n%timeit GFp(x)\n2.84 \u00b5s \u00b1 63.5 ns\n\n%timeit ModP(x, 2 ** 31 - 1)\n297 ns \u00b1 0.876 ns\n\n%timeit GFp(x) ** 2\n30.1 \u00b5s \u00b1 20.6 \u00b5s \n\n%timeit ModP(x, 2 ** 31 - 1) ** 2\n2.23 \u00b5s \u00b1 91.8 ns\n```\n\nwhile galois is faster for vectorized operations (the bigger the array the bigger the gain)\n```python\n%timeit numpy.array([randint(0, 2 ** 31 - 1) for i in range(100)]).view(GFp) ** 2\n65.6 \u00b5s \u00b1 1.86 \u00b5s \n\n%timeit numpy.array([ModP(randint(0, 2 ** 31 - 1), 2 ** 31 - 1) for i in range(100)]) ** 2\n351 \u00b5s \u00b1 9.28 \u00b5s\n```\n\nHowever, galois requires everything to be appropriately typed, while pyadic performs type-casting on-the-fly\n```python\nnumpy.array([randint(0, 2 ** 31 - 1) for i in range(100)]).view(GFp) / 2\nTypeError\n\nnumpy.array([ModP(randint(0, 2 ** 31 - 1), 2 ** 31 - 1) for i in range(100)]) / 2\narray([...], dtype=object)\n```\n\n## Citation\n\nIf you found this library useful, please consider citing it\n\n\n```bibtex\n@inproceedings{DeLaurentis:2023qhd,\n author = \"De Laurentis, Giuseppe\",\n title = \"{Lips: $p$-adic and singular phase space}\",\n booktitle = \"{21th International Workshop on Advanced Computing and Analysis Techniques in Physics Research}: {AI meets Reality}\",\n eprint = \"2305.14075\",\n archivePrefix = \"arXiv\",\n primaryClass = \"hep-th\",\n reportNumber = \"PSI-PR-23-14\",\n month = \"5\",\n year = \"2023\"\n}\n```\n\n\n",
"bugtrack_url": null,
"license": "GNU General Public License v3.0",
"summary": "p-Adic numbers and finite fields in Python",
"version": "0.2.2",
"project_urls": {
"Documentation": "https://gdelaurentis.github.io/pyadic/",
"Download": "https://github.com/GDeLaurentis/pyadic/archive/v0.2.2.tar.gz",
"Homepage": "https://github.com/GDeLaurentis/pyadic",
"Issues": "https://github.com/GDeLaurentis/pyadic/issues"
},
"split_keywords": [
"p-adic numbers",
" finite-fields",
" rational reconstruction"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f28646ee38e10af8e3f7efb63199b2b5bea80e95eec24467c05ab7fea72b4141",
"md5": "96883f588b77222c1ed73c36856696a2",
"sha256": "b2becc470b3bb53fa0f8cadb4d55d0aa361c375b9ca8f7e7914b3a9fb6933e75"
},
"downloads": -1,
"filename": "pyadic-0.2.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "96883f588b77222c1ed73c36856696a2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 28951,
"upload_time": "2024-06-07T11:20:08",
"upload_time_iso_8601": "2024-06-07T11:20:08.718034Z",
"url": "https://files.pythonhosted.org/packages/f2/86/46ee38e10af8e3f7efb63199b2b5bea80e95eec24467c05ab7fea72b4141/pyadic-0.2.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "fbcf5218e0304979356ab42211a18ca8ec1237a176b78e43ddbd9e6d52d76f56",
"md5": "4f215e28d56b2265a55bb9b1aeb4f502",
"sha256": "d2afd953d14ef4f1b7a2aeb00c0d18faab1feca042016e49d8b78fbfb454e596"
},
"downloads": -1,
"filename": "pyadic-0.2.2.tar.gz",
"has_sig": false,
"md5_digest": "4f215e28d56b2265a55bb9b1aeb4f502",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 29547,
"upload_time": "2024-06-07T11:20:10",
"upload_time_iso_8601": "2024-06-07T11:20:10.049712Z",
"url": "https://files.pythonhosted.org/packages/fb/cf/5218e0304979356ab42211a18ca8ec1237a176b78e43ddbd9e6d52d76f56/pyadic-0.2.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-07 11:20:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "GDeLaurentis",
"github_project": "pyadic",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pyadic"
}