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
76 changes: 68 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,82 @@ For the latest development version, clone the [GitHub repository](https://github

## Quick start

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.

```mojo
from decimojo import *
```

This will import the following types or aliases into your namespace:

- `dm`: An alias for the `decimojo` module.
- `BigInt` (alias `BInt`): An arbitrary-precision signed integer type.
- `BigDecimal` (alias `BDec`): An arbitrary-precision decimal type.
- `Decimal` (alias `Dec`): A 128-bit fixed-precision decimal type.
- `RoundingMode` (alias `RM`): An enumeration for rounding modes.
- `ROUND_DOWN`, `ROUND_HALF_UP`, `ROUND_HALF_EVEN`, `ROUND_UP`: Constants for common rounding modes.

---

Here are some examples showcasing the arbitrary-precision feature of the `BigDecimal` type. Note that Mojo does not support global variables at the moment, so we need to pass the `precision` parameter explicitly to each function call. In future, we will add a global precision setting with the default value of, *e.g.*, `28`, to avoid passing it around.

```mojo
from decimojo import BDec, RM
from decimojo.prelude import *


fn main() raises:
var PRECISION = 100
var a = BDec("123456789.123456789")
var b = BDec("1234.56789")
print(a.sqrt(precision=PRECISION))
# 11111.11106611111096943055498174930232833813065468909453818857935956641682120364106016272519460988485
print(a.power(b, precision=PRECISION))
# 3.346361102419080234023813540078946868219632448203078657310495672766009862564151996325555496759911131748170844123475135377098326591508239654961E+9989
print(a.log(b, precision=PRECISION))
# 2.617330026656548299907884356415293977170848626010103229392408225981962436022623783231699264341492663671325580092077394824180414301026578169909

# === Basic Arithmetic === #
print(a + b) # 123458023.691346789
print(a - b) # 123455554.555566789
print(a * b) # 152415787654.32099750190521
print(a.true_divide(b, precision=80)) # 100000.0001

# === Mathematical Functions === #
print(a.sqrt(precision=80))
# 11111.111066111110969430554981749302328338130654689094538188579359566416821203641
print(a.cbrt(precision=80))
# 497.93385938415242742001134219007635925452951248903093962731782327785111102410518
print(a.root(b, precision=80))
# 1.0152058862996527138602610522640944903320735973237537866713119992581006582644107
print(a.power(b, precision=80))
# 3.3463611024190802340238135400789468682196324482030786573104956727660098625641520E+9989
print(a.exp(precision=80))
# 1.8612755889649587035842377856492201091251654136588338983610243887893287518637652E+53616602
print(a.log(b, precision=80))
# 2.6173300266565482999078843564152939771708486260101032293924082259819624360226238
print(a.ln(precision=80))
# 18.631401767168018032693933348296537542797015174553735308351756611901741276655161

# === Internal representation of the number === #
(
BDec(
"3.141592653589793238462643383279502884197169399375105820974944"
).power(2, precision=60)
).print_internal_representation()
# Internal Representation Details of BigDecimal
# ----------------------------------------------
# number: 9.8696044010893586188344909998
# 761511353136994072407906264133
# 5
# coefficient: 986960440108935861883449099987
# 615113531369940724079062641335
# negative: False
# scale: 59
# word 0: 62641335
# word 1: 940724079
# word 2: 113531369
# word 3: 99987615
# word 4: 861883449
# word 5: 440108935
# word 6: 986960
# ----------------------------------------------
```

---

Here is a comprehensive quick-start guide showcasing each major function of the `BigInt` type.

```mojo
Expand Down Expand Up @@ -114,6 +172,8 @@ fn main() raises:
print(BInt("123456789" * 400) // BInt("987654321" * 200))
```

---

Here is a comprehensive quick-start guide showcasing each major function of the `Decimal` type.

```mojo
Expand Down
52 changes: 52 additions & 0 deletions docs/examples_on_bdec.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from decimojo.prelude import *


fn main() raises:
var a = BDec("123456789.123456789")
var b = BDec("1234.56789")

# === Basic Arithmetic === #
print(a + b) # 123458023.691346789
print(a - b) # 123455554.555566789
print(a * b) # 152415787654.32099750190521
print(a.true_divide(b, precision=80)) # 100000.0001

# === Mathematical Functions === #
print(a.sqrt(precision=80))
# 11111.111066111110969430554981749302328338130654689094538188579359566416821203641
print(a.cbrt(precision=80))
# 497.93385938415242742001134219007635925452951248903093962731782327785111102410518
print(a.root(b, precision=80))
# 1.0152058862996527138602610522640944903320735973237537866713119992581006582644107
print(a.power(b, precision=80))
# 3.3463611024190802340238135400789468682196324482030786573104956727660098625641520E+9989
print(a.exp(precision=80))
# 1.8612755889649587035842377856492201091251654136588338983610243887893287518637652E+53616602
print(a.log(b, precision=80))
# 2.6173300266565482999078843564152939771708486260101032293924082259819624360226238
print(a.ln(precision=80))
# 18.631401767168018032693933348296537542797015174553735308351756611901741276655161

# === Internal representation of the number === #
(
BDec(
"3.141592653589793238462643383279502884197169399375105820974944"
).power(2, precision=60)
).print_internal_representation()
# Internal Representation Details of BigDecimal
# ----------------------------------------------
# number: 9.8696044010893586188344909998
# 761511353136994072407906264133
# 5
# coefficient: 986960440108935861883449099987
# 615113531369940724079062641335
# negative: False
# scale: 59
# word 0: 62641335
# word 1: 940724079
# word 2: 113531369
# word 3: 99987615
# word 4: 861883449
# word 5: 440108935
# word 6: 986960
# ----------------------------------------------
134 changes: 106 additions & 28 deletions src/decimojo/bigdecimal/bigdecimal.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,36 @@ struct BigDecimal(

@staticmethod
fn from_raw_components(
coefficient: BigUInt, scale: Int = 0, sign: Bool = False
owned words: List[UInt32], scale: Int = 0, sign: Bool = False
) -> Self:
"""Creates a BigDecimal from its raw components."""
return Self(coefficient, scale, sign)
"""**UNSAFE** Creates a BigDecimal from its raw components.
The raw components are words, scale, and sign.

Args:
words: The raw words of the coefficient.
scale: The scale of the BigDecimal.
sign: The sign of the BigDecimal.

Returns:
A BigDecimal object constructed from the raw components.

Notes:

This method is unsafe because it does not check the validity of the
words. It is the caller's responsibility to ensure that the words
represent a valid BigUInt.
"""
var coefficient = BigUInt(words=words^)
return Self(coefficient^, scale, sign)

@staticmethod
fn from_raw_components(
coefficient: UInt32, scale: Int = 0, sign: Bool = False
word: UInt32, scale: Int = 0, sign: Bool = False
) -> Self:
"""Creates a BigDecimal from its raw components."""
return Self(BigUInt(List[UInt32](coefficient)), scale, sign)
"""**UNSAFE** Creates a BigDecimal from its raw components.
The raw components are a single word, scale, and sign.
"""
return Self(BigUInt(words=List[UInt32](word)), scale, sign)

@staticmethod
fn from_int(value: Int) -> Self:
Expand Down Expand Up @@ -644,6 +663,8 @@ struct BigDecimal(
# Mathematical methods that do not implement a trait (not a dunder)
# ===------------------------------------------------------------------=== #

# === Comparisons === #

@always_inline
fn compare(self, other: Self) raises -> Int8:
"""Compares two BigDecimal numbers.
Expand All @@ -658,6 +679,36 @@ struct BigDecimal(
"""
return decimojo.bigdecimal.comparison.compare_absolute(self, other)

# === Extrema === #

@always_inline
fn max(self, other: Self) raises -> Self:
"""Returns the maximum of two BigDecimal numbers."""
return decimojo.bigdecimal.comparison.max(self, other)

@always_inline
fn min(self, other: Self) raises -> Self:
"""Returns the minimum of two BigDecimal numbers."""
return decimojo.bigdecimal.comparison.min(self, other)

# === Constants === #

@always_inline
@staticmethod
fn pi(precision: Int) raises -> Self:
"""Returns the mathematical constant pi to the specified precision."""
return decimojo.bigdecimal.constants.pi(precision=precision)

@always_inline
@staticmethod
fn e(precision: Int) raises -> Self:
"""Returns the mathematical constant e to the specified precision."""
return decimojo.bigdecimal.exponential.exp(
x=BigDecimal(BigUInt.ONE), precision=precision
)

# === Exponentional operations === #

@always_inline
fn exp(self, precision: Int = 28) raises -> Self:
"""Returns the exponential of the BigDecimal number."""
Expand All @@ -679,16 +730,6 @@ struct BigDecimal(
"""Returns the base-10 logarithm of the BigDecimal number."""
return decimojo.bigdecimal.exponential.log10(self, precision)

@always_inline
fn max(self, other: Self) raises -> Self:
"""Returns the maximum of two BigDecimal numbers."""
return decimojo.bigdecimal.comparison.max(self, other)

@always_inline
fn min(self, other: Self) raises -> Self:
"""Returns the minimum of two BigDecimal numbers."""
return decimojo.bigdecimal.comparison.min(self, other)

@always_inline
fn root(self, root: Self, precision: Int = 28) raises -> Self:
"""Returns the root of the BigDecimal number."""
Expand All @@ -704,6 +745,21 @@ struct BigDecimal(
"""Returns the cube root of the BigDecimal number."""
return decimojo.bigdecimal.exponential.cbrt(self, precision)

@always_inline
fn power(self, exponent: Self, precision: Int) raises -> Self:
"""Returns the result of exponentiation with the given precision.
See `exponential.power()` for more information.
"""
return decimojo.bigdecimal.exponential.power(self, exponent, precision)

# === Trigonometric operations === #
@always_inline
fn arctan(self, precision: Int = 28) raises -> Self:
"""Returns the arctangent of the BigDecimal number."""
return decimojo.bigdecimal.trigonometric.arctan(self, precision)

# === Arithmetic operations === #

@always_inline
fn true_divide(self, other: Self, precision: Int) raises -> Self:
"""Returns the result of true division of two BigDecimal numbers.
Expand Down Expand Up @@ -731,12 +787,7 @@ struct BigDecimal(
"""
return decimojo.bigdecimal.arithmetics.truncate_divide(self, other)

@always_inline
fn power(self, exponent: Self, precision: Int) raises -> Self:
"""Returns the result of exponentiation with the given precision.
See `exponential.power()` for more information.
"""
return decimojo.bigdecimal.exponential.power(self, exponent, precision)
# === Rounding operations === #

@always_inline
fn round(
Expand Down Expand Up @@ -867,7 +918,7 @@ struct BigDecimal(
)

@always_inline
fn print_internal_representation(self) raises:
fn print_internal_representation(self):
"""Prints the internal representation of the BigDecimal."""
var line_width = 30
var string_of_number = self.to_string(line_width=line_width).split("\n")
Expand Down Expand Up @@ -897,14 +948,41 @@ struct BigDecimal(
else:
ndigits = 3
print(
String("word {}:{}{}")
.format(
i, " " * (10 - ndigits), String(self.coefficient.words[i])
)
.rjust(9, fillchar="0")
String(
"word ",
i,
":",
" " * (10 - ndigits),
self.coefficient.words[i],
).rjust(9, fillchar="0")
)
print("----------------------------------------------")

@always_inline
fn print_representation_as_components(self):
"""Prints the representation of the BigDecimal as components."""
print(
(
"BigDecimal(\n coefficient=BigUInt(\n "
" words=List[UInt32](\n "
),
end="",
)
ref words = self.coefficient.words
for i in range(len(words)):
if i != len(words) - 1:
print(words[i], end=",\n ")
else:
print(words[i], end=",\n ),\n ),\n")
print(
" scale=",
self.scale,
",\n sign=",
self.sign,
")",
sep="",
)

@always_inline
fn is_integer(self) -> Bool:
"""Returns True if this number represents an integer value."""
Expand Down
Loading