1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Multi precision integer and rational number using gmp lib
18 private import native_gmp
22 # The BigInt equivalent of `self`
23 fun to_bi
: BigInt do return self.to_i
.to_bi
25 # The Ratio equivalent of `self`
26 fun to_r
: Ratio do return self.to_f
.to_r
32 # Is `self` a well-formed BigInt (i.e. parsable via `to_bi`)
36 # assert not "0b1011".is_bi
37 # assert not "123u8".is_bi
38 # assert not "Not a BigInt".is_bi
42 return pre
.text_after
.is_dec
48 # Is `self` a well-formed Ratio (i.e. parsable via `to_r`)
54 # assert not "-1/-2".is_r
55 # assert not "0b1011".is_r
56 # assert not "123u8".is_r
57 # assert not "Not an Ratio".is_r
59 var frac
= split_once_on
('/')
60 if frac
.length
== 2 then
61 return frac
[0].is_bi
and frac
[1].is_dec
67 # If `self` contains a BigInt, return the corresponding BigInt
69 # assert("123".to_bi == 123.to_bi)
70 # assert("-123".to_bi == -123.to_bi)
73 var tmp
= new NativeMPZ
74 tmp
.set_str
(self.to_cstring
, 10i32
)
75 return new BigInt(tmp
)
78 # If `self` contains a Ratio, return the corresponding Ratio
80 # assert("123".to_r == 123.to_r)
81 # assert("-123".to_r == -123.to_r)
82 # assert("1/2".to_r == 0.5.to_r)
83 # assert("-1/2".to_r == -0.5.to_r)
86 var tmp
= new NativeMPQ
87 tmp
.set_str
self.to_cstring
94 var tmp
= new NativeMPZ
96 return new BigInt(tmp
)
100 var tmp
= new NativeMPQ
102 return new Ratio(tmp
)
108 var tmp
= new NativeMPZ
110 return new BigInt(tmp
)
114 var tmp
= new NativeMPQ
116 return new Ratio(tmp
)
120 # Multi precision Integer numbers.
124 super FinalizableOnce
126 redef type OTHER: BigInt
128 private var val
: NativeMPZ
130 redef fun successor
(i
) do return self + i
.to_bi
131 redef fun predecessor
(i
) do return self - i
.to_bi
133 redef fun hash
do return self.to_i
136 var res
= val
.cmp
(i
.val
)
139 else if (res
) > 0 then
146 redef fun ==(i
) do return i
isa BigInt and (self <=> i
) == 0
147 redef fun <=(i
) do return (self <=> i
) <= 0
148 redef fun <(i
) do return (self <=> i
) < 0
149 redef fun >=(i
) do return (self <=> i
) >= 0
150 redef fun >(i
) do return (self <=> i
) > 0
153 # assert(2.to_bi + 2.to_bi == 4.to_bi)
155 var res
= new NativeMPZ
157 return new BigInt(res
)
160 # assert(-(2.to_bi) == (-2).to_bi)
162 var res
= new NativeMPZ
164 return new BigInt(res
)
167 # assert(2.to_bi - 2.to_bi == 0.to_bi)
169 var res
= new NativeMPZ
171 return new BigInt(res
)
174 # assert(2.to_bi * 2.to_bi == 4.to_bi)
176 var res
= new NativeMPZ
178 return new BigInt(res
)
181 # assert(3.to_bi / 2.to_bi == 1.to_bi)
183 var res
= new NativeMPZ
184 val
.tdiv_q
(res
, i
.val
)
185 return new BigInt(res
)
188 # Modulo of `self` with `i`.
190 # Finds the remainder of the division of `self` by `i`.
192 # assert(5.to_bi % 2.to_bi == 1.to_bi)
193 fun %(i
: BigInt): BigInt do
194 var res
= new NativeMPZ
196 return new BigInt(res
)
199 # Returns `self` raised to the power of `e`.
201 # assert(3.to_bi ** 2 == 9.to_bi)
202 fun **(e
: Int): BigInt do
203 var res
= new NativeMPZ
208 return new BigInt(res
)
211 # The absolute value of `self`.
213 # assert((-3).to_bi.abs == 3.to_bi)
215 var res
= new NativeMPZ
217 return new BigInt(res
)
220 # Returns the greatest common divisor of `self` and `i`
222 # assert(15.to_bi.gcd(10.to_bi) == 5.to_bi)
223 fun gcd
(i
: BigInt): BigInt do
224 var res
= new NativeMPZ
226 return new BigInt(res
)
229 # Determine if `self` is a prime number.
230 # Return 2 if `self` is prime, return 1 if `self` is probably prime and
231 # return 0 if `self` is definitely not a prime number.
233 # This function begins by trying some divisions with small number to find if
234 # there is other factors then `self` and one. After that, it uses the
235 # Miller-Rabin probabilistic primality tests. The probability of a non-prime
236 # being identified as probably prime with that test is less than
237 # `4^(-reps)`. It is recommended to use a `reps` value between 15 and 50.
239 # assert((0x10001).to_bi.probab_prime(15) == 2)
240 fun probab_prime
(reps
: Int): Int do
241 return val
.probab_prime_p
(reps
.to_i32
)
244 # Return the next prime number greater than `self`.
245 # This fonction uses a probabilistic algorithm.
247 # assert(11.to_bi.next_prime == 13.to_bi)
248 fun next_prime
: BigInt do
249 var res
= new NativeMPZ
251 return new BigInt(res
)
254 # assert(11.to_bi.zero == 0.to_bi)
255 redef fun zero
do return new BigInt(new NativeMPZ)
257 # assert(11.to_bi.value_of(4) == 4.to_bi)
258 redef fun value_of
(i
) do return i
.to_bi
260 # assert(11.to_bi.to_i == 11)
261 redef fun to_i
do return val
.get_si
263 # assert(11.to_bi.to_f == 11.0)
264 redef fun to_f
do return val
.get_d
266 # assert(11.to_bi.to_s == "11")
268 var cstr
= val
.get_str
(10.to_i32
)
274 redef fun to_bi
do return self
276 # assert(123.to_bi.to_r == 123.to_r)
278 var tmp
= new NativeMPQ
280 return new Ratio(tmp
)
283 # assert(3.to_bi.distance(6.to_bi) == -3)
284 redef fun distance
(i
) do return (self - i
).to_i
286 redef fun finalize_once
do val
.finalize
289 # Multi precision Rational numbers.
291 # assert((0.2 + 0.1) == 0.30000000000000004)
292 # assert(("1/5".to_r + "1/10".to_r) == "3/10".to_r)
295 super FinalizableOnce
297 redef type OTHER: Ratio
299 private var val
: NativeMPQ
301 redef fun hash
do return self.to_i
304 var res
= val
.cmp
(r
.val
)
307 else if (res
) > 0 then
314 redef fun ==(r
) do return r
isa Ratio and (self <=> r
) == 0
315 redef fun <=(r
) do return (self <=> r
) <= 0
316 redef fun <(r
) do return (self <=> r
) < 0
317 redef fun >=(r
) do return (self <=> r
) >= 0
318 redef fun >(r
) do return (self <=> r
) > 0
320 # assert("3/2".to_r + "5/2".to_r == 4.to_r)
322 var res
= new NativeMPQ
324 return new Ratio(res
)
327 # assert( -("1/2".to_r) == ("-1/2").to_r)
329 var res
= new NativeMPQ
331 return new Ratio(res
)
334 # assert("5/2".to_r - "3/2".to_r == 1.to_r)
336 var res
= new NativeMPQ
338 return new Ratio(res
)
341 # assert("3/2".to_r * 2.to_r == 3.to_r)
343 var res
= new NativeMPQ
345 return new Ratio(res
)
348 # assert(3.to_r / 2.to_r == "3/2".to_r)
350 var res
= new NativeMPQ
352 return new Ratio(res
)
355 # The absolute value of `self`.
357 # assert((-3.to_r).abs == 3.to_r)
358 # assert(3.to_r.abs == 3.to_r)
360 var res
= new NativeMPQ
362 return new Ratio(res
)
365 # assert((3.to_r).zero == 0.to_r)
366 redef fun zero
do return new Ratio(new NativeMPQ)
368 # assert((3.to_r).value_of(2) == 2.to_r)
369 redef fun value_of
(n
) do return n
.to_r
371 # assert("7/2".to_r.to_i == 3)
373 var res
= new NativeMPZ
374 val
.numref
.tdiv_q
(res
, val
.denref
)
378 # assert(3.to_r.to_f == 3.0)
379 redef fun to_f
do return val
.get_d
381 # assert(3.to_r.to_s == "3")
383 var cstr
= val
.get_str
(10i32
)
389 # assert("7/2".to_r.to_bi == 3.to_bi)
391 var res
= new NativeMPZ
392 val
.numref
.tdiv_q
(res
, val
.denref
)
393 return new BigInt(res
)
396 redef fun to_r
do return self
398 redef fun finalize_once
do val
.finalize