snarkvm_console_types_integers/
to_field.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use super::*;
17
18impl<E: Environment, I: IntegerType> ToField for Integer<E, I> {
19    type Field = Field<E>;
20
21    /// Converts an integer into a field element.
22    fn to_field(&self) -> Result<Self::Field> {
23        // Note: We are reconstituting the integer as a base field.
24        // This is safe as the number of bits in the integer is less than the base field modulus,
25        // and thus will always fit within a single base field element.
26        debug_assert!(I::BITS < Field::<E>::size_in_bits() as u64);
27
28        // Reconstruct the bits as a linear combination representing the original field value.
29        Field::from_bits_le(&self.to_bits_le())
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36    use snarkvm_console_network_environment::Console;
37
38    type CurrentEnvironment = Console;
39
40    const ITERATIONS: u64 = 10_000;
41
42    fn check_to_field<I: IntegerType>() -> Result<()> {
43        let mut rng = TestRng::default();
44
45        for _ in 0..ITERATIONS {
46            // Sample a random integer.
47            let expected = Integer::<CurrentEnvironment, I>::rand(&mut rng);
48
49            // Perform the operation.
50            let candidate = expected.to_field()?;
51
52            // Extract the bits from the base field representation.
53            let candidate_bits_le = candidate.to_bits_le();
54            assert_eq!(Field::<CurrentEnvironment>::size_in_bits(), candidate_bits_le.len());
55
56            // Ensure all integer bits match with the expected result.
57            let i_bits = usize::try_from(I::BITS).unwrap();
58            let expected_bits = expected.to_bits_le();
59            for (expected_bit, candidate_bit) in expected_bits.iter().zip_eq(&candidate_bits_le[0..i_bits]) {
60                assert_eq!(expected_bit, candidate_bit);
61            }
62
63            // Ensure all remaining bits are 0.
64            for candidate_bit in &candidate_bits_le[i_bits..] {
65                assert!(!candidate_bit);
66            }
67        }
68        Ok(())
69    }
70
71    #[test]
72    fn test_u8_to_field() -> Result<()> {
73        type I = u8;
74        check_to_field::<I>()
75    }
76
77    #[test]
78    fn test_i8_to_field() -> Result<()> {
79        type I = i8;
80        check_to_field::<I>()
81    }
82
83    #[test]
84    fn test_u16_to_field() -> Result<()> {
85        type I = u16;
86        check_to_field::<I>()
87    }
88
89    #[test]
90    fn test_i16_to_field() -> Result<()> {
91        type I = i16;
92        check_to_field::<I>()
93    }
94
95    #[test]
96    fn test_u32_to_field() -> Result<()> {
97        type I = u32;
98        check_to_field::<I>()
99    }
100
101    #[test]
102    fn test_i32_to_field() -> Result<()> {
103        type I = i32;
104        check_to_field::<I>()
105    }
106
107    #[test]
108    fn test_u64_to_field() -> Result<()> {
109        type I = u64;
110        check_to_field::<I>()
111    }
112
113    #[test]
114    fn test_i64_to_field() -> Result<()> {
115        type I = i64;
116        check_to_field::<I>()
117    }
118
119    #[test]
120    fn test_u128_to_field() -> Result<()> {
121        type I = u128;
122        check_to_field::<I>()
123    }
124
125    #[test]
126    fn test_i128_to_field() -> Result<()> {
127        type I = i128;
128        check_to_field::<I>()
129    }
130}