snarkvm_console_program/data/literal/cast_lossy/
integer.rs1use super::*;
17
18impl<E: Environment, I: IntegerType> CastLossy<Address<E>> for Integer<E, I> {
19 #[inline]
25 fn cast_lossy(&self) -> Address<E> {
26 let field: Field<E> = self.cast_lossy();
27 field.cast_lossy()
28 }
29}
30
31impl<E: Environment, I: IntegerType> CastLossy<Boolean<E>> for Integer<E, I> {
32 #[inline]
35 fn cast_lossy(&self) -> Boolean<E> {
36 let bits_le = self.to_bits_le();
37 debug_assert!(!bits_le.is_empty(), "An integer must have at least one bit");
38 Boolean::new(bits_le[0])
39 }
40}
41
42impl<E: Environment, I: IntegerType> CastLossy<Field<E>> for Integer<E, I> {
43 #[inline]
46 fn cast_lossy(&self) -> Field<E> {
47 let result = self.to_field();
48 debug_assert!(result.is_ok(), "Casting an integer to field cannot fail");
49 result.unwrap()
50 }
51}
52
53impl<E: Environment, I: IntegerType> CastLossy<Group<E>> for Integer<E, I> {
54 #[inline]
60 fn cast_lossy(&self) -> Group<E> {
61 let field: Field<E> = self.cast_lossy();
62 field.cast_lossy()
63 }
64}
65
66impl<E: Environment, I0: IntegerType + AsPrimitive<I1>, I1: IntegerType> CastLossy<Integer<E, I1>> for Integer<E, I0> {
67 #[inline]
69 fn cast_lossy(&self) -> Integer<E, I1> {
70 Integer::new((**self).as_())
71 }
72}
73
74impl<E: Environment, I: IntegerType> CastLossy<Scalar<E>> for Integer<E, I> {
75 #[inline]
78 fn cast_lossy(&self) -> Scalar<E> {
79 self.to_scalar()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 type CurrentEnvironment = snarkvm_console_network::Console;
88
89 const ITERATIONS: u64 = 1_000;
90
91 #[test]
92 fn test_integer_to_address() {
93 macro_rules! check_integer_to_address {
94 ($type:ty) => {
95 let rng = &mut TestRng::default();
96
97 let integer = Integer::<CurrentEnvironment, $type>::one();
98 let address: Address<CurrentEnvironment> = integer.cast_lossy();
99 assert_eq!(address, Address::new(Group::generator()));
100 assert_eq!(address.to_group(), &Group::generator());
101
102 let integer = Integer::<CurrentEnvironment, $type>::zero();
103 let address: Address<CurrentEnvironment> = integer.cast_lossy();
104 assert_eq!(address, Address::zero());
105 assert_eq!(address.to_group(), &Group::zero());
106
107 for _ in 0..ITERATIONS {
108 let integer = Integer::<CurrentEnvironment, $type>::rand(rng);
110 let candidate: Address<CurrentEnvironment> = integer.cast_lossy();
112 let expected: Group<CurrentEnvironment> = integer.cast_lossy();
114 assert_eq!(Address::new(expected), candidate);
115 }
116 };
117 }
118
119 check_integer_to_address!(i8);
120 check_integer_to_address!(i16);
121 check_integer_to_address!(i32);
122 check_integer_to_address!(i64);
123 check_integer_to_address!(i128);
124 check_integer_to_address!(u8);
125 check_integer_to_address!(u16);
126 check_integer_to_address!(u32);
127 check_integer_to_address!(u64);
128 check_integer_to_address!(u128);
129 }
130
131 #[test]
132 fn test_integer_to_boolean() {
133 macro_rules! check_integer_to_boolean {
134 ($type:ty) => {
135 let rng = &mut TestRng::default();
136
137 let integer = Integer::<CurrentEnvironment, $type>::one();
138 let boolean: Boolean<CurrentEnvironment> = integer.cast_lossy();
139 assert_eq!(boolean, Boolean::new(true));
140
141 let integer = Integer::<CurrentEnvironment, $type>::zero();
142 let boolean: Boolean<CurrentEnvironment> = integer.cast_lossy();
143 assert_eq!(boolean, Boolean::new(false));
144
145 for _ in 0..ITERATIONS {
146 let integer = Integer::<CurrentEnvironment, $type>::rand(rng);
148 let candidate: Boolean<CurrentEnvironment> = integer.cast_lossy();
150 let expected = Boolean::new(integer.to_bits_be().pop().unwrap());
152 assert_eq!(expected, candidate);
153 }
154 };
155 }
156
157 check_integer_to_boolean!(i8);
158 check_integer_to_boolean!(i16);
159 check_integer_to_boolean!(i32);
160 check_integer_to_boolean!(i64);
161 check_integer_to_boolean!(i128);
162 check_integer_to_boolean!(u8);
163 check_integer_to_boolean!(u16);
164 check_integer_to_boolean!(u32);
165 check_integer_to_boolean!(u64);
166 check_integer_to_boolean!(u128);
167 }
168
169 #[test]
170 fn test_integer_to_field() {
171 macro_rules! check_integer_to_field {
172 ($type:ty) => {
173 let rng = &mut TestRng::default();
174
175 for _ in 0..ITERATIONS {
176 let integer = Integer::<CurrentEnvironment, $type>::rand(rng);
178 let candidate: Field<CurrentEnvironment> = integer.cast_lossy();
180 let expected = integer.to_field().unwrap();
182 assert_eq!(expected, candidate);
183 }
184 };
185 }
186
187 check_integer_to_field!(i8);
188 check_integer_to_field!(i16);
189 check_integer_to_field!(i32);
190 check_integer_to_field!(i64);
191 check_integer_to_field!(i128);
192 check_integer_to_field!(u8);
193 check_integer_to_field!(u16);
194 check_integer_to_field!(u32);
195 check_integer_to_field!(u64);
196 check_integer_to_field!(u128);
197 }
198
199 #[test]
200 fn test_integer_to_group() {
201 macro_rules! check_integer_to_group {
202 ($type:ty) => {
203 let rng = &mut TestRng::default();
204
205 let integer = Integer::<CurrentEnvironment, $type>::one();
206 let group: Group<CurrentEnvironment> = integer.cast_lossy();
207 assert_eq!(group, Group::generator());
208
209 let integer = Integer::<CurrentEnvironment, $type>::zero();
210 let group: Group<CurrentEnvironment> = integer.cast_lossy();
211 assert_eq!(group, Group::zero());
212
213 for _ in 0..ITERATIONS {
214 let integer = Integer::<CurrentEnvironment, $type>::rand(rng);
216 let candidate: Group<CurrentEnvironment> = integer.cast_lossy();
218 let expected: Group<CurrentEnvironment> = integer.to_field().unwrap().cast_lossy();
220 assert_eq!(expected, candidate);
221 }
222 };
223 }
224
225 check_integer_to_group!(i8);
226 check_integer_to_group!(i16);
227 check_integer_to_group!(i32);
228 check_integer_to_group!(i64);
229 check_integer_to_group!(i128);
230 check_integer_to_group!(u8);
231 check_integer_to_group!(u16);
232 check_integer_to_group!(u32);
233 check_integer_to_group!(u64);
234 check_integer_to_group!(u128);
235 }
236
237 #[test]
238 fn test_integer_to_scalar() {
239 macro_rules! check_integer_to_scalar {
240 ($type:ty) => {
241 let rng = &mut TestRng::default();
242
243 for _ in 0..ITERATIONS {
244 let integer = Integer::<CurrentEnvironment, $type>::rand(rng);
246 let candidate: Scalar<CurrentEnvironment> = integer.cast_lossy();
248 let expected = integer.to_scalar();
250 assert_eq!(expected, candidate);
251 }
252 };
253 }
254
255 check_integer_to_scalar!(i8);
256 check_integer_to_scalar!(i16);
257 check_integer_to_scalar!(i32);
258 check_integer_to_scalar!(i64);
259 check_integer_to_scalar!(i128);
260 check_integer_to_scalar!(u8);
261 check_integer_to_scalar!(u16);
262 check_integer_to_scalar!(u32);
263 check_integer_to_scalar!(u64);
264 check_integer_to_scalar!(u128);
265 }
266
267 #[test]
268 fn test_integer_to_integer() {
269 macro_rules! check_integer_to_integer {
270 ($type_a:ty, $type_b:ty) => {
271 let rng = &mut TestRng::default();
272
273 println!("Checking {} -> {}", stringify!($type_a), stringify!($type_b));
274
275 for _ in 0..ITERATIONS {
276 let integer = Integer::<CurrentEnvironment, $type_a>::rand(rng);
278 let candidate: Integer<CurrentEnvironment, $type_b> = integer.cast_lossy();
280
281 let data_bits = std::cmp::min(<$type_a>::BITS, <$type_b>::BITS) as usize;
283 for (expected_bit, candidate_bit) in
285 integer.to_bits_le()[0..data_bits].iter().zip_eq(&candidate.to_bits_le()[0..data_bits])
286 {
287 assert_eq!(
288 expected_bit, candidate_bit,
289 "Data bits do not match - ({:b} != {:b})",
290 *integer, *candidate
291 );
292 }
293 for candidate_bit in &candidate.to_bits_le()[data_bits..] {
295 let expected_bit = match <$type_a>::is_signed() {
296 true => integer.to_bits_le()[data_bits - 1],
297 false => false,
298 };
299 assert_eq!(
300 expected_bit, *candidate_bit,
301 "Remaining bits are not correct - ({:b} != {:b})",
302 *integer, *candidate
303 );
304 }
305 }
306 };
307 }
308 {
309 check_integer_to_integer!(i8, i8);
310 check_integer_to_integer!(i8, i16);
311 check_integer_to_integer!(i8, i32);
312 check_integer_to_integer!(i8, i64);
313 check_integer_to_integer!(i8, i128);
314 check_integer_to_integer!(i8, u8);
315 check_integer_to_integer!(i8, u16);
316 check_integer_to_integer!(i8, u32);
317 check_integer_to_integer!(i8, u64);
318 check_integer_to_integer!(i8, u128);
319 }
320 {
321 check_integer_to_integer!(i16, i8);
322 check_integer_to_integer!(i16, i16);
323 check_integer_to_integer!(i16, i32);
324 check_integer_to_integer!(i16, i64);
325 check_integer_to_integer!(i16, i128);
326 check_integer_to_integer!(i16, u8);
327 check_integer_to_integer!(i16, u16);
328 check_integer_to_integer!(i16, u32);
329 check_integer_to_integer!(i16, u64);
330 check_integer_to_integer!(i16, u128);
331 }
332 {
333 check_integer_to_integer!(i32, i8);
334 check_integer_to_integer!(i32, i16);
335 check_integer_to_integer!(i32, i32);
336 check_integer_to_integer!(i32, i64);
337 check_integer_to_integer!(i32, i128);
338 check_integer_to_integer!(i32, u8);
339 check_integer_to_integer!(i32, u16);
340 check_integer_to_integer!(i32, u32);
341 check_integer_to_integer!(i32, u64);
342 check_integer_to_integer!(i32, u128);
343 }
344 {
345 check_integer_to_integer!(i64, i8);
346 check_integer_to_integer!(i64, i16);
347 check_integer_to_integer!(i64, i32);
348 check_integer_to_integer!(i64, i64);
349 check_integer_to_integer!(i64, i128);
350 check_integer_to_integer!(i64, u8);
351 check_integer_to_integer!(i64, u16);
352 check_integer_to_integer!(i64, u32);
353 check_integer_to_integer!(i64, u64);
354 check_integer_to_integer!(i64, u128);
355 }
356 {
357 check_integer_to_integer!(i128, i8);
358 check_integer_to_integer!(i128, i16);
359 check_integer_to_integer!(i128, i32);
360 check_integer_to_integer!(i128, i64);
361 check_integer_to_integer!(i128, i128);
362 check_integer_to_integer!(i128, u8);
363 check_integer_to_integer!(i128, u16);
364 check_integer_to_integer!(i128, u32);
365 check_integer_to_integer!(i128, u64);
366 check_integer_to_integer!(i128, u128);
367 }
368 {
369 check_integer_to_integer!(u8, i8);
370 check_integer_to_integer!(u8, i16);
371 check_integer_to_integer!(u8, i32);
372 check_integer_to_integer!(u8, i64);
373 check_integer_to_integer!(u8, i128);
374 check_integer_to_integer!(u8, u8);
375 check_integer_to_integer!(u8, u16);
376 check_integer_to_integer!(u8, u32);
377 check_integer_to_integer!(u8, u64);
378 check_integer_to_integer!(u8, u128);
379 }
380 {
381 check_integer_to_integer!(u16, i8);
382 check_integer_to_integer!(u16, i16);
383 check_integer_to_integer!(u16, i32);
384 check_integer_to_integer!(u16, i64);
385 check_integer_to_integer!(u16, i128);
386 check_integer_to_integer!(u16, u8);
387 check_integer_to_integer!(u16, u16);
388 check_integer_to_integer!(u16, u32);
389 check_integer_to_integer!(u16, u64);
390 check_integer_to_integer!(u16, u128);
391 }
392 {
393 check_integer_to_integer!(u32, i8);
394 check_integer_to_integer!(u32, i16);
395 check_integer_to_integer!(u32, i32);
396 check_integer_to_integer!(u32, i64);
397 check_integer_to_integer!(u32, i128);
398 check_integer_to_integer!(u32, u8);
399 check_integer_to_integer!(u32, u16);
400 check_integer_to_integer!(u32, u32);
401 check_integer_to_integer!(u32, u64);
402 check_integer_to_integer!(u32, u128);
403 }
404 {
405 check_integer_to_integer!(u64, i8);
406 check_integer_to_integer!(u64, i16);
407 check_integer_to_integer!(u64, i32);
408 check_integer_to_integer!(u64, i64);
409 check_integer_to_integer!(u64, i128);
410 check_integer_to_integer!(u64, u8);
411 check_integer_to_integer!(u64, u16);
412 check_integer_to_integer!(u64, u32);
413 check_integer_to_integer!(u64, u64);
414 check_integer_to_integer!(u64, u128);
415 }
416 }
417}