This release is a pre-release and may not be stable for production use.
decimo
A drop-in replacement for Python's decimal, written in
Mojo.
⚠️ Development release. The API is settled enough to use, but the versions carry a timestamp:
0.14.0.devYYYYMMDDHHMMSS, where0.14.0is the version of the Mojo library the wheel packages. Wheels: macOS arm64 (14 and later), CPython 3.13 and 3.14. Everywhere else, build from source.
Change one import and your program keeps working:
# from decimal import Decimal, getcontext
from decimo import Decimal, getcontext
getcontext().prec = 50
print(Decimal(1) / Decimal(7))
# 0.14285714285714285714285714285714285714285714285714
The two libraries agree digit for digit. The test suite checks every
operation against the standard library rather than against a table of
expected strings, so "agrees with decimal" is a property that is measured,
not a claim.
How fast is it?
The same benchmark file run against both libraries -- python/benchmarks/compare.py
in the repository, which imports one or the other and runs identical code.
Best of five, on an Apple M-series laptop:
| Program | decimo | decimal | |
|---|---|---|---|
| add/sub/mul/div, 28 digits | 90.6 ns | 73.0 ns | 1.24× slower |
| add/sub/mul/div, 200 digits | 331.8 ns | 409.0 ns | 1.23× faster |
| add/sub/mul/div, 1000 digits | 2.02 µs | 5.89 µs | 2.91× faster |
| compound interest, 150 years | 12.71 µs | 13.08 µs | about the same |
| e from its series, 500 digits | 197.92 µs | 162.75 µs | 1.22× slower |
| sqrt by Newton, 1000 digits | 143.29 µs | 232.29 µs | 1.62× faster |
| pi by Machin, 500 digits | 620.12 µs | 520.17 µs | 1.19× slower |
| parse and print, 1000 digits | 3.28 µs | 2.60 µs | 1.26× slower |
decimo is faster once the numbers are large, and 20-25% behind on small
ones. The small-number gap is not the arithmetic: measured against
libmpdec directly, without an interpreter in the way, decimo is 2-4× faster
at 9 digits and faster at every operation at 1000 digits. What is left is the
cost of the Python call itself -- building the result object and converting
the operands -- which CPython's decimal has had thirty years to shave. See
the benchmarks.
What works
Everything a decimal program normally touches:
- all the operators, including
//,%,divmod()and** getcontext().precandgetcontext().rounding,setcontext(),localcontext()(with keyword overrides),Contextobjects- all the rounding modes:
ROUND_HALF_EVEN,ROUND_HALF_UP,ROUND_HALF_DOWN,ROUND_DOWN,ROUND_UP,ROUND_CEILING,ROUND_FLOOR, exact for arithmetic,quantize,round()andto_integral_value() int(),float(),round(),math.floor/ceil/trunc,hash(),format()quantize,normalize,as_tuple,as_integer_ratio,compare,fma,sqrt,exp,ln,log10,scaleb,adjusted,copy_abs,copy_negate,copy_sign,same_quantum,to_eng_string,max,min- the rest of the specification's surface:
remainder_near,next_plus,next_minus,next_toward,shift,rotate,logical_and,logical_or,logical_xor,logical_invert,logb,compare_total,compare_total_mag,compare_signal,max_mag,min_mag,number_class,to_integral_exact,is_normal,is_subnormal,from_number - the same coercion rules:
intconverts in arithmetic,floatdoes not, and both convert in a comparison copy,deepcopyandpickleZeroDivisionErrorwhere you expect it, and hashes that agree withint,floatanddecimal.Decimal
What does not
decimo refuses these rather than answering differently:
- NaN and infinity. decimo has no non-finite values.
is_nan()andis_infinite()are alwaysFalse. ROUND_05UP. Nothing implements it; setting it raisesNotImplementedError.**under a rounding mode other thanROUND_HALF_EVENis computed nine digits wider and rounded once more, so the last digit can differ fromdecimalwhen the true value lies within10^-9relative of a rounding boundary.sqrt,exp,lnandlog10are always half to even, as they are indecimal, whatever the context says. Arithmetic,quantizeandround()are exact under every mode.//,%,divmod()andremainder_nearwith a long quotient.decimalraisesInvalidOperationwhen the integer quotient has more digits than the precision; decimo answers. The remainder is rounded to the context, as indecimal.Eminonly reaches four methods. Exponents are unbounded, soEminchanges nothing except whatnext_plus(0),next_minus(0),is_subnormal()andnumber_class()say, wheredecimal's answers need a smallest exponent.- Signals and traps.
Context.flagsandContext.trapsexist and stay empty.Inexact,Roundedand the rest are importable but never raised. Emin/Emax. Exponents are unbounded, so nothing ever underflows to zero or overflows to infinity. A loop that waits for a term to become exactly zero will not stop; wait for the sum to stop changing instead.- One context per process, not per thread.
DivisionByZero and InvalidOperation are aliases for ZeroDivisionError
and ValueError, which is what decimo actually raises, so except clauses
written against decimal still catch.
Installing
pip install decimo
Wheels are built for macOS arm64 (macOS 14 and later), for CPython 3.13 and 3.14. On anything else -- Linux included, until its build is verified -- build from source with pixi:
git clone https://github.com/forfudan/decimo && cd decimo
pixi run -e py314 release # or py313; the wheel lands in python/dist/
pip install python/dist/*.whl
Links
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file decimo-0.14.0.dev20260828181144-cp314-cp314-macosx_14_0_arm64.whl.
File metadata
- Download URL: decimo-0.14.0.dev20260828181144-cp314-cp314-macosx_14_0_arm64.whl
- Upload date:
- Size: 862.9 kB
- Tags: CPython 3.14, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75e940f77399104d018e3df891eb66184a7446d5f61f8f57759b28beb80686c6
|
|
| MD5 |
8f4ab1d0405f941d6fe0ffd3241a3c16
|
|
| BLAKE2b-256 |
50d1274699981c43c0f17e4ca0b62931b1f4c1e56c94287613dd29ce86540c3f
|
Provenance
The following attestation bundles were made for decimo-0.14.0.dev20260828181144-cp314-cp314-macosx_14_0_arm64.whl:
Publisher:
release_python.yaml on forfudan/decimo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
decimo-0.14.0.dev20260828181144-cp314-cp314-macosx_14_0_arm64.whl -
Subject digest:
75e940f77399104d018e3df891eb66184a7446d5f61f8f57759b28beb80686c6 - Sigstore transparency entry: 2627835722
- Sigstore integration time:
-
Permalink:
forfudan/decimo@b316a42f2c48ab15d8520a78dee72fab8a24047c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/forfudan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release_python.yaml@b316a42f2c48ab15d8520a78dee72fab8a24047c -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file decimo-0.14.0.dev20260828181144-cp313-cp313-macosx_14_0_arm64.whl.
File metadata
- Download URL: decimo-0.14.0.dev20260828181144-cp313-cp313-macosx_14_0_arm64.whl
- Upload date:
- Size: 862.9 kB
- Tags: CPython 3.13, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4430268380e4e24e056072dc1fd42560c29987815c6764827e995d11ed1f529
|
|
| MD5 |
9b3a549b6871b579e13753ca6e3cc46e
|
|
| BLAKE2b-256 |
5eb974e7bebf885cf4775656780ccf0033e69fcc570f2f21772b895ddc53e311
|
Provenance
The following attestation bundles were made for decimo-0.14.0.dev20260828181144-cp313-cp313-macosx_14_0_arm64.whl:
Publisher:
release_python.yaml on forfudan/decimo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
decimo-0.14.0.dev20260828181144-cp313-cp313-macosx_14_0_arm64.whl -
Subject digest:
e4430268380e4e24e056072dc1fd42560c29987815c6764827e995d11ed1f529 - Sigstore transparency entry: 2627835662
- Sigstore integration time:
-
Permalink:
forfudan/decimo@b316a42f2c48ab15d8520a78dee72fab8a24047c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/forfudan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release_python.yaml@b316a42f2c48ab15d8520a78dee72fab8a24047c -
Trigger Event:
workflow_dispatch
-
Statement type: