Skip to main content

Fused multiply-add with 32-bit float support and configurable IEEE 754 rounding modes

Project description

python-fma

coverage

A Python fused multiply-add (FMA) binding with 32 and 64-bit float support and configurable IEEE 754 rounding modes.

Python 3.13+ provides math.fma, but it operates on float (IEEE 754 double) only and does not expose the rounding direction. This module fills both gaps:

  • Accepts ct.c_double (float64) and ct.c_float (float32).
  • Lets the caller select the rounding mode per-call.
  • Detects and reports IEEE 754 floating-point exceptions (invalid, overflow, underflow, inexact, divide-by-zero).
  • Restores the original FP rounding state after each operation.

Note

I write this project with vibe coding, but I carefully read every line in /src/ and /csrc/ folder, and I glanced at test code (and provides some data for rounding test), so the core logic should be ok.

The coverage test rate is high, and all non-platform-dependent code is covered in test.


Installation

$ pip install python-fma

The package ships a pre-built wheel for Linux, Windows and MacOS, support x86 and ARM architecture.

Requirements

  • Python >= 3.10

if you want to build from source:

  • C11 compiler
  • CMake >= 3.15

API

fma(x, y, z, round=None, unsuppressed_exception=...)

import ctypes as ct

from python_fma import fma, DivByZeroException, OverflowException

r = fma(ct.c_double(2.0), ct.c_double(3.0), ct.c_double(1.0))
# r.value == 7.0
Parameter Type Default Description
x, y, z ct.c_double or ct.c_float Operands (must all be the same type)
round str or None None Rounding mode (see below). None leaves the current FP mode unchanged.
unsuppressed_exception set of exception classes {DivByZeroException, OverflowException} Exception types allowed to propagate; all others are silently suppressed.

Rounding mode strings:

Name Behaviour
"FE_TONEAREST" Round to nearest, ties to even
"FE_UPWARD" Round toward +infinity
"FE_DOWNWARD" Round toward -infinity
"FE_TOWARDZERO" Truncate toward zero

Returns: ct.c_double or ct.c_float (same type as the inputs).

Raises:

  • TypeError — inputs are not all the same type or not a supported type.
  • ValueError — unrecognised rounding-mode string.
  • FeatureNotCompiledError — the rounding mode or an exception flag was not detected at compile time.
  • UnsupportedRoundingModeError — the platform does not support the requested rounding mode at runtime.
  • DivByZeroException, OverflowException — by default; other exceptions (InvalidException, UnderflowException, InexactException) are suppressed unless explicitly included in unsuppressed_exception.

exception_compiled(name)

Return whether detection of the floating-point exception name is available in the C build.

from python_fma import exception_compiled

exception_compiled("FE_INVALID")   # True / False
exception_compiled("FE_NOSUCH")    # ValueError

round_mode_compiled(name)

Return whether the rounding mode name was detected at compile time.

from python_fma import round_mode_compiled

round_mode_compiled("FE_UPWARD")   # True / False

round_mode_supported(name)

Return whether the rounding mode name is supported at runtime.

from python_fma import round_mode_supported

round_mode_supported("FE_TOWARDZERO")   # True / False

Exception hierarchy

Exception
  └── FloatException
        ├── InvalidException          (FE_INVALID)
        ├── DivByZeroException        (FE_DIVBYZERO)
        ├── OverflowException         (FE_OVERFLOW)
        ├── UnderflowException        (FE_UNDERFLOW)
        ├── InexactException          (FE_INEXACT)
        ├── FeatureNotCompiledError   (query/compile-time support)
        └── UnsupportedRoundingModeError  (also a ValueError)

Usage examples

Basic FMA

import ctypes as ct
from python_fma import fma

r = fma(ct.c_double(2.0), ct.c_double(3.0), ct.c_double(1.0))
# 2.0 * 3.0 + 1.0 = 7.0

Single-precision FMA

r = fma(ct.c_float(1.5), ct.c_float(2.0), ct.c_float(0.5))
# r.value == 3.5, type(r) is ct.c_float

Explicit rounding mode

r = fma(ct.c_double(1.0), ct.c_double(1.0), ct.c_double(0.1),
        round="FE_UPWARD")

Controlling which exceptions propagate

# Only allow InvalidException to propagate; suppress everything else.
r = fma(ct.c_double(float("inf")), ct.c_double(0.0), ct.c_double(0.0),
        unsuppressed_exception={InvalidException})

Querying compile-time feature support

from python_fma import exception_compiled, round_mode_compiled

if not round_mode_compiled("FE_UPWARD"):
    print("FE_UPWARD not available in this build")

Development

Setup

$ python -m venv .venv
$ source .venv/bin/activate
$ pip install -e .

Lint and type-check

$ ruff check src/ tests/
$ ruff format --check src/ tests/
$ npx pyright src/ tests/

Test

$ python -m pytest tests/ -v

Build a wheel

$ pip install build
$ python -m build

CI / Docker build

Manylinux wheels are built via Docker:

$ docker build \
  --build-arg BASE_IMAGE=quay.io/pypa/manylinux2014_x86_64 \
  -t builder .
$ docker run --rm -v "$PWD/wheelhouse:/wheelhouse" builder

Windows and macOS wheels are built natively on GitHub Actions runners. See .github/workflows/build.yml for the full CI matrix.


Project structure

python-fma/
├── csrc/                  # C source (fma_module.c, fma_module.h, CMakeLists.txt)
├── src/
│   └── python_fma/
│       ├── __init__.py    # Public Python API
│       └── _binding.py    # ctypes bindings to the C library
├── badges/                # generated coverage badge
├── tests/                 # pytest test suite
├── pyproject.toml         # Build configuration (scikit-build-core, ruff)
├── README.md              # This file
├── Dockerfile             # manylinux wheel builder
└── .github/workflows/     # CI workflows

License

MPL

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

python_fma-0.2.1-py3-none-win_arm64.whl (17.2 kB view details)

Uploaded Python 3Windows ARM64

python_fma-0.2.1-py3-none-win_amd64.whl (18.0 kB view details)

Uploaded Python 3Windows x86-64

python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl (15.7 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_34_aarch64.whl (15.9 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64manylinux: glibc 2.34+ ARM64

python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (15.9 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_34_x86_64.manylinux_2_5_x86_64.whl (15.7 kB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64manylinux: glibc 2.5+ x86-64

python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (15.7 kB view details)

Uploaded Python 3manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl (15.7 kB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

python_fma-0.2.1-py3-none-macosx_26_0_x86_64.whl (14.2 kB view details)

Uploaded Python 3macOS 26.0+ x86-64

python_fma-0.2.1-py3-none-macosx_15_0_arm64.whl (14.4 kB view details)

Uploaded Python 3macOS 15.0+ ARM64

File details

Details for the file python_fma-0.2.1-py3-none-win_arm64.whl.

File metadata

  • Download URL: python_fma-0.2.1-py3-none-win_arm64.whl
  • Upload date:
  • Size: 17.2 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for python_fma-0.2.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 a0cda555bf86e33ec6070fcacc2d6bd746b510a7b2857af5d5dce2f34690bba3
MD5 6c82aa87e91245f0ef2318a9bc03b2e1
BLAKE2b-256 7b14312304631ea45c2c2ef53a1914abf3801b12ace3a8b22889df31f6f4cdda

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-win_arm64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: python_fma-0.2.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for python_fma-0.2.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 5bc36eced6eba4dfe451e70b7577915be07ebd7c052ce83526214b199fe8f1b6
MD5 8075a3a25bfe9780a1d213c9c94f7257
BLAKE2b-256 bd7f56a76c839b6243a33a6c51efde8221484c851d4de5008a47a2aecf970e0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-win_amd64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 30175a19cae8824844903bf33c637235d4d4af10aed8fee1b50b00dd875a7123
MD5 48586f9311c4dd97f58adbd8c0ef9179
BLAKE2b-256 80d6feea0a20a4019f00d88918c944be9632ad3490a319edfdf1e4320f3e74d6

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 7e643bec25392dfeb67aaf955cf415fddc3081bc2b7d2659871afdf985afed0f
MD5 eb56b043a512cd9779f209e1c9a9def4
BLAKE2b-256 71553917267ec2ea40eb99b8b0b6e1655879053f8c5eb5eb3027a5972d435175

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_34_aarch64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0fc249d97dc3433b516a7225e8f79d215d687754ddfe21a6d52d548f0af18e47
MD5 e98ded436029f4ecab7f47b0f9fc03b6
BLAKE2b-256 a309e25e18e69db43172a1a92c6e771a8b3bfcb53b0a436bbdcb4fe4dd6a7cec

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_34_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_34_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 56512b34703858455855d4d13993902629f47b0995ebb71ae2b77f0bad2362a1
MD5 cf2260eefd03bf92c72dab47884e5a3c
BLAKE2b-256 461805930080ea0e91a9662d04b6c8c45a30af59256e0e3b47fc794eee4678b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_34_x86_64.manylinux_2_5_x86_64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 0ad907f3b5bfaa4bc184e1fe7e5b1b6173e3b3278e9e3ce1aa737cb14b915e8f
MD5 b0dd16839337c6218384cee29b065779
BLAKE2b-256 60c4232c4e54d5964a5f11ca990db6324c8948984962728e67848c865899f0d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 e149bdd68b81af6675e37aa334a1baafc1fa764d587a1e60076690f56b8c78c5
MD5 7bb81288e50015a00fa01a2f4e47bcea
BLAKE2b-256 8308948515c04dffcd08dab48a1b5e76b8c011f91550af2b8fa91453641f6dbd

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-macosx_26_0_x86_64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-macosx_26_0_x86_64.whl
Algorithm Hash digest
SHA256 0eeded925647189c5acb80ea1c1abfc0285ffcb096db10d550c1299a17aade33
MD5 041497c25cbe73c3bfa6af9ae69bd186
BLAKE2b-256 8588fb9526268040feb30bbbb9ae5038866f47e64ba175258e39b8c9b81f9782

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-macosx_26_0_x86_64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_fma-0.2.1-py3-none-macosx_15_0_arm64.whl.

File metadata

File hashes

Hashes for python_fma-0.2.1-py3-none-macosx_15_0_arm64.whl
Algorithm Hash digest
SHA256 48d6e49f8296a94b85007f5d7727289acc02516f18e690773bd6668f9a72e72e
MD5 cf20e6d7b8fdd30966e10b94e3855c08
BLAKE2b-256 77846124e70d73519b02a291bed28a81ffee01522d97388ce2ce8d7a6d9422a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_fma-0.2.1-py3-none-macosx_15_0_arm64.whl:

Publisher: release.yml on LXYan2333/python_fma

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page