@@ -26,11 +26,13 @@ mathematical methods that do not implement a trait.
2626from memory import UnsafePointer
2727import testing
2828
29+ import decimojo.bigint.arithmetics
30+ import decimojo.bigint.comparison
2931import decimojo.str
3032
3133
3234@value
33- struct BigInt :
35+ struct BigInt ( Absable , IntableRaising , Writable ) :
3436 """ Represents an integer with arbitrary precision.
3537
3638 Notes:
@@ -62,6 +64,13 @@ struct BigInt:
6264
6365 # ===------------------------------------------------------------------=== #
6466 # Constructors and life time dunder methods
67+ #
68+ # __init__(out self)
69+ # __init__(out self, empty: Bool)
70+ # __init__(out self, empty: Bool, capacity: Int)
71+ # __init__(out self, *words: UInt32, sign: Bool) raises
72+ # __init__(out self, value: Int) raises
73+ # __init__(out self, value: String) raises
6574 # ===------------------------------------------------------------------=== #
6675
6776 fn __init__ (out self ):
@@ -99,23 +108,43 @@ struct BigInt:
99108 fn __init__ (out self , * words : UInt32, sign : Bool) raises :
100109 """ Initializes a BigInt from raw components.
101110
111+ Args:
112+ words: The UInt32 words representing the coefficient.
113+ Each UInt32 word represents digits ranging from 0 to 10^9 - 1.
114+ The words are stored in little-endian order.
115+ sign: The sign of the BigInt.
116+
102117 Notes:
103118
104119 This method checks whether the words are smaller than `999_999_999`.
120+
121+ Example:
122+ ```console
123+ BigInt(123456789, 987654321, sign=False) # 987654321_123456789
124+ BigInt(123456789, 987654321, sign=True) # -987654321_123456789
125+ ```
126+
127+ End of examples.
105128 """
106- self .words = Self._words_type()
129+ self .words = Self._words_type(capacity = len (words) )
107130 self .sign = sign
108131
109132 # Check if the words are valid
110133 for word in words:
111134 if word > Self.MAX_OF_WORD :
112135 raise Error(
113- " Error in `from_components `: Word value exceeds maximum"
136+ " Error in `BigInt.__init__() `: Word value exceeds maximum"
114137 " value of 999_999_999"
115138 )
116139 else :
117140 self .words.append(word)
118141
142+ fn __init__ (out self , value : Int) raises :
143+ """ Initializes a BigInt from an Int.
144+ See `from_int()` for more information.
145+ """
146+ self = Self.from_int(value)
147+
119148 fn __init__ (out self , value : String) raises :
120149 """ Initializes a BigInt from a string representation.
121150 See `from_string()` for more information.
@@ -127,44 +156,50 @@ struct BigInt:
127156
128157 # ===------------------------------------------------------------------=== #
129158 # Constructing methods that are not dunders
159+ #
160+ # from_raw_words(*words: UInt32, sign: Bool) -> Self
161+ # from_int(value: Int) -> Self
162+ # from_uint128(value: UInt128, sign: Bool = False) -> Self
163+ # from_string(value: String) -> Self
130164 # ===------------------------------------------------------------------=== #
131165
132166 @ staticmethod
133- fn from_components (* words : UInt32, sign : Bool = False ) raises -> Self:
134- """ Creates a BigInt from raw components.
167+ fn from_raw_words (* words : UInt32, sign : Bool) -> Self:
168+ """ Initializes a BigInt from raw words without validating the words.
169+
170+ Args:
171+ words: The UInt32 words representing the coefficient.
172+ Each UInt32 word represents digits ranging from 0 to 10^9 - 1.
173+ The words are stored in little-endian order.
174+ sign: The sign of the BigInt.
135175
136176 Notes:
137177
138- Compare to `BigInt.__init__()`, this method checks the validity of words
139- by checking if the words are smaller than `999_999_999`.
178+ This method does not validate whether the words are smaller than
179+ `999_999_999`.
140180 """
141181
142- var result = Self(empty = True )
182+ result = Self(empty = True , capacity = len (words) )
143183 result.sign = sign
144-
145- # Check if the words are valid
146184 for word in words:
147- if word > Self.MAX_OF_WORD :
148- raise Error(
149- " Error in `from_components`: Word value exceeds maximum"
150- " value of 999_999_999"
151- )
152- else :
153- result.words.append(word)
154-
155- return result
185+ result.words.append(word)
186+ return result^
156187
157188 @ staticmethod
158- fn from_int (value : Int) -> Self:
189+ fn from_int (value : Int) raises -> Self:
159190 """ Creates a BigInt from an integer."""
160191 if value == 0 :
161192 return Self()
162193
163194 var result = Self(empty = True )
164-
165195 var remainder : Int
166196 var quotient : Int
167197 if value < 0 :
198+ # Handle the case of Int.MIN due to asymmetry of Int.MIN and Int.MAX
199+ if value == Int.MIN :
200+ return Self.from_raw_words(
201+ UInt32(854775807 ), UInt32(223372036 ), UInt32(9 ), sign = True
202+ )
168203 result.sign = True
169204 remainder = - value
170205 else :
@@ -301,6 +336,12 @@ struct BigInt:
301336 # Output dunders, type-transfer dunders
302337 # ===------------------------------------------------------------------=== #
303338
339+ fn __int__ (self ) raises -> Int:
340+ """ Returns the number as Int.
341+ See `to_int()` for more information.
342+ """
343+ return self .to_int()
344+
304345 fn __str__ (self ) -> String:
305346 """ Returns string representation of the BigInt.
306347 See `to_str()` for more information.
@@ -321,6 +362,37 @@ struct BigInt:
321362 """
322363 writer.write(String(self ))
323364
365+ fn to_int (self ) raises -> Int:
366+ """ Returns the number as Int.
367+
368+ Returns:
369+ The number as Int.
370+
371+ Raises:
372+ Error: If the number is too large or too small to fit in Int.
373+ """
374+
375+ # 2^63-1 = 9_223_372_036_854_775_807
376+ # is larger than 10^18 -1 but smaller than 10^27 - 1
377+
378+ if len (self .words) > 3 :
379+ raise Error(
380+ " Error in `BigInt.to_int()`: The number exceeds the size of Int"
381+ )
382+
383+ var value : Int128 = 0
384+ for i in range (len (self .words)):
385+ value += Int128(self .words[i]) * Int128(Self.BASE_OF_WORD ) ** i
386+
387+ value = - value if self .sign else value
388+
389+ if value < Int128(Int.MIN ) or value > Int128(Int.MAX ):
390+ raise Error(
391+ " Error in `BigInt.to_int()`: The number exceeds the size of Int"
392+ )
393+
394+ return Int(value)
395+
324396 fn to_str (self ) -> String:
325397 """ Returns string representation of the BigInt."""
326398
0 commit comments