snarkvm_circuit_program/data/literal/cast_lossy/
boolean.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> CastLossy<Address<E>> for Boolean<E> {
19    /// Casts a `Boolean` to an `Address`.
20    /// This is safe because casting from a boolean to any other type is **always** lossless.
21    ///
22    /// If the boolean is true, the address is the generator of the prime-order subgroup.
23    /// If the boolean is false, the address is the zero group element.
24    #[inline]
25    fn cast_lossy(&self) -> Address<E> {
26        Address::ternary(self, &Address::from_group(Group::generator()), &Address::zero())
27    }
28}
29
30impl<E: Environment> CastLossy<Boolean<E>> for Boolean<E> {
31    /// Casts a `Boolean` to a `Boolean`.
32    /// This is an identity cast, so it is **always** lossless.
33    #[inline]
34    fn cast_lossy(&self) -> Boolean<E> {
35        self.clone()
36    }
37}
38
39impl<E: Environment> CastLossy<Field<E>> for Boolean<E> {
40    /// Casts a `Boolean` to a `Field`.
41    /// This is safe because casting from a boolean to any other type is **always** lossless.
42    #[inline]
43    fn cast_lossy(&self) -> Field<E> {
44        Field::from_boolean(self)
45    }
46}
47
48impl<E: Environment> CastLossy<Group<E>> for Boolean<E> {
49    /// Casts a `Boolean` to a `Group`.
50    /// This is safe because casting from a boolean to any other type is **always** lossless.
51    ///
52    /// If the boolean is true, the group element is the generator of the prime-order subgroup.
53    /// If the boolean is false, the group element is the zero group element.
54    #[inline]
55    fn cast_lossy(&self) -> Group<E> {
56        Group::ternary(self, &Group::generator(), &Group::zero())
57    }
58}
59
60impl<E: Environment, I: IntegerType> CastLossy<Integer<E, I>> for Boolean<E> {
61    /// Casts a `Boolean` to an `Integer`.
62    #[inline]
63    fn cast_lossy(&self) -> Integer<E, I> {
64        Integer::ternary(self, &Integer::one(), &Integer::zero())
65    }
66}
67
68impl<E: Environment> CastLossy<Scalar<E>> for Boolean<E> {
69    /// Casts a `Boolean` to a `Scalar`.
70    /// This is safe because casting from a boolean to any other type is **always** lossless.
71    #[inline]
72    fn cast_lossy(&self) -> Scalar<E> {
73        Scalar::ternary(self, &Scalar::one(), &Scalar::zero())
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use console::CastLossy as _;
81    use console_root::{network::MainnetV0, prelude::TestRng};
82    use snarkvm_circuit_types::environment::{Circuit, Eject, Inject, Mode, UpdatableCount, count_is};
83
84    use std::fmt::Debug;
85
86    const ITERATIONS: usize = 2;
87
88    fn sample_values(
89        i: usize,
90        mode: Mode,
91        _: &mut TestRng,
92    ) -> (console_root::types::Boolean<MainnetV0>, Boolean<Circuit>) {
93        (console_root::types::Boolean::new(i % 2 == 0), Boolean::new(mode, i % 2 == 0))
94    }
95
96    check_cast_lossy!(cast_lossy, Boolean<Circuit>, console_root::types::Boolean::<MainnetV0>);
97
98    #[test]
99    fn test_boolean_to_address() {
100        check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
101            Mode::Constant,
102            count_is!(10, 0, 0, 0),
103        );
104        check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
105            Mode::Public,
106            count_is!(10, 0, 0, 0),
107        );
108        check_cast_lossy::<Address<Circuit>, console_root::types::Address<MainnetV0>>(
109            Mode::Private,
110            count_is!(10, 0, 0, 0),
111        );
112    }
113
114    #[test]
115    fn test_boolean_to_boolean() {
116        check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
117            Mode::Constant,
118            count_is!(0, 0, 0, 0),
119        );
120        check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
121            Mode::Public,
122            count_is!(0, 0, 0, 0),
123        );
124        check_cast_lossy::<Boolean<Circuit>, console_root::types::Boolean<MainnetV0>>(
125            Mode::Private,
126            count_is!(0, 0, 0, 0),
127        );
128    }
129
130    #[test]
131    fn test_boolean_to_field() {
132        check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(
133            Mode::Constant,
134            count_is!(0, 0, 0, 0),
135        );
136        check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Public, count_is!(0, 0, 0, 0));
137        check_cast_lossy::<Field<Circuit>, console_root::types::Field<MainnetV0>>(Mode::Private, count_is!(0, 0, 0, 0));
138    }
139
140    #[test]
141    fn test_boolean_to_group() {
142        check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
143            Mode::Constant,
144            count_is!(10, 0, 0, 0),
145        );
146        check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(Mode::Public, count_is!(10, 0, 0, 0));
147        check_cast_lossy::<Group<Circuit>, console_root::types::Group<MainnetV0>>(
148            Mode::Private,
149            count_is!(10, 0, 0, 0),
150        );
151    }
152
153    #[test]
154    fn test_boolean_to_i8() {
155        check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Constant, count_is!(16, 0, 0, 0));
156        check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Public, count_is!(16, 0, 0, 0));
157        check_cast_lossy::<I8<Circuit>, console_root::types::I8<MainnetV0>>(Mode::Private, count_is!(16, 0, 0, 0));
158    }
159
160    #[test]
161    fn test_boolean_to_i16() {
162        check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Constant, count_is!(32, 0, 0, 0));
163        check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Public, count_is!(32, 0, 0, 0));
164        check_cast_lossy::<I16<Circuit>, console_root::types::I16<MainnetV0>>(Mode::Private, count_is!(32, 0, 0, 0));
165    }
166
167    #[test]
168    fn test_boolean_to_i32() {
169        check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Constant, count_is!(64, 0, 0, 0));
170        check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Public, count_is!(64, 0, 0, 0));
171        check_cast_lossy::<I32<Circuit>, console_root::types::I32<MainnetV0>>(Mode::Private, count_is!(64, 0, 0, 0));
172    }
173
174    #[test]
175    fn test_boolean_to_i64() {
176        check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Constant, count_is!(128, 0, 0, 0));
177        check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Public, count_is!(128, 0, 0, 0));
178        check_cast_lossy::<I64<Circuit>, console_root::types::I64<MainnetV0>>(Mode::Private, count_is!(128, 0, 0, 0));
179    }
180
181    #[test]
182    fn test_boolean_to_i128() {
183        check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(
184            Mode::Constant,
185            count_is!(256, 0, 0, 0),
186        );
187        check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(Mode::Public, count_is!(256, 0, 0, 0));
188        check_cast_lossy::<I128<Circuit>, console_root::types::I128<MainnetV0>>(Mode::Private, count_is!(256, 0, 0, 0));
189    }
190
191    #[test]
192    fn test_boolean_to_scalar() {
193        check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
194            Mode::Constant,
195            count_is!(2, 0, 0, 0),
196        );
197        check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
198            Mode::Public,
199            count_is!(2, 0, 0, 0),
200        );
201        check_cast_lossy::<Scalar<Circuit>, console_root::types::Scalar<MainnetV0>>(
202            Mode::Private,
203            count_is!(2, 0, 0, 0),
204        );
205    }
206
207    #[test]
208    fn test_boolean_to_u8() {
209        check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Constant, count_is!(16, 0, 0, 0));
210        check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Public, count_is!(16, 0, 0, 0));
211        check_cast_lossy::<U8<Circuit>, console_root::types::U8<MainnetV0>>(Mode::Private, count_is!(16, 0, 0, 0));
212    }
213
214    #[test]
215    fn test_boolean_to_u16() {
216        check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Constant, count_is!(32, 0, 0, 0));
217        check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Public, count_is!(32, 0, 0, 0));
218        check_cast_lossy::<U16<Circuit>, console_root::types::U16<MainnetV0>>(Mode::Private, count_is!(32, 0, 0, 0));
219    }
220
221    #[test]
222    fn test_boolean_to_u32() {
223        check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Constant, count_is!(64, 0, 0, 0));
224        check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Public, count_is!(64, 0, 0, 0));
225        check_cast_lossy::<U32<Circuit>, console_root::types::U32<MainnetV0>>(Mode::Private, count_is!(64, 0, 0, 0));
226    }
227
228    #[test]
229    fn test_boolean_to_u64() {
230        check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Constant, count_is!(128, 0, 0, 0));
231        check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Public, count_is!(128, 0, 0, 0));
232        check_cast_lossy::<U64<Circuit>, console_root::types::U64<MainnetV0>>(Mode::Private, count_is!(128, 0, 0, 0));
233    }
234
235    #[test]
236    fn test_boolean_to_u128() {
237        check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(
238            Mode::Constant,
239            count_is!(256, 0, 0, 0),
240        );
241        check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(Mode::Public, count_is!(256, 0, 0, 0));
242        check_cast_lossy::<U128<Circuit>, console_root::types::U128<MainnetV0>>(Mode::Private, count_is!(256, 0, 0, 0));
243    }
244}