1use crate::ext::xmpz;
18#[allow(deprecated)]
19use crate::integer::SmallInteger;
20use crate::integer::big;
21use crate::integer::{MiniInteger, ParseIntegerError, TryFromIntegerError};
22use crate::misc::StringLike;
23use crate::{Assign, Integer};
24use az::{Az, CheckedCast};
25use core::error::Error;
26use core::fmt::{
27 Binary, Debug, Display, Formatter, LowerHex, Octal, Result as FmtResult, UpperHex,
28};
29use core::hash::{Hash, Hasher};
30use core::mem;
31use core::mem::MaybeUninit;
32use core::str::FromStr;
33use gmp_mpfr_sys::gmp::limb_t;
34
35impl Default for Integer {
36 #[inline]
37 fn default() -> Integer {
38 Integer::new()
39 }
40}
41
42impl Clone for Integer {
43 #[inline]
44 fn clone(&self) -> Integer {
45 unsafe {
46 let mut dst = MaybeUninit::uninit();
47 xmpz::init_set(dst.as_mut_ptr(), self);
48 dst.assume_init()
49 }
50 }
51
52 #[inline]
53 fn clone_from(&mut self, source: &Integer) {
54 self.assign(source);
55 }
56}
57
58impl Drop for Integer {
59 #[inline]
60 fn drop(&mut self) {
61 unsafe {
62 xmpz::clear(self);
63 }
64 }
65}
66
67impl Hash for Integer {
68 #[inline]
69 fn hash<H: Hasher>(&self, state: &mut H) {
70 self.inner().size.hash(state);
71 self.inner_data().hash(state);
72 }
73}
74
75impl Assign for Integer {
76 #[inline]
77 fn assign(&mut self, src: Integer) {
78 drop(mem::replace(self, src));
79 }
80}
81
82impl Assign<&Integer> for Integer {
83 #[inline]
84 fn assign(&mut self, src: &Integer) {
85 xmpz::set(self, src);
86 }
87}
88
89impl From<&Integer> for Integer {
90 #[inline]
91 fn from(val: &Integer) -> Self {
92 val.clone()
93 }
94}
95
96impl Assign<MiniInteger> for Integer {
97 #[inline]
98 fn assign(&mut self, mut src: MiniInteger) {
99 self.assign(src.borrow_excl());
100 }
101}
102
103impl Assign<&MiniInteger> for Integer {
104 #[inline]
105 fn assign(&mut self, src: &MiniInteger) {
106 self.assign(&*src.borrow());
107 }
108}
109
110impl From<MiniInteger> for Integer {
111 #[inline]
112 fn from(mut src: MiniInteger) -> Self {
113 Integer::from(src.borrow_excl())
114 }
115}
116
117impl From<&MiniInteger> for Integer {
118 #[inline]
119 fn from(src: &MiniInteger) -> Self {
120 Integer::from(&*src.borrow())
121 }
122}
123
124#[allow(deprecated)]
125impl Assign<SmallInteger> for Integer {
126 #[inline]
127 fn assign(&mut self, src: SmallInteger) {
128 self.assign(&*src);
129 }
130}
131
132#[allow(deprecated)]
133impl Assign<&SmallInteger> for Integer {
134 #[inline]
135 fn assign(&mut self, src: &SmallInteger) {
136 self.assign(&**src);
137 }
138}
139
140#[allow(deprecated)]
141impl From<SmallInteger> for Integer {
142 #[inline]
143 fn from(src: SmallInteger) -> Self {
144 Integer::from(&*src)
145 }
146}
147
148#[allow(deprecated)]
149impl From<&SmallInteger> for Integer {
150 #[inline]
151 fn from(src: &SmallInteger) -> Self {
152 Integer::from(&**src)
153 }
154}
155
156macro_rules! try_from {
157 ($T:ty) => {
158 impl TryFrom<Integer> for $T {
159 type Error = TryFromIntegerError;
160 #[inline]
161 fn try_from(value: Integer) -> Result<Self, TryFromIntegerError> {
162 TryFrom::try_from(&value)
163 }
164 }
165
166 impl TryFrom<&Integer> for $T {
167 type Error = TryFromIntegerError;
168 #[inline]
169 fn try_from(value: &Integer) -> Result<Self, TryFromIntegerError> {
170 value
171 .checked_cast()
172 .ok_or(TryFromIntegerError { _unused: () })
173 }
174 }
175 };
176}
177
178try_from! { i8 }
179try_from! { i16 }
180try_from! { i32 }
181try_from! { i64 }
182try_from! { i128 }
183try_from! { isize }
184try_from! { u8 }
185try_from! { u16 }
186try_from! { u32 }
187try_from! { u64 }
188try_from! { u128 }
189try_from! { usize }
190
191macro_rules! unsafe_assign {
192 ($T:ty, $set:path, $init_set:path) => {
193 impl Assign<$T> for Integer {
194 #[inline]
195 fn assign(&mut self, src: $T) {
196 $set(self, src);
197 }
198 }
199
200 impl Assign<&$T> for Integer {
201 #[inline]
202 fn assign(&mut self, src: &$T) {
203 self.assign(*src);
204 }
205 }
206
207 impl From<$T> for Integer {
208 #[inline]
209 fn from(src: $T) -> Self {
210 unsafe {
211 let mut dst = MaybeUninit::uninit();
212 $init_set(dst.as_mut_ptr(), src);
213 dst.assume_init()
214 }
215 }
216 }
217 };
218}
219
220macro_rules! assign {
221 ($T:ty as $U:ty) => {
222 impl Assign<$T> for Integer {
223 #[inline]
224 fn assign(&mut self, src: $T) {
225 self.assign(src.az::<$U>());
226 }
227 }
228
229 impl Assign<&$T> for Integer {
230 #[inline]
231 fn assign(&mut self, src: &$T) {
232 self.assign((*src).az::<$U>());
233 }
234 }
235
236 impl From<$T> for Integer {
237 #[inline]
238 fn from(src: $T) -> Self {
239 Integer::from(src.az::<$U>())
240 }
241 }
242 };
243}
244
245assign! { i8 as i32 }
246assign! { i16 as i32 }
247unsafe_assign! { i32, xmpz::set_i32, xmpz::init_set_i32 }
248unsafe_assign! { i64, xmpz::set_i64, xmpz::init_set_i64 }
249unsafe_assign! { i128, xmpz::set_i128, xmpz::init_set_i128 }
250#[cfg(target_pointer_width = "32")]
251assign! { isize as i32 }
252#[cfg(target_pointer_width = "64")]
253assign! { isize as i64 }
254
255assign! { bool as u32 }
256assign! { u8 as u32 }
257assign! { u16 as u32 }
258unsafe_assign! { u32, xmpz::set_u32, xmpz::init_set_u32 }
259unsafe_assign! { u64, xmpz::set_u64, xmpz::init_set_u64 }
260unsafe_assign! { u128, xmpz::set_u128, xmpz::init_set_u128 }
261#[cfg(target_pointer_width = "32")]
262assign! { usize as u32 }
263#[cfg(target_pointer_width = "64")]
264assign! { usize as u64 }
265
266impl FromStr for Integer {
267 type Err = ParseIntegerError;
268 #[inline]
269 fn from_str(src: &str) -> Result<Integer, ParseIntegerError> {
270 Ok(Integer::from(Integer::parse(src)?))
271 }
272}
273
274impl Display for Integer {
275 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
276 fmt_radix(self, f, 10, false, "")
277 }
278}
279
280impl Debug for Integer {
281 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
282 fmt_radix(self, f, 10, false, "")
283 }
284}
285
286impl Binary for Integer {
287 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
288 fmt_radix(self, f, 2, false, "0b")
289 }
290}
291
292impl Octal for Integer {
293 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
294 fmt_radix(self, f, 8, false, "0o")
295 }
296}
297
298impl LowerHex for Integer {
299 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
300 fmt_radix(self, f, 16, false, "0x")
301 }
302}
303
304impl UpperHex for Integer {
305 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
306 fmt_radix(self, f, 16, true, "0x")
307 }
308}
309
310fn fmt_radix(
311 i: &Integer,
312 f: &mut Formatter<'_>,
313 radix: i32,
314 to_upper: bool,
315 prefix: &str,
316) -> FmtResult {
317 let mut s = StringLike::new_malloc();
318 big::append_to_string(&mut s, i, radix, to_upper);
319 let st = s.as_str();
320 let (neg, buf) = if let Some(stripped) = st.strip_prefix('-') {
321 (true, stripped)
322 } else {
323 (false, st)
324 };
325 f.pad_integral(!neg, prefix, buf)
326}
327
328#[cfg(feature = "float")]
329mod float_conv {
330 use crate::float;
331 use crate::{Float, Integer};
332 use core::fmt::{Formatter, LowerExp, Result as FmtResult, UpperExp};
333
334 fn float_from_int(i: &Integer) -> Float {
335 let abs = i.as_abs();
336 let mut prec = abs.significant_bits();
337 if let Some(zeros) = abs.find_one(0) {
339 prec -= zeros;
340 }
341 prec = prec.max(float::prec_min());
342 Float::with_val(prec, i)
343 }
344
345 impl LowerExp for Integer {
346 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
347 LowerExp::fmt(&float_from_int(self), f)
348 }
349 }
350
351 impl UpperExp for Integer {
352 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
353 UpperExp::fmt(&float_from_int(self), f)
354 }
355 }
356}
357
358impl AsRef<[limb_t]> for Integer {
362 #[inline]
363 fn as_ref(&self) -> &[limb_t] {
364 self.as_limbs()
365 }
366}
367
368impl TryFromIntegerError {
369 fn desc(&self) -> &str {
370 "out of range conversion attempted"
371 }
372}
373
374impl Display for TryFromIntegerError {
375 fn fmt(&self, f: &mut Formatter) -> FmtResult {
376 Display::fmt(self.desc(), f)
377 }
378}
379
380impl Error for TryFromIntegerError {
381 #[allow(deprecated)]
382 fn description(&self) -> &str {
383 self.desc()
384 }
385}
386
387unsafe impl Send for Integer {}
389unsafe impl Sync for Integer {}
390
391#[cfg(test)]
392mod tests {
393 use crate::{Assign, Integer};
394
395 #[test]
396 fn check_assign() {
397 let mut i = Integer::from(1);
398 assert_eq!(i, 1);
399 let other = Integer::from(2);
400 i.assign(&other);
401 assert_eq!(i, 2);
402 i.assign(-other);
403 assert_eq!(i, -2);
404 }
405
406 macro_rules! check_fallible_conversions_helper {
407 ($int:ident, $bits:expr, $I:ty, $U:ty) => {{
408 const I_MIN: $I = -1 << ($bits - 1);
409 const I_MAX: $I = -1 - I_MIN;
410 $int.assign(I_MIN);
411 assert_eq!(<$I>::try_from(&$int).ok(), Some(I_MIN));
412 $int -= 1;
413 assert!(<$I>::try_from(&$int).is_err());
414 $int.assign(I_MAX);
415 assert_eq!(<$I>::try_from(&$int).ok(), Some(I_MAX));
416 $int += 1;
417 assert!(<$I>::try_from(&$int).is_err());
418
419 const U_MIN: $U = 0;
420 const U_MAX: $U = !0;
421 $int.assign(U_MIN);
422 assert_eq!(<$U>::try_from(&$int).ok(), Some(U_MIN));
423 $int -= 1;
424 assert!(<$U>::try_from(&$int).is_err());
425 $int.assign(U_MAX);
426 assert_eq!(<$U>::try_from(&$int).ok(), Some(U_MAX));
427 $int += 1;
428 assert!(<$U>::try_from(&$int).is_err());
429 }};
430 }
431
432 #[test]
433 fn check_fallible_conversions() {
434 let mut int = Integer::new();
435 check_fallible_conversions_helper!(int, 8, i8, u8);
436 check_fallible_conversions_helper!(int, 16, i16, u16);
437 check_fallible_conversions_helper!(int, 32, i32, u32);
438 check_fallible_conversions_helper!(int, 64, i64, u64);
439 check_fallible_conversions_helper!(int, 128, i128, u128);
440 }
441}