1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Toolbox to simulate error correction codes performance.

use crate::{Decoder, DecodingResult};
use rayon::prelude::*;

pub struct Simulator<'a, D>
where
    D: Decoder,
{
    decoder: &'a D,
}

impl<'a, D> Simulator<'a, D>
where
    D: Decoder,
{
    pub fn new(decoder: &'a D) -> Self {
        Self { decoder }
    }

    pub fn simulate_n_iterations(&self, n_iterations: usize) -> SimulationResult {
        let successes: usize = (0..n_iterations)
            .into_par_iter()
            .map::<_, D::Result>(|_| {
                let error = self.decoder.random_error();
                self.decoder.decode(&error)
            })
            .filter(|decoding| decoding.succeed())
            .count();

        SimulationResult {
            successes,
            failures: n_iterations - successes,
        }
    }

    pub fn simulate_until_failures_are_found(
        &self,
        n_threads: usize,
        n_failures_per_thread: usize,
    ) -> SimulationResult {
        let successes = (0..n_threads)
            .into_par_iter()
            .map::<_, usize>(|_| {
                (0..n_failures_per_thread)
                    .into_par_iter()
                    .map(|_| {
                        let mut successes = 0;
                        let mut has_failed = false;
                        while !has_failed {
                            let error = self.decoder.random_error();
                            if self.decoder.decode(&error).succeed() {
                                successes += 1;
                            } else {
                                has_failed = true;
                            }
                        }
                        successes
                    })
                    .sum()
            })
            .sum();

        SimulationResult {
            successes,
            failures: n_failures_per_thread * n_threads,
        }
    }
}

pub struct SimulationResult {
    successes: usize,
    failures: usize,
}

impl SimulationResult {
    pub fn failure_rate(&self) -> f64 {
        self.failures() as f64 / self.total() as f64
    }

    pub fn failures(&self) -> usize {
        self.failures
    }

    pub fn success_rate(&self) -> f64 {
        self.successes() as f64 / self.total() as f64
    }

    pub fn successes(&self) -> usize {
        self.successes
    }

    pub fn total(&self) -> usize {
        self.failures() + self.successes()
    }
}