diff --git a/hash_list_correction/.gitignore b/hash_list_correction/.gitignore new file mode 100644 index 0000000..5cd94bf --- /dev/null +++ b/hash_list_correction/.gitignore @@ -0,0 +1 @@ +switch_hash_correction_*.csv \ No newline at end of file diff --git a/hash_list_correction/Cargo.toml b/hash_list_correction/Cargo.toml index 35e0f16..0b450f8 100644 --- a/hash_list_correction/Cargo.toml +++ b/hash_list_correction/Cargo.toml @@ -4,3 +4,13 @@ version = "0.1.0" edition = "2021" [dependencies] +hyperloglog-rs = {path = "../", features = ["all_precisions", "std"]} +syn = "2.0" +quote = "1.0" +proc-macro2 = "1.0" +prettyplease = "0.2" +indicatif = { version = "0.17.8", features = ["rayon"] } +rayon = "1.10.0" +twox-hash = "1.6.3" +test_utils = {path="../test_utils"} +serde = { version = "1.0.208", features = ["derive"] } \ No newline at end of file diff --git a/hash_list_correction/README.md b/hash_list_correction/README.md new file mode 100644 index 0000000..9b2f5c0 --- /dev/null +++ b/hash_list_correction/README.md @@ -0,0 +1,62 @@ +# Hash List correction +The Hash List low-cardinality correction approach for HyperLogLog counters is itself subject to biases, primarily derived by the so-called birthday paradox, i.e. the probability of two elements in a set of size n to have the same hash value is higher than one might expect. This is a well-known issue in computer science and cryptography, and it is the reason why hash functions are designed to be collision-resistant. Fortunately, while theoretically hard to estimate because of the several techniques we employ, we can empirically measure the bias introduced by the Hash List correction approach. + +Once the error is measured, we can trivially subtract it to the cardinality estimate and obtain a much nicer result. This is the purpose of the `hash_list_correction` module, which provides a simple interface to measure the bias and correct the cardinality estimate. + +## Usage +As any rust script, just use: + +```bash +RUSTFLAGS='-C target-cpu=native' cargo run --release +``` + +## Switch Hash Results +The results regarding the switch hash are as follows: + +| precision | bits | maximal_mean_relative_error | peak_estimated_cardinality | bias | error_reduction | +|-----------|------|-----------------------------|-----------------------------|------|-----------------| +| 4 | 4 | 0.0691152 | 7.45 | 1.00 | 56.22 | +| 4 | 5 | 0.0001191 | 8.00 | 1.00 | 156.17 | +| 4 | 6 | 0.0001077 | 8.00 | 1.00 | 109.75 | +| 5 | 4 | 0.0001238 | 8.00 | 1.00 | 105.03 | +| 5 | 5 | 0.0001798 | 12.00 | 1.00 | 57.33 | +| 5 | 6 | 0.0001709 | 12.00 | 1.00 | 70.69 | +| 6 | 4 | 0.0002604 | 16.00 | 1.00 | 191.23 | +| 6 | 5 | 0.0002986 | 19.99 | 1.00 | 162.92 | +| 6 | 6 | 0.0003535 | 23.99 | 1.00 | 221.90 | +| 7 | 4 | 0.0004990 | 31.98 | 1.00 | 826.10 | +| 7 | 5 | 0.0005987 | 39.98 | 1.00 | 751.54 | +| 7 | 6 | 0.0007155 | 47.97 | 1.00 | 668.20 | +| 8 | 4 | 0.0005582 | 63.96 | 41.00 | 26.07 | +| 8 | 5 | 0.0006774 | 79.95 | 51.00 | 24.80 | +| 8 | 6 | 0.0008063 | 95.92 | 62.00 | 26.04 | +| 9 | 4 | 0.0010797 | 127.86 | 83.00 | 25.15 | +| 9 | 5 | 0.0013529 | 159.78 | 103.00 | 25.56 | +| 9 | 6 | 0.0016084 | 191.69 | 125.00 | 25.72 | +| 10 | 4 | 0.0021341 | 255.45 | 165.00 | 26.05 | +| 10 | 5 | 0.0026572 | 319.15 | 207.00 | 24.27 | +| 10 | 6 | 0.0349638 | 379.62 | 251.00 | 17.03 | +| 11 | 4 | 0.0041498 | 509.88 | 331.99 | 21.21 | +| 11 | 5 | 0.0293490 | 637.79 | 414.99 | 17.81 | +| 11 | 6 | 0.0000331 | 511.98 | 1.00 | 207.34 | +| 12 | 4 | 0.0235120 | 1021.98 | 664.97 | 20.97 | +| 12 | 5 | 0.0000586 | 852.95 | 1.00 | 203.13 | +| 12 | 6 | 0.0000633 | 1023.94 | 1.00 | 283.56 | +| 13 | 4 | 0.0000954 | 1364.87 | 1.00 | 292.92 | +| 13 | 5 | 0.0001082 | 1705.82 | 1.00 | 302.12 | +| 13 | 6 | 0.0001232 | 2047.75 | 1.00 | 352.58 | +| 14 | 4 | 0.0000813 | 2729.78 | 2017.00 | 22.68 | +| 14 | 5 | 0.0000917 | 3412.69 | 2523.00 | 22.42 | +| 14 | 6 | 0.0001078 | 4095.56 | 3028.00 | 22.78 | +| 15 | 4 | 0.0001507 | 5460.18 | 4034.00 | 23.08 | +| 15 | 5 | 0.0001801 | 6824.77 | 5040.99 | 22.02 | +| 15 | 6 | 0.0002143 | 8190.24 | 6049.99 | 21.92 | +| 16 | 4 | 0.0002903 | 10918.83 | 8058.98 | 22.23 | +| 16 | 5 | 0.0003558 | 13649.14 | 10082.97 | 21.80 | +| 16 | 6 | 0.0004274 | 16380.00 | 12106.96 | 21.89 | +| 17 | 4 | 0.0005662 | 21838.63 | 16133.93 | 21.76 | +| 17 | 5 | 0.0007094 | 27306.61 | 20172.88 | 21.90 | +| 17 | 6 | 0.0008523 | 32772.45 | 24199.83 | 22.47 | +| 18 | 4 | 0.0011257 | 43711.11 | 32258.70 | 22.13 | +| 18 | 5 | 0.0014110 | 54661.67 | 40339.54 | 22.14 | +| 18 | 6 | 0.0198708 | 66823.58 | 48436.36 | 35.60 | diff --git a/hash_list_correction/src/main.rs b/hash_list_correction/src/main.rs index 56605e3..1593eca 100644 --- a/hash_list_correction/src/main.rs +++ b/hash_list_correction/src/main.rs @@ -1,5 +1,15 @@ //! Rust script to identify the optimal correction +#![deny(unsafe_code)] +#![deny(unused_macro_rules)] +#![deny(missing_docs)] +extern crate prettyplease; +extern crate proc_macro2; +extern crate quote; +extern crate syn; + +mod switch_hash; +use switch_hash::compute_switch_hash_correction; fn main() { - println!("Hello, world!"); + compute_switch_hash_correction(); } diff --git a/hash_list_correction/src/switch_hash.rs b/hash_list_correction/src/switch_hash.rs new file mode 100644 index 0000000..6284dcf --- /dev/null +++ b/hash_list_correction/src/switch_hash.rs @@ -0,0 +1,354 @@ +//! Error correction for switch hash. + +use hyperloglog_rs::composite_hash::CompositeHash; +use prettyplease::unparse; +use proc_macro2::TokenStream; +use quote::quote; +use syn::{File, Ident}; + +use hyperloglog_rs::composite_hash::switch::SwitchHash; +use hyperloglog_rs::prelude::*; +use indicatif::MultiProgress; +use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; +use rayon::prelude::*; +use serde::ser::Serializer; +use serde::{Deserialize, Serialize}; +use std::collections::HashSet; +use test_utils::prelude::{read_csv, write_csv}; +use twox_hash::XxHash64; + +fn float_formatter(value: &f64, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&format!("{value:.7}")) +} + +fn small_float_formatter(value: &f64, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&format!("{value:.2}")) +} + +#[derive(Debug, Serialize, Deserialize, Default, Copy, Clone)] +struct SwitchHashCorrection { + precision: u8, + bits: u8, + #[serde(serialize_with = "float_formatter")] + maximal_mean_relative_error: f64, + #[serde(serialize_with = "small_float_formatter")] + peak_estimated_cardinality: f64, + #[serde(serialize_with = "small_float_formatter")] + bias: f64, + #[serde(serialize_with = "small_float_formatter")] + error_reduction: f64, +} + +impl SwitchHashCorrection { + /// Implements the BirthDayParadoxCorrection trait for the SwitchHash struct at + /// the associated precision and bit size. + fn to_birthday_correction(&self) -> TokenStream { + let precision = self.precision; + let bits = self.bits; + let bias = self.bias; + let peak_estimated_cardinality = self.peak_estimated_cardinality; + let maximal_mean_relative_error = self.maximal_mean_relative_error; + let ident_precision: Ident = Ident::new( + &format!("Precision{}", precision), + proc_macro2::Span::call_site(), + ); + let ident_bits: Ident = + Ident::new(&format!("Bits{}", bits), proc_macro2::Span::call_site()); + let precision_flag = format!("precision_{}", precision); + let precision_flag = quote! { + #[cfg(feature = #precision_flag)] + }; + + quote! { + #precision_flag + impl crate::composite_hash::BirthDayParadoxCorrection for crate::composite_hash::SwitchHash { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = #bias; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = #peak_estimated_cardinality; + const MAXIMAL_ERROR_RATE: f64 = #maximal_mean_relative_error; + } + } + } +} + +#[derive(Debug, Serialize, Deserialize, Default, Copy, Clone)] +struct CardinalityError { + cardinality: f64, + error: f64, +} + +/// Measures the gap between subsequent hashes in the Listhash variant of HyperLogLog. +fn switch_hash_correction( + multiprogress: &MultiProgress, +) -> SwitchHashCorrection +where + P: ArrayRegister, + SwitchHash: CompositeHash, +{ + // We read the switch_hash_correction.csv file to check if the correction has already been + // computed. If so, we return the correction. + if let Some(correction) = read_csv::("switch_hash_correction.csv") + .ok() + .and_then(|corrections: Vec| { + corrections.into_iter().find(|correction| { + correction.precision == P::EXPONENT && correction.bits == B::NUMBER_OF_BITS + }) + }) + { + return correction; + } + + let iterations: u32 = if P::EXPONENT < 9 { + 10_000_000 + } else if P::EXPONENT < 16 { + 1_000_000 + } else { + 50_000 + }; + + let progress_bar = multiprogress.add(ProgressBar::new(iterations as u64)); + progress_bar.set_style( + ProgressStyle::default_bar() + .template( + "Samples: [{elapsed_precise} | {eta}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}", + ) + .unwrap() + .progress_chars("##-"), + ); + + let random_state = 6_539_823_745_562_884_u64; + + let (number_of_unique_hash_bits, mut total_report): (usize, Vec) = + ParallelIterator::reduce( + (0..iterations) + .into_par_iter() + .progress_with(progress_bar) + .map(|i| { + let random_state = splitmix64(random_state.wrapping_mul(u64::from(i) + 1)); + let mut hash_set = HashSet::with_capacity(100_000); + let mut hll = Hybrid::< + PlusPlus>::Packed, XxHash64>, + SwitchHash, + >::default(); + let mut report: Vec = Vec::with_capacity(100_000); + let mut unique_hash_bits: HashSet = HashSet::with_capacity(2); + + for value in iter_random_values::(1_000_000, None, Some(random_state)) { + hash_set.insert(value); + hll.insert(&value); + if !hll.is_hash_list() { + break; + } + unique_hash_bits.insert(hll.hash_bits()); + let cardinality = + f64::from(hll.duplicates().unwrap() + hll.number_of_hashes().unwrap()); + let exact_cardinality = f64::from(u32::try_from(hash_set.len()).unwrap()); + let error = (exact_cardinality - cardinality).abs() / exact_cardinality; + report.push(CardinalityError { cardinality, error }); + } + + (unique_hash_bits.len(), report) + }), + || (0, Vec::new()), + |mut acc, (unique_hash_bits, report)| { + acc.0 = unique_hash_bits; + if acc.1.is_empty() { + acc.1 = report; + } else { + for (acc, report) in acc.1.iter_mut().zip(report.iter()) { + acc.cardinality += report.cardinality; + acc.error += report.error; + } + } + acc + }, + ); + + // We expect that there should be at most two steps. + assert!(number_of_unique_hash_bits <= 2); + assert!(number_of_unique_hash_bits > 0); + + // We expect at least one value in the report. + assert!(!total_report.is_empty()); + + // We normalize the results by the number of iterations. + total_report.par_iter_mut().for_each(|report| { + report.cardinality /= f64::from(iterations); + report.error /= f64::from(iterations); + }); + + // We sort the results by the estimated cardinality, which most likely will be the + // already sorted but it is not guaranteed. + total_report.sort_by(|a, b| a.cardinality.partial_cmp(&b.cardinality).unwrap()); + + // We find the maximal mean relative error and its corresponding estimated cardinality. + let peak_error: CardinalityError = ParallelIterator::reduce( + total_report.par_iter().copied(), + || CardinalityError { + cardinality: 0.0, + error: 0.0, + }, + |mut acc, report| { + if report.error > acc.error { + acc = report; + } + acc + }, + ); + + // We check that neither the maximal mean relative error nor the peak estimated cardinality + // are zero. + assert!( + peak_error.error > 0.0, + "The maximal error at precision {} and bits {} seems to be zero.", + P::EXPONENT, + B::NUMBER_OF_BITS + ); + assert!(peak_error.cardinality > 0.0); + + // We compute the total error + let total_error = total_report.iter().map(|report| report.error).sum::(); + + // We iterate on the reports to find the point with minimal relative error. + let (total_error_reduced, bias): (f64, f64) = (0..total_report.len()) + .into_par_iter() + .map(|i| { + let mut total_error_reduced = 0.0; + let bias = total_report[i].cardinality; + if bias >= peak_error.cardinality { + return (total_error, bias); + } + for (j, this_report) in total_report.iter().enumerate() { + if j < i { + total_error_reduced += this_report.error; + } else { + let predicted_error = peak_error.error * (this_report.cardinality - bias) + / (peak_error.cardinality - bias); + assert!(predicted_error >= 0.0); + total_error_reduced += (this_report.error - predicted_error).abs(); + } + } + + (total_error_reduced, bias) + }) + .min_by(|(error_a, _), (error_b, _)| error_a.partial_cmp(error_b).unwrap()) + .unwrap(); + + // We compute the error reduction + let error_reduction = total_error / total_error_reduced; + + SwitchHashCorrection { + precision: P::EXPONENT, + bits: B::NUMBER_OF_BITS, + maximal_mean_relative_error: peak_error.error, + peak_estimated_cardinality: peak_error.cardinality, + bias, + error_reduction, + } +} + +/// Procedural macro to generate the switch_hash_correction function for the provided precision, +/// and bit sizes. +macro_rules! generate_switch_hash_correction_for_precision { + ($reports:ident, $multiprogress:ident, $precision:ty, $($bit_size:ty),*) => { + let progress_bar = $multiprogress.add(ProgressBar::new(3 as u64)); + + progress_bar.set_style( + ProgressStyle::default_bar() + .template("Bits: [{elapsed_precise} | {eta}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}") + .unwrap() + .progress_chars("##-"), + ); + + progress_bar.tick(); + + $( + let report = switch_hash_correction::<$precision, $bit_size>($multiprogress); + $reports.push(report); + progress_bar.inc(1); + )* + + progress_bar.finish_and_clear(); + }; +} + +/// Procedural macro to generate the switch_hash_correction function for the provided precisions. +macro_rules! generate_switch_hash_correction_for_precisions { + ($reports:ident, $multiprogress:ident, $($precision:ty),*) => { + let progress_bar = $multiprogress.add(ProgressBar::new(18-4)); + + progress_bar.set_style( + ProgressStyle::default_bar() + .template("Precisions: [{elapsed_precise} | {eta}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}") + .unwrap() + .progress_chars("##-"), + ); + + progress_bar.tick(); + + $( + generate_switch_hash_correction_for_precision!($reports, $multiprogress, $precision, Bits4, Bits5, Bits6); + progress_bar.inc(1); + )* + + progress_bar.finish_and_clear(); + }; +} + +pub fn compute_switch_hash_correction() { + let mut reports: Vec<_> = Vec::new(); + let multiprogress = &MultiProgress::new(); + generate_switch_hash_correction_for_precisions!( + reports, + multiprogress, + Precision4, + Precision5, + Precision6, + Precision7, + Precision8, + Precision9, + Precision10, + Precision11, + Precision12, + Precision13, + Precision14, + Precision15, + Precision16, + Precision17, + Precision18 + ); + multiprogress.clear().unwrap(); + + write_csv(reports.iter(), "switch_hash_correction.csv"); + + let valid_impls: Vec = reports + .iter() + .map(|report| report.to_birthday_correction()) + .collect(); + + let output = quote! { + #(#valid_impls)* + }; + + // We write out the output token stream to '../src/composite_hash/switch_birthday_paradox.rs' + let output_path = "../src/composite_hash/switch_birthday_paradox.rs"; + + // Convert the generated TokenStream to a string + let code_string = output.to_string(); + + // Parse the generated code string into a syn::Item + let syntax_tree: File = syn::parse_str(&code_string).unwrap(); + + // Use prettyplease to format the syntax tree + let formatted_code = unparse(&syntax_tree); + + // Write the formatted code to the output file + std::fs::write(output_path, formatted_code).unwrap(); + + println!("Generated optimal codes in '{}'", output_path); +} diff --git a/hash_list_correction/switch_hash_correction.csv b/hash_list_correction/switch_hash_correction.csv new file mode 100644 index 0000000..d3d0067 --- /dev/null +++ b/hash_list_correction/switch_hash_correction.csv @@ -0,0 +1,46 @@ +precision,bits,maximal_mean_relative_error,peak_estimated_cardinality,bias,error_reduction +4,4,0.0691152,7.45,1.00,56.22 +4,5,0.0001191,8.00,1.00,156.17 +4,6,0.0001077,8.00,1.00,109.75 +5,4,0.0001238,8.00,1.00,105.03 +5,5,0.0001798,12.00,1.00,57.33 +5,6,0.0001709,12.00,1.00,70.69 +6,4,0.0002604,16.00,1.00,191.23 +6,5,0.0002986,19.99,1.00,162.92 +6,6,0.0003535,23.99,1.00,221.90 +7,4,0.0004990,31.98,1.00,826.10 +7,5,0.0005987,39.98,1.00,751.54 +7,6,0.0007155,47.97,1.00,668.20 +8,4,0.0005582,63.96,41.00,26.07 +8,5,0.0006774,79.95,51.00,24.80 +8,6,0.0008063,95.92,62.00,26.04 +9,4,0.0010797,127.86,83.00,25.15 +9,5,0.0013529,159.78,103.00,25.56 +9,6,0.0016084,191.69,125.00,25.72 +10,4,0.0021341,255.45,165.00,26.05 +10,5,0.0026572,319.15,207.00,24.27 +10,6,0.0349638,379.62,251.00,17.03 +11,4,0.0041498,509.88,331.99,21.21 +11,5,0.0293490,637.79,414.99,17.81 +11,6,0.0000331,511.98,1.00,207.34 +12,4,0.0235120,1021.98,664.97,20.97 +12,5,0.0000586,852.95,1.00,203.13 +12,6,0.0000633,1023.94,1.00,283.56 +13,4,0.0000954,1364.87,1.00,292.92 +13,5,0.0001082,1705.82,1.00,302.12 +13,6,0.0001232,2047.75,1.00,352.58 +14,4,0.0000813,2729.78,2017.00,22.68 +14,5,0.0000917,3412.69,2523.00,22.42 +14,6,0.0001078,4095.56,3028.00,22.78 +15,4,0.0001507,5460.18,4034.00,23.08 +15,5,0.0001801,6824.77,5040.99,22.02 +15,6,0.0002143,8190.24,6049.99,21.92 +16,4,0.0002903,10918.83,8058.98,22.23 +16,5,0.0003558,13649.14,10082.97,21.80 +16,6,0.0004274,16380.00,12106.96,21.89 +17,4,0.0005662,21838.63,16133.93,21.76 +17,5,0.0007094,27306.61,20172.88,21.90 +17,6,0.0008523,32772.45,24199.83,22.47 +18,4,0.0011257,43711.11,32258.70,22.13 +18,5,0.0014110,54661.67,40339.54,22.14 +18,6,0.0198708,66823.58,48436.36,35.60 diff --git a/measure_variant/comparison.png b/measure_variant/comparison.png index 3311114..53696ed 100644 Binary files a/measure_variant/comparison.png and b/measure_variant/comparison.png differ diff --git a/measure_variant/latest_report.csv b/measure_variant/latest_report.csv index 07b0802..4331439 100644 --- a/measure_variant/latest_report.csv +++ b/measure_variant/latest_report.csv @@ -360,667 +360,496 @@ relative_error,estimated_cardinality,cardinality 0.0,359,359 0.0,360,360 0.0,361,361 -0.0003038674033149171,362,362 -0.000743801652892562,362,363 -0.001043956043956044,363,364 -0.0013424657534246577,363,365 -0.0017213114754098364,364,366 -0.0019346049046321523,365,367 -0.0021195652173913045,366,368 -0.0023577235772357726,367,369 -0.002756756756756757,368,370 -0.0030997304582210243,369,371 -0.0035483870967741938,369,372 -0.003887399463806971,370,373 -0.0042780748663101605,371,374 -0.004666666666666667,372,375 -0.004893617021276595,373,376 -0.005305039787798409,374,377 -0.005529100529100529,375,378 -0.005910290237467019,376,379 -0.006342105263157895,377,380 -0.006666666666666667,377,381 -0.007015706806282722,378,382 -0.007258485639686685,379,383 -0.007578125,380,384 -0.0077662337662337665,381,385 -0.008082901554404144,382,386 -0.008397932816537468,383,387 -0.008582474226804124,384,388 -0.008946015424164525,385,389 -0.009333333333333334,386,390 -0.009514066496163683,387,391 -0.009770408163265305,387,392 -0.010025445292620864,388,393 -0.010431472081218274,389,394 -0.010759493670886076,390,395 -0.011136363636363637,391,396 -0.011511335012594458,392,397 -0.011708542713567839,393,398 -0.01213032581453634,394,399 -0.012350000000000002,395,400 -0.012493765586034912,396,401 -0.01271144278606965,397,402 -0.012903225806451615,397,403 -0.01311881188118812,398,404 -0.01365432098765432,399,405 -0.01396551724137931,400,406 -0.014226044226044225,401,407 -0.01431372549019608,402,408 -0.01449877750611247,403,409 -0.014878048780487804,404,410 -0.01506082725060827,405,411 -0.015364077669902911,405,412 -0.01559322033898305,406,413 -0.015869565217391305,407,414 -0.01621686746987952,408,415 -0.0165625,409,416 -0.016906474820143885,410,417 -0.01715311004784689,411,418 -0.01730310262529833,411,419 -0.017476190476190475,412,420 -0.017790973871733964,413,421 -0.01796208530805687,414,422 -0.01813238770685579,415,423 -0.01830188679245283,416,424 -0.018494117647058824,416,425 -0.01868544600938967,417,426 -0.01892271662763466,418,427 -0.019275700934579438,419,428 -0.019487179487179488,420,429 -0.019953488372093025,421,430 -0.020208816705336426,422,431 -0.020486111111111108,423,432 -0.020785219399538105,423,433 -0.021013824884792625,424,434 -0.021379310344827585,424,435 -0.021582568807339452,425,436 -0.021807780320366132,426,437 -0.02198630136986301,427,438 -0.02214123006833713,428,439 -0.022386363636363635,429,440 -0.02258503401360544,430,441 -0.022805429864253393,431,442 -0.02304740406320542,432,443 -0.023288288288288283,433,444 -0.02357303370786517,434,445 -0.02390134529147982,435,446 -0.024093959731543622,436,447 -0.024375,437,448 -0.02465478841870824,437,449 -0.024777777777777777,438,450 -0.025121951219512197,439,451 -0.02533185840707965,440,452 -0.025805739514348787,441,453 -0.026035242290748897,442,454 -0.026351648351648355,443,455 -0.02660087719298246,444,456 -0.026936542669584247,445,457 -0.027161572052401745,446,458 -0.027429193899782135,447,459 -0.027608695652173915,447,460 -0.02785249457700651,447,461 -0.02800865800865801,448,462 -0.028164146868250542,448,463 -0.028405172413793103,449,464 -0.02870967741935484,449,465 -0.029034334763948497,449,466 -0.029464668094218417,450,467 -0.02980769230769231,451,468 -0.02997867803837953,452,469 -0.030148936170212765,453,470 -0.03040339702760085,454,471 -0.030529661016949153,455,472 -0.030739957716701904,456,473 -0.03090717299578059,457,474 -0.031178947368421053,457,475 -0.031365546218487396,458,476 -0.031635220125786165,459,477 -0.03200836820083682,460,478 -0.032192066805845514,461,479 -0.03233333333333333,462,480 -0.03247401247401247,462,481 -0.032614107883817425,463,482 -0.032815734989648036,464,483 -0.032892561983471076,465,484 -0.03309278350515464,465,485 -0.03335390946502057,465,486 -0.03359342915811088,466,487 -0.03383196721311475,467,488 -0.033946830265848674,468,489 -0.03424489795918367,468,490 -0.034541751527494904,469,491 -0.03483739837398374,470,492 -0.03509127789046653,471,493 -0.03536437246963563,472,494 -0.035454545454545454,473,495 -0.03570564516129032,474,496 -0.03587525150905432,475,497 -0.03590361445783133,476,498 -0.036152304609218436,476,499 -0.03632,477,500 -0.03648702594810379,477,501 -0.03673306772908366,477,502 -0.036938369781312125,477,503 -0.03716269841269841,478,504 -0.037445544554455444,479,505 -0.03762845849802371,480,506 -0.03785009861932939,481,507 -0.03801181102362205,482,508 -0.03819253438113949,482,509 -0.03831372549019608,482,510 -0.03853228962818003,483,511 -0.03869140625,484,512 -0.03886939571150097,485,513 -0.03892996108949416,486,514 -0.039242718446601946,487,515 -0.039321705426356594,488,516 -0.03951644100580271,489,517 -0.03971042471042471,490,518 -0.03992292870905587,491,519 -0.040211538461538465,492,520 -0.04047984644913628,493,521 -0.04067049808429119,494,522 -0.040917782026768636,495,523 -0.041106870229007636,495,524 -0.04133333333333334,496,525 -0.0415019011406844,497,526 -0.041840607210626185,497,527 -0.04206439393939394,498,528 -0.04221172022684311,498,529 -0.04241509433962265,499,530 -0.04263653483992467,499,531 -0.042894736842105256,500,532 -0.04313320825515948,501,533 -0.04331460674157303,502,534 -0.043514018691588795,503,535 -0.04375,504,536 -0.04392923649906891,505,537 -0.044089219330855016,506,538 -0.04430426716141001,507,539 -0.0445925925925926,508,540 -0.04478743068391867,509,541 -0.04488929889298893,510,542 -0.04517495395948434,511,543 -0.04544117647058824,512,544 -0.04577981651376147,512,545 -0.046007326007326,513,546 -0.046234003656307136,514,547 -0.04651459854014599,515,548 -0.04673952641165756,516,549 -0.047,517,550 -0.047313974591651535,517,551 -0.047608695652173905,518,552 -0.04770343580470162,519,553 -0.04783393501805055,520,554 -0.04801801801801801,521,555 -0.04823741007194245,522,556 -0.04845601436265709,523,557 -0.048673835125448026,523,558 -0.04883720930232558,524,559 -0.049,525,560 -0.04932263814616755,526,561 -0.04955516014234876,527,562 -0.04982238010657193,528,563 -0.0500709219858156,529,564 -0.05021238938053097,530,565 -0.05042402826855124,531,566 -0.05056437389770723,531,567 -0.05073943661971831,532,568 -0.05084358523725835,533,569 -0.05108771929824561,534,570 -0.05129597197898424,535,571 -0.05148601398601398,535,572 -0.05158813263525305,536,573 -0.051707317073170736,537,574 -0.05184347826086956,537,575 -0.05197916666666666,538,576 -0.05214904679376083,539,577 -0.0522318339100346,540,578 -0.052383419689119165,541,579 -0.0525,541,580 -0.05270223752151462,542,581 -0.05286941580756013,542,582 -0.05298456260720411,543,583 -0.05316780821917808,544,584 -0.05338461538461539,544,585 -0.053617747440273034,544,586 -0.053781942078364564,545,587 -0.05404761904761905,546,588 -0.05422750424448217,546,589 -0.054491525423728815,547,590 -0.054619289340101525,547,591 -0.05486486486486486,547,592 -0.05507588532883642,548,593 -0.05523569023569024,549,594 -0.05546218487394958,550,595 -0.05563758389261744,551,596 -0.05577889447236181,552,597 -0.05590301003344481,553,598 -0.05619365609348915,554,599 -0.056400000000000006,555,600 -0.05658901830282862,555,601 -0.05679401993355482,555,602 -0.05706467661691542,556,603 -0.057284768211920536,557,604 -0.05743801652892563,558,605 -0.05773927392739273,559,606 -0.05802306425041186,559,607 -0.058207236842105256,560,608 -0.058407224958949094,560,609 -0.05854098360655738,560,610 -0.05870703764320785,561,611 -0.058807189542483665,562,612 -0.059004893964110926,562,613 -0.05920195439739413,562,614 -0.05938211382113821,563,615 -0.05965909090909091,564,616 -0.05988654781199352,564,617 -0.06006472491909385,564,618 -0.060339256865912766,565,619 -0.06046774193548387,566,620 -0.06059581320450885,567,621 -0.06070739549839228,567,622 -0.06088282504012841,568,623 -0.0610576923076923,569,624 -0.061216,570,625 -0.06137380191693291,571,626 -0.061594896331738445,572,627 -0.06178343949044587,572,628 -0.061971383147853734,573,629 -0.062174603174603174,574,630 -0.06240887480190174,575,631 -0.06262658227848102,576,632 -0.06276461295418642,577,633 -0.06296529968454259,578,634 -0.06321259842519686,579,635 -0.06345911949685534,580,636 -0.06364207221350078,581,637 -0.06380877742946708,582,638 -0.06406885758998436,583,639 -0.06421875,584,640 -0.06449297971918877,585,641 -0.0646417445482866,585,642 -0.0648367029548989,586,643 -0.06509316770186335,586,644 -0.06514728682170542,587,645 -0.06540247678018576,588,646 -0.06559505409582689,588,647 -0.06578703703703705,588,648 -0.06590138674884438,589,649 -0.06612307692307691,589,650 -0.06629800307219663,589,651 -0.06639570552147239,590,652 -0.06652373660030628,591,653 -0.066697247706422,592,654 -0.0668854961832061,592,655 -0.0670579268292683,593,656 -0.06729071537290715,594,657 -0.06747720364741641,595,658 -0.06769347496206374,596,659 -0.06786363636363636,596,660 -0.06797276853252647,597,661 -0.06809667673716012,597,662 -0.06826546003016593,598,663 -0.06849397590361446,599,664 -0.06869172932330826,600,665 -0.06888888888888889,600,666 -0.06907046476761619,601,667 -0.06919161676646707,601,668 -0.0694170403587444,602,669 -0.06964179104477612,603,670 -0.06980625931445603,604,671 -0.06995535714285714,605,672 -0.07017830609212482,606,673 -0.07038575667655786,607,674 -0.07050370370370371,608,675 -0.07071005917159763,609,676 -0.07078286558345642,609,677 -0.070929203539823,610,678 -0.0711340206185567,611,679 -0.07125,612,680 -0.07145374449339208,612,681 -0.071524926686217,613,682 -0.07165446559297219,614,683 -0.07181286549707602,615,684 -0.07194160583941606,616,685 -0.0721137026239067,616,686 -0.07231441048034934,617,687 -0.07247093023255814,617,688 -0.07272859216255442,618,689 -0.07292753623188405,619,690 -0.07309696092619392,620,691 -0.07332369942196532,621,692 -0.07347763347763347,621,693 -0.07360230547550434,621,694 -0.0737841726618705,622,695 -0.0739655172413793,623,696 -0.0742180774748924,624,697 -0.07434097421203438,625,698 -0.07456366237482118,626,699 -0.07474285714285714,627,700 -0.07483594864479316,628,701 -0.07504273504273504,629,702 -0.07530583214793742,629,703 -0.07546875,630,704 -0.07567375886524824,631,705 -0.07597733711048159,631,706 -0.07609618104667609,631,707 -0.07618644067796611,632,708 -0.07633286318758815,633,709 -0.07649295774647888,634,710 -0.07661040787623066,635,711 -0.07682584269662922,636,712 -0.07699859747545582,637,713 -0.07714285714285714,638,714 -0.07728671328671328,639,715 -0.0774441340782123,639,716 -0.07764295676429567,640,717 -0.07775766016713093,641,718 -0.07778859527121001,641,719 -0.07783333333333334,642,720 -0.07804438280166436,643,721 -0.07831024930747922,644,722 -0.07840940525587828,645,723 -0.07854972375690608,646,724 -0.0788,647,725 -0.07898071625344354,647,726 -0.07932599724896837,648,727 -0.07949175824175823,649,728 -0.0797119341563786,650,729 -0.07984931506849315,651,730 -0.07999999999999999,652,731 -0.08020491803278688,653,732 -0.08031377899045021,653,733 -0.08046321525885558,654,734 -0.08063945578231292,654,735 -0.08085597826086957,655,736 -0.08103120759837176,656,737 -0.08116531165311652,657,738 -0.0813531799729364,658,739 -0.08154054054054054,659,740 -0.08172739541160594,660,741 -0.08180592991913746,661,742 -0.08197846567967698,662,743 -0.08213709677419356,663,744 -0.08233557046979864,663,745 -0.0825201072386059,664,746 -0.08270414993306559,665,747 -0.08294117647058823,666,748 -0.08309746328437917,666,749 -0.08322666666666667,667,750 -0.08336884154460719,667,751 -0.08347074468085108,668,752 -0.08373173970783533,669,753 -0.08389920424403183,669,754 -0.08405298013245034,670,755 -0.0843121693121693,670,756 -0.08441215323645972,670,757 -0.08461741424802112,671,758 -0.08484848484848484,672,759 -0.08496052631578949,673,760 -0.08505913272010514,674,761 -0.08527559055118111,675,762 -0.08559633027522935,675,763 -0.08577225130890052,675,764 -0.08605228758169936,676,765 -0.08618798955613577,677,766 -0.08632333767926986,678,767 -0.08647135416666668,679,768 -0.086592977893368,680,769 -0.0867012987012987,680,770 -0.0867963683527886,681,771 -0.08694300518134714,682,772 -0.08711513583441138,683,773 -0.08729974160206719,684,774 -0.08739354838709676,685,775 -0.08755154639175258,686,776 -0.08761904761904762,686,777 -0.08777634961439588,687,778 -0.08797175866495507,687,779 -0.08816666666666667,688,780 -0.08825864276568503,689,781 -0.08842710997442456,690,782 -0.08859514687100895,691,783 -0.08876275510204082,692,784 -0.08887898089171976,693,785 -0.08908396946564885,694,786 -0.08914866581956797,695,787 -0.08927664974619288,696,788 -0.08940430925221798,697,789 -0.08959493670886076,698,790 -0.08973451327433628,699,791 -0.08982323232323232,700,792 -0.08989911727616645,701,793 -0.09011335012594458,702,794 -0.09028930817610065,703,795 -0.09055276381909548,703,796 -0.0906900878293601,704,797 -0.09087719298245613,705,798 -0.09102628285356695,706,799 -0.0911625,707,800 -0.09132334581772784,708,801 -0.09153366583541146,709,802 -0.09171855541718553,710,803 -0.09186567164179106,710,804 -0.09196273291925466,710,805 -0.09213399503722083,711,806 -0.09234200743494425,712,807 -0.09248762376237625,713,808 -0.09263288009888752,714,809 -0.09275308641975308,715,810 -0.09288532675708999,716,811 -0.09301724137931036,716,812 -0.09321033210332104,717,813 -0.09339066339066339,717,814 -0.09355828220858896,717,815 -0.09371323529411764,717,816 -0.09386780905752755,718,817 -0.0938997555012225,719,818 -0.09402930402930404,720,819 -0.09426829268292682,721,820 -0.0943605359317905,722,821 -0.09450121654501217,722,822 -0.09471445929526123,723,823 -0.09487864077669902,724,824 -0.09503030303030303,724,825 -0.09515738498789346,725,826 -0.09538089480048367,725,827 -0.09548309178743962,726,828 -0.09568154402895054,726,829 -0.09583132530120482,727,830 -0.09600481347773768,728,831 -0.09615384615384615,729,832 -0.09636254501800721,730,833 -0.09652278177458033,731,834 -0.09663473053892215,731,835 -0.09673444976076555,732,836 -0.09697729988052568,733,837 -0.09714797136038186,734,838 -0.09731823599523243,734,839 -0.09753571428571428,735,840 -0.09771700356718192,735,841 -0.09785035629453681,736,842 -0.0980427046263345,737,843 -0.09822274881516588,738,844 -0.09837869822485207,739,845 -0.09849881796690309,740,846 -0.09865407319952774,741,847 -0.09890330188679247,742,848 -0.09902237926972908,743,849 -0.09920000000000001,744,850 -0.09930669800235017,745,851 -0.09948356807511737,745,852 -0.09968347010550996,746,853 -0.0999063231850117,747,854 -0.1000701754385965,748,855 -0.10022196261682242,748,856 -0.10035005834305717,749,857 -0.10045454545454545,749,858 -0.10058207217694996,750,859 -0.10079069767441862,751,860 -0.10099883855981417,751,861 -0.1011600928074246,752,862 -0.10132097334878332,753,863 -0.10140046296296296,753,864 -0.10160693641618497,754,865 -0.10174364896073904,755,866 -0.10188004613610151,756,867 -0.1020046082949309,757,868 -0.1021403912543153,758,869 -0.10224137931034483,759,870 -0.1023076923076923,760,871 -0.10245412844036697,761,872 -0.10261168384879724,762,873 -0.1027345537757437,763,874 -0.10280000000000002,764,875 -0.1028310502283105,765,876 -0.10296465222348918,765,877 -0.10309794988610477,766,878 -0.10329920364050058,767,879 -0.1034090909090909,768,880 -0.1036095346197503,769,881 -0.10375283446712018,770,882 -0.10389580973952434,771,883 -0.10400452488687784,772,884 -0.10406779661016947,773,885 -0.10420993227990971,773,886 -0.10431792559188274,774,887 -0.1043918918918919,775,888 -0.10443194600674915,776,889 -0.10466292134831459,777,890 -0.1047699214365881,778,891 -0.10492152466367713,779,892 -0.10500559910414334,780,893 -0.10508948545861298,781,894 -0.10529608938547487,782,895 -0.1045348180872,782,896 -0.10401482015040169,783,897 -0.10421600387519935,784,898 -0.10346113658249076,785,899 -0.1036112627605688,786,900 -0.10212641760399208,787,901 -0.10179367069318868,787,902 -0.10112330245168692,787,903 -0.1000136074450205,788,904 -0.10017785969703724,789,905 -0.09955537942649681,790,906 -0.09855231931334497,791,907 -0.09634649111811143,791,908 -0.09286125910626461,792,909 -0.09240957768592377,793,910 -0.08855815690877027,793,911 -0.08606596553985454,794,912 -0.08360086309082902,795,913 -0.08176418319652744,796,914 -0.07798995714908663,797,915 -0.07508351795411808,798,916 -0.07144619478764141,799,917 -0.06726258528536641,799,918 -0.06546201619388593,800,919 -0.06122434847626553,800,920 -0.0582708077140329,800,921 -0.05765847854885271,801,922 -0.055175816738694296,802,923 -0.05239625763927446,803,924 -0.05249552266469193,804,925 -0.046469143733968,805,926 -0.04269255739195379,806,927 -0.04258123441744944,807,928 -0.04187085888521324,807,929 -0.0365056420765173,808,930 -0.03322586105350539,809,931 -0.03208357110313895,809,932 -0.03187057518853484,809,933 -0.03174841950344002,810,934 -0.03086557815469177,811,935 -0.026062422641317612,811,936 -0.026189672162476238,812,937 -0.02522924056751469,813,938 -0.0241797695352993,814,939 -0.0231193975755217,815,940 -0.02213952765761532,816,941 -0.021134521427402353,817,942 -0.02110859450523488,818,943 -0.02109639977229974,818,944 -0.02042026762209941,819,945 -0.019215833411408992,936,946 -0.019168498564416707,936,947 -0.018405070448119,938,948 -0.01836854312703045,939,949 -0.01837123752035287,940,950 -0.018276669038174088,941,951 -0.017303458283156496,941,952 -0.017326271739391098,941,953 -0.017357964405372312,941,954 -0.01738162958645362,941,955 -0.017446020326116064,941,956 -0.01756732223581771,941,957 -0.017669662424820706,941,958 -0.01767873585041813,941,959 -0.017917610695118144,941,960 -0.01801904926561212,941,961 -0.018185761378119492,941,962 -0.018235117826891724,941,963 -0.0182295563684694,943,964 -0.018195894846760926,945,965 -0.018044577943919508,945,966 -0.018234699404740016,947,967 -0.018375244447117363,949,968 -0.018233921318947,950,969 -0.01802888056569636,950,970 -0.018130787899812074,950,971 -0.018184623005301756,950,972 -0.01809128595300313,950,973 -0.018166467314058535,950,974 -0.018173998268722652,950,975 -0.018218257126301176,950,976 -0.01820571738479154,950,977 -0.018488335385056925,952,978 -0.018499913235813972,953,979 -0.01840550015606855,953,980 -0.018310833595594943,954,981 -0.018404642266583792,954,982 -0.018388911478957205,956,983 -0.018416066336376328,956,984 -0.018442410895488755,959,985 -0.018604373431642826,960,986 -0.018708058041402086,963,987 -0.01847587622902412,963,988 -0.018469633412104364,963,989 -0.018463661491136363,963,990 -0.018537377371593496,963,991 -0.01853020565811647,963,992 -0.018473193395548194,963,993 -0.018510201803573597,963,994 -0.018557901735127846,963,995 -0.0186414127577045,963,996 -0.018649704413381808,963,997 -0.01851779482705164,963,998 -0.018261617648642887,965,999 -0.018370807203798342,967,1000 -0.018512517501978396,970,1001 -0.018517540759701873,971,1002 -0.018801806396407317,973,1003 -0.018817403781636783,974,1004 -0.018885136603187313,975,1005 -0.01883689064678924,975,1006 -0.01893641923931456,977,1007 -0.018904649719663345,978,1008 -0.01871770505936041,978,1009 -0.01879711733379907,978,1010 -0.019004672564666203,978,1011 -0.019143838616093832,978,1012 -0.01913932054716869,980,1013 -0.019090384300727802,980,1014 -0.0191083832499933,983,1015 -0.018864517545892398,983,1016 -0.019014091447043222,983,1017 -0.01890269278973934,986,1018 -0.018750985564669954,986,1019 -0.01869989549019309,987,1020 -0.018734171697678294,987,1021 -0.01883555127822943,987,1022 -0.019073940812790256,987,1023 -0.018971651096214185,990,1024 -0.018971651096214185,990,1024 +0.0,362,362 +0.0,363,363 +0.0,364,364 +0.0,365,365 +0.0,366,366 +0.0,367,367 +0.0,368,368 +0.0,369,369 +0.0,370,370 +0.0,371,371 +0.0,372,372 +0.0,373,373 +0.0,374,374 +0.0,375,375 +0.0,376,376 +0.0,377,377 +0.0,378,378 +0.00002638522427440633,379,379 +0.00002631578947368421,380,380 +0.000026246719160104988,381,381 +0.00002617801047120419,382,382 +0.000026109660574412533,383,383 +0.000026041666666666665,384,384 +0.000025974025974025975,385,385 +0.000025906735751295337,386,386 +0.00002583979328165375,387,387 +0.000025773195876288658,388,388 +0.000025706940874035987,389,389 +0.00002564102564102564,390,390 +0.000025575447570332482,391,391 +0.00002551020408163265,392,392 +0.000025445292620865142,393,393 +0.000025380710659898476,394,394 +0.000025316455696202533,395,395 +0.000025252525252525256,396,396 +0.000025188916876574308,397,397 +0.000025125628140703518,398,398 +0.000025062656641604008,399,399 +0.000025,400,400 +0.000024937655860349125,401,401 +0.000024875621890547263,402,402 +0.000024813895781637717,403,403 +0.000024752475247524754,404,404 +0.000024691358024691357,405,405 +0.000024630541871921184,406,406 +0.00002457002457002457,407,407 +0.000024509803921568626,408,408 +0.000024449877750611248,409,409 +0.000024390243902439026,410,410 +0.000024330900243309002,411,411 +0.000024271844660194173,412,412 +0.00002421307506053269,413,413 +0.000024154589371980676,414,414 +0.00002570017487383359,415,415 +0.00015603667144674754,416,416 +0.0002850754870293434,417,417 +0.00041411456331717306,418,418 +0.0005431538984433381,419,419 +0.0006721934905588614,420,420 +0.0008012333378328678,421,421 +0.0009302734384511635,422,422 +0.0010593137906167172,423,423 +0.0011883543925503795,424,424 +0.0013173952424885447,425,425 +0.0014464363386847085,426,426 +0.0015135879972552496,427,427 +0.0015475365920568618,428,428 +0.0015519986183084279,429,429 +0.0015532554493652095,430,430 +0.0016959590622140997,431,431 +0.0016780467898746094,432,432 +0.0014936809509292987,432,433 +0.001535814793138929,434,434 +0.0015324881934801705,434,435 +0.0016254451696662404,435,436 +0.0017248420068065368,436,437 +0.0017096098125990813,437,438 +0.001798858639756524,438,439 +0.0018706936381616855,439,440 +0.001936969437234038,440,441 +0.001951457905988312,441,442 +0.0019494368442655374,442,443 +0.0020458775128461538,443,444 +0.0020556613769692525,444,445 +0.0020964037674313174,445,446 +0.0021333290733516865,446,447 +0.0021036874243377172,447,448 +0.0020466445260414134,448,449 +0.002086513327200109,449,450 +0.002252981040856384,451,451 +0.0022893560149292312,452,452 +0.0022966092524116287,453,453 +0.0023039825902024746,454,454 +0.002387945533945134,455,455 +0.0025018141817993666,456,456 +0.0024931095139669422,457,457 +0.0025749884276818668,458,458 +0.0026918347530905207,459,459 +0.00269853013735037,459,460 +0.002803717931278234,460,461 +0.0029165896378834065,461,462 +0.002948672285536521,461,463 +0.002868801152623487,462,464 +0.0029782070003366644,462,465 +0.003012713346331289,462,466 +0.0030646576883578826,463,467 +0.003198536395907451,464,468 +0.0032330145649523286,465,469 +0.003250099621706078,466,470 +0.0032445102563196586,468,471 +0.00322474173153384,469,472 +0.0032608273292730507,470,473 +0.0033136075776813113,471,474 +0.003354949698231974,472,475 +0.0034127483994801353,473,476 +0.003435770362205482,474,477 +0.003366492089506571,475,478 +0.0033586814937263524,476,479 +0.0033372247413835533,477,480 +0.0033520111833811473,478,481 +0.0033222088607912166,479,482 +0.00340703198886213,480,483 +0.0035260492206453005,481,484 +0.0035153153250243752,483,485 +0.0035939618371546565,483,486 +0.0037179799343981905,484,487 +0.003736891403974948,485,488 +0.003730111522069866,486,489 +0.003810114620415126,486,490 +0.003852707339967162,487,491 +0.003970765616728539,488,492 +0.0039986298839276855,489,493 +0.004054435467150277,490,494 +0.004066561767861176,491,495 +0.004100213382713943,492,496 +0.004112071554873862,493,497 +0.004099291428880447,494,498 +0.004175127921123293,494,499 +0.004113003834051654,495,500 +0.0040782239473508035,495,501 +0.004114504549722979,496,502 +0.004037608561946382,496,503 +0.004147127067148211,498,504 +0.004228803389357505,499,505 +0.004245762535614273,500,506 +0.004296581852149161,501,507 +0.004319861156747971,502,508 +0.004330221492886771,503,509 +0.004403936556577883,503,510 +0.004435611406885395,504,511 +0.00445247994493954,505,512 +0.004469416776966909,506,513 +0.004446955668635363,507,514 +0.004493981275353954,508,515 +0.004495385271948872,509,516 +0.004502332122721958,510,517 +0.004565687833924102,512,518 +0.004684855246861729,513,519 +0.004687301307950409,514,520 +0.004645176552308958,515,521 +0.004638357764461186,516,522 +0.004547670513213745,517,523 +0.004564608214302561,517,524 +0.004680422825169689,518,525 +0.004776338702704956,519,526 +0.004805153564198871,520,527 +0.004889235408733689,521,528 +0.004891847452947954,522,529 +0.0048947597466319735,523,530 +0.004939022858878396,523,531 +0.005035519624882106,525,532 +0.005008376231244649,526,533 +0.0049318337743633756,527,534 +0.004910110854509174,528,535 +0.004836415742120449,529,536 +0.004867960750327593,530,537 +0.004885380708591732,531,538 +0.004888921736244301,532,539 +0.00499187827274875,533,540 +0.0050259853226297625,534,541 +0.005034758994640209,535,542 +0.005109664754341842,536,543 +0.005211672168853051,538,544 +0.005130738682539857,539,545 +0.005096963266765477,540,546 +0.005049832913343623,541,547 +0.005062325809571084,542,548 +0.005042936085731619,543,549 +0.005068634435418089,544,550 +0.005121440362403549,545,551 +0.005170672307061497,546,552 +0.005165690840601245,547,553 +0.0051683774874951485,548,554 +0.005140619822926455,549,555 +0.005192413341490088,551,556 +0.005141901171765986,552,557 +0.005189240129355301,553,558 +0.005247416103217301,554,559 +0.005201650607586808,555,560 +0.005300419888626721,556,561 +0.005283840822652312,557,562 +0.005202281668236718,558,563 +0.005229720953471732,559,564 +0.0052185080153503,560,565 +0.005245872875164161,561,566 +0.005292534294242347,563,567 +0.005324671327091493,564,568 +0.005377321057958795,565,569 +0.005318072388677469,566,570 +0.005303397270187753,567,571 +0.005422560022024911,567,572 +0.005396927969537019,568,573 +0.005433642579295857,569,574 +0.005405492955207818,570,575 +0.0054589402154071424,571,576 +0.005486862364942466,572,577 +0.005508174321846098,573,578 +0.005541869639658532,575,579 +0.0055311907248245884,575,580 +0.0055706147098834435,576,581 +0.005678631739667166,577,582 +0.005657387733814772,578,583 +0.00563600352169678,579,584 +0.005540657759161185,580,585 +0.005542569148113797,580,586 +0.005532168058761948,581,587 +0.005488368233968299,582,588 +0.0054342532812478,583,589 +0.005389551689552936,584,590 +0.005408911792532988,584,591 +0.005407537062783605,584,592 +0.005386329142361857,586,593 +0.005383668727336892,587,594 +0.005380968548783921,588,595 +0.005363188096117635,589,596 +0.005321272237619441,590,597 +0.005435416698025439,591,598 +0.005345466791367041,592,599 +0.0053943269094326755,593,600 +0.005429738020017124,593,601 +0.005386930919022608,593,602 +0.005516977949571523,594,603 +0.005467531121603717,595,604 +0.005414970646565156,597,605 +0.0054167813732904245,598,606 +0.0053869985325827605,598,607 +0.005383720578764883,599,608 +0.005417306682643041,599,609 +0.005480382117958899,600,610 +0.005464490907897852,601,611 +0.005401472733139277,602,612 +0.005412702688468216,602,613 +0.005451010848703676,602,614 +0.005406226164229159,603,615 +0.005446673145028309,604,616 +0.005348107890291527,604,617 +0.0053861547453339445,604,618 +0.00541450602111774,605,619 +0.005497237189139881,606,620 +0.005492077422500312,608,621 +0.005570899483870734,609,622 +0.00558279187771503,610,623 +0.005510588413609248,611,624 +0.005471002337272486,612,625 +0.005470247912681352,613,626 +0.005501673879392618,614,627 +0.005487283251295798,615,628 +0.0055436142069517835,616,629 +0.00551818229022941,617,630 +0.005513488622299119,619,631 +0.005533943907028849,620,632 +0.0055519773380609365,621,633 +0.0055729458681913506,622,634 +0.005619418208416576,623,635 +0.005599854877450529,624,636 +0.005523828730605926,625,637 +0.00552344466126885,626,638 +0.005558975535000113,627,639 +0.005533718851542644,628,640 +0.0054982537155903064,630,641 +0.0054458905322989325,631,642 +0.005472344885309235,632,643 +0.0054663426937577265,632,644 +0.005490092702056366,633,645 +0.005439483958928828,634,646 +0.005450802523749674,634,647 +0.005472330377583235,634,648 +0.005435591493582465,635,649 +0.0055343800951596,636,650 +0.0056033645248960194,636,651 +0.005640404242439172,637,652 +0.005703210404665499,638,653 +0.005654058622767174,640,654 +0.005718647116375332,640,655 +0.005698387544196255,641,656 +0.005625949876416618,642,657 +0.00565406816594179,643,658 +0.005638031462135804,644,659 +0.005626047761450064,644,660 +0.005600539548123502,645,661 +0.00561872066431723,646,662 +0.005571311372205966,647,663 +0.005591620405518389,648,664 +0.005415109956558826,650,665 +0.005423822088721736,650,666 +0.005473904741705837,651,667 +0.00558948910881655,651,668 +0.005642562607478848,652,669 +0.005685758509545291,653,670 +0.006190664597542818,654,671 +0.006657102552315319,655,672 +0.007136395522928649,656,673 +0.007488053841877273,657,674 +0.00783624447439453,658,675 +0.008307145760211975,660,676 +0.008748415900234457,661,677 +0.009272375877495574,662,678 +0.009835153365582662,663,679 +0.010102528675696144,664,680 +0.010158391787766143,665,681 +0.01062531360771246,666,682 +0.011068228957569443,667,683 +0.011185768423011458,669,684 +0.011224157353722307,670,685 +0.011055550761378423,670,686 +0.011225214245834815,671,687 +0.011225941290393154,672,688 +0.011115443976144612,673,689 +0.0110692417854716,674,690 +0.01105826920894465,676,691 +0.010958851275610188,677,692 +0.010845548637577673,679,693 +0.0110756975713818,680,694 +0.010924138961647362,681,695 +0.010954943536257344,681,696 +0.011026356031217417,683,697 +0.01102787813528566,684,698 +0.011083354710519912,686,699 +0.011153649802912852,687,700 +0.011277485908388537,688,701 +0.011413652193775754,690,702 +0.011405673239669923,691,703 +0.011394102116450762,693,704 +0.011506941426549845,694,705 +0.011496474377804704,695,706 +0.011512534295333271,697,707 +0.011581944828239678,698,708 +0.011621725999820509,698,709 +0.011521587499383113,700,710 +0.011601259492405355,701,711 +0.011560736246536647,702,712 +0.011598824465952416,702,713 +0.011640004495359966,704,714 +0.011580913701465483,705,715 +0.01149902409430509,707,716 +0.011402687672291231,707,717 +0.011400229554757646,708,718 +0.011497964951406744,708,719 +0.011455818239061173,710,720 +0.01147353114876786,711,721 +0.011534839692722043,712,722 +0.01151700184141894,714,723 +0.01138186223712185,715,724 +0.01131784803320946,717,725 +0.011265989819620605,717,726 +0.011311977698237862,718,727 +0.011276243279191231,719,728 +0.01124321714945761,721,729 +0.011059221372591396,722,730 +0.011126015466819555,722,731 +0.011086995029333115,724,732 +0.011201285531276094,724,733 +0.011234919036414324,725,734 +0.011293706840161297,725,735 +0.01117762655643817,727,736 +0.01104489267928032,727,737 +0.011025297438469982,728,738 +0.011119473773910126,729,739 +0.011170745502692257,731,740 +0.011159494553765583,732,741 +0.011332693967670155,732,742 +0.011277203987211796,734,743 +0.011105887749147192,734,744 +0.011177891762560543,734,745 +0.011231149363666386,735,746 +0.011389058171647206,737,747 +0.011393077738506579,737,748 +0.011263679345651574,738,749 +0.011254872907257159,739,750 +0.011193502204863974,739,751 +0.011363119266069676,741,752 +0.011353438409781157,742,753 +0.011232752363411352,744,754 +0.011117610831655154,745,755 +0.011079147840447105,745,756 +0.011136786034926113,747,757 +0.011063583328861237,748,758 +0.010856530447812061,749,759 +0.010945486685938416,751,760 +0.010854615871714041,751,761 +0.010904982035861925,751,762 +0.010984007656782237,751,763 +0.011005190018921805,751,764 +0.011030520614938913,752,765 +0.011151597438409384,754,766 +0.011211859941752602,755,767 +0.011349361177680116,755,768 +0.011358748950544055,757,769 +0.011442170359861234,757,770 +0.01145828111146183,757,771 +0.011362662704626754,758,772 +0.011463706162418305,760,773 +0.011525668707754027,761,774 +0.011450240515990228,763,775 +0.011428647841332804,764,776 +0.011547374310366872,765,777 +0.011678047102644352,767,778 +0.011598497103987682,767,779 +0.011665619043931843,768,780 +0.011745881251499179,770,781 +0.011833923885255098,771,782 +0.011753153222574881,773,783 +0.011835274060904549,774,784 +0.011883187275554263,776,785 +0.011707879689875203,777,786 +0.011578072431442949,779,787 +0.011492011950001841,780,788 +0.011482538228332135,781,789 +0.011477452059038598,783,790 +0.011515044163951634,784,791 +0.011627494135569953,786,792 +0.011748744240139443,787,793 +0.011790373039060022,787,794 +0.011976637460763315,789,795 +0.011925102782700689,789,796 +0.01186609380065477,790,797 +0.0118875130379036,792,798 +0.01203241790124384,793,799 +0.011990847155404777,795,800 +0.011911937703317197,796,801 +0.01184184075575546,798,802 +0.01172728456075968,799,803 +0.011563673237447841,801,804 +0.011614084250579424,801,805 +0.011718785906952316,802,806 +0.011866956582079608,802,807 +0.011972319026414345,804,808 +0.011987322295699885,805,809 +0.011855492984427486,807,810 +0.011723749282918297,808,811 +0.01169638226525343,808,812 +0.011736781371097455,809,813 +0.011821699471460625,811,814 +0.011766991898536187,812,815 +0.011804020244831565,812,816 +0.011782698652244563,814,817 +0.011777190532068374,814,818 +0.011820774789320239,815,819 +0.01186054185639349,817,820 +0.01193474040244549,817,821 +0.011978955799195804,817,822 +0.011888261221653545,818,823 +0.012005763393366871,820,824 +0.01173277467646756,821,825 +0.011691845118388383,823,826 +0.011791238296052354,823,827 +0.01173078283427249,823,828 +0.011692680645919717,823,829 +0.011737413856317618,824,830 +0.011697973809709036,826,831 +0.011783821552836854,827,832 +0.011816778935385654,829,833 +0.0117090423643472,830,834 +0.011813918519345223,830,835 +0.0118467626337012,832,836 +0.011844036880968769,833,837 +0.01187230964142119,835,838 +0.011847057819113278,835,839 +0.011800782749135274,836,840 +0.011747589888401761,836,841 +0.011718327725058358,838,842 +0.011717273539167223,838,843 +0.011601925903238608,839,844 +0.011649422742812625,841,845 +0.011497363634364625,842,846 +0.011565539521967321,844,847 +0.011541257762028396,845,848 +0.011634984340847643,847,849 +0.011727348854639186,848,850 +0.011744226554885853,850,851 +0.011595505042652991,850,852 +0.011499597245854094,852,853 +0.011499597245854094,852,853 diff --git a/measure_variant/reference_report.csv b/measure_variant/reference_report.csv index 01c3137..56aef11 100644 --- a/measure_variant/reference_report.csv +++ b/measure_variant/reference_report.csv @@ -255,772 +255,601 @@ relative_error,estimated_cardinality,cardinality 0.0,254,254 0.0,255,255 0.0,256,256 -0.000311284046692607,257,257 -0.0007751937984496124,258,258 -0.001081081081081081,259,259 -0.0012692307692307692,260,260 -0.0014942528735632182,261,261 -0.0017175572519083971,262,262 -0.002015209125475285,263,263 -0.0021969696969696972,264,264 -0.0025283018867924534,265,265 -0.002744360902255639,266,266 -0.003183520599250936,267,267 -0.0035074626865671636,268,268 -0.0039776951672862455,269,269 -0.004185185185185185,270,270 -0.0043542435424354245,271,271 -0.004779411764705882,272,272 -0.004945054945054945,273,273 -0.00551094890510949,274,274 -0.005781818181818182,275,275 -0.00605072463768116,276,276 -0.0061010830324909745,277,277 -0.006510791366906476,278,278 -0.006666666666666667,279,279 -0.0070714285714285705,280,280 -0.007580071174377224,281,281 -0.008049645390070921,282,282 -0.008233215547703182,283,283 -0.008450704225352112,284,284 -0.00863157894736842,285,285 -0.008811188811188812,286,286 -0.009128919860627178,287,287 -0.009409722222222222,288,288 -0.009653979238754325,289,289 -0.00989655172413793,290,290 -0.01,290,291 -0.010342465753424656,291,292 -0.010511945392491468,292,293 -0.010680272108843536,293,294 -0.011118644067796607,294,295 -0.011418918918918919,295,296 -0.011818181818181818,296,297 -0.012114093959731544,297,298 -0.012474916387959866,298,299 -0.0128,298,300 -0.013156146179401994,298,301 -0.01337748344370861,299,302 -0.01353135313531353,300,303 -0.01375,301,304 -0.014032786885245901,302,305 -0.01437908496732026,303,306 -0.014820846905537456,304,307 -0.015,305,308 -0.015113268608414238,306,309 -0.01532258064516129,307,310 -0.015562700964630225,308,311 -0.015897435897435898,309,312 -0.016166134185303514,309,313 -0.016528662420382166,310,314 -0.01685714285714286,311,315 -0.01708860759493671,311,316 -0.017318611987381702,312,317 -0.01754716981132076,313,318 -0.017868338557993732,314,319 -0.018031250000000002,315,320 -0.018161993769470405,316,321 -0.018354037267080747,317,322 -0.0186687306501548,318,323 -0.018950617283950616,319,324 -0.019230769230769232,320,325 -0.019417177914110427,321,326 -0.019663608562691132,322,327 -0.01996951219512195,323,328 -0.02012158054711246,324,329 -0.02039393939393939,325,330 -0.020604229607250755,326,331 -0.02078313253012048,326,332 -0.0209009009009009,327,333 -0.021017964071856285,328,334 -0.02137313432835821,329,335 -0.021726190476190475,330,336 -0.02198813056379822,330,337 -0.022366863905325444,331,338 -0.022566371681415932,332,339 -0.02276470588235294,332,340 -0.023020527859237534,333,341 -0.023362573099415203,334,342 -0.023586005830903787,335,343 -0.023982558139534885,336,344 -0.024260869565217388,336,345 -0.024421965317919073,337,346 -0.024610951008645535,338,347 -0.024741379310344824,339,348 -0.025042979942693413,340,349 -0.025199999999999997,341,350 -0.02544159544159544,342,351 -0.025795454545454545,343,352 -0.02597733711048159,344,353 -0.026186440677966098,345,354 -0.026422535211267605,346,355 -0.02657303370786517,347,356 -0.02677871148459384,348,357 -0.027011173184357543,349,358 -0.027325905292479115,350,359 -0.02747222222222222,351,360 -0.027590027700831028,352,361 -0.027845303867403314,353,362 -0.028209366391184574,353,363 -0.028434065934065934,354,364 -0.02865753424657534,354,365 -0.02896174863387978,355,366 -0.029100817438692098,356,367 -0.029211956521739132,357,368 -0.029376693766937665,358,369 -0.029702702702702703,359,370 -0.029973045822102425,360,371 -0.030349462365591398,360,372 -0.030616621983914207,361,373 -0.03093582887700535,362,374 -0.031253333333333334,363,375 -0.0314095744680851,364,376 -0.031750663129973475,365,377 -0.0319047619047619,366,378 -0.032216358839050135,367,379 -0.032578947368421055,368,380 -0.03283464566929134,368,381 -0.0331151832460733,369,382 -0.03328981723237598,370,383 -0.033541666666666664,371,384 -0.033662337662337664,372,385 -0.0339119170984456,373,386 -0.034160206718346256,374,387 -0.034278350515463914,375,388 -0.03457583547557841,376,389 -0.0348974358974359,377,390 -0.03501278772378517,378,391 -0.03520408163265306,378,392 -0.03539440203562341,379,393 -0.03573604060913706,380,394 -0.036000000000000004,381,395 -0.03631313131313132,382,396 -0.036624685138539045,383,397 -0.03675879396984925,384,398 -0.037117794486215536,385,399 -0.03744248318589441,386,400 -0.03742296720000959,387,401 -0.037502327253817344,388,402 -0.03758601206021719,388,403 -0.03758515107046655,389,404 -0.0374367903043635,390,405 -0.037726118837142116,391,406 -0.03719971697180939,392,407 -0.036898372912489485,393,408 -0.03549844875832345,398,409 -0.034462414553562665,399,410 -0.03307151122444478,401,411 -0.03113868970493531,401,412 -0.029369349565675655,402,413 -0.02736771940399005,404,414 -0.02615223102140765,405,415 -0.024972864699618506,405,416 -0.02338498878115298,405,417 -0.021348403839583367,407,418 -0.02037723836699482,407,419 -0.020130558809819395,408,420 -0.01939501713663392,410,421 -0.01872969194668277,411,422 -0.018550286375095943,413,423 -0.018313633539984844,414,424 -0.01814007569629659,414,425 -0.017756801755558924,416,426 -0.017546333013037402,417,427 -0.017700761056705643,419,428 -0.01782200841051282,420,429 -0.017665200137334722,420,430 -0.017549442286845945,422,431 -0.017614220867342007,423,432 -0.01743362343505566,423,433 -0.01746954781924847,425,434 -0.017857158054499868,425,435 -0.017813885665068422,426,436 -0.01786167612247259,428,437 -0.01748771206078505,429,438 -0.017612678419709957,431,439 -0.017472616954530645,432,440 -0.01730124501983472,434,441 -0.017316687253244326,435,442 -0.017496698581814577,437,443 -0.0174804615333821,438,444 -0.017263456321604823,440,445 -0.01738736473039759,442,446 -0.017655898084601506,442,447 -0.017589337523656944,443,448 -0.017853117502762705,443,449 -0.01771874370792116,445,450 -0.01773086691891088,446,451 -0.017523633025223424,446,452 -0.017477753921644686,448,453 -0.017610086394812433,449,454 -0.01775488003868706,449,455 -0.017666041390596476,451,456 -0.017631583540992573,451,457 -0.017536620183856134,451,458 -0.01747523286758909,452,459 -0.017541046108672066,452,460 -0.017503625361070408,452,461 -0.017530788336108105,454,462 -0.017639963798902,454,463 -0.0174932046656221,455,464 -0.01754325141856359,455,465 -0.01750111533029628,455,466 -0.017343835516107832,455,467 -0.017714096542085285,457,468 -0.01753819483812832,459,469 -0.017274200071516463,460,470 -0.017147149102873575,462,471 -0.016996190382036543,463,472 -0.017085779969840037,465,473 -0.01722362030795054,465,474 -0.01696102558435435,465,475 -0.017136539149316374,466,476 -0.017253979076320383,468,477 -0.017314402802289464,470,478 -0.01750322649164958,471,479 -0.017477466939029473,473,480 -0.01740866521492497,473,481 -0.01742456054909341,474,482 -0.01747241828000072,476,483 -0.017452054498105253,478,484 -0.01749680308042444,478,485 -0.01726064863173021,478,486 -0.01719085510048335,479,487 -0.01704497908232387,479,488 -0.016729979492578134,479,489 -0.016866240171488595,479,490 -0.016880393909275072,479,491 -0.016942381728697234,481,492 -0.016686394150737482,482,493 -0.016500981680256474,484,494 -0.01672055191914006,486,495 -0.016493651579148075,487,496 -0.01659359443209764,489,497 -0.0163585302141017,490,498 -0.0164372640840438,490,499 -0.016613589792768016,492,500 -0.016645025245335364,492,501 -0.016605092872485846,492,502 -0.016442814183082088,492,503 -0.016545022702770844,494,504 -0.016707605300071964,495,505 -0.016609462779993027,497,506 -0.016612335139688485,497,507 -0.01661624686567794,499,508 -0.016454986834382634,499,509 -0.016449410033764357,499,510 -0.016757926076027236,499,511 -0.0167685275136599,500,512 -0.01658249520339573,502,513 -0.016503886647044875,502,514 -0.0163657492337633,503,515 -0.016059452740544412,505,516 -0.016105727310176437,507,517 -0.01611627547566954,508,518 -0.016048280311160835,508,519 -0.016099008329826435,510,520 -0.016426019576609843,512,521 -0.016557677156516702,513,522 -0.01643612315920147,515,523 -0.016622133415846084,515,524 -0.016567587009311716,517,525 -0.01655090611295394,518,526 -0.016673281150299823,518,527 -0.01679157674395149,520,528 -0.01691207607257279,520,529 -0.016851207212515,522,530 -0.017102015733837204,522,531 -0.016940183165035854,522,532 -0.017041519699034367,522,533 -0.017219434801896118,522,534 -0.01729460290529385,523,535 -0.017208344641795915,525,536 -0.017039276723114304,527,537 -0.017012741429293782,528,538 -0.016969848560383624,530,539 -0.01693889241325045,530,540 -0.016979771910473354,532,541 -0.017126860048399094,533,542 -0.016938716334626853,535,543 -0.016671925049656425,537,544 -0.01672039250919571,537,545 -0.01696930351908565,538,546 -0.016846421919609257,538,547 -0.016985967605965532,540,548 -0.016932069133075184,542,549 -0.01656211551494512,543,550 -0.01689960111269392,543,551 -0.01697398296466541,545,552 -0.016924974019485763,547,553 -0.017076341227815605,547,554 -0.016936792692957316,549,555 -0.017030074734908626,550,556 -0.017354709541540496,552,557 -0.017463775816982857,552,558 -0.01745511547482664,552,559 -0.017556422973348453,552,560 -0.017318999312774527,554,561 -0.017022649822729056,555,562 -0.017121778208429562,557,563 -0.017229953208519572,559,564 -0.017336063137592582,561,565 -0.017325075202822306,562,566 -0.017472518445258295,562,567 -0.017445658911477254,564,568 -0.01752503582849579,566,569 -0.01726974998747168,568,570 -0.017122781012089937,568,571 -0.017213005473351563,568,572 -0.0170492642512195,569,573 -0.01713120614366096,571,574 -0.016972075680385057,571,575 -0.016855445455910997,573,576 -0.016588218753464022,575,577 -0.016505823555729212,576,578 -0.016470603299512828,578,579 -0.016577409423571932,578,580 -0.016585141246131762,578,581 -0.0167229197070603,578,582 -0.016790715187112015,578,583 -0.016739560217442,580,584 -0.01710188545951706,580,585 -0.01716143887819563,580,586 -0.017212487114410015,582,587 -0.01731076167570274,582,588 -0.017462554333437755,582,589 -0.01731714965566479,583,590 -0.01751408419179854,583,591 -0.01749359822225303,583,592 -0.017554623210812012,585,593 -0.017564488919660587,585,594 -0.01753405968754016,585,595 -0.017505701894047862,587,596 -0.01745630353282802,589,597 -0.017691379851438777,589,598 -0.017700004662550683,589,599 -0.017572985775428332,590,600 -0.017370004790965576,590,601 -0.017196033748964844,590,602 -0.01716277393966714,592,603 -0.017355230883314508,594,604 -0.017498874554604953,596,605 -0.017577043720837526,598,606 -0.01754926112002114,598,607 -0.017613348324597936,599,608 -0.017475086746440768,599,609 -0.01765584218637443,599,610 -0.01756070797715907,599,611 -0.017502513855263854,601,612 -0.017749875890874314,601,613 -0.01763402065576448,601,614 -0.01766491371170345,601,615 -0.01751723373843943,603,616 -0.017602670304997837,603,617 -0.017878176009262375,603,618 -0.017827981449305277,605,619 -0.017782593969498727,607,620 -0.01787885684778855,608,621 -0.017832489158297014,608,622 -0.017661430401257307,610,623 -0.01779047087254963,612,624 -0.017586943253823394,614,625 -0.017573991020305012,616,626 -0.01749086626807821,618,627 -0.017661302391145845,618,628 -0.017781463498911382,619,629 -0.01763235040824873,621,630 -0.017747701787003568,621,631 -0.017741294603309133,623,632 -0.017755592970531052,625,633 -0.01753488172235495,627,634 -0.0177493559023631,629,635 -0.017766221387044957,629,636 -0.017620604966645106,630,637 -0.017555322883209955,630,638 -0.017811366656464708,632,639 -0.01785792104787208,634,640 -0.01797136799034711,634,641 -0.017973562442838147,634,642 -0.01791635270595485,636,643 -0.017891373689671544,636,644 -0.017947970380315818,636,645 -0.01796824900970993,638,646 -0.018042232670961347,638,647 -0.018119467923816312,638,648 -0.01815008268485227,638,649 -0.01812134527062646,638,650 -0.01816705482618297,638,651 -0.01816800299857665,640,652 -0.018116812897319246,642,653 -0.017930617586675465,642,654 -0.018033396728026875,642,655 -0.01801975420704782,642,656 -0.01793612335264534,643,657 -0.018240657363958693,645,658 -0.017840792798358766,647,659 -0.01786550194002239,647,660 -0.01786544528335983,647,661 -0.01789251951185984,647,662 -0.01794760596337908,649,663 -0.017881402207043862,651,664 -0.018055090961246346,653,665 -0.018080846001862404,653,666 -0.01796002035572296,653,667 -0.017721722090201716,653,668 -0.01775682826354801,653,669 -0.017708226084864054,655,670 -0.017609786155996888,655,671 -0.017864266061485657,655,672 -0.017943132920194515,657,673 -0.017757675029209313,659,674 -0.017702382156185532,660,675 -0.017859088228854788,660,676 -0.01806080241226869,660,677 -0.018243319947010218,662,678 -0.018086652167525454,662,679 -0.01823136712323015,664,680 -0.01839234573450339,664,681 -0.018535350764901332,666,682 -0.018271389515443076,668,683 -0.01829750080821886,670,684 -0.018055640968797318,672,685 -0.018026148749747808,672,686 -0.018018594187082154,674,687 -0.01815405683628655,674,688 -0.01811516712319436,676,689 -0.018134326292999305,676,690 -0.018098343898433483,676,691 -0.017925980089666525,678,692 -0.01803229844508069,678,693 -0.01796966263176479,678,694 -0.017699379839167396,680,695 -0.017728456313320422,680,696 -0.017852588612682845,682,697 -0.01782810543045316,684,698 -0.017699338160262697,686,699 -0.01760522590143628,686,700 -0.017682353218596434,688,701 -0.01756536689696083,688,702 -0.017441349658699642,688,703 -0.017555741236014444,688,704 -0.017337790500355492,688,705 -0.017222098423152365,688,706 -0.017519720126591375,688,707 -0.017471799015658308,689,708 -0.017418107489070543,689,709 -0.017517014759438402,691,710 -0.01775980501483115,693,711 -0.017792063521840856,693,712 -0.0178708154198674,693,713 -0.017939402390229665,695,714 -0.017832403545252732,697,715 -0.017888288985600017,697,716 -0.018048656174686987,697,717 -0.017853148886697784,697,718 -0.0180328712079204,697,719 -0.01772708921467731,699,720 -0.017870477389744423,701,721 -0.017951289829903593,701,722 -0.01785103041880167,703,723 -0.01787602490174227,703,724 -0.01769347859443285,705,725 -0.017687654013277782,705,726 -0.01781398384985091,707,727 -0.017613045551134986,707,728 -0.01760158560270057,707,729 -0.01751400681760965,709,730 -0.017560492126429385,709,731 -0.01730169092817839,711,732 -0.017322103886217976,711,733 -0.01706574585987136,713,734 -0.017082504879124813,713,735 -0.01708635126948168,715,736 -0.0170149056852685,715,737 -0.016958968048487334,717,738 -0.01714299426171661,719,739 -0.016905286241030857,721,740 -0.016787782282329793,723,741 -0.016956596563645038,723,742 -0.016943665855900077,725,743 -0.016917328289362557,725,744 -0.01718392318970501,725,745 -0.017184661677132885,725,746 -0.017318307795105764,727,747 -0.017155757090772213,727,748 -0.017173018987567824,727,749 -0.016958000134143975,729,750 -0.017153699375368436,729,751 -0.017061567646529375,732,752 -0.01703591479384395,734,753 -0.017076279899087075,734,754 -0.017249516383211583,736,755 -0.017393201001379865,736,756 -0.017369736270159423,736,757 -0.017132011899204148,738,758 -0.017042252490776292,740,759 -0.01722696241790648,742,760 -0.017080948749644352,742,761 -0.01718064844435824,742,762 -0.01698495473584822,742,763 -0.016979978631787244,742,764 -0.01678698381839396,744,765 -0.016903127507711356,746,766 -0.016888742965349493,748,767 -0.01715946707941329,748,768 -0.01721275441713933,750,769 -0.01750784616319,750,770 -0.01753059272723921,750,771 -0.0173790255561086,752,772 -0.017351471794054187,752,773 -0.01725579600714749,754,774 -0.017208867322358105,756,775 -0.017348524681303056,758,776 -0.017385408021705618,758,777 -0.017651146416409618,761,778 -0.01788892259276735,761,779 -0.017856314833197908,763,780 -0.01778718534932644,763,781 -0.017640779034438028,765,782 -0.017464142954794152,767,783 -0.017180323388173,769,784 -0.017170070297632557,771,785 -0.01737927507325717,771,786 -0.017435233220850027,773,787 -0.017349868310468235,775,788 -0.0176090684613661,775,789 -0.017370320398102587,778,790 -0.017358745355430926,780,791 -0.01723794617200484,782,792 -0.017049961252504974,782,793 -0.017034503382627245,782,794 -0.017119660120141253,784,795 -0.017021243012553974,784,796 -0.01699840544523884,786,797 -0.016885190212446343,788,798 -0.01697824664350445,790,799 -0.017173482287667297,793,800 -0.01696213248035808,795,801 -0.017091534256927336,795,802 -0.016944572834322633,797,803 -0.016778299547561427,797,804 -0.01696578024876682,797,805 -0.016622200405401223,799,806 -0.01668564133377913,799,807 -0.016836644155754525,799,808 -0.01672976322219509,801,809 -0.016700368574615744,803,810 -0.016895559945482457,806,811 -0.016884850715428605,806,812 -0.016860513363909986,808,813 -0.0169782779715554,808,814 -0.017060237200541048,808,815 -0.017054633022795296,808,816 -0.0169237022692175,810,817 -0.016863534350871814,810,818 -0.01702476984836376,812,819 -0.017201680847384954,815,820 -0.017092202563164946,815,821 -0.017163624889204504,815,822 -0.017063901169367908,817,823 -0.017112491008124245,819,824 -0.017008392278127685,819,825 -0.016869842546288788,821,826 -0.01689010095672339,821,827 -0.0168074029978713,821,828 -0.016891919902262985,821,829 -0.016967018585001624,823,830 -0.01702794040948449,826,831 -0.01702554398861539,828,832 -0.01707209708380505,830,833 -0.01692086622253433,832,834 -0.016994266000206214,832,835 -0.016962813474725325,835,836 -0.017033434248704547,837,837 -0.017079001462761912,837,838 -0.017051403839624626,837,839 -0.016822611962904396,839,840 -0.01672879167232306,839,841 -0.016607847770043857,839,842 -0.01664711083401569,839,843 -0.016594117659808155,841,844 -0.01659154203094183,844,845 -0.016658020178682426,846,846 -0.01671478444185529,848,847 -0.016526024332280686,851,848 -0.016617081024316523,851,849 -0.01673831147519992,851,850 -0.016678252204347165,853,851 -0.016610805570331635,853,852 -0.01669368169271521,855,853 -0.016821091237302913,858,854 -0.017002007999625767,860,855 -0.01701156262249275,860,856 -0.01696472272316496,862,857 -0.016821340937893933,862,858 -0.016780798733851972,864,859 -0.016751576845323874,864,860 -0.016706391971495066,864,861 -0.016733427261012318,867,862 -0.016781830244109883,867,863 -0.016752375670423664,867,864 -0.01671992030735977,869,865 -0.016608257751532064,871,866 -0.01631957342990612,871,867 -0.016368255405969343,874,868 -0.016186760996584764,876,869 -0.016306151761659227,879,870 -0.016449181109636873,879,871 -0.016372453038629914,879,872 -0.016472686891853244,881,873 -0.016393412207673607,883,874 -0.01638909544111381,886,875 -0.016099367618955033,888,876 -0.015800279781285318,888,877 -0.015765579216048486,890,878 -0.015430579122713362,890,879 -0.015630904554123148,893,880 -0.01570257143189182,895,881 -0.015768735671263433,898,882 -0.01588551209796363,898,883 -0.015971325063166474,898,884 -0.016122069637521642,898,885 -0.016246110406999165,898,886 -0.016192969933652795,898,887 -0.015964386026838463,898,888 -0.015836266204326366,900,889 -0.015639483312627413,877,890 -0.015509972527558959,877,891 -0.015580967147367114,879,892 -0.015617068727560114,879,893 -0.015761653388546053,880,894 -0.01591185126028905,882,895 -0.01584291377171183,882,896 -0.016158428565598692,884,897 -0.01605103231570056,886,898 -0.01599225500409941,887,899 -0.016116250577796986,889,900 -0.016536687875207425,892,901 -0.01667382449211646,892,902 -0.01712227150448696,892,903 -0.017305053166188262,895,904 -0.01733030470840136,898,905 -0.01735799851106807,900,906 -0.017490925976578843,902,907 -0.017387274859112012,902,908 -0.017446516196996824,902,909 -0.01752511101592878,905,910 -0.01756409464761894,905,911 -0.0176006548683469,907,912 -0.017519985996119748,907,913 -0.017419017664187693,908,914 -0.01741119962073207,910,915 -0.01725246188503727,911,916 -0.016625824665572324,911,917 -0.01654810876233757,911,918 -0.01671209516283933,914,919 -0.01633489657900269,914,920 -0.016477577733959067,914,921 -0.01672741000500435,917,922 -0.016888388352470897,918,923 -0.016854427384563445,918,924 -0.016856579748461598,921,925 -0.017150296100780647,922,926 -0.017082203425014892,924,927 -0.01689109606204449,925,928 -0.017144484418935537,925,929 -0.017093835418835676,926,930 -0.01717254998389008,926,931 -0.01708340148721795,926,932 -0.0167473322250441,926,933 -0.016638760445930476,926,934 -0.01681708073886087,927,935 -0.016879290801911008,927,936 -0.017017761032431303,927,937 -0.01717839482601053,927,938 -0.01727177148944668,928,939 -0.017197891251693586,929,940 -0.017317934343215043,929,941 -0.017305082319751638,930,942 -0.017235394343685463,930,943 -0.017232480495737595,930,944 -0.017341091265786427,933,945 -0.017344010873126148,936,946 -0.0173092122695745,936,947 -0.01737040287456106,938,948 -0.01732917774638325,939,949 -0.017312042648599132,940,950 -0.017195888220580987,941,951 -0.017303458283156496,941,952 -0.017326271739391098,941,953 -0.017357964405372312,941,954 -0.01738162958645362,941,955 -0.017446020326116064,941,956 -0.01756732223581771,941,957 -0.017669662424820706,941,958 -0.01767873585041813,941,959 -0.017917610695118144,941,960 -0.01801904926561212,941,961 -0.018185761378119492,941,962 -0.018235117826891724,941,963 -0.0182295563684694,943,964 -0.018195894846760926,945,965 -0.018044577943919508,945,966 -0.018234699404740016,947,967 -0.018375244447117363,949,968 -0.018233921318947,950,969 -0.01802888056569636,950,970 -0.018130787899812074,950,971 -0.018184623005301756,950,972 -0.01809128595300313,950,973 -0.018166467314058535,950,974 -0.018173998268722652,950,975 -0.018218257126301176,950,976 -0.01820571738479154,950,977 -0.018488335385056925,952,978 -0.018499913235813972,953,979 -0.01840550015606855,953,980 -0.018310833595594943,954,981 -0.018404642266583792,954,982 -0.018388911478957205,956,983 -0.018416066336376328,956,984 -0.018442410895488755,959,985 -0.018604373431642826,960,986 -0.018708058041402086,963,987 -0.01847587622902412,963,988 -0.018469633412104364,963,989 -0.018463661491136363,963,990 -0.018537377371593496,963,991 -0.01853020565811647,963,992 -0.018473193395548194,963,993 -0.018510201803573597,963,994 -0.018557901735127846,963,995 -0.0186414127577045,963,996 -0.018649704413381808,963,997 -0.01851779482705164,963,998 -0.018261617648642887,965,999 -0.018370807203798342,967,1000 -0.018512517501978396,970,1001 -0.018517540759701873,971,1002 -0.018801806396407317,973,1003 -0.018817403781636783,974,1004 -0.018885136603187313,975,1005 -0.01883689064678924,975,1006 -0.01893641923931456,977,1007 -0.018904649719663345,978,1008 -0.01871770505936041,978,1009 -0.01879711733379907,978,1010 -0.019004672564666203,978,1011 -0.019143838616093832,978,1012 -0.01913932054716869,980,1013 -0.019090384300727802,980,1014 -0.0191083832499933,983,1015 -0.018864517545892398,983,1016 -0.019014091447043222,983,1017 -0.01890269278973934,986,1018 -0.018750985564669954,986,1019 -0.01869989549019309,987,1020 -0.018734171697678294,987,1021 -0.01883555127822943,987,1022 -0.019073940812790256,987,1023 -0.018971651096214185,990,1024 -0.018971651096214185,990,1024 +0.0,257,257 +0.0,258,258 +0.0,259,259 +0.0,260,260 +0.0,261,261 +0.0,262,262 +0.0,263,263 +0.0,264,264 +0.0,265,265 +0.0,266,266 +0.0,267,267 +0.0,268,268 +0.0,269,269 +0.0,270,270 +0.0,271,271 +0.0,272,272 +0.0,273,273 +0.0,274,274 +0.0,275,275 +0.0,276,276 +0.0,277,277 +0.0,278,278 +0.0,279,279 +0.0,280,280 +0.0,281,281 +0.0,282,282 +0.0,283,283 +0.0,284,284 +0.0,285,285 +0.0,286,286 +0.0,287,287 +0.0,288,288 +0.0,289,289 +0.0,290,290 +0.0,291,291 +0.0,292,292 +0.0,293,293 +0.0,294,294 +0.0,295,295 +0.0,296,296 +0.0,297,297 +0.0,298,298 +0.0,299,299 +0.0,300,300 +0.0,301,301 +0.0,302,302 +0.0,303,303 +0.0,304,304 +0.0,305,305 +0.0,306,306 +0.0,307,307 +0.0,308,308 +0.0,309,309 +0.0,310,310 +0.0,311,311 +0.0,312,312 +0.0,313,313 +0.0,314,314 +0.0,315,315 +0.0,316,316 +0.0,317,317 +0.0,318,318 +0.0,319,319 +0.0,320,320 +0.0,321,321 +0.0,322,322 +0.0,323,323 +0.0,324,324 +0.0,325,325 +0.0,326,326 +0.0,327,327 +0.0,328,328 +0.0,329,329 +0.0,330,330 +0.0,331,331 +0.0,332,332 +0.0,333,333 +0.0,334,334 +0.0,335,335 +0.0,336,336 +0.0,337,337 +0.0,338,338 +0.0,339,339 +0.0,340,340 +0.0,341,341 +0.0,342,342 +0.0,343,343 +0.0,344,344 +0.0,345,345 +0.0,346,346 +0.0,347,347 +0.0,348,348 +0.0,349,349 +0.0,350,350 +0.0,351,351 +0.0,352,352 +0.0,353,353 +0.0,354,354 +0.0,355,355 +0.0,356,356 +0.0,357,357 +0.0,358,358 +0.0,359,359 +0.0,360,360 +0.0,361,361 +0.0,362,362 +0.0,363,363 +0.0,364,364 +0.0,365,365 +0.0,366,366 +0.0,367,367 +0.0,368,368 +0.0,369,369 +0.0,370,370 +0.0,371,371 +0.0,372,372 +0.0,373,373 +0.0,374,374 +0.0,375,375 +0.0,376,376 +0.0,377,377 +0.0,378,378 +0.00002638522427440633,379,379 +0.00002631578947368421,380,380 +0.000026246719160104988,381,381 +0.00002617801047120419,382,382 +0.000026109660574412533,383,383 +0.000026041666666666665,384,384 +0.000025974025974025975,385,385 +0.000025906735751295337,386,386 +0.00002583979328165375,387,387 +0.000025773195876288658,388,388 +0.000025706940874035987,389,389 +0.00002564102564102564,390,390 +0.000025575447570332482,391,391 +0.00002551020408163265,392,392 +0.000025445292620865142,393,393 +0.000025380710659898476,394,394 +0.000025316455696202533,395,395 +0.000025252525252525256,396,396 +0.000025188916876574308,397,397 +0.000025125628140703518,398,398 +0.000025062656641604008,399,399 +0.000025,400,400 +0.000024937655860349125,401,401 +0.000024875621890547263,402,402 +0.000024813895781637717,403,403 +0.000024752475247524754,404,404 +0.000024691358024691357,405,405 +0.000024630541871921184,406,406 +0.00002457002457002457,407,407 +0.000024509803921568626,408,408 +0.000024449877750611248,409,409 +0.000024390243902439026,410,410 +0.000024330900243309002,411,411 +0.000024271844660194173,412,412 +0.00002421307506053269,413,413 +0.000024154589371980676,414,414 +0.000024096385542168677,415,415 +0.00002403846153846154,416,416 +0.00002398081534772182,417,417 +0.000023923444976076556,418,418 +0.000023866348448687352,419,419 +0.00002380952380952381,420,420 +0.000023752969121140145,421,421 +0.00002369668246445498,422,422 +0.00002364066193853428,423,423 +0.000023584905660377357,424,424 +0.00002352941176470588,425,425 +0.00002347417840375587,426,426 +0.00023419203747072597,427,427 +0.0004906542056074766,428,428 +0.0006293706293706295,429,429 +0.0009069767441860465,430,430 +0.0010440835266821344,431,431 +0.0012037037037037036,432,432 +0.0014549653579676676,432,433 +0.0015898617511520734,433,434 +0.001724137931034483,433,435 +0.0018807339449541285,434,436 +0.0018993135011441647,435,437 +0.002054794520547945,436,438 +0.002164009111617312,437,439 +0.002318181818181818,438,440 +0.002471655328798186,439,441 +0.0025791855203619912,440,442 +0.0027765237020316025,441,443 +0.002927927927927928,442,444 +0.0030337078651685393,443,445 +0.0032286995515695065,444,446 +0.0033557046979865767,445,447 +0.0035044642857142857,446,448 +0.0036080178173719373,447,449 +0.0036888888888888887,448,450 +0.003880266075388027,449,451 +0.003982300884955752,450,452 +0.004282560706401766,451,453 +0.004427312775330397,452,454 +0.004593406593406593,453,455 +0.004714912280701754,454,456 +0.004989059080962801,455,457 +0.005109170305676856,456,458 +0.005294117647058825,457,459 +0.005434782608695652,457,460 +0.005596529284164859,458,461 +0.005692640692640693,459,462 +0.005745140388768899,459,463 +0.005818965517241379,460,464 +0.006043010752688173,460,465 +0.0062017167381974245,460,466 +0.006466809421841541,461,467 +0.00655982905982906,462,468 +0.006652452025586353,463,469 +0.006765957446808511,464,470 +0.006900212314225054,465,471 +0.007033898305084745,466,472 +0.007188160676532771,467,473 +0.007299578059071729,468,474 +0.007389473684210526,469,475 +0.007542016806722689,470,476 +0.007693920335429769,471,477 +0.007949790794979079,472,478 +0.008100208768267224,473,479 +0.008229166666666668,474,480 +0.008295218295218296,475,481 +0.008360995850622407,476,482 +0.008509316770186336,477,483 +0.00859504132231405,478,484 +0.008597938144329898,479,485 +0.00874485596707819,479,486 +0.008891170431211499,480,487 +0.009098360655737705,481,488 +0.009202453987730062,482,489 +0.009469387755102041,482,490 +0.00965376782077393,483,491 +0.009898373983739836,484,492 +0.010040567951318458,485,493 +0.0101417004048583,486,494 +0.010242424242424242,487,495 +0.01040322580645161,488,496 +0.010503018108651912,489,497 +0.010562248995983934,490,498 +0.010741482965931864,490,499 +0.01084,491,500 +0.01091816367265469,491,501 +0.011075697211155377,492,502 +0.01125248508946322,492,503 +0.011408730158730158,493,504 +0.011623762376237625,494,505 +0.0116798418972332,495,506 +0.011794871794871795,496,507 +0.01188976377952756,497,508 +0.012023575638506876,498,509 +0.012098039215686276,498,510 +0.012211350293542074,499,511 +0.01240234375,500,512 +0.012475633528265107,501,513 +0.012470817120622568,502,514 +0.012601941747572813,503,515 +0.012693798449612404,504,516 +0.012785299806576403,505,517 +0.012915057915057915,506,518 +0.0130635838150289,507,519 +0.013192307692307694,508,520 +0.013378119001919386,509,521 +0.013524904214559385,510,522 +0.01367112810707457,511,523 +0.013778625954198471,511,524 +0.013923809523809526,512,525 +0.014030418250950572,513,526 +0.014231499051233398,514,527 +0.01433712121212121,515,528 +0.014385633270321363,516,529 +0.014452830188679246,517,530 +0.014613935969868173,517,531 +0.014736842105263154,518,532 +0.014821763602251408,519,533 +0.014962546816479403,520,534 +0.015046728971962617,521,535 +0.01513059701492537,522,536 +0.015307262569832402,523,537 +0.015353159851301115,524,538 +0.015510204081632652,525,539 +0.01574074074074074,526,540 +0.01587800369685767,527,541 +0.015940959409594096,528,542 +0.016169429097605895,529,543 +0.01630514705882353,530,544 +0.016440366972477066,531,545 +0.016593406593406593,532,546 +0.016654478976234004,533,547 +0.016733576642335764,534,548 +0.016848816029143898,535,549 +0.01698181818181818,536,550 +0.017150635208711434,537,551 +0.017282608695652173,538,552 +0.01732368896925859,539,553 +0.017418772563176893,540,554 +0.017477477477477476,541,555 +0.01762589928057554,542,556 +0.017737881508078993,543,557 +0.017831541218637992,544,558 +0.017924865831842576,545,559 +0.018035714285714287,546,560 +0.0182174688057041,547,561 +0.018327402135231315,548,562 +0.018507992895204262,549,563 +0.018599290780141844,550,564 +0.01865486725663717,551,565 +0.018780918727915194,552,566 +0.018853615520282186,553,567 +0.01897887323943662,554,568 +0.019068541300527243,555,569 +0.019263157894736843,556,570 +0.01936952714535902,557,571 +0.019493006993006993,557,572 +0.01951134380453752,558,573 +0.019599303135888504,559,574 +0.019704347826086956,560,575 +0.019774305555555555,561,576 +0.019861351819757365,562,577 +0.019948096885813147,563,578 +0.02001727115716753,564,579 +0.020086206896551728,564,580 +0.020137693631669534,565,581 +0.020257731958762886,566,582 +0.02032590051457976,567,583 +0.020445205479452052,568,584 +0.020598290598290596,569,585 +0.020750853242320816,569,586 +0.020834752981260647,570,587 +0.02100340136054422,571,588 +0.02108658743633277,572,589 +0.021305084745762714,573,590 +0.021387478849407778,573,591 +0.021554054054054052,573,592 +0.021686340640809446,574,593 +0.02176767676767677,575,594 +0.02184873949579832,576,595 +0.02187919463087248,577,596 +0.021993299832495813,578,597 +0.02207357859531773,579,598 +0.022287145242070115,580,599 +0.02238333333333333,581,600 +0.022479201331114806,581,601 +0.022691029900332223,581,602 +0.022802653399668325,582,603 +0.022880794701986753,583,604 +0.022925619834710743,584,605 +0.023052805280528058,585,606 +0.02322899505766063,585,607 +0.02333881578947368,586,608 +0.02348111658456486,586,609 +0.023557377049180327,587,610 +0.023633387888707037,588,611 +0.023692810457516335,589,612 +0.023817292006525284,589,613 +0.023941368078175894,589,614 +0.02403252032520325,590,615 +0.02418831168831169,591,616 +0.024376012965964346,591,617 +0.02454692556634304,591,618 +0.024668820678513736,592,619 +0.02475806451612903,593,620 +0.02483091787439613,594,621 +0.02487138263665595,595,622 +0.02492776886035313,596,623 +0.025032051282051285,597,624 +0.025088,598,625 +0.02522364217252396,599,626 +0.0254066985645933,600,627 +0.02552547770700637,601,628 +0.025675675675675677,602,629 +0.025793650793650792,603,630 +0.025863708399366088,604,631 +0.02606012658227848,605,632 +0.02614533965244865,606,633 +0.026293375394321767,607,634 +0.026456692913385826,608,635 +0.026603773584905666,609,636 +0.026750392464678176,610,637 +0.026880877742946705,611,638 +0.027042253521126765,612,639 +0.027171874999999998,613,640 +0.0274414976599064,614,641 +0.027507788161993764,615,642 +0.027636080870917575,616,643 +0.027732919254658386,616,644 +0.027782945736434108,617,645 +0.027910216718266254,618,646 +0.0280370942812983,618,647 +0.028148148148148144,618,648 +0.028212634822804318,619,649 +0.028261538461538463,620,650 +0.02861757474293774,620,651 +0.02863503245038722,621,652 +0.028750233400155336,622,653 +0.028782725398014426,623,654 +0.028897363436426727,623,655 +0.02893544678665366,624,656 +0.02912563553521581,625,657 +0.029239272685978843,626,658 +0.029407346627274778,627,659 +0.029565681434996362,627,660 +0.029617651314111697,628,661 +0.029654372741367466,629,662 +0.029745391787006435,630,663 +0.029911437883712744,631,664 +0.029830652684210986,632,665 +0.029947706645863766,632,666 +0.029796076558799636,633,667 +0.02973145533115012,633,668 +0.029419412658166763,634,669 +0.028727570599416278,635,670 +0.028301457782042263,636,671 +0.027449725528563763,637,672 +0.025686325612470848,638,673 +0.024830155572749563,639,674 +0.0235433566288098,640,675 +0.021991053273917895,641,676 +0.020103772522801204,642,677 +0.019159960787082635,643,678 +0.01763537083327118,644,679 +0.01730798053987366,645,680 +0.016783152467649044,646,681 +0.016346565702598577,647,682 +0.015005099628996401,648,683 +0.014521646763444774,649,684 +0.014257937712239752,650,685 +0.01287050020559455,650,686 +0.012119322545388887,651,687 +0.012123873685640753,652,688 +0.01170633813635507,653,689 +0.011662677821261559,654,690 +0.01135455591671445,676,691 +0.011256407841767943,677,692 +0.011144375198978256,679,693 +0.011374093546959037,680,694 +0.010924138961647362,681,695 +0.010954943536257344,681,696 +0.011026356031217417,683,697 +0.01102787813528566,684,698 +0.011083354710519912,686,699 +0.011153649802912852,687,700 +0.011277485908388537,688,701 +0.011413652193775754,690,702 +0.011405673239669923,691,703 +0.011394102116450762,693,704 +0.011506941426549845,694,705 +0.011496474377804704,695,706 +0.011512534295333271,697,707 +0.011581944828239678,698,708 +0.011621725999820509,698,709 +0.011521587499383113,700,710 +0.011601259492405355,701,711 +0.011560736246536647,702,712 +0.011598824465952416,702,713 +0.011640004495359966,704,714 +0.011580913701465483,705,715 +0.01149902409430509,707,716 +0.011402687672291231,707,717 +0.011400229554757646,708,718 +0.011497964951406744,708,719 +0.011455818239061173,710,720 +0.01147353114876786,711,721 +0.011534839692722043,712,722 +0.01151700184141894,714,723 +0.01138186223712185,715,724 +0.01131784803320946,717,725 +0.011265989819620605,717,726 +0.011311977698237862,718,727 +0.011276243279191231,719,728 +0.01124321714945761,721,729 +0.011059221372591396,722,730 +0.011126015466819555,722,731 +0.011086995029333115,724,732 +0.011201285531276094,724,733 +0.011234919036414324,725,734 +0.011293706840161297,725,735 +0.01117762655643817,727,736 +0.01104489267928032,727,737 +0.011025297438469982,728,738 +0.011119473773910126,729,739 +0.011170745502692257,731,740 +0.011159494553765583,732,741 +0.011332693967670155,732,742 +0.011277203987211796,734,743 +0.011105887749147192,734,744 +0.011177891762560543,734,745 +0.011231149363666386,735,746 +0.011389058171647206,737,747 +0.011393077738506579,737,748 +0.011263679345651574,738,749 +0.011254872907257159,739,750 +0.011193502204863974,739,751 +0.011363119266069676,741,752 +0.011353438409781157,742,753 +0.011232752363411352,744,754 +0.011117610831655154,745,755 +0.011079147840447105,745,756 +0.011136786034926113,747,757 +0.011063583328861237,748,758 +0.010856530447812061,749,759 +0.010945486685938416,751,760 +0.010854615871714041,751,761 +0.010904982035861925,751,762 +0.010984007656782237,751,763 +0.011005190018921805,751,764 +0.011030520614938913,752,765 +0.011151597438409384,754,766 +0.011211859941752602,755,767 +0.011349361177680116,755,768 +0.011358748950544055,757,769 +0.011442170359861234,757,770 +0.01145828111146183,757,771 +0.011362662704626754,758,772 +0.011463706162418305,760,773 +0.011525668707754027,761,774 +0.011450240515990228,763,775 +0.011428647841332804,764,776 +0.011547374310366872,765,777 +0.011678047102644352,767,778 +0.011598497103987682,767,779 +0.011665619043931843,768,780 +0.011745881251499179,770,781 +0.011833923885255098,771,782 +0.011753153222574881,773,783 +0.011835274060904549,774,784 +0.011883187275554263,776,785 +0.011707879689875203,777,786 +0.011578072431442949,779,787 +0.011492011950001841,780,788 +0.011482538228332135,781,789 +0.011477452059038598,783,790 +0.011515044163951634,784,791 +0.011627494135569953,786,792 +0.011748744240139443,787,793 +0.011790373039060022,787,794 +0.011976637460763315,789,795 +0.011925102782700689,789,796 +0.01186609380065477,790,797 +0.0118875130379036,792,798 +0.01203241790124384,793,799 +0.011990847155404777,795,800 +0.011911937703317197,796,801 +0.01184184075575546,798,802 +0.01172728456075968,799,803 +0.011563673237447841,801,804 +0.011614084250579424,801,805 +0.011718785906952316,802,806 +0.011866956582079608,802,807 +0.011972319026414345,804,808 +0.011987322295699885,805,809 +0.011855492984427486,807,810 +0.011723749282918297,808,811 +0.01169638226525343,808,812 +0.011736781371097455,809,813 +0.011821699471460625,811,814 +0.011766991898536187,812,815 +0.011804020244831565,812,816 +0.011782698652244563,814,817 +0.011777190532068374,814,818 +0.011820774789320239,815,819 +0.01186054185639349,817,820 +0.01193474040244549,817,821 +0.011978955799195804,817,822 +0.011888261221653545,818,823 +0.012005763393366871,820,824 +0.01173277467646756,821,825 +0.011691845118388383,823,826 +0.011791238296052354,823,827 +0.01173078283427249,823,828 +0.011692680645919717,823,829 +0.011737413856317618,824,830 +0.011697973809709036,826,831 +0.011783821552836854,827,832 +0.011816778935385654,829,833 +0.0117090423643472,830,834 +0.011813918519345223,830,835 +0.0118467626337012,832,836 +0.011844036880968769,833,837 +0.01187230964142119,835,838 +0.011847057819113278,835,839 +0.011800782749135274,836,840 +0.011747589888401761,836,841 +0.011718327725058358,838,842 +0.011717273539167223,838,843 +0.011601925903238608,839,844 +0.011649422742812625,841,845 +0.011497363634364625,842,846 +0.011565539521967321,844,847 +0.011541257762028396,845,848 +0.011634984340847643,847,849 +0.011727348854639186,848,850 +0.011744226554885853,850,851 +0.011595505042652991,850,852 +0.011499597245854094,852,853 +0.011499597245854094,852,853 diff --git a/measure_variant/src/main.rs b/measure_variant/src/main.rs index 1c20315..9797458 100644 --- a/measure_variant/src/main.rs +++ b/measure_variant/src/main.rs @@ -10,23 +10,23 @@ use test_utils::prelude::{compare_features, read_csv, write_csv}; type HLL1 = Hybrid< PlusPlus< - Precision10, - Bits6, - >::Packed, + Precision11, + Bits5, + >::Packed, twox_hash::XxHash64, >, - SwitchHash, + SwitchHash, >; -type HLL2 = Hybrid< - PlusPlus< - Precision10, - Bits6, - >::Packed, - twox_hash::XxHash64, - >, - GapHash>, ->; +// type HLL2 = Hybrid< +// PlusPlus< +// Precision10, +// Bits6, +// >::Packed, +// twox_hash::XxHash64, +// >, +// GapHash>, +// >; const ITERATIONS: usize = 100; const MINIMUM_CARDINALITY_FOR_SAMPLING: u64 = 0; @@ -43,7 +43,7 @@ struct Report { fn main() { let random_state = 7_536_558_723_694_876_u64; - let max_hashes = (1 << 10) * 6 / 6; + let max_hashes = (1 << 11) * 5 / 12; let max = max_hashes as u64; let progress_bar = ProgressBar::new(ITERATIONS as u64); @@ -62,7 +62,7 @@ fn main() { .map(|i| { let mut measurement_step = 0; let thread_random_state = splitmix64(random_state.wrapping_mul(i as u64 + 1)); - let mut hll = HLL2::default(); + let mut hll = HLL1::default(); let mut reports: Vec = Vec::with_capacity((size) as usize); let mut hashset: HashSet = HashSet::default(); @@ -71,9 +71,9 @@ fn main() { if hashset.insert(value) { let mut cardinality = hll.estimate_cardinality(); - if hll.is_hash_list() { - cardinality = (1.0 + 0.0048384760745443225 * cardinality / 83774.0) * cardinality; - } + // if hll.is_hash_list() { + // cardinality = (1.0 + 0.0048384760745443225 * cardinality / 83774.0) * cardinality; + // } let exact_cardinality = hashset.len() as u64; let relative_error = (exact_cardinality as f64 - cardinality).abs() / exact_cardinality as f64; diff --git a/src/composite_hash.rs b/src/composite_hash.rs index a8c101d..ad95c3b 100644 --- a/src/composite_hash.rs +++ b/src/composite_hash.rs @@ -10,6 +10,7 @@ pub use gaps::GapHash; mod shared; pub mod switch; +mod switch_birthday_paradox; pub use switch::SwitchHash; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -21,6 +22,31 @@ pub enum CompositeHashError { Saturation, } +/// Trait defining constants and methods needed to apply the BirthDay Paradox correction. +pub trait BirthDayParadoxCorrection { + /// The minimal value after which the correction is applied. + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64; + /// The maximal value after which the correction is applied. + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64; + /// The expected maximal error rate. + const MAXIMAL_ERROR_RATE: f64; + + /// Returns the corrected cardinality. + fn birthday_paradox_correction(cardinality: u32) -> f64 { + let cardinality = f64::from(cardinality); + if cardinality <= Self::MINIMAL_CARDINALITY_FOR_CORRECTION { + return f64::from(cardinality); + } + + cardinality + * (1.0 + + Self::MAXIMAL_ERROR_RATE + * (cardinality - Self::MINIMAL_CARDINALITY_FOR_CORRECTION) + / (Self::MAXIMAL_CARDINALITY_FOR_CORRECTION + - Self::MINIMAL_CARDINALITY_FOR_CORRECTION)) + } +} + /// A reader buffer with a known last buffered bit. pub trait LastBufferedBit { /// Returns the last buffered bit. @@ -28,7 +54,7 @@ pub trait LastBufferedBit { } /// A composite hash is a 64-bit hash that encodes a register, index and original hash. -pub trait CompositeHash: Send + Sync + Debug { +pub trait CompositeHash: Send + Sync + Debug + BirthDayParadoxCorrection { /// The precision of the hyperloglog. type Precision: Precision; /// The number of bits for the hash. @@ -188,8 +214,7 @@ mod test_composite_hash { { let number_of_bits = (1 << CH::Precision::EXPONENT) * usize::from(CH::Bits::NUMBER_OF_BITS); - let number_of_hashes = number_of_bits - / usize::from(CH::SMALLEST_VIABLE_HASH_BITS); + let number_of_hashes = number_of_bits / usize::from(CH::SMALLEST_VIABLE_HASH_BITS); assert!(number_of_bits >= 64); assert!(number_of_hashes > 2); @@ -389,7 +414,11 @@ mod test_composite_hash { let encoded_hash = CH::encode(index, register, original_hash, hash_bits); // We check that the encoded hash indeed fits within the provided number of bits. - assert_eq!(encoded_hash >> hash_bits, 0, "The encoded hash is too large for the provided number of bits."); + assert_eq!( + encoded_hash >> hash_bits, + 0, + "The encoded hash is too large for the provided number of bits." + ); let (decoded_register, decoded_index) = CH::decode(encoded_hash, hash_bits); assert_eq!(register, decoded_register, "Failed to recover the register at hash bits {hash_bits}. The hash is {encoded_hash:b}. The fake hash is {original_hash:064b}."); @@ -427,19 +456,21 @@ mod test_composite_hash { fn test_switch_hash() where P: ArrayRegister, + switch::SwitchHash: BirthDayParadoxCorrection, { test_composite_hash_stateless_operations::>(); test_composite_hash::>(); } - #[test_precisions_and_bits([[5, 4], [4, 5], [4, 6]])] - #[cfg(feature = "prefix_free_codes")] - fn test_gap_switch_hash() - where - P: ArrayRegister, - switch::SwitchHash: PrefixFreeCode, - { - test_composite_hash_stateless_operations::>>(); - test_composite_hash::>>(); - } + // #[test_precisions_and_bits([[5, 4], [4, 5], [4, 6]])] + // #[cfg(feature = "prefix_free_codes")] + // fn test_gap_switch_hash() + // where + // P: ArrayRegister, + // switch::SwitchHash: PrefixFreeCode + BirthDayParadoxCorrection, + // gaps::GapHash>: BirthDayParadoxCorrection, + // { + // test_composite_hash_stateless_operations::>>(); + // test_composite_hash::>>(); + // } } diff --git a/src/composite_hash/gaps.rs b/src/composite_hash/gaps.rs index a7d8d8c..8774f8b 100644 --- a/src/composite_hash/gaps.rs +++ b/src/composite_hash/gaps.rs @@ -4,7 +4,7 @@ mod bitreader; mod bitwriter; mod optimal_codes; mod prefix_free_codes; -use crate::utils::ceil; +use crate::{bits::Bits, utils::ceil}; use bitreader::BitReader; use bitwriter::BitWriter; use prefix_free_codes::{CodeRead, CodeSize, CodeWrite}; @@ -44,9 +44,64 @@ impl GapHash { } } +pub(super) const fn smallest_viable_gap_hash() -> u8 { + assert!(P::EXPONENT >= 4); + assert!(B::NUMBER_OF_BITS == 4 || B::NUMBER_OF_BITS == 5 || B::NUMBER_OF_BITS == 6); + assert!(P::EXPONENT <= 18); + match (P::EXPONENT, B::NUMBER_OF_BITS) { + (4, 4) => 8, + (4, 5) => 9, + (4, 6) => 10, + (5, 4) => 9, + (5, 5) => 10, + (5, 6) => 11, + (6, 4) => 10, + (6, 5) => 11, + (6, 6) => 12, + (7, 4) => 11, + (7, 5) => 12, + (7, 6) => 13, + (8, 4) => 12, + (8, 5) => 13, + (8, 6) => 14, + (9, 4) => 13, + (9, 5) => 14, + (9, 6) => 16, + (10, 4) => 15, + (10, 5) => 16, + (10, 6) => 17, + (11, 4) => 16, + (11, 5) => 17, + (11, 6) => 18, + (12, 4) => 17, + (12, 5) => 18, + (12, 6) => 19, + (13, 4) => 19, + (13, 5) => 20, + (13, 6) => 21, + (14, 4) => 20, + (14, 5) => 21, + (14, 6) => 22, + (15, 4) => 22, + (15, 5) => 23, + (15, 6) => 24, + (16, 4) => 23, + (16, 5) => 24, + (16, 6) => 25, + (17, 4) => 24, + (17, 5) => 25, + (17, 6) => 26, + (18, 4) => 26, + (18, 5) => 27, + (18, 6) => 28, + _ => unreachable!(), + } +} + impl CompositeHash for GapHash where CH: PrefixFreeCode, + Self: super::BirthDayParadoxCorrection, { type Precision = ::Precision; type Bits = ::Bits; @@ -327,7 +382,7 @@ where } } - const SMALLEST_VIABLE_HASH_BITS: u8 = CH::SMALLEST_VIABLE_HASH_BITS; + const SMALLEST_VIABLE_HASH_BITS: u8 = smallest_viable_gap_hash::(); const LARGEST_VIABLE_HASH_BITS: u8 = CH::LARGEST_VIABLE_HASH_BITS; } @@ -338,7 +393,10 @@ fn downgrade_inplace_with_writer (u32, usize) { +) -> (u32, usize) +where + GapHash: super::BirthDayParadoxCorrection, +{ // safe because the slice is originally allocated as u64s debug_assert!(hashes.len() % core::mem::size_of::() == 0); let hashes_64 = unsafe { @@ -405,19 +463,24 @@ fn downgrade_inplace_with_writer( +fn to_prefix_code_inplace_with_writer( hashes: &mut [u8], number_of_hashes: usize, bit_index: usize, hash_bits: u8, -) -> usize { - +) -> usize +where + GapHash: super::BirthDayParadoxCorrection, +{ #[cfg(test)] - #[cfg(feature="std")] - println!("to_prefix_code_inplace_with_writer({}, {}, {}, {})", number_of_hashes, bit_index, hash_bits, hashes.len()); + #[cfg(feature = "std")] + println!( + "to_prefix_code_inplace_with_writer({}, {}, {}, {})", + number_of_hashes, + bit_index, + hash_bits, + hashes.len() + ); assert!( bit_index + usize::from(hash_bits) >= hashes.len() * 8, @@ -494,7 +557,10 @@ fn insert_sorted_desc_with_writer< register: u8, original_hash: u64, hash_bits: u8, -) -> Result, CompositeHashError> { +) -> Result, CompositeHashError> +where + GapHash: super::BirthDayParadoxCorrection, +{ debug_assert!( GapHash::::is_prefix_free_encoded(number_of_hashes, hash_bits, bit_index), "The hashes must be prefix-free encoded to be able to use prefix-free codes." diff --git a/src/composite_hash/switch.rs b/src/composite_hash/switch.rs index f5adb50..31b1a45 100644 --- a/src/composite_hash/switch.rs +++ b/src/composite_hash/switch.rs @@ -24,15 +24,11 @@ pub(super) const fn smallest_viable_switch_hash() -> u8 { return 8; } - if P::EXPONENT < 11 { + if P::EXPONENT + B::NUMBER_OF_BITS <= 16 { return 16; } - if P::EXPONENT < 18 || B::NUMBER_OF_BITS < 6 { - return 24; - } - - 32 + 24 } const fn maximal_viable_switch_hash() -> u8 { @@ -40,22 +36,21 @@ const fn maximal_viable_switch_hash() -> u8 { return 8; } - if P::EXPONENT == 4 { - return 16; - } - if P::EXPONENT < 8 { return 16; } - if P::EXPONENT < 18 || B::NUMBER_OF_BITS < 6 { + if P::EXPONENT < 14 { return 24; } 32 } -impl CompositeHash for SwitchHash { +impl CompositeHash for SwitchHash +where + SwitchHash: super::BirthDayParadoxCorrection, +{ type Precision = P; type Bits = B; diff --git a/src/composite_hash/switch_birthday_paradox.rs b/src/composite_hash/switch_birthday_paradox.rs new file mode 100644 index 0000000..9f10eef --- /dev/null +++ b/src/composite_hash/switch_birthday_paradox.rs @@ -0,0 +1,450 @@ +#[cfg(feature = "precision_4")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision4, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 7.4470782f64; + const MAXIMAL_ERROR_RATE: f64 = 0.069115225f64; +} +#[cfg(feature = "precision_4")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision4, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 7.9990473f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0001190875f64; +} +#[cfg(feature = "precision_4")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision4, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 7.9991386f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000107675f64; +} +#[cfg(feature = "precision_5")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision5, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 7.9990097f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0001237875f64; +} +#[cfg(feature = "precision_5")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision5, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 11.997842f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00017983333333333333f64; +} +#[cfg(feature = "precision_5")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision5, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 11.9979488f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00017093333333333333f64; +} +#[cfg(feature = "precision_6")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision6, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 15.9958329f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00026044375f64; +} +#[cfg(feature = "precision_6")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision6, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 19.9940288f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00029856f64; +} +#[cfg(feature = "precision_6")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision6, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 23.9915161f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0003534958333333333f64; +} +#[cfg(feature = "precision_7")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision7, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 31.9840328f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000498975f64; +} +#[cfg(feature = "precision_7")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision7, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 39.9760532f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00059867f64; +} +#[cfg(feature = "precision_7")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision7, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 47.9656578f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0007154625f64; +} +#[cfg(feature = "precision_8")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision8, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 40.9998781f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 63.9642738f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000558221875f64; +} +#[cfg(feature = "precision_8")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision8, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 50.9998138f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 79.9458113f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0006773587499999999f64; +} +#[cfg(feature = "precision_8")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision8, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 61.9997136f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 95.9225957f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0008062947916666665f64; +} +#[cfg(feature = "precision_9")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision9, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 82.999485f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 127.861793f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0010797421875f64; +} +#[cfg(feature = "precision_9")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision9, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 102.999191f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 159.783536f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0013529000000000002f64; +} +#[cfg(feature = "precision_9")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision9, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 124.998878f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 191.691182f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0016084270833333332f64; +} +#[cfg(feature = "precision_10")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision10, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 164.998001f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 255.453668f64; + const MAXIMAL_ERROR_RATE: f64 = 0.002134109375f64; +} +#[cfg(feature = "precision_10")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision10, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 206.996854f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 319.149702f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0026571812499999996f64; +} +#[cfg(feature = "precision_10")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision10, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 250.995605f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 379.624165f64; + const MAXIMAL_ERROR_RATE: f64 = 0.03496384634760704f64; +} +#[cfg(feature = "precision_11")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision11, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 331.991951f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 509.875321f64; + const MAXIMAL_ERROR_RATE: f64 = 0.004149763671875f64; +} +#[cfg(feature = "precision_11")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision11, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 414.987702f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 637.788193f64; + const MAXIMAL_ERROR_RATE: f64 = 0.029349031914893613f64; +} +#[cfg(feature = "precision_11")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision11, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 511.983053f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000033099609375f64; +} +#[cfg(feature = "precision_12")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision12, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 664.96825f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1021.984038f64; + const MAXIMAL_ERROR_RATE: f64 = 0.023512015252621546f64; +} +#[cfg(feature = "precision_12")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision12, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 852.950051f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00005855685814771395f64; +} +#[cfg(feature = "precision_12")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision12, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1023.935166f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000063314453125f64; +} +#[cfg(feature = "precision_13")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision13, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1364.869738f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00009543003663003662f64; +} +#[cfg(feature = "precision_13")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision13, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1705.815365f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00010822684642438454f64; +} +#[cfg(feature = "precision_13")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision13, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 1f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 2047.747728f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0001231796875f64; +} +#[cfg(feature = "precision_14")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision14, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 2016.998821f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 2729.778103f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00008128095238095239f64; +} +#[cfg(feature = "precision_14")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision14, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 2522.998133f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 3412.687145f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00009166569000878994f64; +} +#[cfg(feature = "precision_14")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision14, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 3027.997322f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 4095.558457f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000107798583984375f64; +} +#[cfg(feature = "precision_15")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision15, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 4033.995292f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 5460.176994f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0001507060977842886f64; +} +#[cfg(feature = "precision_15")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision15, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 5040.992587f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 6824.770523f64; + const MAXIMAL_ERROR_RATE: f64 = 0.000180116759449165f64; +} +#[cfg(feature = "precision_15")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision15, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 6049.989407f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 8190.24486f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00021425048828125f64; +} +#[cfg(feature = "precision_16")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision16, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 8058.98186f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 10918.829f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0002903314411279985f64; +} +#[cfg(feature = "precision_16")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision16, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 10082.97046f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 13649.14148f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0003558312582393438f64; +} +#[cfg(feature = "precision_16")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision16, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 12106.9592f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 16379.99644f64; + const MAXIMAL_ERROR_RATE: f64 = 0.00042738512235308476f64; +} +#[cfg(feature = "precision_17")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision17, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 16133.92558f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 21838.62768f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0005662129879639376f64; +} +#[cfg(feature = "precision_17")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision17, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 20172.88228f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 27306.61384f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0007094400936836712f64; +} +#[cfg(feature = "precision_17")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision17, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 24199.8343f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 32772.44828f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0008522792257277854f64; +} +#[cfg(feature = "precision_18")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision18, + crate::bits::Bits4, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 32258.70464f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 43711.11212f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0011256563763910152f64; +} +#[cfg(feature = "precision_18")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision18, + crate::bits::Bits5, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 40339.53634f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 54661.66606f64; + const MAXIMAL_ERROR_RATE: f64 = 0.0014110182681768362f64; +} +#[cfg(feature = "precision_18")] +impl crate::composite_hash::BirthDayParadoxCorrection +for crate::composite_hash::SwitchHash< + crate::precisions::Precision18, + crate::bits::Bits6, +> { + const MINIMAL_CARDINALITY_FOR_CORRECTION: f64 = 48436.36302f64; + const MAXIMAL_CARDINALITY_FOR_CORRECTION: f64 = 66823.58262f64; + const MAXIMAL_ERROR_RATE: f64 = 0.019870805841470923f64; +} diff --git a/src/hybrid.rs b/src/hybrid.rs index 9d7b499..eb8801a 100644 --- a/src/hybrid.rs +++ b/src/hybrid.rs @@ -1,6 +1,8 @@ //! Marker struct for the hybrid approach, that keeps the hash explicit up until they fit into the registers. -use crate::composite_hash::{CompositeHash, CompositeHashError, SwitchHash}; +use crate::composite_hash::{ + BirthDayParadoxCorrection, CompositeHash, CompositeHashError, SwitchHash, +}; use crate::prelude::*; use core::cmp::Ordering; use core::fmt::Debug; @@ -439,6 +441,32 @@ impl Result { + if self.is_hash_list() { + Ok(decode_duplicates(self.inner.harmonic_sum())) + } else { + Err("The counter is not in hash list mode.") + } + } + + #[inline] + /// Returns the number of hashes in the hash list, not including the duplicates. + /// + /// # Errors + /// Returns an error if the counter is not in hash list mode. + pub fn number_of_hashes(&self) -> Result { + if self.is_hash_list() { + Ok(self.inner.get_number_of_zero_registers()) + } else { + Err("The counter is not in hash list mode.") + } + } + #[inline] /// Returns the number of bytes currently used for the hash. pub fn hash_bytes(&self) -> u8 { @@ -588,10 +616,17 @@ impl< #[inline] fn estimate_cardinality(&self) -> f64 { if self.is_hash_list() { - let preliminary_estimate = self.inner.get_number_of_zero_registers() - + decode_duplicates(self.inner.harmonic_sum()); + let preliminary_estimate = + self.number_of_hashes().unwrap() + self.duplicates().unwrap(); + // let exponent = self.hash_bits() - H::Bits::NUMBER_OF_BITS + 2; - f64::from(preliminary_estimate) + // if (1 << exponent) - preliminary_estimate < (1 << H::Precision::EXPONENT) { + // linear_counting_correction(exponent, (1 << exponent) - preliminary_estimate) + // } else { + // f64::from(preliminary_estimate) + // } + + ::birthday_paradox_correction(preliminary_estimate) } else { self.inner.estimate_cardinality() } @@ -736,7 +771,10 @@ mod test_hybrid_propertis { use twox_hash::XxHash; #[test_estimator] - fn test_plusplus_hybrid_properties, H: HasherType>() { + fn test_plusplus_hybrid_properties, H: HasherType>() + where + SwitchHash: CompositeHash, + { let mut hybrid: Hybrid> = Default::default(); assert!(hybrid.is_hash_list()); assert!(hybrid.is_empty());