Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ kgen.trace.json*
local
# CLI binary
/decimo
# Compiled GMP/MPFR wrapper (built from source)
*.dylib
*.so
# Python build artifacts
*.so
__pycache__/
Expand Down
26 changes: 26 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Decimo
Copyright 2025 Yuhao Zhu

Licensed under the Apache License, Version 2.0.


Third-Party Dependencies
========================

Decimo optionally uses the following libraries at runtime, if installed by
the user. Decimo does not include, copy, or distribute any source code or
binaries from these projects.

GNU MPFR Library (https://www.mpfr.org/)
Copyright (C) Free Software Foundation, Inc.
Licensed under the GNU Lesser General Public License v3.0 or later (LGPLv3+).

GNU Multiple Precision Arithmetic Library (GMP) (https://gmplib.org/)
Copyright (C) Free Software Foundation, Inc.
Licensed under the GNU Lesser General Public License v3.0 or later (LGPLv3+),
or the GNU General Public License v2.0 or later (GPLv2+).

MPFR and GMP are loaded at runtime via dlopen/dlsym when the user has
independently installed them (e.g. `brew install mpfr` on macOS or
`apt install libmpfr-dev` on Linux). The BigFloat type requires MPFR;
all other Decimo types work without any external dependencies.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ The core types are[^auxiliary]:
| `Decimal` | `BDec`, `BigDecimal` | Equivalent to Python's `decimal.Decimal` | Base-10^9 |
| `Dec128` | `Decimal128` | 128-bit fixed-precision decimal type | Triple 32-bit words |

---

**Decimo** combines "**Deci**mal" and "**Mo**jo" - reflecting its purpose and implementation language. "Decimo" is also a Latin word meaning "tenth" and is the root of the word "decimal".

---
A CLI calculator tool, built on top of the Decimo library and powered by [ArgMojo](https://github.com/forfudan/argmojo) (a command-line argument parser library), is also available in this repository. It provides a convenient way to perform high-precision calculations directly from the command line.

This repository includes a built-in [TOML parser](./docs/readme_toml.md) (`decimo.toml`), a lightweight pure-Mojo implementation supporting TOML v1.0. It parses configuration files and test data, supporting basic types, arrays, and nested tables. While created for Decimo's testing framework, it offers general-purpose structured data parsing with a clean, simple API.

Expand Down
1,610 changes: 1,610 additions & 0 deletions docs/plans/gmp_integration.md

Large diffs are not rendered by default.

Empty file added docs/readme_cli.md
Empty file.
22 changes: 6 additions & 16 deletions docs/readme_unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
An arbitrary-precision integer and decimal library for [Mojo](https://www.modular.com/mojo), inspired by Python's `int` and `Decimal`.

[![Version](https://img.shields.io/github/v/tag/forfudan/decimo?label=version&color=blue)](https://github.com/forfudan/decimo/releases)
[![Mojo](https://img.shields.io/badge/mojo-0.26.2-orange)](https://docs.modular.com/mojo/manual/)
[![pixi](https://img.shields.io/badge/pixi%20add-decimo-purple)](https://prefix.dev/channels/modular-community/packages/decimo)
[![CI](https://img.shields.io/github/actions/workflow/status/forfudan/decimo/run_tests.yaml?branch=main&label=tests)](https://github.com/forfudan/decimo/actions/workflows/run_tests.yaml)
[![Last Commit](https://img.shields.io/github/last-commit/forfudan/decimo?color=red)](https://github.com/forfudan/decimo/commits/main)

<!--
[![Mojo](https://img.shields.io/badge/mojo-0.26.2-orange)](https://docs.modular.com/mojo/manual/)
[![License](https://img.shields.io/github/license/forfudan/decimo)](LICENSE)
[![Stars](https://img.shields.io/github/stars/forfudan/decimo?style=flat)](https://github.com/forfudan/decimo/stargazers)
[![Issues](https://img.shields.io/github/issues/forfudan/decimo)](https://github.com/forfudan/decimo/issues)
![Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey)
[![Last Commit](https://img.shields.io/github/last-commit/forfudan/decimo?color=red)](https://github.com/forfudan/decimo/commits/main)
-->

<!--
Expand Down Expand Up @@ -40,23 +40,11 @@ The core types are[^auxiliary]:
| `Decimal` | `BDec`, `BigDecimal` | Equivalent to Python's `decimal.Decimal` | Base-10^9 |
| `Dec128` | `Decimal128` | 128-bit fixed-precision decimal type | Triple 32-bit words |

---

**Decimo** combines "**Deci**mal" and "**Mo**jo" - reflecting its purpose and implementation language. "Decimo" is also a Latin word meaning "tenth" and is the root of the word "decimal".

---

Decimo also includes **a command-line calculator application** that supports arbitrary-precision calculations, powered by [ArgMojo - a command-line argument parser library for Mojo](https://github.com/forfudan/argmojo).

You can use it to evaluate complex mathematical expressions with high precision directly from your terminal. For example:
A CLI calculator tool, built on top of the Decimo library and powered by [ArgMojo](https://github.com/forfudan/argmojo) (a command-line argument parser library), is also available in this repository. It provides a convenient way to perform high-precision calculations directly from the command line.

```bash
./decimo "2^10 + sqrt(pi) * ln(e^3) - root(125, 3) / abs(-5) + sin(pi/2)" -p 50 --scientific
```

---

Decimo also includes a built-in [TOML parser](./docs/readme_toml.md) (`decimo.toml`), a lightweight pure-Mojo implementation supporting TOML v1.0. It parses configuration files and test data, supporting basic types, arrays, and nested tables. While created for Decimo's testing framework, it offers general-purpose structured data parsing with a clean, simple API.
This repository includes a built-in [TOML parser](./docs/readme_toml.md) (`decimo.toml`), a lightweight pure-Mojo implementation supporting TOML v1.0. It parses configuration files and test data, supporting basic types, arrays, and nested tables. While created for Decimo's testing framework, it offers general-purpose structured data parsing with a clean, simple API.

## Installation

Expand Down Expand Up @@ -384,6 +372,8 @@ If you find Decimo useful, consider listing it in your citations.

This repository and its contributions are licensed under the Apache License v2.0.

The `BigFloat` type optionally uses the [GNU MPFR Library](https://www.mpfr.org/) (LGPLv3+) and [GMP](https://gmplib.org/) (LGPLv3+ or GPLv2+) at runtime. Decimo does not include or distribute any MPFR/GMP source code or binaries — they are loaded via `dlopen` only if the user has independently installed them. All other Decimo types work without any external dependencies. See the [NOTICE](./NOTICE) file for details.

[^fixed]: The `Decimal128` type can represent values with up to 29 significant digits and a maximum of 28 digits after the decimal point. When a value exceeds the maximum representable value (`2^96 - 1`), Decimo either raises an error or rounds the value to fit within these constraints. For example, the significant digits of `8.8888888888888888888888888888` (29 eights total with 28 after the decimal point) exceeds the maximum representable value (`2^96 - 1`) and is automatically rounded to `8.888888888888888888888888889` (28 eights total with 27 after the decimal point). Decimo's `Decimal128` type is similar to `System.Decimal` (C#/.NET), `rust_decimal` in Rust, `DECIMAL/NUMERIC` in SQL Server, etc.
[^bigint]: The `BigInt` implementation uses a base-2^32 representation with a little-endian format, where the least significant word is stored at index 0. Each word is a `UInt32`, allowing for efficient storage and arithmetic operations on large integers. This design choice optimizes performance for binary computations while still supporting arbitrary precision.
[^auxiliary]: The auxiliary types include a base-10 arbitrary-precision signed integer type (`BigInt10`) and a base-10 arbitrary-precision unsigned integer type (`BigUInt`) supporting unlimited digits[^bigint10]. `BigUInt` is used as the internal representation for `BigInt10` and `Decimal`.
Expand Down
4 changes: 4 additions & 0 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ ttoml = "clear && pixi run testtoml"
# bench
bench = "pixi run package && bash benches/run_bench.sh"

# gmp/mpfr wrapper (compile C wrapper — no MPFR needed at build time)
bgmp = "clear && pixi run buildgmp"
buildgmp = "bash src/decimo/gmp/build_gmp_wrapper.sh"

# bench with debug assertions enabled
bdec_debug = """clear && pixi run package && cd benches/bigdecimal \
&& pixi run mojo run -I ../ -D ASSERT=all bench.mojo && cd ../.. \
Expand Down
30 changes: 30 additions & 0 deletions src/decimo/bigfloat/__init__.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# ===----------------------------------------------------------------------=== #
# Copyright 2025 Yuhao Zhu
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #

"""Sub-package for arbitrary-precision binary floating-point type.

BigFloat is an MPFR-backed binary float type. It requires MPFR to be installed
on the system (`brew install mpfr` on macOS, `apt install libmpfr-dev` on Linux).

BigFloat is the fast path for scientific computing at high precision. Every
operation (sqrt, exp, ln, sin, cos, tan, pi, divide) is a single MPFR call.

For exact decimal arithmetic without external dependencies, use BigDecimal instead.

Modules:
- bigfloat: Core BigFloat struct with constructors, arithmetic, transcendentals
- mpfr_wrapper: Low-level FFI bindings to the MPFR C wrapper
"""
98 changes: 98 additions & 0 deletions src/decimo/bigfloat/bigfloat.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# ===----------------------------------------------------------------------=== #
# Copyright 2025 Yuhao Zhu
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #

"""Implements the BigFloat type: arbitrary-precision binary floating-point.

BigFloat wraps a single MPFR handle via a C wrapper. Every arithmetic and
transcendental operation is a single MPFR call. Requires MPFR at runtime.

Usage:
from decimo.bigfloat.bigfloat import BigFloat

var x = BigFloat("3.14159", precision=1000)
var r = x.sqrt()
var bd = r.to_bigdecimal(1000)

Design:
- Single field: `handle: Int32` (index into C wrapper's mpfr_t handle pool)
- Precision specified in decimal digits, converted to bits internally
- Guard bits (64 extra) ensure requested decimal digits are correct
- RAII: destructor frees MPFR handle via `mpfrw_clear`
"""

from decimo.bigfloat.mpfr_wrapper import (
mpfrw_available,
mpfrw_init,
mpfrw_clear,
mpfrw_set_str,
mpfrw_get_str,
mpfrw_free_str,
mpfrw_add,
mpfrw_sub,
mpfrw_mul,
mpfrw_div,
mpfrw_neg,
mpfrw_abs,
mpfrw_cmp,
mpfrw_sqrt,
mpfrw_exp,
mpfrw_log,
mpfrw_sin,
mpfrw_cos,
mpfrw_tan,
mpfrw_pow,
mpfrw_rootn_ui,
mpfrw_const_pi,
)

# Guard bits added to user-requested precision to absorb binary↔decimal rounding.
comptime _GUARD_BITS: Int = 64

# Approximate bits per decimal digit: ceil(log2(10)) ≈ 3.322 → use 4 for safety.
comptime _BITS_PER_DIGIT: Int = 4


fn _dps_to_bits(precision: Int) -> Int:
"""Converts decimal digit precision to MPFR bit precision with guard bits.
"""
return precision * _BITS_PER_DIGIT + _GUARD_BITS


# TODO: Implement BigFloat struct.
#
# struct BigFloat:
# var handle: Int32
#
# fn __init__(out self, value: String, precision: Int) raises:
# ...
#
# fn __init__(out self, bd: BigDecimal, precision: Int) raises:
# ...
#
# fn sqrt(self) raises -> Self:
# ...
#
# fn exp(self) raises -> Self:
# ...
#
# fn ln(self) raises -> Self:
# ...
#
# fn to_bigdecimal(self, precision: Int) raises -> BigDecimal:
# ...
#
# fn __del__(owned self):
# mpfrw_clear(self.handle)
Loading
Loading