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: 1 addition & 2 deletions .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,9 @@ jobs:
cp decimojo.mojopkg tests/
cp decimojo.mojopkg benches/

- name: Run tests and benches
- name: Run tests
run: |
magic run mojo test tests
magic run bench

- name: Install pre-commit
run: |
Expand Down
326 changes: 123 additions & 203 deletions README.md

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions benches/bench_exp.mojo → benches/decimal/bench_exp.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn run_benchmark(
var py_decimal = pydecimal.Decimal(input_value)

# Execute the operations once to verify correctness
var mojo_result = dm.exponential.exp(mojo_decimal)
var mojo_result = mojo_decimal.exp()
var py_result = py_decimal.exp()

# Display results for verification
Expand All @@ -83,7 +83,7 @@ fn run_benchmark(
# Benchmark Mojo implementation
var t0 = perf_counter_ns()
for _ in range(iterations):
_ = dm.exponential.exp(mojo_decimal)
_ = mojo_decimal.exp()
var mojo_time = (perf_counter_ns() - t0) / iterations
if mojo_time == 0:
mojo_time = 1 # Prevent division by zero
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions benches/bench_ln.mojo → benches/decimal/bench_ln.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fn run_benchmark(
var py_decimal = pydecimal.Decimal(input_value)

# Execute the operations once to verify correctness
var mojo_result = dm.exponential.ln(mojo_decimal)
var mojo_result = dm.decimal.exponential.ln(mojo_decimal)
var py_result = py_decimal.ln()

# Display results for verification
Expand All @@ -83,7 +83,7 @@ fn run_benchmark(
# Benchmark Mojo implementation
var t0 = perf_counter_ns()
for _ in range(iterations):
_ = dm.exponential.ln(mojo_decimal)
_ = dm.decimal.exponential.ln(mojo_decimal)
var mojo_time = (perf_counter_ns() - t0) / iterations
if mojo_time == 0:
mojo_time = 1 # Prevent division by zero
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ fn main() raises:

# Case 11: Decimal multiplication with many digits after the decimal point
var case11_a_mojo = Decimal.E()
var case11_b_mojo = dm.constants.E0D5()
var case11_b_mojo = dm.decimal.constants.E0D5()
var case11_a_py = pydecimal.Decimal("1").exp()
var case11_b_py = pydecimal.Decimal("0.5").exp()
run_benchmark(
Expand Down
4 changes: 2 additions & 2 deletions benches/bench_power.mojo → benches/decimal/bench_power.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn run_benchmark(
var py_exponent = pydecimal.Decimal(exponent_value)

# Execute the operations once to verify correctness
var mojo_result = dm.exponential.power(mojo_base, mojo_exponent)
var mojo_result = dm.decimal.exponential.power(mojo_base, mojo_exponent)
var py_result = py_base**py_exponent

# Display results for verification
Expand All @@ -88,7 +88,7 @@ fn run_benchmark(
# Benchmark Mojo implementation
var t0 = perf_counter_ns()
for _ in range(iterations):
_ = dm.exponential.power(mojo_base, mojo_exponent)
_ = dm.decimal.exponential.power(mojo_base, mojo_exponent)
var mojo_time = (perf_counter_ns() - t0) / iterations
if mojo_time == 0:
mojo_time = 1 # Prevent division by zero
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions benches/bench_root.mojo → benches/decimal/bench_root.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ fn run_benchmark(
var py_result: PythonObject

# Execute the operations once to verify correctness
var mojo_result = dm.exponential.root(mojo_decimal, nth_root)
var mojo_result = dm.decimal.exponential.root(mojo_decimal, nth_root)

# Handle Python calculation, accounting for negative odd root limitation
if is_negative_odd_root:
Expand Down Expand Up @@ -127,7 +127,7 @@ fn run_benchmark(
# Benchmark Mojo implementation
var t0 = perf_counter_ns()
for _ in range(iterations):
_ = dm.exponential.root(mojo_decimal, nth_root)
_ = dm.decimal.exponential.root(mojo_decimal, nth_root)
var mojo_time = (perf_counter_ns() - t0) / iterations
if mojo_time == 0:
mojo_time = 1 # Prevent division by zero
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
162 changes: 162 additions & 0 deletions docs/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Examples on Decimal

Here are 8 key examples highlighting the most important features of the `Decimal` type in its current state:

## 1. Fixed-Point Precision for Financial Calculations

```mojo
from decimojo import dm, Decimal

# The classic floating-point problem
print(0.1 + 0.2) # 0.30000000000000004 (not exactly 0.3)

# Decimal solves this with exact representation
var d1 = Decimal("0.1")
var d2 = Decimal("0.2")
var sum = d1 + d2
print(sum) # Exactly 0.3

# Financial calculation example - computing tax
var price = Decimal("19.99")
var tax_rate = Decimal("0.0725")
var tax = price * tax_rate # Exactly 1.449275
var total = price + tax # Exactly 21.439275
```

## 2. Basic Arithmetic with Proper Banker's Rounding

```mojo
# Addition with different scales
var a = Decimal("123.45")
var b = Decimal("67.8")
print(a + b) # 191.25 (preserves highest precision)

# Subtraction with negative result
var c = Decimal("50")
var d = Decimal("75.25")
print(c - d) # -25.25

# Multiplication with banker's rounding (round to even)
var e = Decimal("12.345")
var f = Decimal("5.67")
print(round(e * f, 2)) # 69.96 (rounds to nearest even)

# Division with banker's rounding
var g = Decimal("10")
var h = Decimal("3")
print(round(g / h, 2)) # 3.33 (rounded banker's style)
```

## 3. Scale and Precision Management

```mojo
# Scale refers to number of decimal places
var d1 = Decimal("123.45")
print(d1.scale()) # 2

# Precision control with explicit rounding
var d2 = Decimal("123.456")
print(d2.round_to_scale(1)) # 123.5 (banker's rounding)

# High precision is preserved (up to 28 decimal places)
var precise = Decimal("0.1234567890123456789012345678")
print(precise) # 0.1234567890123456789012345678
```

## 4. Sign Handling and Absolute Value

```mojo
# Negation operator
var pos = Decimal("123.45")
var neg = -pos
print(neg) # -123.45

# Absolute value
var abs_val = abs(Decimal("-987.65"))
print(abs_val) # 987.65

# Sign checking
print(Decimal("-123.45").is_negative()) # True
print(Decimal("0").is_negative()) # False

# Sign preservation in multiplication
print(Decimal("-5") * Decimal("3")) # -15
print(Decimal("-5") * Decimal("-3")) # 15
```

## 5. Advanced Mathematical Operations

```mojo
# Highly accurate square root implementation
var root2 = Decimal("2").sqrt()
print(root2) # 1.4142135623730950488016887242

# Square root of imperfect squares
var root_15_9999 = Decimal("15.9999").sqrt()
print(root_15_9999) # 3.9999874999804686889646053305

# Integer powers with fast binary exponentiation
var cubed = Decimal("3") ** 3
print(cubed) # 27

# Negative powers (reciprocals)
var recip = Decimal("2") ** (-1)
print(recip) # 0.5
```

## 6. Robust Edge Case Handling

```mojo
# Division by zero is properly caught
try:
var result = Decimal("10") / Decimal("0")
except:
print("Division by zero properly detected")

# Zero raised to negative power
try:
var invalid = Decimal("0") ** (-1)
except:
print("Zero to negative power properly detected")

# Overflow detection and prevention
var max_val = Decimal.MAX()
try:
var overflow = max_val * Decimal("2")
except:
print("Overflow correctly detected")
```

## 7. Equality and Comparison Operations

```mojo
# Equal values with different scales
var a = Decimal("123.4500")
var b = Decimal("123.45")
print(a == b) # True (numeric value equality)

# Comparison operators
var c = Decimal("100")
var d = Decimal("200")
print(c < d) # True
print(c <= d) # True
print(c > d) # False
print(c >= d) # False
print(c != d) # True
```

## 8. Real World Financial Examples

```mojo
# Monthly loan payment calculation with precise interest
var principal = Decimal("200000") # $200,000 loan
var annual_rate = Decimal("0.05") # 5% interest rate
var monthly_rate = annual_rate / Decimal("12")
var num_payments = Decimal("360") # 30 years

# Monthly payment formula: P * r(1+r)^n/((1+r)^n-1)
var numerator = monthly_rate * (Decimal("1") + monthly_rate) ** 360
var denominator = (Decimal("1") + monthly_rate) ** 360 - Decimal("1")
var payment = principal * (numerator / denominator)
print("Monthly payment: $" + String(round(payment, 2))) # $1,073.64
```
54 changes: 5 additions & 49 deletions mojoproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,56 +19,12 @@ format = "magic run mojo format ./"
package = "magic run format && magic run mojo package src/decimojo && cp decimojo.mojopkg tests/ && cp decimojo.mojopkg benches/ && rm decimojo.mojopkg"
p = "clear && magic run package"

# delete the package files in tests folder
delete_package = "rm tests/decimojo.mojopkg && rm benches/decimojo.mojopkg"

# debugs (run the testing files only)
debug = "magic run package && magic run mojo tests/*.mojo && magic run delete_package"
debug_arith = "magic run package && magic run mojo tests/test_arithmetics.mojo && magic run delete_package"
debug_div = "magic run package && magic run mojo tests/test_division.mojo && magic run delete_package"
debug_sqrt = "magic run package && magic run mojo tests/test_sqrt.mojo && magic run delete_package"
# clean the package files in tests folder
clean = "rm tests/decimojo.mojopkg && rm benches/decimojo.mojopkg"

# tests (use the mojo testing tool)
test = "magic run package && magic run mojo test tests && magic run delete_package"
t = "clear && magic run test"
test_arith = "magic run package && magic run mojo test tests/test_arithmetics.mojo && magic run delete_package"
test_multiply = "magic run package && magic run mojo test tests/test_multiply.mojo && magic run delete_package"
test_divide = "magic run package && magic run mojo test tests/test_divide.mojo && magic run delete_package"
test_floor_divide = "magic run package && magic run mojo test tests/test_floor_divide.mojo && magic run delete_package"
test_modulo = "magic run package && magic run mojo test tests/test_modulo.mojo && magic run delete_package"
test_sqrt = "magic run package && magic run mojo test tests/test_sqrt.mojo && magic run delete_package"
test_root = "magic run package && magic run mojo test tests/test_root.mojo && magic run delete_package"
test_round = "magic run package && magic run mojo test tests/test_round.mojo && magic run delete_package"
test_quantize = "magic run package && magic run mojo test tests/test_quantize.mojo && magic run delete_package"
test_from_components = "magic run package && magic run mojo test tests/test_from_components.mojo && magic run delete_package"
test_from_float = "magic run package && magic run mojo test tests/test_from_float.mojo && magic run delete_package"
test_from_string = "magic run package && magic run mojo test tests/test_from_string.mojo && magic run delete_package"
test_from_int = "magic run package && magic run mojo test tests/test_from_int.mojo && magic run delete_package"
test_to_float = "magic run package && magic run mojo test tests/test_to_float.mojo && magic run delete_package"
test_comparison = "magic run package && magic run mojo test tests/test_comparison.mojo && magic run delete_package"
test_factorial = "magic run package && magic run mojo test tests/test_factorial.mojo && magic run delete_package"
test_exp = "magic run package && magic run mojo test tests/test_exp.mojo && magic run delete_package"
test_ln = "magic run package && magic run mojo test tests/test_ln.mojo && magic run delete_package"
test_log = "magic run package && magic run mojo test tests/test_log.mojo && magic run delete_package"
test_log10 = "magic run package && magic run mojo test tests/test_log10.mojo && magic run delete_package"
test_power = "magic run package && magic run mojo test tests/test_power.mojo && magic run delete_package"
test = "magic run package && magic run mojo test tests --filter"
t = "clear && magic run package && magic run mojo test tests --filter"

# benches
bench = "magic run package && cd benches && magic run mojo bench.mojo && cd .. && magic run delete_package"
b = "clear && magic run bench"
bench_multiply = "magic run package && cd benches && magic run mojo bench_multiply.mojo && cd .. && magic run delete_package"
bench_divide = "magic run package && cd benches && magic run mojo bench_divide.mojo && cd .. && magic run delete_package"
bench_floor_divide = "magic run package && cd benches && magic run mojo bench_floor_divide.mojo && cd .. && magic run delete_package"
bench_modulo = "magic run package && cd benches && magic run mojo bench_modulo.mojo && cd .. && magic run delete_package"
bench_sqrt = "magic run package && cd benches && magic run mojo bench_sqrt.mojo && cd .. && magic run delete_package"
bench_root = "magic run package && cd benches && magic run mojo bench_root.mojo && cd .. && magic run delete_package"
bench_round = "magic run package && cd benches && magic run mojo bench_round.mojo && cd .. && magic run delete_package"
bench_quantize = "magic run package && cd benches && magic run mojo bench_quantize.mojo && cd .. && magic run delete_package"
bench_from_float = "magic run package && cd benches && magic run mojo bench_from_float.mojo && cd .. && magic run delete_package"
bench_from_string = "magic run package && cd benches && magic run mojo bench_from_string.mojo && cd .. && magic run delete_package"
bench_from_int = "magic run package && cd benches && magic run mojo bench_from_int.mojo && cd .. && magic run delete_package"
bench_comparison = "magic run package && cd benches && magic run mojo bench_comparison.mojo && cd .. && magic run delete_package"
bench_exp = "magic run package && cd benches && magic run mojo bench_exp.mojo && cd .. && magic run delete_package"
bench_ln = "magic run package && cd benches && magic run mojo bench_ln.mojo && cd .. && magic run delete_package"
bench_log10 = "magic run package && cd benches && magic run mojo bench_log10.mojo && cd .. && magic run delete_package"
bench_power = "magic run package && cd benches && magic run mojo bench_power.mojo && cd .. && magic run delete_package"
bench_decimal = "magic run package && cd benches/decimal && magic run mojo -I ../ bench.mojo && cd ../.. && magic run clean"
12 changes: 6 additions & 6 deletions src/decimojo/__init__.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ from decimojo.prelude import dm, Decimal, RoundingMode
```
"""

from .decimal import Decimal
from .decimal.decimal import Decimal

from .rounding_mode import RoundingMode

from .arithmetics import (
from .decimal.arithmetics import (
add,
subtract,
absolute,
Expand All @@ -42,7 +42,7 @@ from .arithmetics import (
modulo,
)

from .comparison import (
from .decimal.comparison import (
greater,
greater_equal,
less,
Expand All @@ -51,10 +51,10 @@ from .comparison import (
not_equal,
)

from .exponential import power, root, sqrt, exp, ln, log, log10
from .decimal.exponential import power, root, sqrt, exp, ln, log, log10

from .rounding import round, quantize
from .decimal.rounding import round, quantize

from .special import (
from .decimal.special import (
factorial,
)
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Implements functions for mathematical operations on Decimal objects.
import time
import testing

from decimojo.decimal import Decimal
from decimojo.decimal.decimal import Decimal
from decimojo.rounding_mode import RoundingMode
import decimojo.utility

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Implements functions for comparison operations on Decimal objects.

import testing

from decimojo.decimal import Decimal
from decimojo.decimal.decimal import Decimal
import decimojo.utility


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

"""Useful constants for Decimal type."""

from decimojo.decimal.decimal import Decimal

# ===----------------------------------------------------------------------=== #
#
# Integer and decimal constants
Expand Down
Loading