snarkvm_console_program/data/literal/cast_lossy/
scalar.rs1use super::*;
17
18impl<E: Environment> CastLossy<Address<E>> for Scalar<E> {
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> CastLossy<Boolean<E>> for Scalar<E> {
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> CastLossy<Group<E>> for Scalar<E> {
43 #[inline]
49 fn cast_lossy(&self) -> Group<E> {
50 let field: Field<E> = self.cast_lossy();
51 field.cast_lossy()
52 }
53}
54
55impl<E: Environment> CastLossy<Field<E>> for Scalar<E> {
56 #[inline]
59 fn cast_lossy(&self) -> Field<E> {
60 let result = self.to_field();
61 debug_assert!(result.is_ok(), "A scalar should always be able to be converted to a field");
62 result.unwrap()
63 }
64}
65
66impl<E: Environment, I: IntegerType> CastLossy<Integer<E, I>> for Scalar<E> {
67 #[inline]
69 fn cast_lossy(&self) -> Integer<E, I> {
70 debug_assert!(I::BITS < Scalar::<E>::size_in_bits() as u64);
74
75 let result = Integer::<E, I>::from_bits_le(&self.to_bits_le()[..usize::try_from(I::BITS).unwrap()]);
78 debug_assert!(result.is_ok(), "A lossy integer should always be able to be constructed from scalar bits");
79 result.unwrap()
80 }
81}
82
83impl<E: Environment> CastLossy<Scalar<E>> for Scalar<E> {
84 #[inline]
87 fn cast_lossy(&self) -> Scalar<E> {
88 *self
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 type CurrentEnvironment = Console;
97
98 const ITERATIONS: u64 = 10_000;
99
100 #[test]
101 fn test_scalar_to_address() {
102 let rng = &mut TestRng::default();
103
104 let scalar = Scalar::<CurrentEnvironment>::one();
105 let address: Address<CurrentEnvironment> = scalar.cast_lossy();
106 assert_eq!(address, Address::new(Group::generator()));
107 assert_eq!(address.to_group(), &Group::generator());
108
109 let scalar = Scalar::<CurrentEnvironment>::zero();
110 let address: Address<CurrentEnvironment> = scalar.cast_lossy();
111 assert_eq!(address, Address::zero());
112 assert_eq!(address.to_group(), &Group::zero());
113
114 for _ in 0..ITERATIONS {
115 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
117 let candidate = scalar.cast_lossy();
119 let expected: Group<CurrentEnvironment> = scalar.cast_lossy();
121 assert_eq!(Address::new(expected), candidate);
122 }
123 }
124
125 #[test]
126 fn test_scalar_to_boolean() {
127 let rng = &mut TestRng::default();
128
129 let scalar = Scalar::<CurrentEnvironment>::one();
130 let boolean: Boolean<CurrentEnvironment> = scalar.cast_lossy();
131 assert_eq!(boolean, Boolean::new(true));
132
133 let scalar = Scalar::<CurrentEnvironment>::zero();
134 let boolean: Boolean<CurrentEnvironment> = scalar.cast_lossy();
135 assert_eq!(boolean, Boolean::new(false));
136
137 for _ in 0..ITERATIONS {
138 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
140 let candidate = scalar.cast_lossy();
142 let expected = Boolean::new(scalar.to_bits_be().pop().unwrap());
144 assert_eq!(expected, candidate);
145 }
146 }
147
148 #[test]
149 fn test_scalar_to_field() {
150 let rng = &mut TestRng::default();
151
152 for _ in 0..ITERATIONS {
153 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
155 let candidate = scalar.cast_lossy();
157 assert_eq!(scalar.to_field().unwrap(), candidate);
158 }
159 }
160
161 #[test]
162 fn test_scalar_to_group() {
163 let rng = &mut TestRng::default();
164
165 let scalar = Scalar::<CurrentEnvironment>::one();
166 let group: Group<CurrentEnvironment> = scalar.cast_lossy();
167 assert_eq!(group, Group::generator());
168
169 let scalar = Scalar::<CurrentEnvironment>::zero();
170 let group: Group<CurrentEnvironment> = scalar.cast_lossy();
171 assert_eq!(group, Group::zero());
172
173 for _ in 0..ITERATIONS {
174 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
176 let candidate: Group<CurrentEnvironment> = scalar.cast_lossy();
178 let expected: Address<CurrentEnvironment> = scalar.cast_lossy();
180 assert_eq!(expected.to_group(), &candidate);
181 }
182 }
183
184 #[test]
185 fn test_scalar_to_scalar() {
186 let rng = &mut TestRng::default();
187
188 for _ in 0..ITERATIONS {
189 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
191 let candidate: Scalar<CurrentEnvironment> = scalar.cast_lossy();
193 assert_eq!(scalar, candidate);
194 }
195 }
196
197 macro_rules! check_scalar_to_integer {
198 ($type:ty) => {
199 let rng = &mut TestRng::default();
200
201 let scalar = Scalar::<CurrentEnvironment>::one();
202 let integer: Integer<CurrentEnvironment, $type> = scalar.cast_lossy();
203 assert_eq!(integer, Integer::<CurrentEnvironment, $type>::one());
204
205 let scalar = Scalar::<CurrentEnvironment>::zero();
206 let integer: Integer<CurrentEnvironment, $type> = scalar.cast_lossy();
207 assert_eq!(integer, Integer::<CurrentEnvironment, $type>::zero());
208
209 for _ in 0..ITERATIONS {
210 let scalar = Scalar::<CurrentEnvironment>::rand(rng);
212 let candidate: Integer<CurrentEnvironment, $type> = scalar.cast_lossy();
214 let expected = Integer::<CurrentEnvironment, $type>::from_bits_le(
216 &scalar.to_bits_le()[..usize::try_from(<$type>::BITS).unwrap()],
217 )
218 .unwrap();
219 assert_eq!(expected, candidate);
220 }
221 };
222 }
223
224 #[test]
225 fn test_scalar_to_i8() {
226 check_scalar_to_integer!(i8);
227 }
228
229 #[test]
230 fn test_scalar_to_i16() {
231 check_scalar_to_integer!(i16);
232 }
233
234 #[test]
235 fn test_scalar_to_i32() {
236 check_scalar_to_integer!(i32);
237 }
238
239 #[test]
240 fn test_scalar_to_i64() {
241 check_scalar_to_integer!(i64);
242 }
243
244 #[test]
245 fn test_scalar_to_i128() {
246 check_scalar_to_integer!(i128);
247 }
248
249 #[test]
250 fn test_scalar_to_u8() {
251 check_scalar_to_integer!(u8);
252 }
253
254 #[test]
255 fn test_scalar_to_u16() {
256 check_scalar_to_integer!(u16);
257 }
258
259 #[test]
260 fn test_scalar_to_u32() {
261 check_scalar_to_integer!(u32);
262 }
263
264 #[test]
265 fn test_scalar_to_u64() {
266 check_scalar_to_integer!(u64);
267 }
268
269 #[test]
270 fn test_scalar_to_u128() {
271 check_scalar_to_integer!(u128);
272 }
273}