diff --git a/extras/simple-bench/src/main.rs b/extras/simple-bench/src/main.rs
index 94ec781..23bd621 100644
--- a/extras/simple-bench/src/main.rs
+++ b/extras/simple-bench/src/main.rs
@@ -2,7 +2,7 @@ mod random;
 
 use std::fs;
 use std::iter;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::str::FromStr;
 use std::time::Instant;
 
@@ -27,6 +27,9 @@ struct Opt {
     /// How many times to repeat parsing
     #[structopt(short, default_value = "1000")]
     repeat: usize,
+    /// Only run fast-float benches
+    #[structopt(short)]
+    only_fast_float: bool,
     #[structopt(subcommand)]
     command: Cmd,
 }
@@ -49,8 +52,8 @@ enum Cmd {
         )]
         gen: RandomGen,
         /// Number of random floats generated
-        #[structopt(short, default_value = "100000")]
-        number: usize,
+        #[structopt(short = "n", default_value = "50000")]
+        count: usize,
         /// Random generator seed
         #[structopt(short, default_value = "0")]
         seed: u64,
@@ -58,83 +61,148 @@ enum Cmd {
         #[structopt(short = "f", parse(from_os_str))]
         filename: Option<PathBuf>,
     },
+    /// Run all benchmarks for fast-float only
+    All {
+        /// Number of random floats generated
+        #[structopt(short = "n", default_value = "50000")]
+        count: usize,
+        /// Random generator seed
+        #[structopt(short, default_value = "0")]
+        seed: u64,
+    },
 }
 
 #[derive(Debug, Clone)]
 struct BenchResult {
     pub name: String,
     pub times: Vec<i64>,
+    pub count: usize,
+    pub bytes: usize,
 }
 
-fn run_one_bench<T: FastFloat, F: Fn(&str) -> T>(
-    name: &str,
+fn black_box<T>(dummy: T) -> T {
+    unsafe {
+        let ret = core::ptr::read_volatile(&dummy);
+        core::mem::forget(dummy);
+        ret
+    }
+}
+
+fn run_bench<T: FastFloat, F: Fn(&str) -> T>(
     inputs: &[String],
     repeat: usize,
     func: F,
-) -> BenchResult {
-    let mut times = Vec::with_capacity(repeat);
-    let mut dummy = T::default();
-    for _ in 0..repeat {
+) -> Vec<i64> {
+    const WARMUP: usize = 1000;
+    let mut times = Vec::with_capacity(repeat + WARMUP);
+    for _ in 0..repeat + WARMUP {
         let t0 = Instant::now();
         for input in inputs {
-            dummy = dummy + func(input.as_str());
+            black_box(func(input.as_str()));
         }
         times.push(t0.elapsed().as_nanos() as _);
     }
-    assert_ne!(dummy, T::default());
-    times.sort();
-    let name = name.into();
-    BenchResult { name, times }
+    times.split_at(WARMUP).1.into()
 }
 
-fn run_all_benches<T: FastFloat + FromLexical + FromLexicalLossy + FromStr>(
-    inputs: &[String],
-    repeat: usize,
-) -> Vec<BenchResult> {
-    let ff_func = |s: &str| fast_float::parse_partial::<T, _>(s).unwrap_or_default().0;
-    let ff_res = run_one_bench("fast_float", inputs, repeat, ff_func);
-
-    let lex_func = |s: &str| {
-        lexical_core::parse_partial::<T>(s.as_bytes())
-            .unwrap_or_default()
-            .0
-    };
-    let lex_res = run_one_bench("lexical", inputs, repeat, lex_func);
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+enum Method {
+    FastFloat,
+    Lexical,
+    LexicalLossy,
+    FromStr,
+}
 
-    let lexl_func = |s: &str| {
-        lexical_core::parse_partial_lossy::<T>(s.as_bytes())
-            .unwrap_or_default()
-            .0
-    };
-    let lexl_res = run_one_bench("lexical/lossy", inputs, repeat, lexl_func);
+fn type_str(float32: bool) -> &'static str {
+    if float32 {
+        "f32"
+    } else {
+        "f64"
+    }
+}
 
-    let std_func = |s: &str| s.parse::<T>().unwrap_or_default();
-    let std_res = run_one_bench("from_str", inputs, repeat, std_func);
+impl Method {
+    pub fn name(&self) -> &'static str {
+        match self {
+            Self::FastFloat => "fast-float",
+            Self::Lexical => "lexical",
+            Self::LexicalLossy => "lexical/lossy",
+            Self::FromStr => "from_str",
+        }
+    }
 
-    vec![ff_res, lex_res, lexl_res, std_res]
-}
+    fn run_as<T: FastFloat + FromLexical + FromLexicalLossy + FromStr>(
+        &self,
+        input: &Input,
+        repeat: usize,
+        name: &str,
+    ) -> BenchResult {
+        let data = &input.data;
+        let times = match self {
+            Self::FastFloat => run_bench(data, repeat, |s: &str| {
+                fast_float::parse_partial::<T, _>(s).unwrap_or_default().0
+            }),
+            Self::Lexical => run_bench(data, repeat, |s: &str| {
+                lexical_core::parse_partial::<T>(s.as_bytes())
+                    .unwrap_or_default()
+                    .0
+            }),
+            Self::LexicalLossy => run_bench(data, repeat, |s: &str| {
+                lexical_core::parse_partial_lossy::<T>(s.as_bytes())
+                    .unwrap_or_default()
+                    .0
+            }),
+            Self::FromStr => run_bench(data, repeat, |s: &str| s.parse::<T>().unwrap_or_default()),
+        };
 
-fn print_report(inputs: &[String], results: &[BenchResult], inputs_name: &str, ty: &str) {
-    let n = inputs.len();
-    let mb = (inputs.iter().map(|s| s.len()).sum::<usize>() as f64) / 1024. / 1024.;
+        BenchResult {
+            times,
+            name: name.into(),
+            count: input.count(),
+            bytes: input.bytes(),
+        }
+    }
+
+    pub fn run(&self, input: &Input, repeat: usize, name: &str, float32: bool) -> BenchResult {
+        if float32 {
+            self.run_as::<f32>(input, repeat, name)
+        } else {
+            self.run_as::<f64>(input, repeat, name)
+        }
+    }
 
-    let width = 76;
+    pub fn all() -> &'static [Self] {
+        &[
+            Method::FastFloat,
+            Method::Lexical,
+            Method::LexicalLossy,
+            Method::FromStr,
+        ]
+    }
+}
+
+fn print_report(results: &[BenchResult], title: &str) {
+    let width = 81;
     println!("{:=<width$}", "", width = width + 4);
-    println!(
-        "| {:^width$} |",
-        format!("{} ({}, {:.2} MB, {})", inputs_name, n, mb, ty),
-        width = width
-    );
+    println!("| {:^width$} |", title, width = width);
     println!("|{:=<width$}|", "", width = width + 2);
-    let n = n as f64;
-    print_table("ns/float", results, width, |t| t / n);
-    print_table("Mfloat/s", results, width, |t| 1e3 * n / t);
-    print_table("MB/s", results, width, |t| mb * 1e9 / t);
+    print_table("ns/float", results, width, |t, n, _| t as f64 / n as f64);
+    print_table("Mfloat/s", results, width, |t, n, _| {
+        1e3 * n as f64 / t as f64
+    });
+    print_table("MB/s", results, width, |t, _, b| {
+        b as f64 * 1e9 / 1024. / 1024. / t as f64
+    });
     println!("|{:width$}|", "", width = width + 2);
     println!("{:=<width$}", "", width = width + 4);
 }
 
-fn print_table(title: &str, results: &[BenchResult], width: usize, transform: impl Fn(f64) -> f64) {
+fn print_table(
+    heading: &str,
+    results: &[BenchResult],
+    width: usize,
+    transform: impl Fn(i64, usize, usize) -> f64,
+) {
     let repeat = results[0].times.len();
     let columns = &[
         ("min", 0),
@@ -149,7 +217,7 @@ fn print_table(title: &str, results: &[BenchResult], width: usize, transform: im
     let h = width - 7 * w;
 
     println!("|{:width$}|", "", width = width + 2);
-    print!("| {:<h$}", title, h = h);
+    print!("| {:<h$}", heading, h = h);
     for (name, _) in columns {
         print!("{:>w$}", name, w = w);
     }
@@ -157,46 +225,117 @@ fn print_table(title: &str, results: &[BenchResult], width: usize, transform: im
     println!("|{:-<width$}|", "", width = width + 2);
     for res in results {
         print!("| {:<h$}", res.name, h = h);
+        let (n, b) = (res.count, res.bytes);
+        let mut metrics = res
+            .times
+            .iter()
+            .map(|&t| transform(t, n, b))
+            .collect::<Vec<_>>();
+        metrics.sort_by(|a, b| a.partial_cmp(b).unwrap());
         for &(_, idx) in columns {
-            print!("{:>w$.2}", transform(res.times[idx] as f64), w = w);
+            print!("{:>w$.2}", metrics[idx], w = w);
         }
         println!(" |");
     }
 }
 
+struct Input {
+    pub data: Vec<String>,
+    pub name: String,
+}
+
+impl Input {
+    pub fn from_file(filename: impl AsRef<Path>) -> Self {
+        let filename = filename.as_ref();
+        let data = fs::read_to_string(&filename)
+            .unwrap()
+            .trim()
+            .lines()
+            .map(String::from)
+            .collect();
+        let name = filename.file_name().unwrap().to_str().unwrap().into();
+        Self { data, name }
+    }
+
+    pub fn from_random(gen: RandomGen, count: usize, seed: u64) -> Self {
+        let mut rng = Rng::with_seed(seed);
+        let data = iter::repeat_with(|| gen.gen(&mut rng))
+            .take(count)
+            .collect();
+        let name = format!("{}", gen);
+        Self { data, name }
+    }
+
+    pub fn count(&self) -> usize {
+        self.data.len()
+    }
+
+    pub fn bytes(&self) -> usize {
+        self.data.iter().map(|s| s.len()).sum()
+    }
+
+    pub fn title(&self, float32: bool) -> String {
+        format!(
+            "{} ({}, {:.2} MB, {})",
+            self.name,
+            self.count(),
+            self.bytes() as f64 / 1024. / 1024.,
+            type_str(float32),
+        )
+    }
+}
+
 fn main() {
     let opt: Opt = StructOpt::from_args();
-    let (inputs, inputs_name) = match opt.command {
-        Cmd::File { filename } => (
-            fs::read_to_string(&filename)
-                .unwrap()
-                .trim()
-                .lines()
-                .map(String::from)
-                .collect::<Vec<_>>(),
-            filename.to_str().unwrap().to_owned(),
-        ),
+
+    let methods = if !opt.only_fast_float && !matches!(&opt.command, &Cmd::All {..}) {
+        Method::all().into()
+    } else {
+        vec![Method::FastFloat]
+    };
+
+    let inputs = match opt.command {
+        Cmd::File { filename } => vec![Input::from_file(filename)],
         Cmd::Random {
             gen,
-            number,
+            count,
             seed,
             filename,
         } => {
-            let mut rng = Rng::with_seed(seed);
-            let inputs: Vec<String> = iter::repeat_with(|| gen.gen(&mut rng))
-                .take(number)
-                .collect();
+            let input = Input::from_random(gen, count, seed);
             if let Some(filename) = filename {
-                fs::write(filename, inputs.join("\n")).unwrap();
+                fs::write(filename, input.data.join("\n")).unwrap();
             }
-            (inputs, format!("{}", gen))
+            vec![input]
+        }
+        Cmd::All { count, seed } => {
+            let mut inputs = vec![];
+            let data_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("ext/data");
+            inputs.push(Input::from_file(data_dir.join("mesh.txt")));
+            inputs.push(Input::from_file(data_dir.join("canada.txt")));
+            for &gen in RandomGen::all() {
+                inputs.push(Input::from_random(gen, count, seed))
+            }
+            inputs
         }
     };
-    let repeat = opt.repeat.max(1);
-    let (results, ty) = if opt.float32 {
-        (run_all_benches::<f32>(&inputs, repeat), "f32")
+
+    let mut results = vec![];
+    for input in &inputs {
+        for method in &methods {
+            let name = if inputs.len() == 1 {
+                method.name()
+            } else {
+                &input.name
+            };
+            results.push(method.run(input, opt.repeat.max(1), name, opt.float32));
+        }
+    }
+
+    let title = if inputs.len() == 1 {
+        inputs[0].title(opt.float32)
     } else {
-        (run_all_benches::<f64>(&inputs, repeat), "f64")
+        format!("fast-float (all, {})", type_str(opt.float32))
     };
-    print_report(&inputs, &results, &inputs_name, ty);
+    print_report(&results, &title);
 }
diff --git a/extras/simple-bench/src/random.rs b/extras/simple-bench/src/random.rs
index c08a02b..276bfed 100644
--- a/extras/simple-bench/src/random.rs
+++ b/extras/simple-bench/src/random.rs
@@ -63,6 +63,19 @@ impl RandomGen {
         ]
     }
 
+    pub fn all() -> &'static [Self] {
+        &[
+            Self::Uniform,
+            Self::OneOverRand32,
+            Self::SimpleUniform32,
+            Self::SimpleInt32,
+            Self::IntEInt,
+            Self::SimpleInt64,
+            Self::BigIntDotInt,
+            Self::BigInts,
+        ]
+    }
+
     pub fn gen(&self, rng: &mut Rng) -> String {
         match self {
             Self::Uniform
diff --git a/src/decimal.rs b/src/decimal.rs
index 5ed16b3..43112c9 100644
--- a/src/decimal.rs
+++ b/src/decimal.rs
@@ -29,7 +29,7 @@ impl PartialEq for Decimal {
             && self.decimal_point == other.decimal_point
             && self.negative == other.negative
             && self.truncated == other.truncated
-            && &self.digits[..] == &other.digits[..]
+            && self.digits[..] == other.digits[..]
     }
 }
 
diff --git a/src/float.rs b/src/float.rs
index 315d230..39bec41 100644
--- a/src/float.rs
+++ b/src/float.rs
@@ -68,10 +68,12 @@ impl Float for f32 {
     }
 
     #[inline]
-    #[allow(clippy::use_self)]
     fn pow10_fast_path(exponent: usize) -> Self {
-        const TABLE: [f32; 11] = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10];
-        unsafe { *TABLE.get_unchecked(exponent) }
+        #[allow(clippy::use_self)]
+        const TABLE: [f32; 16] = [
+            1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 0., 0., 0., 0., 0.,
+        ];
+        TABLE[exponent & 15]
     }
 }
 
@@ -102,10 +104,10 @@ impl Float for f64 {
     #[inline]
     fn pow10_fast_path(exponent: usize) -> Self {
         #[allow(clippy::use_self)]
-        const TABLE: [f64; 23] = [
+        const TABLE: [f64; 32] = [
             1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
-            1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
+            1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 0., 0., 0., 0., 0., 0., 0., 0., 0.,
         ];
-        unsafe { *TABLE.get_unchecked(exponent) }
+        TABLE[exponent & 31]
     }
 }