diff --git a/src/bbp.rs b/src/bbp.rs new file mode 100644 index 0000000..52efa68 --- /dev/null +++ b/src/bbp.rs @@ -0,0 +1,93 @@ +pub fn get_byte(id: i32) -> u8 { + let pid : f64 = 4.0 * series(1, id) - 2.0 * series(4, id) - series(5, id) - series(6, id); + + let mut y : f64 = (pid - (pid as i32) as f64 + 1.0).abs(); // TODO use .trunc() instead + + y = 16.0 * (y - y.floor()); // TODO use .trunc() instead of floor? + + let first : u8 = y as u8; + + y = 16.0 * (y - y.floor()); // TODO use .trunc() instead of floor? + + let second : u8 = y as u8; + + (first << 4) | second +} + +fn series(m: i32, id: i32) -> f64 { + const EPS : f64 = 1e-17; + + let mut ak : f64; + let mut t : f64; + let mut s : f64 = 0.0; + + for k in 0..id { + ak = (8 * k + m) as f64; + t = expm((id - k) as f64, ak); + + s += t / ak; + s -= (s as i32) as f64; // TODO: use .truc() instead. + } + + for k in id..id + 101 { + ak = (8 * k + m) as f64; + t = 16f64.powi(id - k) / ak; + + if t < EPS { + break; + } + + s += t; + s -= (s as i32) as f64; // TODO: use .truc() instead. + } + + s +} + +fn expm(p: f64, ak: f64) -> f64 { + if ak == 1.0 { + return 0.0; + } + + const NTP : usize = 25; + + lazy_static! { + static ref TP : Vec = { + let mut v = vec![1f64; NTP]; + + for i in 1..NTP { + v[i] = 2.0 * v[i - 1]; + } + + v + }; + } + + let mut i : usize = 0; + + while TP[i] <= p { + i += 1; + } + + let mut pt = TP[i - 1]; + let mut p1 : f64 = p; // TODO: use p instead of p1? + let mut r : f64 = 1.0; + + for _ in 1..i + 1 { + if p1 >= pt { + r = 16.0 * r; + r = r - ((r / ak) as i32) as f64 * ak; // TODO: use .truc() instead. + + p1 -= pt; + } + + pt = 0.5 * pt; + + if pt >= 1.0 { + r *= r; + r -= ((r / ak) as i32) as f64 * ak; // TODO: use .truc() instead. + } + } + + r +} diff --git a/src/main.rs b/src/main.rs index 5ba0ea9..9db8e74 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ extern crate getopts; extern crate byteorder; extern crate pbr; + #[macro_use] extern crate lazy_static; @@ -15,6 +16,8 @@ use getopts::Options; use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian}; use pbr::{ProgressBar, Units}; +mod bbp; + fn main() { let args: Vec = env::args().collect(); @@ -68,7 +71,7 @@ fn compress(input: &String, output: &String) { let b = b.unwrap(); for n in 0..i32::MAX { - if b == get_byte(n) { + if b == bbp::get_byte(n) { i = n; break; } @@ -105,102 +108,8 @@ fn extract(input: &String, output: &String) { let mut c = Cursor::new(&buf); let index = c.read_i32::().unwrap(); - output_file.write_all(&[get_byte(index)]).unwrap(); + output_file.write_all(&[bbp::get_byte(index)]).unwrap(); pb.add(size as u64); } } - -fn get_byte(id: i32) -> u8 { - let pid : f64 = 4.0 * series(1, id) - 2.0 * series(4, id) - series(5, id) - series(6, id); - - let mut y : f64 = (pid - (pid as i32) as f64 + 1.0).abs(); - - y = 16.0 * (y - y.floor()); - - let first : u8 = y as u8; - - y = 16.0 * (y - y.floor()); - - let second : u8 = y as u8; - - (first << 4) | second -} - -fn series(m: i32, id: i32) -> f64 { - const EPS : f64 = 1e-17; - - let mut ak : f64; - let mut t : f64; - let mut s : f64 = 0.0; - - for k in 0..id { - ak = (8 * k + m) as f64; - t = expm((id - k) as f64, ak); - - s += t / ak; - s -= (s as i32) as f64; - } - - for k in id..id + 101 { - ak = (8 * k + m) as f64; - t = 16f64.powi(id - k) / ak; - - if t < EPS { - break; - } - - s += t; - s -= (s as i32) as f64; - } - - s -} - -fn expm(p: f64, ak: f64) -> f64 { - if ak == 1.0 { - return 0.0; - } - - const NTP : usize = 25; - - lazy_static! { - static ref TP : Vec = { - let mut v = vec![1f64; NTP]; - - for i in 1..NTP { - v[i] = 2.0 * v[i - 1]; - } - - v - }; - } - - let mut i : usize = 0; - - while TP[i] <= p { - i += 1; - } - - let mut pt = TP[i - 1]; - let mut p1 : f64 = p; - let mut r : f64 = 1.0; - - for _ in 1..i + 1 { - if p1 >= pt { - r = 16.0 * r; - r = r - ((r / ak) as i32) as f64 * ak; - - p1 -= pt; - } - - pt = 0.5 * pt; - - if pt >= 1.0 { - r *= r; - r -= ((r / ak) as i32) as f64 * ak; - } - } - - r -}