Skip to content

Decimo v0.11.0

Latest

Choose a tag to compare

@forfudan forfudan released this 02 Jul 09:08
e271f85

20260701 (v0.11.0)

Decimo v0.11.0 retargets the codebase to Mojo v1.0.0b2, adds the factorial() and permutation() functions to BigInt and BigDecimal, and includes a series of performance improvements for BigDecimal and BigUInt arithmetic. It also renames the BigDecimal round_to_precision APIs to *_inplace, which is a breaking change for code that calls them directly.

⭐️ New in v0.11.0

Number-theoretic functions:

  1. factorial() for BigInt and BigDecimal — a standalone function in the new special modules and an instance method on both types. BigDecimal.factorial(precision=0) returns the exact value by default and a rounded value when a positive precision is given. The exact path uses balanced binary splitting (product_range) with in-place single-word multiplication at the recursion leaves, which is much faster than a naive running product for large arguments (PR #254, #255, #256).
  2. permutation() — the number of k-permutations of n, P(n, k) = n! / (n − k)!, likewise provided as a special-module function and as a method on BigInt / BigDecimal (with optional rounding for BigDecimal). For BigInt, n is restricted to a single word (PR #255).

🦋 Changed in v0.11.0

Mojo v1.0.0b2 migration (PR #257):

  1. Retarget the codebase to Mojo v1.0.0b2, and bump the Pixi dependencies to mojo >=1.0.0b2 and argmojo 0.7.0.
  2. Switch packaging from the deprecated mojo package / .mojopkg to mojo precompile / .mojoc across the Pixi tasks, CI workflows, and helper scripts.
  3. Update the Decimal128 string formatter to the StringSlice(unsafe_from_utf8=Span(...)) constructor, replacing the deprecated StringSlice(ptr=, length=) form.

BigDecimal — rounding API rename:

  1. The free function round_to_precision and the matching BigDecimal method are renamed to round_to_precision_inplace, which makes their mutating semantics explicit, and now run through an allocation-free in-place path. The out-of-place, Python-compatible BigDecimal.round(ndigits=...) is unchanged. Code that calls the renamed APIs must update its import and call sites (PR #245).

Performance:

  1. BigDecimal addition / subtraction — a same-scale fast path avoids the scale-alignment work when both operands share a scale (and, for add, a sign) (PR #247).
  2. BigDecimal multiplication — compute the exact coefficient product in a single pass and round only afterwards when a precision is requested, removing a recursive call and a duplicated zero fast-path (PR #248).
  3. BigDecimal division and string conversion — fewer allocations in divide, from_string parsing, and to_string rendering, through in-place batching and an exact-size output buffer (PR #249).
  4. BigUInt multiplication — a deferred-carry (product-scanning) schoolbook path is selected once the operand size crosses a threshold; the Toom-3 cutoff is retuned and the "school" helpers are renamed to "schoolbook" (PR #250).
  5. Logarithm constantscompute_ln2 and compute_ln1d25 fold their series factor into a single UInt32 division per term, and BigUInt.floor_divide_by_uint32 hoists its buffer pointers out of the inner loop (PR #251).

Code quality and tooling:

  1. BigInt.from_integral_scalar() is simplified into one generic word-peeling loop over any integral scalar type, backed by a new unsigned_counterpart type helper (PR #253).
  2. The BigInt benchmarks are refactored into a cross-language harness that compares decimo.BigInt against Python int and Rust num-bigint, with a Markdown report aggregator (PR #252).
  3. Documentation — added Raises: sections across the public API, replaced banner-style header comments with module docstrings, and introduced local import aliases in place of fully-qualified references (PR #245, #246).

What's Changed

  • [core][decimal] Create alias for imports + Make round_to_precision allocation-free by @forfudan in #245
  • [core][doc] Add raises to docstrings and fix related issues by @forfudan in #246
  • [decimal] Add same-scale hot path for add() and subtract() by @forfudan in #247
  • [decimal] Implement single pass precise multiplication by @forfudan in #248
  • [decimal] Optimize divide and string conversion with in-place batching by @forfudan in #249
  • [biguint] Add deferred-carry multiplication to BigUInt by @forfudan in #250
  • [decimal] Use exact-reciprocal divide for calculating ln(2) and ln(1.25) by @forfudan in #251
  • [bigint][bench] Refactor BigInt benches against Python and Rust by @forfudan in #252
  • [integer] Polish and simplify the from_integral_scalar() method of BigInt by @forfudan in #253
  • [integer][decimal] Implement factorial() for BigInt and BigDecimal by @forfudan in #254
  • [integer][decimal] Use binary splitting for factorial() + add permutation() by @forfudan in #255
  • [integer] Add multiply_by_word_inplace() and use it for product_range() by @forfudan in #256
  • [mojo][core] Update the codebase to mojo v1.0.0b2 by @forfudan in #257
  • [doc] Update documents for release by @forfudan in #258

Full Changelog: v0.10.0...v0.11.0