1use super::U256;
4use crate::{error::tfie, int::I256};
5use core::{convert::TryFrom, num::TryFromIntError};
6
7macro_rules! impl_from {
8 ($($t:ty),* $(,)?) => {$(
9 impl From<$t> for U256 {
10 #[inline]
11 fn from(value: $t) -> Self {
12 U256::new(value.into())
13 }
14 }
15 )*};
16}
17
18impl_from! {
19 bool, u8, u16, u32, u64, u128,
20}
21
22macro_rules! impl_try_from {
23 ($($t:ty),* $(,)?) => {$(
24 impl TryFrom<$t> for U256 {
25 type Error = TryFromIntError;
26
27 #[inline]
28 fn try_from(value: $t) -> Result<Self, Self::Error> {
29 Ok(U256::new(u128::try_from(value)?))
30 }
31 }
32 )*};
33}
34
35impl_try_from! {
36 i8, i16, i32, i64, i128,
37 isize, usize,
38}
39
40impl TryFrom<I256> for U256 {
41 type Error = TryFromIntError;
42
43 fn try_from(value: I256) -> Result<Self, Self::Error> {
44 if value < 0 {
45 return Err(tfie());
46 }
47 Ok(value.as_u256())
48 }
49}
50
51pub trait AsU256 {
74 #[allow(clippy::wrong_self_convention)]
78 fn as_u256(self) -> U256;
79}
80
81impl AsU256 for U256 {
82 #[inline]
83 fn as_u256(self) -> U256 {
84 self
85 }
86}
87
88impl AsU256 for I256 {
89 #[inline]
90 fn as_u256(self) -> U256 {
91 I256::as_u256(self)
92 }
93}
94
95macro_rules! impl_as_u256 {
96 ($($t:ty),* $(,)?) => {$(
97 impl AsU256 for $t {
98 #[inline]
99 fn as_u256(self) -> U256 {
100 #[allow(unused_comparisons)]
101 let hi = if self >= 0 { 0 } else { !0 };
102 U256::from_words(hi, self as _)
103 }
104 }
105 )*};
106}
107
108impl_as_u256! {
109 i8, i16, i32, i64, i128,
110 u8, u16, u32, u64, u128,
111 isize, usize,
112}
113
114impl AsU256 for bool {
115 #[inline]
116 fn as_u256(self) -> U256 {
117 U256::new(self as _)
118 }
119}
120
121macro_rules! impl_as_u256_float {
122 ($($t:ty [$b:ty]),* $(,)?) => {$(
123 impl AsU256 for $t {
124 #[inline]
125 fn as_u256(self) -> U256 {
126 const M: $b = (<$t>::MANTISSA_DIGITS - 1) as _;
134 const MAN_MASK: $b = !(!0 << M);
135 const MAN_ONE: $b = 1 << M;
136 const EXP_MASK: $b = !0 >> <$t>::MANTISSA_DIGITS;
137 const EXP_OFFSET: $b = EXP_MASK / 2;
138
139 if self >= 1.0 {
140 let bits = self.to_bits();
141 let exponent = ((bits >> M) & EXP_MASK) - EXP_OFFSET;
142 let mantissa = (bits & MAN_MASK) | MAN_ONE;
143 if exponent <= M {
144 U256::from(mantissa >> (M - exponent))
145 } else if exponent < 256 {
146 U256::from(mantissa) << (exponent - M)
147 } else {
148 U256::MAX
149 }
150 } else {
151 U256::ZERO
152 }
153 }
154 }
155 )*};
156}
157
158impl_as_u256_float! {
159 f32[u32], f64[u64],
160}
161
162macro_rules! impl_try_into {
163 ($($t:ty),* $(,)?) => {$(
164 impl TryFrom<U256> for $t {
165 type Error = TryFromIntError;
166
167 #[inline]
168 fn try_from(x: U256) -> Result<Self, Self::Error> {
169 if x <= <$t>::MAX.as_u256() {
170 Ok(*x.low() as _)
171 } else {
172 Err(tfie())
173 }
174 }
175 }
176 )*};
177}
178
179impl_try_into! {
180 i8, i16, i32, i64, i128,
181 u8, u16, u32, u64, u128,
182 isize, usize,
183}
184
185macro_rules! impl_into_float {
186 ($($t:ty => $f:ident),* $(,)?) => {$(
187 impl From<U256> for $t {
188 #[inline]
189 fn from(x: U256) -> $t {
190 x.$f()
191 }
192 }
193 )*};
194}
195
196impl_into_float! {
197 f32 => as_f32, f64 => as_f64,
198}