Skip to content

Commit 635b1fd

Browse files
authored
Update DeciMojo to v0.6.0 (#190)
* update recipe and readme * Update recipe
1 parent 2984474 commit 635b1fd

File tree

2 files changed

+187
-127
lines changed

2 files changed

+187
-127
lines changed

recipes/decimojo/README.md

Lines changed: 178 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -18,119 +18,143 @@ The core types are:
1818

1919
This repository includes [TOMLMojo](https://github.com/forfudan/decimojo/tree/main/src/tomlmojo), a lightweight TOML parser in pure Mojo. It parses configuration files and test data, supporting basic types, arrays, and nested tables. While created for DeciMojo's testing framework, it offers general-purpose structured data parsing with a clean, simple API.
2020

21-
| type | alias | information | internal representation |
22-
| ------------ | ------- | ------------------------------------ | ----------------------------------- |
23-
| `BigUInt` | `BUInt` | arbitrary-precision unsigned integer | `List[UInt32]` |
24-
| `BigInt` | `BInt` | arbitrary-precision integer | `BigUInt`, `Bool` |
25-
| `Decimal` | `Dec` | 128-bit fixed-precision decimal | `UInt32`,`UInt32`,`UInt32`,`UInt32` |
26-
| `BigDecimal` | `BDec` | arbitrary-precision decimal | `BigUInt`, `Int`, `Bool` |
21+
| type | alias | information | internal representation |
22+
| ------------ | ----------------- | ------------------------------------ | ----------------------------------- |
23+
| `BigUInt` | `BUInt` | arbitrary-precision unsigned integer | `List[UInt32]` |
24+
| `BigInt` | `BInt` | arbitrary-precision integer | `BigUInt`, `Bool` |
25+
| `BigDecimal` | `BDec`, `Decimal` | arbitrary-precision decimal | `BigUInt`, `Int`, `Bool` |
26+
| `Decimal128` | `Dec128` | 128-bit fixed-precision decimal | `UInt32`,`UInt32`,`UInt32`,`UInt32` |
2727

2828
## Installation
2929

3030
DeciMojo is available in the [modular-community](https://repo.prefix.dev/modular-community) package repository. You can install it using any of these methods:
3131

32-
From the `magic` CLI, simply run ```magic add decimojo```. This fetches the latest version and makes it immediately available for import.
32+
1. From the `pixi` CLI, run the command ```pixi add decimojo```. This fetches the latest version and makes it immediately available for import.
3333

34-
For projects with a `mojoproject.toml`file, add the dependency ```decimojo = ">=0.3.0"```. Then run `magic install` to download and install the package.
34+
1. In the `mojoproject.toml` file of your project, add the following dependency:
3535

36-
For the latest development version, clone the [GitHub repository](https://github.com/forfudan/decimojo) and build the package locally.
36+
```toml
37+
decimojo = "==0.6.0"
38+
```
3739

38-
| `decimojo` | `mojo` |
39-
| ---------- | ------ |
40-
| v0.1.0 | >=25.1 |
41-
| v0.2.0 | >=25.2 |
42-
| v0.3.0 | >=25.2 |
40+
Then run `pixi install` to download and install the package.
41+
42+
1. For the latest development version in the `main` branch, clone [this GitHub repository](https://github.com/forfudan/decimojo) and build the package locally using the command `pixi run package`.
43+
44+
The following table summarizes the package versions and their corresponding Mojo versions:
45+
46+
| `decimojo` | `mojo` | package manager |
47+
| ---------- | ------------- | --------------- |
48+
| v0.1.0 | ==25.1 | magic |
49+
| v0.2.0 | ==25.2 | magic |
50+
| v0.3.0 | ==25.2 | magic |
51+
| v0.3.1 | >=25.2, <25.4 | pixi |
52+
| v0.4.x | ==25.4 | pixi |
53+
| v0.5.0 | ==25.5 | pixi |
54+
| v0.6.0 | ==0.25.7 | pixi |
4355

4456
## Quick start
4557

46-
Here is a comprehensive quick-start guide showcasing each major function of the `Decimal` type.
58+
You can start using DeciMojo by importing the `decimojo` module. An easy way to do this is to import everything from the `prelude` module, which provides the most commonly used types.
4759

4860
```mojo
49-
from decimojo import Decimal, RoundingMode
50-
51-
fn main() raises:
52-
# === Construction ===
53-
var a = Decimal("123.45") # From string
54-
var b = Decimal(123) # From integer
55-
var c = Decimal(123, 2) # Integer with scale (1.23)
56-
var d = Decimal.from_float(3.14159) # From floating-point
57-
58-
# === Basic Arithmetic ===
59-
print(a + b) # Addition: 246.45
60-
print(a - b) # Subtraction: 0.45
61-
print(a * b) # Multiplication: 15184.35
62-
print(a / b) # Division: 1.0036585365853658536585365854
63-
64-
# === Rounding & Precision ===
65-
print(a.round(1)) # Round to 1 decimal place: 123.5
66-
print(a.quantize(Decimal("0.01"))) # Format to 2 decimal places: 123.45
67-
print(a.round(0, RoundingMode.ROUND_DOWN)) # Round down to integer: 123
68-
69-
# === Comparison ===
70-
print(a > b) # Greater than: True
71-
print(a == Decimal("123.45")) # Equality: True
72-
print(a.is_zero()) # Check for zero: False
73-
print(Decimal("0").is_zero()) # Check for zero: True
74-
75-
# === Type Conversions ===
76-
print(Float64(a)) # To float: 123.45
77-
print(a.to_int()) # To integer: 123
78-
print(a.to_str()) # To string: "123.45"
79-
print(a.coefficient()) # Get coefficient: 12345
80-
print(a.scale()) # Get scale: 2
81-
82-
# === Mathematical Functions ===
83-
print(Decimal("2").sqrt()) # Square root: 1.4142135623730950488016887242
84-
print(Decimal("100").root(3)) # Cube root: 4.641588833612778892410076351
85-
print(Decimal("2.71828").ln()) # Natural log: 0.9999993273472820031578910056
86-
print(Decimal("10").log10()) # Base-10 log: 1
87-
print(Decimal("16").log(Decimal("2"))) # Log base 2: 3.9999999999999999999999999999
88-
print(Decimal("10").exp()) # e^10: 22026.465794806716516957900645
89-
print(Decimal("2").power(10)) # Power: 1024
90-
91-
# === Sign Handling ===
92-
print(-a) # Negation: -123.45
93-
print(abs(Decimal("-123.45"))) # Absolute value: 123.45
94-
print(Decimal("123.45").is_negative()) # Check if negative: False
95-
96-
# === Special Values ===
97-
print(Decimal.PI()) # π constant: 3.1415926535897932384626433833
98-
print(Decimal.E()) # e constant: 2.7182818284590452353602874714
99-
print(Decimal.ONE()) # Value 1: 1
100-
print(Decimal.ZERO()) # Value 0: 0
101-
print(Decimal.MAX()) # Maximum value: 79228162514264337593543950335
102-
103-
# === Convenience Methods ===
104-
print(Decimal("123.400").is_integer()) # Check if integer: False
105-
print(a.number_of_significant_digits()) # Count significant digits: 5
106-
print(Decimal("12.34").to_str_scientific()) # Scientific notation: 1.234E+1
61+
from decimojo import *
10762
```
10863

109-
[Click here for 8 key examples](https://zhuyuhao.com/decimojo/docs/examples) highlighting the most important features of the `Decimal` type.
64+
This will import the following types or aliases into your namespace:
65+
66+
- `dm`: An alias for the `decimojo` module.
67+
- `BigInt` (alias `BInt`): An arbitrary-precision signed integer type.
68+
- `BigDecimal` (aliases `BDec` and `Decimal`): An arbitrary-precision decimal type.
69+
- `Decimal128` (alias `Dec128`): A 128-bit fixed-precision decimal type.
70+
- `RoundingMode` (alias `RM`): An enumeration for rounding modes.
71+
- `ROUND_DOWN`, `ROUND_HALF_UP`, `ROUND_HALF_EVEN`, `ROUND_UP`: Constants for common rounding modes.
11072

111-
Here are some examples showcasing the arbitrary-precision feature of the `BigDecimal` type.
73+
---
74+
75+
Here are some examples showcasing the arbitrary-precision feature of the `BigDecimal` type (aliases: `BDec` and `Decimal`). For some mathematical operations, the default precision (number of significant digits) is set to `36`. You can change the precision by passing the `precision` argument to the function. This default precision will be configurable globally in future when Mojo supports global variables.
11276

11377
```mojo
114-
from decimojo import BDec, RM
78+
from decimojo.prelude import *
11579
11680
11781
fn main() raises:
118-
var PRECISION = 100
119-
var a = BDec("123456789.123456789")
120-
var b = BDec("1234.56789")
121-
print(a.sqrt(precision=PRECISION))
122-
# 11111.11106611111096943055498174930232833813065468909453818857935956641682120364106016272519460988485
123-
print(a.power(b, precision=PRECISION))
124-
# 3.346361102419080234023813540078946868219632448203078657310495672766009862564151996325555496759911131748170844123475135377098326591508239654961E+9989
125-
print(a.log(b, precision=PRECISION))
126-
# 2.617330026656548299907884356415293977170848626010103229392408225981962436022623783231699264341492663671325580092077394824180414301026578169909
82+
var a = BDec("123456789.123456789") # BDec is an alias for BigDecimal
83+
var b = Decimal(
84+
"1234.56789"
85+
) # Decimal is a Python-like alias for BigDecimal
86+
87+
# === Basic Arithmetic === #
88+
print(a + b) # 123458023.691346789
89+
print(a - b) # 123455554.555566789
90+
print(a * b) # 152415787654.32099750190521
91+
print(a.true_divide(b + 1)) # 99919.0656560820700835791386582569736
92+
93+
# === Exponential Functions === #
94+
print(a.sqrt(precision=80))
95+
# 11111.111066111110969430554981749302328338130654689094538188579359566416821203641
96+
print(a.cbrt(precision=80))
97+
# 497.93385938415242742001134219007635925452951248903093962731782327785111102410518
98+
print(a.root(b, precision=80))
99+
# 1.0152058862996527138602610522640944903320735973237537866713119992581006582644107
100+
print(a.power(b, precision=80))
101+
# 3.3463611024190802340238135400789468682196324482030786573104956727660098625641520E+9989
102+
print(a.exp(precision=80))
103+
# 1.8612755889649587035842377856492201091251654136588338983610243887893287518637652E+53616602
104+
print(a.log(b, precision=80))
105+
# 2.6173300266565482999078843564152939771708486260101032293924082259819624360226238
106+
print(a.ln(precision=80))
107+
# 18.631401767168018032693933348296537542797015174553735308351756611901741276655161
108+
109+
# === Trigonometric Functions === #
110+
print(a.sin(precision=200))
111+
# 0.99985093087193092464780008002600992896256609588456
112+
# 91036188395766389946401881352599352354527727927177
113+
# 79589259132243649550891532070326452232864052771477
114+
# 31418817041042336608522984511928095747763538486886
115+
print(b.cos(precision=1000))
116+
# -0.9969577603867772005841841569997528013669868536239849713029893885930748434064450375775817720425329394
117+
# 9756020177557431933434791661179643984869397089102223199519409695771607230176923201147218218258755323
118+
# 7563476302904118661729889931783126826250691820526961290122532541861737355873869924820906724540889765
119+
# 5940445990824482174517106016800118438405307801022739336016834311018727787337447844118359555063575166
120+
# 5092352912854884589824773945355279792977596081915868398143592738704592059567683083454055626123436523
121+
# 6998108941189617922049864138929932713499431655377552668020889456390832876383147018828166124313166286
122+
# 6004871998201597316078894718748251490628361253685772937806895692619597915005978762245497623003811386
123+
# 0913693867838452088431084666963414694032898497700907783878500297536425463212578556546527017688874265
124+
# 0785862902484462361413598747384083001036443681873292719322642381945064144026145428927304407689433744
125+
# 5821277763016669042385158254006302666602333649775547203560187716156055524418512492782302125286330865
126+
127+
# === Internal representation of the number === #
128+
(
129+
Decimal(
130+
"3.141592653589793238462643383279502884197169399375105820974944"
131+
).power(2, precision=60)
132+
).print_internal_representation()
133+
# Internal Representation Details of BigDecimal
134+
# ----------------------------------------------
135+
# number: 9.8696044010893586188344909998
136+
# 761511353136994072407906264133
137+
# 5
138+
# coefficient: 986960440108935861883449099987
139+
# 615113531369940724079062641335
140+
# negative: False
141+
# scale: 59
142+
# word 0: 62641335
143+
# word 1: 940724079
144+
# word 2: 113531369
145+
# word 3: 99987615
146+
# word 4: 861883449
147+
# word 5: 440108935
148+
# word 6: 986960
149+
# ----------------------------------------------
127150
```
128151

129-
Here is a comprehensive quick-start guide showcasing each major function of the `BigInt` type.
152+
---
153+
154+
Here is a comprehensive quick-start guide showcasing each major function of the `BigInt` type (`BInt`).
130155

131156
```mojo
132-
from decimojo import BigInt, BInt
133-
# BInt is an alias for BigInt
157+
from decimojo.prelude import *
134158
135159
fn main() raises:
136160
# === Construction ===
@@ -157,7 +181,7 @@ fn main() raises:
157181
print(a.is_zero()) # Check for zero: False
158182
159183
# === Type Conversions ===
160-
print(a.to_str()) # To string: "12345678901234567890"
184+
print(String(a)) # To string: "12345678901234567890"
161185
162186
# === Sign Handling ===
163187
print(-a) # Negation: -12345678901234567890
@@ -169,6 +193,71 @@ fn main() raises:
169193
print(BInt("123456789" * 400) // BInt("987654321" * 200))
170194
```
171195

196+
---
197+
198+
Here is a comprehensive quick-start guide showcasing each major function of the `Decimal128` type (`Dec128`).
199+
200+
```mojo
201+
from decimojo.prelude import *
202+
203+
fn main() raises:
204+
# === Construction ===
205+
var a = Dec128("123.45") # From string
206+
var b = Dec128(123) # From integer
207+
var c = Dec128(123, 2) # Integer with scale (1.23)
208+
var d = Dec128.from_float(3.14159) # From floating-point
209+
210+
# === Basic Arithmetic ===
211+
print(a + b) # Addition: 246.45
212+
print(a - b) # Subtraction: 0.45
213+
print(a * b) # Multiplication: 15184.35
214+
print(a / b) # Division: 1.0036585365853658536585365854
215+
216+
# === Rounding & Precision ===
217+
print(a.round(1)) # Round to 1 decimal place: 123.5
218+
print(a.quantize(Dec128("0.01"))) # Format to 2 decimal places: 123.45
219+
print(a.round(0, RoundingMode.ROUND_DOWN)) # Round down to integer: 123
220+
221+
# === Comparison ===
222+
print(a > b) # Greater than: True
223+
print(a == Dec128("123.45")) # Equality: True
224+
print(a.is_zero()) # Check for zero: False
225+
print(Dec128("0").is_zero()) # Check for zero: True
226+
227+
# === Type Conversions ===
228+
print(Float64(a)) # To float: 123.45
229+
print(a.to_int()) # To integer: 123
230+
print(a.to_str()) # To string: "123.45"
231+
print(a.coefficient()) # Get coefficient: 12345
232+
print(a.scale()) # Get scale: 2
233+
234+
# === Mathematical Functions ===
235+
print(Dec128("2").sqrt()) # Square root: 1.4142135623730950488016887242
236+
print(Dec128("100").root(3)) # Cube root: 4.641588833612778892410076351
237+
print(Dec128("2.71828").ln()) # Natural log: 0.9999993273472820031578910056
238+
print(Dec128("10").log10()) # Base-10 log: 1
239+
print(Dec128("16").log(Dec128("2"))) # Log base 2: 3.9999999999999999999999999999
240+
print(Dec128("10").exp()) # e^10: 22026.465794806716516957900645
241+
print(Dec128("2").power(10)) # Power: 1024
242+
243+
# === Sign Handling ===
244+
print(-a) # Negation: -123.45
245+
print(abs(Dec128("-123.45"))) # Absolute value: 123.45
246+
print(Dec128("123.45").is_negative()) # Check if negative: False
247+
248+
# === Special Values ===
249+
print(Dec128.PI()) # π constant: 3.1415926535897932384626433833
250+
print(Dec128.E()) # e constant: 2.7182818284590452353602874714
251+
print(Dec128.ONE()) # Value 1: 1
252+
print(Dec128.ZERO()) # Value 0: 0
253+
print(Dec128.MAX()) # Maximum value: 79228162514264337593543950335
254+
255+
# === Convenience Methods ===
256+
print(Dec128("123.400").is_integer()) # Check if integer: False
257+
print(a.number_of_significant_digits()) # Count significant digits: 5
258+
print(Dec128("12.34").to_str_scientific()) # Scientific notation: 1.234E+1
259+
```
260+
172261
## Objective
173262

174263
Financial calculations and data analysis require precise decimal arithmetic that floating-point numbers cannot reliably provide. As someone working in finance and credit risk model validation, I needed a dependable correctly-rounded, fixed-precision numeric type when migrating my personal projects from Python to Mojo.
@@ -191,28 +280,6 @@ Rome wasn't built in a day. DeciMojo is currently under active development. It h
191280

192281
Regular benchmarks against Python's `decimal` module are available in the `bench/` folder, documenting both the performance advantages and the few specific operations where different approaches are needed.
193282

194-
## Tests and benches
195-
196-
After cloning the repo onto your local disk, you can:
197-
198-
- Use `magic run test` to run tests.
199-
- Use `magic run bench_decimal` to generate logs for benchmarking tests against `python.decimal` module. The log files are saved in `benches/decimal/logs/`.
200-
201-
## Citation
202-
203-
If you find DeciMojo useful for your research, consider listing it in your citations.
204-
205-
```tex
206-
@software{Zhu.2025,
207-
author = {Zhu, Yuhao},
208-
year = {2025},
209-
title = {An arbitrary-precision decimal and integer mathematics library for Mojo},
210-
url = {https://github.com/forfudan/decimojo},
211-
version = {0.3.0},
212-
note = {Computer Software}
213-
}
214-
```
215-
216283
## License
217284

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

recipes/decimojo/recipe.yaml

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,28 @@
11
context:
2-
version: "0.4.1"
2+
version: "0.6.0"
3+
mojo_version: "=0.25.7"
34

45
package:
56
name: "decimojo"
67
version: ${{ version }}
78

89
source:
910
- git: https://github.com/forFudan/decimojo.git
10-
rev: 51c983229749df1caf490ccb9ddea19e7f220441
11+
rev: 0fab1a2349cf05b854c4c204ec2121f634396809
1112

1213
build:
1314
number: 0
1415
script:
16+
- mkdir -p ${PREFIX}/lib/mojo
1517
- mojo package src/decimojo -o ${{ PREFIX }}/lib/mojo/decimojo.mojopkg
18+
1619
requirements:
1720
host:
18-
- max=25.4
21+
- mojo-compiler ${{ mojo_version }}
22+
build:
23+
- mojo-compiler ${{ mojo_version }}
1924
run:
20-
- ${{ pin_compatible('max') }}
21-
22-
tests:
23-
- script:
24-
- if: unix
25-
then:
26-
- mojo run tests.mojo
27-
requirements:
28-
run:
29-
- max=25.4
30-
files:
31-
recipe:
32-
- tests.mojo
25+
- mojo-compiler ${{ mojo_version }}
3326

3427
about:
3528
homepage: https://github.com/forFudan/decimojo.git

0 commit comments

Comments
 (0)