crypto_bigint/int/
from.rs

1//! `From`-like conversions for [`Int`].
2
3use crate::{Int, Limb, Uint, Word, I128, I64};
4
5impl<const LIMBS: usize> Int<LIMBS> {
6    /// Create a [`Int`] from an `i8` (const-friendly)
7    // TODO(tarcieri): replace with `const impl From<i8>` when stable
8    pub const fn from_i8(n: i8) -> Self {
9        assert!(LIMBS >= 1, "number of limbs must be greater than zero");
10        Uint::new([Limb(n as Word)]).as_int().resize()
11    }
12
13    /// Create a [`Int`] from an `i16` (const-friendly)
14    // TODO(tarcieri): replace with `const impl From<i16>` when stable
15    pub const fn from_i16(n: i16) -> Self {
16        assert!(LIMBS >= 1, "number of limbs must be greater than zero");
17        Uint::new([Limb(n as Word)]).as_int().resize()
18    }
19
20    /// Create a [`Int`] from an `i32` (const-friendly)
21    // TODO(tarcieri): replace with `const impl From<i32>` when stable
22    pub const fn from_i32(n: i32) -> Self {
23        assert!(LIMBS >= 1, "number of limbs must be greater than zero");
24        Uint::new([Limb(n as Word)]).as_int().resize()
25    }
26
27    /// Create a [`Int`] from an `i64` (const-friendly)
28    // TODO(tarcieri): replace with `const impl From<i64>` when stable
29    #[cfg(target_pointer_width = "32")]
30    pub const fn from_i64(n: i64) -> Self {
31        Uint::<{ I64::LIMBS }>::from_u64(n as u64).as_int().resize()
32    }
33
34    /// Create a [`Int`] from an `i64` (const-friendly)
35    // TODO(tarcieri): replace with `const impl From<i64>` when stable
36    #[cfg(target_pointer_width = "64")]
37    pub const fn from_i64(n: i64) -> Self {
38        assert!(LIMBS >= 1, "number of limbs must be greater than zero");
39        Uint::new([Limb(n as Word)]).as_int().resize()
40    }
41
42    /// Create a [`Int`] from an `i128` (const-friendly)
43    // TODO(tarcieri): replace with `const impl From<i128>` when stable
44    pub const fn from_i128(n: i128) -> Self {
45        Uint::<{ I128::LIMBS }>::from_u128(n as u128)
46            .as_int()
47            .resize()
48    }
49}
50
51impl<const LIMBS: usize> From<i8> for Int<LIMBS> {
52    fn from(n: i8) -> Self {
53        // TODO(tarcieri): const where clause when possible
54        debug_assert!(LIMBS > 0, "limbs must be non-zero");
55        Self::from_i8(n)
56    }
57}
58
59impl<const LIMBS: usize> From<i16> for Int<LIMBS> {
60    fn from(n: i16) -> Self {
61        // TODO(tarcieri): const where clause when possible
62        debug_assert!(LIMBS > 0, "limbs must be non-zero");
63        Self::from_i16(n)
64    }
65}
66
67impl<const LIMBS: usize> From<i32> for Int<LIMBS> {
68    fn from(n: i32) -> Self {
69        // TODO(tarcieri): const where clause when possible
70        debug_assert!(LIMBS > 0, "limbs must be non-zero");
71        Self::from_i32(n)
72    }
73}
74
75impl<const LIMBS: usize> From<i64> for Int<LIMBS> {
76    fn from(n: i64) -> Self {
77        // TODO(tarcieri): const where clause when possible
78        debug_assert!(LIMBS >= 8 / Limb::BYTES, "not enough limbs");
79        Self::from_i64(n)
80    }
81}
82
83impl<const LIMBS: usize> From<i128> for Int<LIMBS> {
84    fn from(n: i128) -> Self {
85        // TODO(tarcieri): const where clause when possible
86        debug_assert!(LIMBS >= 16 / Limb::BYTES, "not enough limbs");
87        Self::from_i128(n)
88    }
89}
90
91impl From<I64> for i64 {
92    fn from(n: I64) -> i64 {
93        u64::from(n.0) as i64
94    }
95}
96
97impl From<I128> for i128 {
98    fn from(n: I128) -> i128 {
99        u128::from(n.0) as i128
100    }
101}
102
103impl<const LIMBS: usize, const LIMBS2: usize> From<&Int<LIMBS>> for Int<LIMBS2> {
104    fn from(num: &Int<LIMBS>) -> Int<LIMBS2> {
105        num.resize()
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    #[cfg(target_pointer_width = "64")]
112    use crate::I128 as IntEx;
113    #[cfg(target_pointer_width = "32")]
114    use crate::I64 as IntEx;
115    use crate::{Limb, I128};
116
117    #[test]
118    fn from_i8() {
119        let n = IntEx::from(42i8);
120        assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
121        let n = IntEx::from(-42i8);
122        assert_eq!(n.as_limbs(), &[Limb::MAX - Limb::from(41u32), Limb::MAX]);
123    }
124
125    #[test]
126    fn from_i16() {
127        let n = IntEx::from(42i16);
128        assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
129        let n = IntEx::from(-42i16);
130        assert_eq!(n.as_limbs(), &[Limb::MAX - Limb::from(41u32), Limb::MAX]);
131    }
132
133    #[test]
134    fn from_i32() {
135        let n = IntEx::from(42i32);
136        assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
137        let n = IntEx::from(-42i32);
138        assert_eq!(n.as_limbs(), &[Limb::MAX - Limb::from(41u32), Limb::MAX]);
139    }
140
141    #[test]
142    fn from_i64() {
143        let n = IntEx::from(42i64);
144        assert_eq!(n.as_limbs(), &[Limb(42), Limb(0)]);
145        let n = IntEx::from(-42i64);
146        assert_eq!(n.as_limbs(), &[Limb::MAX - Limb::from(41u32), Limb::MAX]);
147    }
148
149    #[test]
150    fn from_i128() {
151        let n = I128::from(42i128);
152        assert_eq!(&n.as_limbs()[..2], &[Limb(42), Limb(0)]);
153        assert_eq!(i128::from(n), 42i128);
154        let n = I128::from(-42i128);
155        assert_eq!(&n.as_limbs()[..2], &[Limb::MAX - Limb(41), Limb::MAX]);
156        assert_eq!(i128::from(n), -42i128);
157    }
158}