snarkvm_console_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        match **self {
27            true => Address::new(Group::generator()),
28            false => Address::zero(),
29        }
30    }
31}
32
33impl<E: Environment> CastLossy<Boolean<E>> for Boolean<E> {
34    /// Casts a `Boolean` to a `Boolean`.
35    /// This is an identity cast, so it is **always** lossless.
36    #[inline]
37    fn cast_lossy(&self) -> Boolean<E> {
38        *self
39    }
40}
41
42impl<E: Environment> CastLossy<Field<E>> for Boolean<E> {
43    /// Casts a `Boolean` to a `Field`.
44    /// This is safe because casting from a boolean to any other type is **always** lossless.
45    #[inline]
46    fn cast_lossy(&self) -> Field<E> {
47        match **self {
48            true => Field::one(),
49            false => Field::zero(),
50        }
51    }
52}
53
54impl<E: Environment> CastLossy<Group<E>> for Boolean<E> {
55    /// Casts a `Boolean` to a `Group`.
56    /// This is safe because casting from a boolean to any other type is **always** lossless.
57    ///
58    /// If the boolean is true, the group element is the generator of the prime-order subgroup.
59    /// If the boolean is false, the group element is the zero group element.
60    #[inline]
61    fn cast_lossy(&self) -> Group<E> {
62        match **self {
63            true => Group::generator(),
64            false => Group::zero(),
65        }
66    }
67}
68
69impl<E: Environment, I: IntegerType> CastLossy<Integer<E, I>> for Boolean<E> {
70    /// Casts a `Boolean` to an `Integer`.
71    #[inline]
72    fn cast_lossy(&self) -> Integer<E, I> {
73        match **self {
74            true => Integer::one(),
75            false => Integer::zero(),
76        }
77    }
78}
79
80impl<E: Environment> CastLossy<Scalar<E>> for Boolean<E> {
81    /// Casts a `Boolean` to a `Scalar`.
82    /// This is safe because casting from a boolean to any other type is **always** lossless.
83    #[inline]
84    fn cast_lossy(&self) -> Scalar<E> {
85        match **self {
86            true => Scalar::one(),
87            false => Scalar::zero(),
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    type CurrentEnvironment = snarkvm_console_network::Console;
97
98    #[test]
99    fn test_boolean_to_address() {
100        let boolean = Boolean::<CurrentEnvironment>::new(true);
101        let address: Address<CurrentEnvironment> = boolean.cast_lossy();
102        assert_eq!(address, Address::new(Group::generator()));
103        assert_eq!(address.to_group(), &Group::generator());
104
105        let boolean = Boolean::<CurrentEnvironment>::new(false);
106        let address: Address<CurrentEnvironment> = boolean.cast_lossy();
107        assert_eq!(address, Address::zero());
108        assert_eq!(address.to_group(), &Group::zero());
109    }
110
111    #[test]
112    fn test_boolean_to_boolean() {
113        let boolean = Boolean::<CurrentEnvironment>::new(true);
114        let boolean: Boolean<CurrentEnvironment> = boolean.cast_lossy();
115        assert_eq!(boolean, Boolean::new(true));
116
117        let boolean = Boolean::<CurrentEnvironment>::new(false);
118        let boolean: Boolean<CurrentEnvironment> = boolean.cast_lossy();
119        assert_eq!(boolean, Boolean::new(false));
120    }
121
122    #[test]
123    fn test_boolean_to_field() {
124        let boolean = Boolean::<CurrentEnvironment>::new(true);
125        let field: Field<CurrentEnvironment> = boolean.cast_lossy();
126        assert_eq!(field, Field::one());
127
128        let boolean = Boolean::<CurrentEnvironment>::new(false);
129        let field: Field<CurrentEnvironment> = boolean.cast_lossy();
130        assert_eq!(field, Field::zero());
131    }
132
133    #[test]
134    fn test_boolean_to_group() {
135        let boolean = Boolean::<CurrentEnvironment>::new(true);
136        let group: Group<CurrentEnvironment> = boolean.cast_lossy();
137        assert_eq!(group, Group::generator());
138
139        let boolean = Boolean::<CurrentEnvironment>::new(false);
140        let group: Group<CurrentEnvironment> = boolean.cast_lossy();
141        assert_eq!(group, Group::zero());
142    }
143
144    #[test]
145    fn test_boolean_to_scalar() {
146        let boolean = Boolean::<CurrentEnvironment>::new(true);
147        let scalar: Scalar<CurrentEnvironment> = boolean.cast_lossy();
148        assert_eq!(scalar, Scalar::one());
149
150        let boolean = Boolean::<CurrentEnvironment>::new(false);
151        let scalar: Scalar<CurrentEnvironment> = boolean.cast_lossy();
152        assert_eq!(scalar, Scalar::zero());
153    }
154
155    macro_rules! check_boolean_to_integer {
156        ($type:ty) => {
157            let boolean = Boolean::<CurrentEnvironment>::new(true);
158            let integer: $type = boolean.cast_lossy();
159            assert_eq!(integer, <$type>::one());
160
161            let boolean = Boolean::<CurrentEnvironment>::new(false);
162            let integer: $type = boolean.cast_lossy();
163            assert_eq!(integer, <$type>::zero());
164        };
165    }
166
167    #[test]
168    fn test_boolean_to_i8() {
169        check_boolean_to_integer!(I8<CurrentEnvironment>);
170    }
171
172    #[test]
173    fn test_boolean_to_i16() {
174        check_boolean_to_integer!(I16<CurrentEnvironment>);
175    }
176
177    #[test]
178    fn test_boolean_to_i32() {
179        check_boolean_to_integer!(I32<CurrentEnvironment>);
180    }
181
182    #[test]
183    fn test_boolean_to_i64() {
184        check_boolean_to_integer!(I64<CurrentEnvironment>);
185    }
186
187    #[test]
188    fn test_boolean_to_i128() {
189        check_boolean_to_integer!(I128<CurrentEnvironment>);
190    }
191
192    #[test]
193    fn test_boolean_to_u8() {
194        check_boolean_to_integer!(U8<CurrentEnvironment>);
195    }
196
197    #[test]
198    fn test_boolean_to_u16() {
199        check_boolean_to_integer!(U16<CurrentEnvironment>);
200    }
201
202    #[test]
203    fn test_boolean_to_u32() {
204        check_boolean_to_integer!(U32<CurrentEnvironment>);
205    }
206
207    #[test]
208    fn test_boolean_to_u64() {
209        check_boolean_to_integer!(U64<CurrentEnvironment>);
210    }
211
212    #[test]
213    fn test_boolean_to_u128() {
214        check_boolean_to_integer!(U128<CurrentEnvironment>);
215    }
216}