Observed since 20 Oct, 16:51 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Accelerate numerical Python by recording and compiling it — with optional exact derivatives (AAD)
Run the same numerical code many times, much faster.
AADC records your calculation once — as you already wrote it, in ordinary Python arithmetic — and turns that recording into machine code. Replaying it skips the interpreter entirely, and replays several scenarios at once on the CPU's vector units.
import aadc
f = aadc.Functions()
f.start_recording()
x = aadc.idouble(1.0); xa = x.mark_as_input()
y = my_pricer(x) # your existing code, unchanged
ya = y.mark_as_output()
f.stop_recording()
f.compile("scalar") # -> machine code, once
ws = f.create_workspace(kind="scalar") # a workspace those kernels run on
ws.set_val(xa, 1.5)
ws.forward() # compiled replay: ws.val(ya)
ws.set_diff(ya, 1.0)
ws.reverse() # ws.diff(xa) = dy/dx at x = 1.5
compile() with no argument is the same as compile("scalar"): the same
script runs compiled on x86-64, Apple Silicon and Linux AArch64 alike, and
create_workspace() / aadc.evaluate() with no workspace argument use the
workspace those kernels run on. compile("auto") compiles for the host's
vector lanes instead (AVX2 on x86-64, NEON on Apple Silicon) — use it for
batches: aadc.evaluate() after compile("auto") replays several scenarios
per instruction, typically 3-4x faster than after plain compile(). Choose the
backend at the FIRST compile() of a recording: a later call with another
backend does not replace kernels already installed.
From then on every replay runs compiled. Typical speedups are several times the interpreted path — about 4x on one customer's FX pricer — and more when you replay a batch of scenarios, because the vector backends evaluate four (AVX2) or eight (AVX-512) at a time.
import aadc
help(aadc) # the three ideas, and a quickstart that runs
aadc.llms_txt() # the same, written for a coding agent
dir(aadc) is the declared API (aadc.__all__), and every headline type
carries a docstring — help(aadc.Functions), help(aadc.idouble),
help(aadc.Workspace).
The one trap. if x > k: on an active value forces a plain bool, which
freezes that comparison as it came out while recording — a later replay with
different inputs still follows the recorded branch. Use aadc.iif(x > k, a, b)
when the condition depends on an input. Every such conversion is counted, so
this is detectable rather than silent:
kernel.num_passive_warnings() # 0 is the goal
kernel.passive_warnings() # kind and location of each
Derivatives are optional. If you want them, the same recording gives you exact first-order sensitivities of every output with respect to every input — no bumping, no re-running the pricer per input, and exact rather than finite-difference approximations. If you do not want them, AADC is simply a compiler for the hot loop you already have.
That is the whole idea: record once, replay compiled — and take the derivatives if they are useful to you.
pip install aadc
Supports CPython 3.10 and later. One abi3 wheel serves every CPython >= 3.11 on a given platform (the extension is built against the CPython Limited API); 3.10 is served by its own version-specific wheel.
Binary wheels only — there is no source distribution, so pip install aadc on
anything not listed here fails with no matching distribution rather than
attempting a build.
| CPython 3.10 – 3.14 | |
|---|---|
Linux x86-64 (manylinux_2_28) | yes |
Linux aarch64 (manylinux_2_28) | yes |
| macOS arm64 (Apple Silicon, 11.0+) | yes |
| Windows x64 | yes |
| macOS x86-64 (Intel) | no |
| Alpine / musl | no |
| 32-bit Windows | no |
The macOS wheels are Apple Silicon only. An Intel Mac gets no matching
distribution — the Operating System :: MacOS classifier is as specific as
PyPI allows, so this table is the authority, not the sidebar.
The Linux wheels need glibc 2.28 or newer; the shipped library's own floor is lower (it references no symbol above GLIBC 2.14 / GLIBCXX 3.4.22), so the tag is the binding constraint rather than the binary.
aadc 1.x2.x is a different engine, not a compatible successor. The 1.x line ended
at 1.8.2; 2.x is a ground-up rewrite with its own recording API, and code
written against 1.x will not run unchanged. Notably aadc.license() no longer
exists — entitlement is resolved from the environment instead (see Licence in
one paragraph below).
If you depend on the 1.x behaviour, pin it explicitly:
pip install 'aadc<2'
Migrating is a port rather than an upgrade. Start from Where to look first
above; the recording shape — start_recording(), mark_as_input(),
mark_as_output(), a workspace per evaluation — is what changed most.
Version 2.2.0 renames the distribution from aadc-ng to aadc, continuing the
PyPI aadc 1.x line. The import (import aadc) and every binary name
(_aadc_ng, the aadc_ng runtime package, libaadc-ng) are unchanged.
Upgrading from an environment that has aadc-ng installed: uninstall it
FIRST (pip uninstall -y aadc-ng), then pip install aadc. pip treats the two
as unrelated distributions that own the same files, so installing aadc over
aadc-ng works — but a later pip uninstall aadc-ng would then delete the files
out from under aadc, leaving an install whose metadata says it is fine and
whose import aadc fails.
Proprietary. The free Community Edition covers non-commercial and academic use only — personal study, hobby projects, publicly available open-source development, and research or teaching at a university or recognised research institute. Everything else is Production Use and needs a commercial licence, including evaluation by a company and any calculation whose output reaches a book, a client report or a regulator.
The Community Edition is fast. On x86-64 with AVX2, and on Apple Silicon, it
runs the interpreter and every JIT backend at full speed, and compile()
selects a JIT by default — so on those hosts the ordinary path needs no licence
and no C compiler on the box. Two hosts are the exception: on non-Apple 64-bit
ARM the vector backends compile() picks there need a licence with the
arm64 feature, and on pre-AVX2 x86-64 there is no scalar JIT, so
compile('scalar') falls back to the C emitter and needs codegen_c. Both
report the feature they want, and neither changes your numbers.
What a licence adds is the ahead-of-time code generators (which write a translation unit you keep, inspect and ship), AVX-512 in any form, and double-precision GPU.
Ask for a licensed backend without the licence and those segments replay on the
interpreter: identical results, more slowly, with the reason reported in
compile()'s unavailable field. Nothing expires and nothing contacts a server.
Every numerical answer is the same in every tier — the licence buys speed,
never correctness.
Full terms ship inside the wheel at
<site-packages>/aadc-<version>.dist-info/licenses/LICENSE.txt, with
THIRD-PARTY-NOTICES.txt beside it. Commercial and free full-performance
academic licences: info@matlogica.com.
Two version strings, because there are two things to version:
import aadc
aadc.__version__ # e.g. '2.9.2' -- the WHEEL you pip-installed
aadc.__engine_version__ # e.g. '2.9.0' -- the aadc-ng C++ engine inside it
__version__ is the distribution version, identical to
importlib.metadata.version("aadc") and to what pip freeze reports.
__engine_version__ is the version of the compiled aadc-ng engine the wheel
carries, recorded at build time from the SDK.
They are allowed to differ, and comparing them is not a health check: a
Python-only fix ships a new wheel against an unchanged engine. Record
__version__ next to your risk numbers and __engine_version__ when you need
to say which arithmetic produced them. Both are also available as
aadc_ng.__version__ / aadc_ng.__engine_version__.
For what the loaded library says about itself — a third, independent source —
use aadc.license_status()["build_version"]; disagreeing with
__engine_version__ means the wheel is carrying a different image than its
metadata claims.
import aadc
s = aadc.license_status()
assert s["state"] == "licensed", s["detail"]
state is unlicensed, licensed or expired. expired means the token
is genuine but this build is newer than its version ceiling — the
entitlement is to older builds, which keep running at full speed. Compare
version_max against build_version to see the gap.
Token location, in order: $AADC_NG_LICENSE, ./aadc-ng.lic,
~/.aadc-ng/license.
libaadc-ng carries thread-local recording state, so a second copy in one
process gives correct values and silently zero gradients. This wheel is the
only one that ships it; anything else linking it must resolve it by RPATH.
Assert it:
import aadc_ng
aadc_ng.check_single_image() # raises if more than one is mapped
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 2.22.2 | 29 Sept 2026 | 2 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 16:51 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:5bdeaad3edf85c26423ac58b5d09ead64f8b952dde2c6350cb10c3e6d1a51d39