1use digit_decomposition::{compose_value, decompose_value};
5
6use crate::utils::pre_pad_vec;
7
8fn adjust_prefix_size(
9 prefix: &[usize],
10 nb_digits: usize,
11 suffix_len: usize,
12) -> Result<Vec<usize>, ()> {
13 let expected_len = nb_digits - suffix_len;
14 match prefix.len() {
15 len if len <= expected_len => Ok(pre_pad_vec(prefix.to_vec(), expected_len)),
16 len => {
17 let mut res = prefix.to_vec();
18 if !res.drain(..len - expected_len).all(|x| x == 0) {
19 return Err(());
20 }
21 Ok(res)
22 }
23 }
24}
25
26fn compute_interval_from_prefix(
29 prefix: &[usize],
30 num_digits: usize,
31 base: usize,
32) -> (usize, usize) {
33 let suffix_len = num_digits - prefix.len();
34 let start = compose_value(
35 &prefix
36 .iter()
37 .cloned()
38 .chain((0..suffix_len).map(|_| 0))
39 .collect::<Vec<_>>(),
40 base,
41 );
42 let end = compose_value(
43 &prefix
44 .iter()
45 .cloned()
46 .chain((0..suffix_len).map(|_| base - 1))
47 .collect::<Vec<_>>(),
48 base,
49 );
50 (start, end)
51}
52
53fn num_to_vec(input: usize, nb_digits: usize, ignored_digits: usize, base: usize) -> Vec<usize> {
54 let decomposed = decompose_value(input, base, nb_digits);
55 let to_take = decomposed.len() - ignored_digits;
56
57 decomposed.into_iter().take(to_take).collect::<Vec<_>>()
58}
59
60fn compute_min_support_covering_prefix(
61 start: usize,
62 end: usize,
63 min_support: usize,
64 min_nb_digits: usize,
65) -> Vec<usize> {
66 let left_bound = start - min_support;
67 let right_bound = end + min_support;
68 let left_bound = decompose_value(left_bound, 2, min_nb_digits);
69 let right_bound = decompose_value(right_bound, 2, min_nb_digits);
70
71 left_bound
72 .into_iter()
73 .zip(right_bound)
74 .take_while(|(x, y)| x == y)
75 .map(|(x, _)| x)
76 .collect()
77}
78
79fn compute_left_covering_prefix(
81 start: usize,
82 max_error_exp: usize,
83 min_support: usize,
84 nb_digits: usize,
85) -> Vec<usize> {
86 let left_bound = start - min_support;
87 let left_bound = decompose_value(left_bound, 2, nb_digits);
88 let (prefix, suffix) = left_bound.split_at(nb_digits - max_error_exp);
89
90 prefix
91 .iter()
92 .chain(suffix.iter().take_while(|x| **x == 1))
93 .cloned()
94 .collect()
95}
96
97fn compute_right_covering_prefix(
99 end: usize,
100 max_error_exp: usize,
101 min_support: usize,
102 nb_digits: usize,
103) -> Vec<usize> {
104 let left_bound = end + min_support;
105 let left_bound = decompose_value(left_bound, 2, nb_digits);
106 let (prefix, suffix) = left_bound.split_at(nb_digits - max_error_exp);
107
108 prefix
109 .iter()
110 .chain(suffix.iter().take_while(|x| **x == 0))
111 .cloned()
112 .collect()
113}
114
115fn single_covering_prefix_combinations(
116 main_outcome_prefix: &[usize],
117 secondary_outcomes_prefix: &[usize],
118 oracle_digits_infos: &[usize],
119 suffix_len: usize,
120) -> Vec<Vec<usize>> {
121 let mut secondary = oracle_digits_infos
122 .iter()
123 .skip(1)
124 .map(|nb_digits| {
125 adjust_prefix_size(
126 secondary_outcomes_prefix,
127 *nb_digits,
128 main_outcome_prefix.len() - secondary_outcomes_prefix.len() + suffix_len,
129 )
130 .unwrap()
131 })
132 .collect::<Vec<Vec<_>>>();
133 let mut res =
134 vec![adjust_prefix_size(main_outcome_prefix, oracle_digits_infos[0], suffix_len).unwrap()];
135 res.append(&mut secondary);
136 res
137}
138
139fn double_covering_restricted_prefix_combinations(
142 main_outcome_prefix: &[usize],
143 other_interval_prefix: &[usize],
144 oracle_digits_infos: &[usize],
145 suffix_len: usize,
146) -> Vec<Vec<Vec<usize>>> {
147 let mut combinations = double_covering_prefix_combinations(
148 main_outcome_prefix,
149 main_outcome_prefix,
150 other_interval_prefix,
151 oracle_digits_infos,
152 suffix_len,
153 );
154
155 if main_outcome_prefix > other_interval_prefix {
156 combinations.remove(combinations.len() - 1);
157 combinations
158 } else {
159 combinations.into_iter().skip(1).collect::<Vec<_>>()
160 }
161}
162
163fn double_covering_prefix_combinations(
167 main_outcome_prefix: &[usize],
168 left_interval_prefix: &[usize],
169 right_interval_prefix: &[usize],
170 oracle_digits_infos: &[usize],
171 suffix_len: usize,
172) -> Vec<Vec<Vec<usize>>> {
173 let nb_oracles = oracle_digits_infos.len();
174 let mut res = Vec::with_capacity(nb_oracles);
175 let (first, second) = if left_interval_prefix <= right_interval_prefix {
176 (left_interval_prefix, right_interval_prefix)
177 } else {
178 (right_interval_prefix, left_interval_prefix)
179 };
180
181 for i in 0..(1 << (nb_oracles - 1)) {
182 let mut mid_res = Vec::with_capacity(nb_oracles);
183 for j in 0..(nb_oracles - 1) {
184 let val: Vec<usize> = match i & (1 << j) {
185 0 => first.to_vec(),
186 _ => second.to_vec(),
187 };
188 mid_res.push(val);
189 }
190 mid_res.push(main_outcome_prefix.to_vec());
191 mid_res.reverse();
192 let trimmed = mid_res
193 .into_iter()
194 .zip(oracle_digits_infos)
195 .map(|(x, y)| {
196 adjust_prefix_size(&x, *y, main_outcome_prefix.len() + suffix_len - x.len())
197 })
198 .collect::<Result<Vec<Vec<usize>>, ()>>();
199
200 if let Ok(mid_res) = trimmed {
201 res.push(mid_res)
202 }
203 }
204
205 res
206}
207
208pub fn compute_outcome_combinations(
215 oracle_digits_infos: &[usize],
216 main_outcome_prefix: &[usize],
217 max_error_exp: usize,
218 min_support_exp: usize,
219 maximize_coverage: bool,
220) -> Vec<Vec<Vec<usize>>> {
221 let nb_oracles = oracle_digits_infos.len();
222 assert!(nb_oracles > 1 && max_error_exp > min_support_exp);
223
224 let min_num_digits = oracle_digits_infos[0];
225 let (min_num_digits, max_num, main_outcome_prefix) = if oracle_digits_infos
226 .iter()
227 .skip(1)
228 .all(|x| x == &min_num_digits)
229 {
230 (
231 min_num_digits,
232 (1 << min_num_digits) - 1,
233 main_outcome_prefix.to_vec(),
234 )
235 } else {
236 let mut new_main_outcome_prefix = vec![0];
237 new_main_outcome_prefix.extend_from_slice(main_outcome_prefix);
238 (
239 min_num_digits + 1,
240 (1 << (min_num_digits + 1)) - 1,
241 new_main_outcome_prefix,
242 )
243 };
244 let max_error: usize = 1 << max_error_exp;
245 let half_max_error: usize = max_error >> 1;
246 let min_support: usize = 1 << min_support_exp;
247 let suffix_len = min_num_digits - main_outcome_prefix.len();
248
249 let (start, end) = compute_interval_from_prefix(&main_outcome_prefix, min_num_digits, 2);
250
251 if suffix_len < max_error_exp {
253 let start_max_error_suffix = start & ((1 << max_error_exp) - 1);
254 let left_bound = (start >> max_error_exp) << max_error_exp;
255 let right_bound = left_bound | (max_error - 1);
256 let error_interval_prefix = num_to_vec(left_bound, min_num_digits, max_error_exp, 2);
257
258 if start_max_error_suffix >= min_support && end <= right_bound - min_support {
260 let support_interval_prefix = if maximize_coverage {
261 error_interval_prefix
262 } else {
263 compute_min_support_covering_prefix(start, end, min_support, min_num_digits)
264 };
265
266 return vec![single_covering_prefix_combinations(
267 &main_outcome_prefix,
268 &support_interval_prefix,
269 oracle_digits_infos,
270 suffix_len,
271 )];
272 } else if start_max_error_suffix < min_support {
273 let right_interval_prefix = if maximize_coverage {
274 error_interval_prefix
275 } else {
276 compute_right_covering_prefix(end, max_error_exp, min_support, min_num_digits)
277 };
278
279 return if left_bound == 0 {
280 vec![single_covering_prefix_combinations(
281 &main_outcome_prefix,
282 &right_interval_prefix,
283 oracle_digits_infos,
284 suffix_len,
285 )]
286 } else {
287 let left_interval_prefix = if maximize_coverage {
288 num_to_vec(
289 left_bound - half_max_error,
290 min_num_digits,
291 max_error_exp - 1,
292 2,
293 )
294 } else {
295 compute_left_covering_prefix(start, max_error_exp, min_support, min_num_digits)
296 };
297 double_covering_prefix_combinations(
298 &main_outcome_prefix,
299 &right_interval_prefix,
300 &left_interval_prefix,
301 oracle_digits_infos,
302 suffix_len,
303 )
304 };
305 } else if end > right_bound - min_support {
306 let left_interval_prefix = if maximize_coverage {
307 error_interval_prefix
308 } else {
309 compute_left_covering_prefix(start, max_error_exp, min_support, min_num_digits)
310 };
311
312 return if right_bound == max_num {
313 vec![single_covering_prefix_combinations(
314 &main_outcome_prefix,
315 &left_interval_prefix,
316 oracle_digits_infos,
317 suffix_len,
318 )]
319 } else {
320 let right_interval_prefix = if maximize_coverage {
321 num_to_vec(right_bound + 1, min_num_digits, max_error_exp - 1, 2)
322 } else {
323 compute_right_covering_prefix(end, max_error_exp, min_support, min_num_digits)
324 };
325
326 double_covering_prefix_combinations(
327 &main_outcome_prefix,
328 &left_interval_prefix,
329 &right_interval_prefix,
330 oracle_digits_infos,
331 suffix_len,
332 )
333 };
334 } else {
335 unreachable!();
336 }
337 }
338
339 let mut res = Vec::new();
340
341 if start != 0 {
342 let right_interval_prefix = if maximize_coverage {
343 num_to_vec(start, min_num_digits, max_error_exp - 1, 2)
344 } else {
345 num_to_vec(start, min_num_digits, min_support_exp, 2)
346 };
347
348 let left_interval_prefix = if maximize_coverage {
349 num_to_vec(start - half_max_error, min_num_digits, max_error_exp - 1, 2)
350 } else {
351 num_to_vec(start - min_support, min_num_digits, min_support_exp, 2)
352 };
353
354 let mut combination = double_covering_restricted_prefix_combinations(
355 &right_interval_prefix,
356 &left_interval_prefix,
357 oracle_digits_infos,
358 min_num_digits - right_interval_prefix.len(),
359 );
360
361 res.append(&mut combination);
362 }
363
364 res.push(single_covering_prefix_combinations(
365 &main_outcome_prefix,
366 &main_outcome_prefix,
367 oracle_digits_infos,
368 suffix_len,
369 ));
370
371 if end != max_num {
372 let right_interval_prefix = if maximize_coverage {
373 num_to_vec(
374 end - half_max_error + 1,
375 min_num_digits,
376 max_error_exp - 1,
377 2,
378 )
379 } else {
380 num_to_vec(end - min_support + 1, min_num_digits, min_support_exp, 2)
381 };
382
383 let left_interval_prefix = if maximize_coverage {
384 num_to_vec(end + 1, min_num_digits, max_error_exp - 1, 2)
385 } else {
386 num_to_vec(end + 1, min_num_digits, min_support_exp, 2)
387 };
388
389 let mut combination = double_covering_restricted_prefix_combinations(
390 &right_interval_prefix,
391 &left_interval_prefix,
392 oracle_digits_infos,
393 min_num_digits - right_interval_prefix.len(),
394 );
395 res.append(&mut combination);
396 }
397
398 res
399}
400
401#[cfg(test)]
402mod tests {
403 use super::*;
404 use crate::test_utils::{
405 get_variable_oracle_numeric_infos, same_num_digits_oracle_numeric_infos,
406 };
407 use secp256k1_zkp::rand::{thread_rng, RngCore};
408
409 type CoveringCetsMinMax = (Vec<(Vec<usize>, Vec<usize>)>, Vec<(Vec<usize>, Vec<usize>)>);
410
411 fn compute_covering_cets_min_and_max(
412 oracle_digits_infos: &[usize],
413 main_outcome_prefix: &[usize],
414 max_error_exp: usize,
415 min_support_exp: usize,
416 ) -> CoveringCetsMinMax {
417 let covering_max = compute_outcome_combinations(
418 oracle_digits_infos,
419 main_outcome_prefix,
420 max_error_exp,
421 min_support_exp,
422 true,
423 );
424 let covering_min = compute_outcome_combinations(
425 oracle_digits_infos,
426 main_outcome_prefix,
427 max_error_exp,
428 min_support_exp,
429 false,
430 );
431
432 assert!(covering_max.iter().all(|x| x.len() == 2));
433 assert!(covering_min.iter().all(|x| x.len() == 2));
434
435 (
436 covering_max
437 .into_iter()
438 .map(|mut x| (x.remove(0), x.remove(x.len() - 1)))
439 .collect(),
440 covering_min
441 .into_iter()
442 .map(|mut x| (x.remove(0), x.remove(x.len() - 1)))
443 .collect(),
444 )
445 }
446
447 struct TestCase {
448 main_outcome_prefix: Vec<usize>,
449 nb_digits: usize,
450 max_error_exp: usize,
451 min_support_exp: usize,
452 expected_max: Vec<(Vec<usize>, Vec<usize>)>,
453 expected_min: Vec<(Vec<usize>, Vec<usize>)>,
454 }
455
456 fn outcome_prefixes() -> Vec<Vec<usize>> {
457 vec![
458 vec![0, 0, 1, 0, 1, 1, 0, 0, 1],
459 vec![0, 1, 0, 0, 0, 0, 0, 1, 1],
460 vec![0, 1, 1, 1, 1, 1, 0, 1, 0],
461 vec![0, 1],
462 vec![0, 0, 1],
463 vec![1, 1, 1, 1, 1, 1, 1, 1],
464 vec![0, 0],
465 vec![1, 1],
466 ]
467 }
468
469 fn prefix(index: usize) -> Vec<usize> {
470 outcome_prefixes().remove(index)
471 }
472
473 fn test_cases() -> Vec<TestCase> {
474 vec![
475 TestCase {
476 main_outcome_prefix: prefix(0),
477 nb_digits: 14,
478 max_error_exp: 11,
479 min_support_exp: 7,
480 expected_max: vec![(prefix(0), vec![0, 0, 1])],
481 expected_min: vec![(prefix(0), vec![0, 0, 1, 0, 1])],
482 },
483 TestCase {
484 main_outcome_prefix: prefix(1),
485 nb_digits: 13,
486 max_error_exp: 11,
487 min_support_exp: 7,
488 expected_max: vec![(prefix(1), vec![0, 0, 1]), (prefix(1), vec![0, 1])],
489 expected_min: vec![
490 (prefix(1), vec![0, 0, 1, 1, 1, 1]),
491 (prefix(1), vec![0, 1, 0, 0, 0]),
492 ],
493 },
494 TestCase {
495 main_outcome_prefix: prefix(2),
496 nb_digits: 13,
497 max_error_exp: 11,
498 min_support_exp: 7,
499 expected_max: vec![(prefix(2), vec![0, 1]), (prefix(2), vec![1, 0, 0])],
500 expected_min: vec![
501 (prefix(2), vec![0, 1, 1, 1, 1]),
502 (prefix(2), vec![1, 0, 0, 0, 0, 0, 0]),
503 ],
504 },
505 TestCase {
506 main_outcome_prefix: prefix(3),
507 nb_digits: 13,
508 max_error_exp: 11,
509 min_support_exp: 7,
510 expected_max: vec![
511 (vec![0, 1, 0], vec![0, 0, 1]),
512 (prefix(3), prefix(3)),
513 (vec![0, 1, 1], vec![1, 0, 0]),
514 ],
515 expected_min: vec![
516 (vec![0, 1, 0, 0, 0, 0], vec![0, 0, 1, 1, 1, 1]),
517 (prefix(3), prefix(3)),
518 (vec![0, 1, 1, 1, 1, 1], vec![1, 0, 0, 0, 0, 0]),
519 ],
520 },
521 TestCase {
522 main_outcome_prefix: prefix(4),
523 nb_digits: 15,
524 max_error_exp: 11,
525 min_support_exp: 7,
526 expected_max: vec![
527 (vec![0, 0, 1, 0, 0], vec![0, 0, 0, 1, 1]),
528 (prefix(4), prefix(4)),
529 (vec![0, 0, 1, 1, 1], vec![0, 1, 0, 0, 0]),
530 ],
531 expected_min: vec![
532 (vec![0, 0, 1, 0, 0, 0, 0, 0], vec![0, 0, 0, 1, 1, 1, 1, 1]),
533 (prefix(4), prefix(4)),
534 (vec![0, 0, 1, 1, 1, 1, 1, 1], vec![0, 1, 0, 0, 0, 0, 0, 0]),
535 ],
536 },
537 TestCase {
538 main_outcome_prefix: prefix(5),
539 nb_digits: 13,
540 max_error_exp: 11,
541 min_support_exp: 7,
542 expected_max: vec![(prefix(5), vec![1, 1])],
543 expected_min: vec![(prefix(5), vec![1, 1, 1, 1, 1])],
544 },
545 TestCase {
546 main_outcome_prefix: prefix(6),
547 nb_digits: 13,
548 max_error_exp: 11,
549 min_support_exp: 7,
550 expected_max: vec![(prefix(6), prefix(6)), (vec![0, 0, 1], vec![0, 1, 0])],
551 expected_min: vec![
552 (prefix(6), prefix(6)),
553 (vec![0, 0, 1, 1, 1, 1], vec![0, 1, 0, 0, 0, 0]),
554 ],
555 },
556 TestCase {
557 main_outcome_prefix: prefix(7),
558 nb_digits: 14,
559 max_error_exp: 11,
560 min_support_exp: 7,
561 expected_max: vec![(vec![1, 1, 0, 0], vec![1, 0, 1, 1]), (prefix(7), prefix(7))],
562 expected_min: vec![
563 (vec![1, 1, 0, 0, 0, 0, 0], vec![1, 0, 1, 1, 1, 1, 1]),
564 (prefix(7), prefix(7)),
565 ],
566 },
567 ]
568 }
569
570 #[test]
571 fn compute_outcome_combination_tests() {
572 for case in test_cases() {
573 let (max, min) = compute_covering_cets_min_and_max(
574 &same_num_digits_oracle_numeric_infos(2, case.nb_digits, 2).nb_digits,
575 &case.main_outcome_prefix,
576 case.max_error_exp,
577 case.min_support_exp,
578 );
579 assert_eq!(case.expected_max, max);
580 assert_eq!(case.expected_min, min);
581 }
582 }
583
584 #[test]
585 fn compute_outcome_three_oracles() {
586 let prefix = vec![0, 1, 0];
587
588 let res = compute_outcome_combinations(
589 &same_num_digits_oracle_numeric_infos(3, 3, 2).nb_digits,
590 &prefix,
591 2,
592 1,
593 true,
594 );
595
596 let expected = vec![
597 vec![vec![0, 1, 0], vec![0], vec![0]],
598 vec![vec![0, 1, 0], vec![0], vec![1, 0]],
599 vec![vec![0, 1, 0], vec![1, 0], vec![0]],
600 vec![vec![0, 1, 0], vec![1, 0], vec![1, 0]],
601 ];
602
603 assert_eq!(res, expected);
604 }
605
606 #[test]
607 fn multiple_interval_within_bounds() {
608 let mut rng = thread_rng();
609
610 let nb_digits = (rng.next_u32() % 29) + 2;
611 let nb_digits_used = rng.next_u32() % nb_digits + 1;
612 let mut main_outcome_prefix = Vec::with_capacity(nb_digits_used as usize);
613 for _ in 0..nb_digits_used {
614 main_outcome_prefix.push((rng.next_u32() % 2) as usize);
615 }
616 let max_error_exp = (rng.next_u32() % (nb_digits - 1)) + 1;
617 let min_support_exp = rng.next_u32() % max_error_exp;
618 let nb_digits = nb_digits as usize;
619 let max_error_exp = max_error_exp as usize;
620 let min_support_exp = min_support_exp as usize;
621 let max_error = 1 << max_error_exp;
622 let min_support = 1 << min_support_exp;
623 let max_val = (1 << nb_digits) - 1;
624
625 let (cover_max, cover_min) = compute_covering_cets_min_and_max(
626 &same_num_digits_oracle_numeric_infos(2, nb_digits, 2).nb_digits,
627 &main_outcome_prefix,
628 max_error_exp,
629 min_support_exp,
630 );
631
632 assert_eq!(cover_min.len(), cover_max.len());
633 assert!(cover_min
634 .iter()
635 .map(|(a, _)| a)
636 .zip(cover_max.iter().map(|(a, _)| a))
637 .all(|(a, b)| a.iter().zip(b.iter()).all(|(c, d)| c == d)));
638
639 let relevant_primary_prefixes = cover_max.iter().map(|(a, _)| a).collect::<Vec<_>>();
640 let (left, right) = compute_interval_from_prefix(&main_outcome_prefix, nb_digits, 2);
641
642 let primary_and_covering_intervals_max: Vec<((usize, usize), (usize, usize))> = cover_max
643 .iter()
644 .map(|(a, b)| {
645 (
646 compute_interval_from_prefix(a, nb_digits, 2),
647 compute_interval_from_prefix(b, nb_digits, 2),
648 )
649 })
650 .collect();
651 let cover_intervals_min: Vec<(usize, usize)> = cover_max
652 .iter()
653 .map(|(_, b)| compute_interval_from_prefix(b, nb_digits, 2))
654 .collect();
655
656 for (
657 ((primary_left, primary_right), (max_cover_left, max_cover_right)),
658 (min_cover_left, min_cover_right),
659 ) in primary_and_covering_intervals_max
660 .iter()
661 .cloned()
662 .zip(cover_intervals_min.iter().cloned())
663 {
664 assert!(max_cover_left <= min_cover_left);
665 assert!(max_cover_right <= min_cover_right);
666
667 if primary_left == max_cover_left && primary_right == max_cover_right {
668 assert_eq!(min_cover_left, max_cover_left);
669 assert_eq!(min_cover_right, max_cover_right);
670 }
671
672 let assert_valid_cover = |cover_left: usize, cover_right: usize, max_coverage: bool| {
673 if primary_left == cover_left && primary_right == cover_right {
674 } else if primary_left >= cover_left && primary_right <= cover_right {
675 if max_coverage {
676 assert_eq!(cover_right - cover_left + 1, max_error);
677 } else {
678 let side_to_boundary = std::cmp::max(
679 primary_right % max_error,
680 max_error - (primary_left % max_error),
681 );
682 assert!(cover_right - cover_left < 2 * side_to_boundary);
683 assert!(cover_right - cover_left + 1 >= side_to_boundary);
684 }
685
686 assert!(
687 primary_left - cover_left >= min_support
688 || cover_left == 0
689 || relevant_primary_prefixes.len() == 2
690 );
691 assert!(primary_right - cover_left < max_error);
692 assert!(
693 cover_right - primary_right >= min_support
694 || cover_right == max_val
695 || relevant_primary_prefixes.len() == 2
696 );
697 } else {
698 let (most_inner, least_inner, most_outer) = if primary_left <= cover_left {
699 (primary_left, primary_right, cover_right)
700 } else {
701 (primary_right, primary_left, cover_left)
702 };
703
704 let diff = |x: usize, y: usize| -> usize {
705 if x > y {
706 x - y
707 } else {
708 y - x
709 }
710 };
711
712 assert!(diff(least_inner, most_outer) >= min_support);
713 assert!(diff(most_inner, most_outer) < max_error);
714 }
715 };
716
717 assert_valid_cover(max_cover_left, max_cover_right, true);
718 assert_valid_cover(min_cover_left, min_cover_right, false);
719 }
720
721 let primary_interval = primary_and_covering_intervals_max
722 .iter()
723 .map(|(a, _)| *a)
724 .fold((usize::MAX, 0), |(min, max), (start, end)| {
725 (std::cmp::min(min, start), std::cmp::max(max, end))
726 });
727 assert_eq!(primary_interval, (left, right));
728
729 let (max_cover_interval_left, max_cover_interval_right) =
730 primary_and_covering_intervals_max
731 .iter()
732 .map(|(_, b)| *b)
733 .fold((usize::MAX, 0), |(min, max), (start, end)| {
734 (std::cmp::min(min, start), std::cmp::max(max, end))
735 });
736 let (min_cover_interval_left, min_cover_interval_right) = cover_intervals_min
737 .iter()
738 .fold((usize::MAX, 0), |(min, max), (start, end)| {
739 (std::cmp::min(min, *start), std::cmp::max(max, *end))
740 });
741 assert!(max_cover_interval_left <= min_cover_interval_left);
742 assert!(max_cover_interval_right >= min_cover_interval_right);
743
744 assert!(left - max_cover_interval_left >= min_support || max_cover_interval_left == 0);
745 assert!(left - max_cover_interval_left < max_error);
746 assert!(
747 max_cover_interval_right - right >= min_support || max_cover_interval_right == max_val
748 );
749 assert!(max_cover_interval_right - right < max_error);
750
751 assert!(left - min_cover_interval_left >= min_support || min_cover_interval_left == 0);
752 assert!(left - min_cover_interval_left < max_error);
753 assert!(
754 min_cover_interval_right - right >= min_support || min_cover_interval_right == max_val
755 );
756 assert!(min_cover_interval_right - right < max_error);
757 }
758
759 struct VariableLengthTestCase {
760 main_outcome_prefix: Vec<usize>,
761 nb_digits: Vec<usize>,
762 max_error_exp: usize,
763 min_support_exp: usize,
764 expected_max: Vec<(Vec<usize>, Vec<usize>)>,
765 expected_min: Vec<(Vec<usize>, Vec<usize>)>,
766 }
767
768 impl From<TestCase> for VariableLengthTestCase {
769 fn from(test_case: TestCase) -> VariableLengthTestCase {
770 let to_add = ((thread_rng().next_u32() % 10) + 1) as usize;
771
772 let extend = |y: &[usize]| {
773 let mut new_y = Vec::with_capacity(y.len() + to_add);
774 new_y.resize(to_add, 0);
775 new_y.extend(y.iter());
776 new_y
777 };
778
779 let expected_max = test_case
780 .expected_max
781 .iter()
782 .map(|(x, y)| (x.clone(), extend(y)))
783 .collect();
784
785 let expected_min = test_case
786 .expected_min
787 .iter()
788 .map(|(x, y)| (x.clone(), extend(y)))
789 .collect();
790
791 VariableLengthTestCase {
792 main_outcome_prefix: test_case.main_outcome_prefix,
793 nb_digits: vec![test_case.nb_digits, test_case.nb_digits + to_add],
794 max_error_exp: test_case.max_error_exp,
795 min_support_exp: test_case.min_support_exp,
796 expected_max,
797 expected_min,
798 }
799 }
800 }
801
802 fn variable_len_test_cases() -> Vec<VariableLengthTestCase> {
803 let black_list = [5, 7];
804 let mut test_cases = test_cases()
805 .into_iter()
806 .enumerate()
807 .filter(|(i, _)| !black_list.contains(i))
808 .map(|(_, x)| x.into())
809 .collect::<Vec<VariableLengthTestCase>>();
810 test_cases.append(&mut vec![VariableLengthTestCase {
811 main_outcome_prefix: vec![1, 1, 1, 1],
812 nb_digits: vec![4, 5],
813 max_error_exp: 2,
814 min_support_exp: 1,
815 expected_max: vec![
816 (vec![1, 1, 1, 1], vec![0, 1, 1]),
817 (vec![1, 1, 1, 1], vec![1, 0, 0, 0]),
818 ],
819 expected_min: vec![
820 (vec![1, 1, 1, 1], vec![0, 1, 1]),
821 (vec![1, 1, 1, 1], vec![1, 0, 0, 0]),
822 ],
823 }]);
824 test_cases
825 }
826
827 #[test]
828 fn variable_nb_digit_tests() {
829 for case in variable_len_test_cases() {
830 let (max, min) = compute_covering_cets_min_and_max(
831 &get_variable_oracle_numeric_infos(&case.nb_digits, 2).nb_digits,
832 &case.main_outcome_prefix,
833 case.max_error_exp,
834 case.min_support_exp,
835 );
836 assert_eq!(case.expected_max, max);
837 assert_eq!(case.expected_min, min);
838 }
839 }
840}