1use super::*;
17
18impl<E: Environment> CastLossy<Address<E>> for Field<E> {
19 #[inline]
25 fn cast_lossy(&self) -> Address<E> {
26 let group: Group<E> = self.cast_lossy();
28 Address::from_group(group)
30 }
31}
32
33impl<E: Environment> CastLossy<Boolean<E>> for Field<E> {
34 #[inline]
37 fn cast_lossy(&self) -> Boolean<E> {
38 let bits_le = self.to_bits_le();
39 debug_assert!(!bits_le.is_empty(), "An integer must have at least one bit");
40 bits_le[0].clone()
41 }
42}
43
44impl<E: Environment> CastLossy<Field<E>> for Field<E> {
45 #[inline]
48 fn cast_lossy(&self) -> Field<E> {
49 self.clone()
50 }
51}
52
53impl<E: Environment> CastLossy<Group<E>> for Field<E> {
54 #[inline]
63 fn cast_lossy(&self) -> Group<E> {
64 debug_assert!(console::Group::from_x_coordinate(<console::Field<E::Network> as console::One>::one()).is_err());
67
68 let (point_with_x, x_is_not_in_group) = Group::from_x_coordinate_flagged(self.clone());
70
71 let is_x_zero = self.is_zero();
73 let is_x_one = self.is_one();
75
76 let generator = Group::generator();
78
79 let elligator_input = Field::ternary(&is_x_zero, &Field::one(), self);
84 let elligator_point = Elligator2::encode(&elligator_input);
86
87 let generator_or_elligator_point = Group::ternary(&is_x_one, &generator, &elligator_point);
90
91 Group::ternary(&x_is_not_in_group, &generator_or_elligator_point, &point_with_x)
94 }
95}
96
97impl<E: Environment, I: IntegerType> CastLossy<Integer<E, I>> for Field<E> {
98 #[inline]
101 fn cast_lossy(&self) -> Integer<E, I> {
102 Integer::from_field_lossy(self)
103 }
104}
105
106impl<E: Environment> CastLossy<Scalar<E>> for Field<E> {
107 #[inline]
110 fn cast_lossy(&self) -> Scalar<E> {
111 Scalar::from_field_lossy(self)
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use console::CastLossy as _;
119 use console_root::{
120 network::MainnetV0,
121 prelude::{One, TestRng, Uniform, Zero},
122 };
123 use snarkvm_circuit_types::environment::{Circuit, Eject, Inject, Mode, UpdatableCount, count_is, count_less_than};
124
125 use std::fmt::Debug;
126
127 const ITERATIONS: usize = 100;
128
129 fn sample_values(
130 i: usize,
131 mode: Mode,
132 rng: &mut TestRng,
133 ) -> (console_root::types::Field<MainnetV0>, Field<Circuit>) {
134 let console_value = match i {
135 0 => console_root::types::Field::<MainnetV0>::zero(),
136 1 => console_root::types::Field::<MainnetV0>::one(),
137 _ => Uniform::rand(rng),
138 };
139 let circuit_value = Field::<Circuit>::new(mode, console_value);
140 (console_value, circuit_value)
141 }
142
143 check_cast_lossy!(cast_lossy, Field<Circuit>, console_root::types::Field::<MainnetV0>);
144
145 #[test]
146 fn test_field_to_address() {
147 check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
148 Mode::Constant,
149 count_less_than!(4303, 0, 0, 0),
150 );
151 check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
152 Mode::Public,
153 count_is!(2029, 0, 6745, 6750),
154 );
155 check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
156 Mode::Private,
157 count_is!(2029, 0, 6745, 6750),
158 );
159 }
160
161 #[test]
162 fn test_field_to_boolean() {
163 check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
164 Mode::Constant,
165 count_is!(253, 0, 0, 0),
166 );
167 check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
168 Mode::Public,
169 count_is!(0, 0, 505, 507),
170 );
171 check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
172 Mode::Private,
173 count_is!(0, 0, 505, 507),
174 );
175 }
176
177 #[test]
178 fn test_field_to_field() {
179 check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(
180 Mode::Constant,
181 count_is!(0, 0, 0, 0),
182 );
183 check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Public, count_is!(0, 0, 0, 0));
184 check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Private, count_is!(0, 0, 0, 0));
185 }
186
187 #[test]
188 fn test_field_to_group() {
189 check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
190 Mode::Constant,
191 count_less_than!(4303, 0, 0, 0),
192 );
193 check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
194 Mode::Public,
195 count_is!(2029, 0, 6745, 6750),
196 );
197 check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
198 Mode::Private,
199 count_is!(2029, 0, 6745, 6750),
200 );
201 }
202
203 #[test]
204 fn test_field_to_i8() {
205 check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
206 check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
207 check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
208 }
209
210 #[test]
211 fn test_field_to_i16() {
212 check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
213 check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
214 check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
215 }
216
217 #[test]
218 fn test_field_to_i32() {
219 check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
220 check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
221 check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
222 }
223
224 #[test]
225 fn test_field_to_i64() {
226 check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
227 check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
228 check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
229 }
230
231 #[test]
232 fn test_field_to_i128() {
233 check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
234 Mode::Constant,
235 count_is!(253, 0, 0, 0),
236 );
237 check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
238 Mode::Public,
239 count_is!(0, 0, 505, 507),
240 );
241 check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
242 Mode::Private,
243 count_is!(0, 0, 505, 507),
244 );
245 }
246
247 #[test]
248 fn test_field_to_scalar() {
249 check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
250 Mode::Constant,
251 count_is!(253, 0, 0, 0),
252 );
253 check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
254 Mode::Public,
255 count_is!(0, 0, 505, 507),
256 );
257 check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
258 Mode::Private,
259 count_is!(0, 0, 505, 507),
260 );
261 }
262
263 #[test]
264 fn test_field_to_u8() {
265 check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
266 check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
267 check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
268 }
269
270 #[test]
271 fn test_field_to_u16() {
272 check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
273 check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
274 check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
275 }
276
277 #[test]
278 fn test_field_to_u32() {
279 check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
280 check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
281 check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
282 }
283
284 #[test]
285 fn test_field_to_u64() {
286 check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Constant, count_is!(253, 0, 0, 0));
287 check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Public, count_is!(0, 0, 505, 507));
288 check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Private, count_is!(0, 0, 505, 507));
289 }
290
291 #[test]
292 fn test_field_to_u128() {
293 check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
294 Mode::Constant,
295 count_is!(253, 0, 0, 0),
296 );
297 check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
298 Mode::Public,
299 count_is!(0, 0, 505, 507),
300 );
301 check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
302 Mode::Private,
303 count_is!(0, 0, 505, 507),
304 );
305 }
306}