Metadata-Version: 2.4
Name: pyquadp
Version: 2.0.0
Summary: Python's bindings for gcc's libquadmath
Author-email: Robert Farmer <robert.j.farmer37@gmail.com>
License-Expression: GPL-2.0-or-later
Project-URL: Homepage, https://github.com/rjfarmer/pyquadp
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: COPYING.txt
Requires-Dist: numpy>=2.0
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-xdist[psutil]; extra == "test"
Requires-Dist: hypothesis; extra == "test"
Requires-Dist: scipy; extra == "test"
Provides-Extra: coverage
Requires-Dist: pytest; extra == "coverage"
Requires-Dist: pytest-xdist[psutil]; extra == "coverage"
Requires-Dist: pytest-cov; extra == "coverage"
Requires-Dist: scipy; extra == "coverage"
Provides-Extra: dev
Requires-Dist: pre-commit; extra == "dev"
Requires-Dist: black; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-xdist[psutil]; extra == "dev"
Requires-Dist: scipy; extra == "dev"
Provides-Extra: types
Requires-Dist: mypy>=1.11; extra == "types"
Requires-Dist: types-setuptools; extra == "types"
Provides-Extra: perfomance
Requires-Dist: pytest; extra == "perfomance"
Requires-Dist: pytest-codspeed; extra == "perfomance"
Requires-Dist: pytest-xdist[psutil]; extra == "perfomance"
Requires-Dist: scipy; extra == "perfomance"
Dynamic: license-file

[![Continuous Integration](https://github.com/rjfarmer/pyQuadp/actions/workflows/linux.yml/badge.svg)](https://github.com/rjfarmer/pyQuadp/actions/workflows/linux.yml)
[![Coverage Status](https://coveralls.io/repos/github/rjfarmer/pyQuadp/badge.svg?branch=main)](https://coveralls.io/github/rjfarmer/pyQuadp?branch=main)
[![Python versions](https://img.shields.io/pypi/pyversions/pyQuadp.svg)](https://img.shields.io/pypi/pyversions/pyQuadp.svg)
[![gfortran versions](https://img.shields.io/badge/gfortran-8%7C9%7C10%7C11%7C12-blue)](https://img.shields.io/badge/gfortran-8%7C9%7C10%7C11%7C12-blue)


# pyQuadp

Python interface to gcc's libquadmath for quad (128-bit) precision maths.

## Build
This project must be compiled with GCC/GFortran toolchain (`gcc`, `g++`, `gfortran`).
Do not use `clang` for builds.

````bash
CC=gcc CXX=g++ FC=gfortran python -m build
python -m pip install .
````

For editable installs, also force the same toolchain:

````bash
CC=gcc CXX=g++ FC=gfortran python -m pip install -e . --no-build-isolation
````

If your shell should always use GCC/GFortran for local development:

````bash
export CC=gcc
export CXX=g++
export FC=gfortran
python -m build
python -m pip install .
````

This package requires ``quadmath.h`` and ``libquadmath.so``. This might come installed with your installation of gcc/gfortran from your package manager. Or it might require a separate installation. This should be installed before trying to install the Python package.

### Fedora

````bash
sudo dnf install libquadmath libquadmath-devel
````


## Usage

### qfloat

A quad precision number is created by passing either a int, float, or string to ``qfloat``:

````python
import pyquadp

q = pyquadp.qfloat(1)
q = pyquadp.qfloat(1.0)
q = pyquadp.qfloat('1')
````

A ``qfloat`` implements Python's NumberProtocol, thus it can be used like any other number, either with basic math operations or in rich comparisons:

````python

q1 = pyquadp.qfloat(1)
q2 = pyquadp.qfloat(2)

q1+q2 # pyquadp.qfloat(3)
q1*q2  # pyquadp.qfloat(2)
q1+=q2 # pyquadp.qfloat(3)

q1 <= q2 # True
q1 == q2 # False

str(q) # "1.000000000000000000000000000000000000e+00"
````

Scalar utility methods are also available:

````python
q = pyquadp.qfloat("1.5")

q.as_integer_ratio()  # (3, 2)
q.is_integer()        # False
round(q)              # qfloat('2')
q.__floor__()         # qfloat('1')
q.__ceil__()          # qfloat('2')
q.__trunc__()         # qfloat('1')
````

For ``ctypes`` compatibility, scalar ``from_param`` methods return packed bytes:

````python
param = pyquadp.qfloat.from_param("1.25")
isinstance(param, bytes)  # True
````


### qint

``qint`` is a signed 128-bit integer scalar type with full arithmetic and bitwise operators.

````python
import pyquadp

x = pyquadp.qint("13")

x.bit_length()   # 4
x.bit_count()    # 3
x.__index__()    # 13

param = pyquadp.qint.from_param(x)
isinstance(param, bytes)  # True
````

### qarray

``qarray`` provides NumPy-compatible arrays of quad-precision (128-bit) values. It registers a custom NumPy dtype so arrays behave like any other NumPy array where supported.

````python
import pyquadp
import numpy as np

# creation
arr = pyquadp.qarray.zeros(4)           # array of four zeros
arr = pyquadp.qarray.ones(3)            # array of three ones
arr = pyquadp.qarray.from_list([1, 2.5, "3.141592653589793238"])  # from Python sequence
arr = pyquadp.qarray.from_array(np.linspace(0, 1, 5))  # from any NumPy array

# dtype handle for asarray / casting
dt = pyquadp.qarray.dtype

# casting to/from standard NumPy dtypes
out64 = np.asarray(arr, dtype=np.float64)          # qarray → float64
back  = np.asarray(out64, dtype=pyquadp.qarray.dtype)  # float64 → qarray
````

#### Arithmetic ufuncs

All standard element-wise binary and unary arithmetic ufuncs work directly:

````python
a = pyquadp.qarray.from_list([1.0, 2.0, 3.0])
b = pyquadp.qarray.from_list([0.5, 1.5, 2.5])

np.add(a, b)       # qarray([1.5, 3.5, 5.5])
np.subtract(a, b)  # qarray([0.5, 0.5, 0.5])
np.multiply(a, b)  # qarray([0.5, 3.0, 7.5])
np.divide(a, b)    # qarray([2.0, 1.333..., 1.2])
np.negative(a)     # qarray([-1.0, -2.0, -3.0])
np.absolute(a)     # qarray([1.0,  2.0,  3.0])
np.square(a)       # qarray([1.0,  4.0,  9.0])
````

Operands can be mixed with ``float64`` arrays; the output dtype is always ``qarray``:

````python
d = np.array([10.0, 20.0, 30.0], dtype=np.float64)
np.add(a, d)       # qarray([11.0, 22.0, 33.0])
np.multiply(d, a)  # qarray([10.0, 40.0, 90.0])
````

#### Math ufuncs

````python
np.sqrt(a)   # quad-precision square root
np.exp(a)    # quad-precision exponential
np.log(a)    # quad-precision natural log
np.sin(a)    # quad-precision sine
np.cos(a)    # quad-precision cosine
````

#### Platform requirements

``qarray`` requires GCC's ``libquadmath`` and a NumPy ≥ 2.0 installation. 

### qiarray

``qiarray`` provides NumPy-compatible arrays of signed ``__int128`` values through a custom NumPy dtype.

````python
import pyquadp
import numpy as np

arr = pyquadp.qiarray.arange(5)
arr = pyquadp.qiarray.from_list([1, "2", -3])
arr = np.asarray(np.array([4, 5, 6], dtype=np.int64), dtype=pyquadp.qiarray.dtype)

np.add(arr, arr)
np.multiply(arr, 3)
np.bitwise_and(arr, np.array([1, 1, 1], dtype=np.int64))
np.asarray(arr, dtype=np.int64)
````

The surface includes constructors, casts to and from signed fixed-width integer dtypes, and core arithmetic, division, shift, and bitwise ufuncs.

### qcmplx

A quad precision number is created by passing either a complex variable or two ints, floats, strs, or qfloats to ``qcmplx``:

````python
import pyquadp

q = pyquadp.qcmplx(complex(1,1))
q = pyquadp.qcmplx(1,1.0)
q = pyquadp.qcmplx('1',1.0)
q = pyquadp.qcmplx('1','1')
q = pyquadp.qcmplx(pyquadp.qfloat(1), pyquadp.qfloat('1'))
````

``qcmplx`` also accepts a single complex string in Python complex notation:

````python
q = pyquadp.qcmplx('1+1j')
q = pyquadp.qcmplx('1-1j')
q = pyquadp.qcmplx('-2.5j')
q = pyquadp.qcmplx('3.25')
````

Both one-string and two-argument forms are supported.

For ``ctypes`` compatibility, ``qcmplx.from_param`` returns packed bytes.


<!-- A ``qcmplx`` implements Python's NumberProtocol, thus it can be used like any other number, either with basic math operations or in rich comparisons:

````python

q1 = pyquadp.qfloat(1)
q2 = pyquadp.qfloat(2)

q1+q2 # pyquadp.qfloat(3)
q1*q2  # pyquadp.qfloat(2)
q1+=q2 # pyquadp.qfloat(3)

q1 <= q2 # True
q1 == q2 # False

str(q) # "1.000000000000000000000000000000000000e+00"
```` -->

## Math libraries

The ``qmath`` provides the union of math operations from Python's ``math`` library and the routines provided in ``libquadmath``. ``qmath`` provides routines for ``qfloat``, while complex numbers are handled by ``qcmath`` versions.

Where possible functions accessed via the Python name follows Python's conventions
regarding behavior of exceptional values. While routines from ``libquadmath`` (those ending in ``q``) follows ``libquadmath``'s conventions.


### Routines from Python's ``math`` library

| Name     | Implemented | Descritpion |
|----------|-------------|-------------|
| ceil | :heavy_check_mark: |  |
| comb | :x: |  |
| copysign | :heavy_check_mark: |  |
| fabs |:heavy_check_mark: |  |
| factorial | :x: |  |
| floor | :heavy_check_mark: |  |
| fmod | :heavy_check_mark: |  |
| frexp | :heavy_check_mark: |  |
| fsum | :x: |  |
| gcd | :x: |  |
| isclose | :x: |  |
| isfinite | :x: |  |
| isinf | :heavy_check_mark: |  |
| isnan | :heavy_check_mark: |  |
| isqrt | :x: |  |
| lcm | :x: |  |
| ldexp | :heavy_check_mark: |  |
| modf | :heavy_check_mark: |  |
| nextafter | :heavy_check_mark: |  |
| perm | :x: |  |
| prod | :x: |  |
| remainder | :heavy_check_mark: |  |
| trunc | :heavy_check_mark: |  |
| ulp | :x: |  |
| cbrt | :heavy_check_mark: |  |
| exp | :heavy_check_mark: |  |
| exp2 | :heavy_check_mark: |  |
| expm1 | :heavy_check_mark: |  |
| log | :heavy_check_mark: |  |
| log1p | :heavy_check_mark: |  |
| log2 | :heavy_check_mark: |  |
| log10 | :heavy_check_mark: |  |
| pow | :heavy_check_mark: |  |
| sqrt | :heavy_check_mark: |  |
| acos | :heavy_check_mark: |  |
| asin | :heavy_check_mark: |  |
| atan | :heavy_check_mark: |  |
| atan2 | :heavy_check_mark: |  |
| cos | :heavy_check_mark: |  |
| dist | :heavy_check_mark: |  |
| hypot | :heavy_check_mark: |  |
| sin | :heavy_check_mark: |  |
| tan | :heavy_check_mark: |  |
| degress | :heavy_check_mark: |  |
| radians | :heavy_check_mark: |  |
| acosh | :heavy_check_mark: |  |
| asinh| :heavy_check_mark: |  |
| atanh| :heavy_check_mark: |  |
| cosh| :heavy_check_mark: |  |
| sinh| :heavy_check_mark: |  |
| tanh| :heavy_check_mark: |  |
| erf| :heavy_check_mark: |  |
| erfc| :heavy_check_mark: |  |
| gamma| :heavy_check_mark: |  |
| lgamma| :heavy_check_mark: |  |
| pi | :heavy_check_mark: |  |  
| e | :heavy_check_mark: |  |  
| tau | :heavy_check_mark: |  |  
| inf | :heavy_check_mark: |  |
| nan | :heavy_check_mark: |  |  


### Routines from gcc's ``libquadthmath`` library

| Name     | Implemented |
|----------|-------------|
|acosq | :heavy_check_mark: | arc cosine function |
|acoshq | :heavy_check_mark: | inverse hyperbolic cosine function |
|asinq | :heavy_check_mark: | arc sine function |
|asinhq | :heavy_check_mark: | inverse hyperbolic sine function |
|atanq | :heavy_check_mark: | arc tangent function |
|atanhq | :heavy_check_mark: | inverse hyperbolic tangent function |
|atan2q | :heavy_check_mark: | arc tangent function |
|cbrtq | :heavy_check_mark: | cube root function |
|ceilq | :heavy_check_mark: | ceiling value function |
|copysignq |:heavy_check_mark: | copy sign of a number
|coshq | :heavy_check_mark: | hyperbolic cosine function |
|cosq | :heavy_check_mark: | cosine function |
|erfq | :heavy_check_mark: | error function |
|erfcq | :heavy_check_mark: | complementary error function |
|exp2q | :heavy_check_mark: | base 2 exponential function |
|expq | :heavy_check_mark: | exponential function |
|expm1q | :heavy_check_mark: | exponential minus 1 function |
|fabsq | :heavy_check_mark: | absolute value function |
|fdimq | :heavy_check_mark: | positive difference function |
|finiteq | :heavy_check_mark: | check finiteness of value
|floorq | :heavy_check_mark: | floor value function |
|fmaq | :heavy_check_mark: | fused multiply and add |
|fmaxq | :heavy_check_mark: | determine maximum of two values |
|fminq | :heavy_check_mark: | determine minimum of two values |
|fmodq | :heavy_check_mark: | remainder value function |
|frexpq | :heavy_check_mark: | extract mantissa and exponent |
|hypotq | :heavy_check_mark: | Eucledian distance function |
|ilogbq | :heavy_check_mark: | get exponent of the value |
|isinfq | :heavy_check_mark: | check for infinity |
|isnanq | :heavy_check_mark: | check for not a number |
|issignalingq | :heavy_check_mark: | check for signaling not a number |
|j0q | :heavy_check_mark: | Bessel function of the first kind, first order |
|j1q | :heavy_check_mark: | Bessel function of the first kind, second order |
|jnq | :heavy_check_mark: | Bessel function of the first kind, n-th order |
|ldexpq | :heavy_check_mark: | load exponent of the value |
|lgammaq | :heavy_check_mark: | logarithmic gamma function |
|llrintq | :heavy_check_mark: | round to nearest integer value |
|llroundq |:heavy_check_mark: | round to nearest integer value away from zero |
|logbq | :heavy_check_mark: | get exponent of the value |
|logq | :heavy_check_mark: | natural logarithm function |
|log10q | :heavy_check_mark: | base 10 logarithm function |
|log1pq | :heavy_check_mark: | compute natural logarithm of the value plus one |
|log2q | :heavy_check_mark: | base 2 logarithm function |
|lrintq | :heavy_check_mark: | round to nearest integer value |
|lroundq | :heavy_check_mark: | round to nearest integer value away from zero |
|modfq | :heavy_check_mark: | decompose the floating-point number |
|nanq | :heavy_check_mark: | return quiet NaN |
|nearbyintq | :heavy_check_mark: | round to nearest integer |
|nextafterq | :heavy_check_mark: | next representable floating-point number |
|powq | :heavy_check_mark: | power function |
|remainderq | :heavy_check_mark: | remainder function |
|remquoq | :heavy_check_mark: | remainder and part of quotient |
|rintq | :heavy_check_mark: | round-to-nearest integral value |
|roundq | :heavy_check_mark: | round-to-nearest integral value, return __float128 |
|scalblnq | :heavy_check_mark: | compute exponent using FLT_RADIX |
|scalbnq | :heavy_check_mark: | compute exponent using FLT_RADIX |
|signbitq | :heavy_check_mark: | return sign bit |
|sincosq | :heavy_check_mark: | calculate sine and cosine simultaneously |
|sinhq | :heavy_check_mark: | hyperbolic sine function |
|sinq | :heavy_check_mark: | sine function |
|sqrtq | :heavy_check_mark: | square root function |
|tanq | :heavy_check_mark: | tangent function |
|tanhq | :heavy_check_mark: | hyperbolic tangent function |
|tgammaq | :heavy_check_mark: | true gamma function |
|truncq | :heavy_check_mark: | round to integer, towards zero |
|y0q | :heavy_check_mark: | Bessel function of the second kind, first order |
|y1q | :heavy_check_mark: | Bessel function of the second kind, second order |
|ynq | :heavy_check_mark: | Bessel function of the second kind, n-th order |



### Routines from Python's complex math ``cmath`` library

These are available from ``qcmath``

| Name     | Implemented | Descritpion |
|----------|-------------|-------------|
| phase | :heavy_check_mark: | |
| polar | :heavy_check_mark: | |
| rect | :heavy_check_mark: | |
| exp | :heavy_check_mark: | |
| log | :heavy_check_mark: | |
| log10 | :heavy_check_mark: | |
| sqrt | :heavy_check_mark: | |
| acos | :heavy_check_mark: | |
| asin | :heavy_check_mark: | |
| atan | :heavy_check_mark: | |
| cos | :heavy_check_mark: | |
| sin | :heavy_check_mark: | |
| tan | :heavy_check_mark: | |
| acosh | :heavy_check_mark: | |
| asinh | :heavy_check_mark: | |
| atanh | :heavy_check_mark: | |
| cosh | :heavy_check_mark: | |
| sinh | :heavy_check_mark: | |
| tanh | :heavy_check_mark: | |
| isfinite | :heavy_check_mark: | |
| isinf | :heavy_check_mark: | |
| isnan | :heavy_check_mark: | |
| isclose | :x: | |
| pi | :heavy_check_mark: | |
| e | :heavy_check_mark: | |
| tau | :heavy_check_mark: | |
| inf | :heavy_check_mark: | |
| infj | :heavy_check_mark: | |
| nan | :heavy_check_mark: | |
| nanj | :heavy_check_mark: | |


### Routines from complex math ``libquadthmath`` library

These are available from ``qcmath``

| Name     | Implemented | Descritpion |
|----------|-------------|-------------|
| cabsq | :heavy_check_mark: |  complex absolute value function |
| cargq | :heavy_check_mark: | calculate the argument |
| cimagq | :heavy_check_mark: | imaginary part of complex number |
| crealq | :heavy_check_mark: | real part of complex number | 
| cacoshq | :heavy_check_mark: | complex arc hyperbolic cosine function |
| cacosq | :heavy_check_mark: | complex arc cosine function |
| casinhq | :heavy_check_mark: | complex arc hyperbolic sine function |
| casinq | :heavy_check_mark: | complex arc sine function |
| catanhq | :heavy_check_mark: | complex arc hyperbolic tangent function |
| catanq | :heavy_check_mark: | complex arc tangent function |
| ccosq: | :heavy_check_mark: | complex cosine function |
| ccoshq | :heavy_check_mark: | complex hyperbolic cosine function |
| cexpq | :heavy_check_mark: | complex exponential function |
| cexpiq | :heavy_check_mark: | computes the exponential function of ``i`` times a real value |
| clogq | :heavy_check_mark: | complex natural logarithm |
| clog10q | :heavy_check_mark: | complex base 10 logarithm |
| conjq | :heavy_check_mark: | complex conjugate function |
| cpowq | :heavy_check_mark: | complex power function |
| cprojq | :heavy_check_mark: | project into Riemann Sphere |
| csinq | :heavy_check_mark: | complex sine function |
| csinhq | :heavy_check_mark: | complex hyperbolic sine function |
| csqrtq | :heavy_check_mark: | complex square root |
| ctanq | :heavy_check_mark: | complex tangent function |
| ctanhq | :heavy_check_mark: | complex hyperbolic tangent function |


### Constants from  ``libquadthmath`` library.

The following constants are availbe both in ``qmath`` and ``qcmath``

| Name     | Implemented | Descritpion |
|----------|-------------|-------------|
| FLT128_MAX | :heavy_check_mark: | largest finite number | 
| FLT128_MIN| :heavy_check_mark: | smallest positive number with full precision |
| FLT128_EPSILON | :heavy_check_mark: |  difference between 1 and the next larger representable number | 
| FLT128_DENORM_MIN | :heavy_check_mark: | smallest positive denormalized number |
| FLT128_MANT_DIG | :heavy_check_mark: |  number of digits in the mantissa (bit precision) |
| FLT128_MIN_EXP | :heavy_check_mark: |  maximal negative exponent |
| FLT128_MAX_EXP | :heavy_check_mark: |  maximal positive exponent |
| FLT128_DIG | :heavy_check_mark: |  number of decimal digits in the mantissa |
| FLT128_MIN_10_EXP | :heavy_check_mark: |  maximal negative decimal exponent |
| FLT128_MAX_10_EXP | :heavy_check_mark: |  maximal positive decimal exponent |
| M_Eq | :heavy_check_mark: | the constant e (Euler’s number) |
| M_LOG2Eq | :heavy_check_mark: | binary logarithm of 2 |
| M_LOG10Eq | :heavy_check_mark: | common, decimal logarithm of 2 |
| M_LN2q | :heavy_check_mark: | natural logarithm of 2 |
| M_LN10q | :heavy_check_mark: | natural logarithm of 10 |
| M_PIq | :heavy_check_mark: | pi |
| M_PI_2q | :heavy_check_mark: | pi divided by two |
| M_PI_4q | :heavy_check_mark: | pi divided by four |
| M_1_PIq | :heavy_check_mark: | one over pi |
| M_2_PIq | :heavy_check_mark: | one over two pi |
| M_2_SQRTPIq | :heavy_check_mark: | two over square root of pi |
| M_SQRT2q | :heavy_check_mark: | square root of 2 |
| M_SQRT1_2q | :heavy_check_mark: | one over square root of 2 |
