1use itertools::Itertools;
4use shared_types::Field;
5
6use remainder::utils::arithmetic::log2_ceil;
7
8use remainder::mle::evals::MultilinearExtension;
9
10pub fn unsigned_decomposition<const BASE: u64, const N: usize>(value: u64) -> Option<[u16; N]> {
22 debug_assert!(BASE <= (1 << 16));
23 debug_assert!(log2_ceil(BASE) * (N as u32) <= 64, "BASE * N must be <= 64");
24 let mut value = value;
25 let mut result = [0; N];
26 for i in (0..N).rev() {
27 result[i] = (value % BASE) as u16;
28 value /= BASE;
29 }
30 if value != 0 {
31 None
32 } else {
33 Some(result)
34 }
35}
36
37pub fn complementary_decomposition<const BASE: u64, const N: usize>(
51 value: i64,
52) -> Option<([u16; N], bool)> {
53 debug_assert!(BASE <= (1 << 16));
54 debug_assert!(log2_ceil(BASE) * (N as u32) <= 64, "BASE * N must be <= 64");
55 let pow = (BASE as u128).pow(N as u32);
56 if (value >= 0 && (value as u128) > pow) || (value < 0 && (-value as u128) > pow - 1) {
57 return None;
58 }
59 let (val_to_decomp, bit) = if value > 0 {
60 ((pow - (value as u128)), true)
61 } else {
62 ((-value) as u128, false)
63 };
64 Some((
66 unsigned_decomposition::<BASE, N>(val_to_decomp as u64).unwrap(),
67 bit,
68 ))
69}
70
71pub fn digits_to_field<F: Field, const N: usize>(digits: &[u16; N]) -> [F; N] {
79 digits
80 .iter()
81 .map(|x| F::from(*x as u64))
82 .collect::<Vec<_>>()
83 .try_into()
84 .unwrap()
85}
86
87pub fn to_slice_of_mles<F: Field, const N: usize>(
107 inputs: Vec<[F; N]>,
108) -> [MultilinearExtension<F>; N] {
109 let mut result_evals: [Vec<F>; N] = vec![Vec::new(); N].try_into().unwrap();
110 for subarray in inputs {
111 for (i, element) in subarray.iter().enumerate() {
112 result_evals[i].push(*element);
113 }
114 }
115 let result_mles: [MultilinearExtension<F>; N] = result_evals
116 .into_iter()
117 .map(|evals| MultilinearExtension::new(evals))
118 .collect_vec()
119 .try_into()
120 .unwrap();
121 result_mles
122}
123
124#[test]
125fn test_unsigned_decomposition() {
126 assert_eq!(unsigned_decomposition::<10, 3>(987), Some([9, 8, 7]));
127 assert_eq!(unsigned_decomposition::<10, 3>(0), Some([0, 0, 0]));
128 assert_eq!(unsigned_decomposition::<2, 3>(1), Some([0, 0, 1]));
129 assert_eq!(unsigned_decomposition::<2, 3>(4), Some([1, 0, 0]));
130 assert_eq!(unsigned_decomposition::<2, 3>(8), None);
131}
132
133#[test]
134fn test_complementary_decomposition() {
135 assert_eq!(
137 complementary_decomposition::<2, 3>(1),
138 Some(([1, 1, 1], true))
139 );
140 assert_eq!(
141 complementary_decomposition::<2, 3>(3),
142 Some(([1, 0, 1], true))
143 );
144 assert_eq!(
145 complementary_decomposition::<2, 3>(8),
146 Some(([0, 0, 0], true))
147 );
148 assert_eq!(
149 complementary_decomposition::<2, 3>(0),
150 Some(([0, 0, 0], false))
151 );
152 assert_eq!(
153 complementary_decomposition::<2, 3>(-1),
154 Some(([0, 0, 1], false))
155 );
156 assert_eq!(
157 complementary_decomposition::<2, 3>(-3),
158 Some(([0, 1, 1], false))
159 );
160 assert_eq!(complementary_decomposition::<2, 3>(-8), None);
161 assert_eq!(complementary_decomposition::<2, 3>(9), None);
162 assert_eq!(
164 complementary_decomposition::<10, 3>(-987),
165 Some(([9, 8, 7], false))
166 );
167 assert_eq!(
168 complementary_decomposition::<10, 3>(987),
169 Some(([0, 1, 3], true))
170 );
171 assert_eq!(
172 complementary_decomposition::<10, 3>(0),
173 Some(([0, 0, 0], false))
174 );
175 assert_eq!(complementary_decomposition::<10, 3>(-1000), None);
176 assert_eq!(complementary_decomposition::<10, 3>(1001), None);
177}