brillig_vm/
cast.rs

1//! Implementation for the [cast operation][acir::brillig::Opcode::Cast].
2use acir::{
3    AcirField,
4    acir_field::truncate_to,
5    brillig::{BitSize, IntegerBitSize},
6};
7
8use crate::MemoryValue;
9
10/// Casts a value to a different bit size.
11pub(crate) fn cast<F: AcirField>(
12    source_value: MemoryValue<F>,
13    target_bit_size: BitSize,
14) -> MemoryValue<F> {
15    use MemoryValue::*;
16
17    match (source_value, target_bit_size) {
18        // Field downcast to arbitrary bit size
19        (Field(field), BitSize::Integer(target_bit_size)) => {
20            let as_u128 = truncate_to(&field, 128).to_u128();
21            match target_bit_size {
22                IntegerBitSize::U1 => U1(as_u128 & 0x01 == 1),
23                IntegerBitSize::U8 => U8(as_u128 as u8),
24                IntegerBitSize::U16 => U16(as_u128 as u16),
25                IntegerBitSize::U32 => U32(as_u128 as u32),
26                IntegerBitSize::U64 => U64(as_u128 as u64),
27                IntegerBitSize::U128 => U128(as_u128),
28            }
29        }
30
31        (U1(value), BitSize::Integer(IntegerBitSize::U8)) => U8(value.into()),
32        (U1(value), BitSize::Integer(IntegerBitSize::U16)) => U16(value.into()),
33        (U1(value), BitSize::Integer(IntegerBitSize::U32)) => U32(value.into()),
34        (U1(value), BitSize::Integer(IntegerBitSize::U64)) => U64(value.into()),
35        (U1(value), BitSize::Integer(IntegerBitSize::U128)) => U128(value.into()),
36        (U1(value), BitSize::Field) => Field(value.into()),
37
38        (U8(value), BitSize::Integer(IntegerBitSize::U1)) => U1(value & 0x01 == 1),
39        (U8(value), BitSize::Integer(IntegerBitSize::U16)) => U16(value.into()),
40        (U8(value), BitSize::Integer(IntegerBitSize::U32)) => U32(value.into()),
41        (U8(value), BitSize::Integer(IntegerBitSize::U64)) => U64(value.into()),
42        (U8(value), BitSize::Integer(IntegerBitSize::U128)) => U128(value.into()),
43        (U8(value), BitSize::Field) => Field(u128::from(value).into()),
44
45        (U16(value), BitSize::Integer(IntegerBitSize::U1)) => U1(value & 0x01 == 1),
46        (U16(value), BitSize::Integer(IntegerBitSize::U8)) => U8(value as u8),
47        (U16(value), BitSize::Integer(IntegerBitSize::U32)) => U32(value.into()),
48        (U16(value), BitSize::Integer(IntegerBitSize::U64)) => U64(value.into()),
49        (U16(value), BitSize::Integer(IntegerBitSize::U128)) => U128(value.into()),
50        (U16(value), BitSize::Field) => Field(u128::from(value).into()),
51
52        (U32(value), BitSize::Integer(IntegerBitSize::U1)) => U1(value & 0x01 == 1),
53        (U32(value), BitSize::Integer(IntegerBitSize::U8)) => U8(value as u8),
54        (U32(value), BitSize::Integer(IntegerBitSize::U16)) => U16(value as u16),
55        (U32(value), BitSize::Integer(IntegerBitSize::U64)) => U64(value.into()),
56        (U32(value), BitSize::Integer(IntegerBitSize::U128)) => U128(value.into()),
57        (U32(value), BitSize::Field) => Field(u128::from(value).into()),
58
59        (U64(value), BitSize::Integer(IntegerBitSize::U1)) => U1(value & 0x01 == 1),
60        (U64(value), BitSize::Integer(IntegerBitSize::U8)) => U8(value as u8),
61        (U64(value), BitSize::Integer(IntegerBitSize::U16)) => U16(value as u16),
62        (U64(value), BitSize::Integer(IntegerBitSize::U32)) => U32(value as u32),
63        (U64(value), BitSize::Integer(IntegerBitSize::U128)) => U128(value.into()),
64        (U64(value), BitSize::Field) => Field(u128::from(value).into()),
65
66        (U128(value), BitSize::Integer(IntegerBitSize::U1)) => U1(value & 0x01 == 1),
67        (U128(value), BitSize::Integer(IntegerBitSize::U8)) => U8(value as u8),
68        (U128(value), BitSize::Integer(IntegerBitSize::U16)) => U16(value as u16),
69        (U128(value), BitSize::Integer(IntegerBitSize::U32)) => U32(value as u32),
70        (U128(value), BitSize::Integer(IntegerBitSize::U64)) => U64(value as u64),
71        (U128(value), BitSize::Field) => Field(value.into()),
72
73        // no ops
74        (Field(_), BitSize::Field) => source_value,
75        (U1(_), BitSize::Integer(IntegerBitSize::U1)) => source_value,
76        (U8(_), BitSize::Integer(IntegerBitSize::U8)) => source_value,
77        (U16(_), BitSize::Integer(IntegerBitSize::U16)) => source_value,
78        (U32(_), BitSize::Integer(IntegerBitSize::U32)) => source_value,
79        (U64(_), BitSize::Integer(IntegerBitSize::U64)) => source_value,
80        (U128(_), BitSize::Integer(IntegerBitSize::U128)) => source_value,
81    }
82}