reed_solomon_erasure/
lib.rs1#![allow(dead_code)]
11#![cfg_attr(not(feature = "std"), no_std)]
12
13#[cfg(test)]
14#[macro_use]
15extern crate quickcheck;
16
17#[cfg(test)]
18extern crate rand;
19
20extern crate smallvec;
21
22#[cfg(feature = "simd-accel")]
23extern crate libc;
24
25use ::core::iter;
26use ::core::iter::FromIterator;
27
28#[macro_use]
29mod macros;
30
31mod core;
32mod errors;
33mod matrix;
34
35#[cfg(test)]
36mod tests;
37
38pub mod galois_16;
39pub mod galois_8;
40
41pub use crate::errors::Error;
42pub use crate::errors::SBSError;
43
44pub use crate::core::ReedSolomon;
45pub use crate::core::ShardByShard;
46
47#[cfg(not(feature = "std"))]
49use libm::log2f as log2;
50#[cfg(feature = "std")]
51fn log2(n: f32) -> f32 {
52 n.log2()
53}
54
55pub trait Field: Sized {
57 const ORDER: usize;
60
61 type Elem: Default + Clone + Copy + PartialEq + ::core::fmt::Debug;
63
64 fn add(a: Self::Elem, b: Self::Elem) -> Self::Elem;
66
67 fn mul(a: Self::Elem, b: Self::Elem) -> Self::Elem;
69
70 fn div(a: Self::Elem, b: Self::Elem) -> Self::Elem;
72
73 fn exp(a: Self::Elem, n: usize) -> Self::Elem;
75
76 fn zero() -> Self::Elem;
78
79 fn one() -> Self::Elem;
81
82 fn nth_internal(n: usize) -> Self::Elem;
83
84 fn nth(n: usize) -> Self::Elem {
87 if n >= Self::ORDER {
88 let pow = log2(Self::ORDER as f32) as usize;
89 panic!("{} out of bounds for GF(2^{}) member", n, pow)
90 }
91
92 Self::nth_internal(n)
93 }
94
95 fn mul_slice(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
100 assert_eq!(input.len(), out.len());
101
102 for (i, o) in input.iter().zip(out) {
103 *o = Self::mul(elem.clone(), i.clone())
104 }
105 }
106
107 fn mul_slice_add(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
113 assert_eq!(input.len(), out.len());
114
115 for (i, o) in input.iter().zip(out) {
116 *o = Self::add(o.clone(), Self::mul(elem.clone(), i.clone()))
117 }
118 }
119}
120
121pub trait ReconstructShard<F: Field> {
126 fn len(&self) -> Option<usize>;
128
129 fn get(&mut self) -> Option<&mut [F::Elem]>;
131
132 fn get_or_initialize(
135 &mut self,
136 len: usize,
137 ) -> Result<&mut [F::Elem], Result<&mut [F::Elem], Error>>;
138}
139
140impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]> + FromIterator<F::Elem>> ReconstructShard<F>
141 for Option<T>
142{
143 fn len(&self) -> Option<usize> {
144 self.as_ref().map(|x| x.as_ref().len())
145 }
146
147 fn get(&mut self) -> Option<&mut [F::Elem]> {
148 self.as_mut().map(|x| x.as_mut())
149 }
150
151 fn get_or_initialize(
152 &mut self,
153 len: usize,
154 ) -> Result<&mut [F::Elem], Result<&mut [F::Elem], Error>> {
155 let is_some = self.is_some();
156 let x = self
157 .get_or_insert_with(|| iter::repeat(F::zero()).take(len).collect())
158 .as_mut();
159
160 if is_some {
161 Ok(x)
162 } else {
163 Err(Ok(x))
164 }
165 }
166}
167
168impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]>> ReconstructShard<F> for (T, bool) {
169 fn len(&self) -> Option<usize> {
170 if !self.1 {
171 None
172 } else {
173 Some(self.0.as_ref().len())
174 }
175 }
176
177 fn get(&mut self) -> Option<&mut [F::Elem]> {
178 if !self.1 {
179 None
180 } else {
181 Some(self.0.as_mut())
182 }
183 }
184
185 fn get_or_initialize(
186 &mut self,
187 len: usize,
188 ) -> Result<&mut [F::Elem], Result<&mut [F::Elem], Error>> {
189 let x = self.0.as_mut();
190 if x.len() == len {
191 if self.1 {
192 Ok(x)
193 } else {
194 Err(Ok(x))
195 }
196 } else {
197 Err(Err(Error::IncorrectShardSize))
198 }
199 }
200}