Skip to content
Permalink
9a695fb03b
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
1093 lines (995 sloc) 31.6 KB
use std::fs::File;
use std::io;
use std::path::Path;
use std::slice;
use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use failure::Error;
use fixedbitset::FixedBitSet;
use crate::index::sbt::Update;
use crate::sketch::minhash::KmerMinHash;
use crate::HashIntoType;
#[derive(Debug, Default, Clone)]
pub struct Nodegraph {
pub(crate) bs: Vec<FixedBitSet>,
ksize: usize,
occupied_bins: usize,
unique_kmers: usize,
}
// TODO: not checking for unique_kmers,
// since it is not saved in a khmer nodegraph
impl PartialEq for Nodegraph {
fn eq(&self, other: &Nodegraph) -> bool {
self.bs == other.bs
&& self.occupied_bins == other.occupied_bins
&& self.ksize == other.ksize
}
}
impl Update<Nodegraph> for Nodegraph {
fn update(&self, other: &mut Nodegraph) -> Result<(), Error> {
other.occupied_bins = other
.bs
.iter_mut()
.zip(&self.bs)
.enumerate()
.map(|(i, (bs, bs_me))| {
bs.union_with(bs_me);
if i == 0 {
bs.count_ones(..)
} else {
0
}
})
.sum();
Ok(())
}
}
impl Update<Nodegraph> for KmerMinHash {
fn update(&self, other: &mut Nodegraph) -> Result<(), Error> {
for h in self.mins() {
other.count(h);
}
Ok(())
}
}
impl Nodegraph {
pub fn new(tablesizes: &[usize], ksize: usize) -> Nodegraph {
let mut bs = Vec::with_capacity(tablesizes.len());
for size in tablesizes.iter() {
bs.push(FixedBitSet::with_capacity(*size));
}
Nodegraph {
bs,
ksize,
occupied_bins: 0,
unique_kmers: 0,
}
}
pub fn with_tables(tablesize: usize, n_tables: usize, ksize: usize) -> Nodegraph {
let mut tablesizes = Vec::with_capacity(n_tables);
let mut i = (tablesize - 1) as u64;
if i % 2 == 0 {
i -= 1
}
while tablesizes.len() != n_tables {
if primal_check::miller_rabin(i) {
tablesizes.push(i as usize);
}
if i == 1 {
break;
}
i -= 2;
}
Nodegraph::new(tablesizes.as_slice(), ksize)
}
pub(crate) fn count_kmer(&mut self, kmer: &[u8]) -> bool {
let h = _hash(kmer);
self.count(h)
}
pub fn count(&mut self, hash: HashIntoType) -> bool {
let mut is_new_kmer = false;
for (i, bitset) in self.bs.iter_mut().enumerate() {
let bin = hash % bitset.len() as u64;
if !bitset.put(bin as usize) {
if i == 0 {
self.occupied_bins += 1;
}
is_new_kmer = true;
}
}
if is_new_kmer {
self.unique_kmers += 1
}
is_new_kmer
}
pub fn get(&self, hash: HashIntoType) -> usize {
for bitset in &self.bs {
let bin = hash % bitset.len() as u64;
if !bitset.contains(bin as usize) {
return 0;
}
}
1
}
pub(crate) fn get_kmer(&self, kmer: &[u8]) -> usize {
let h = _hash(kmer);
self.get(h)
}
pub fn expected_collisions(&self) -> f64 {
let min_size = self.bs.iter().map(|x| x.len()).min().unwrap();
let n_ht = self.bs.len();
let occupancy = self.occupied_bins;
let fp_one = occupancy as f64 / min_size as f64;
f64::powf(fp_one as f64, n_ht as f64)
}
pub fn tablesize(&self) -> usize {
self.bs.iter().map(|x| x.len()).sum()
}
pub fn noccupied(&self) -> usize {
self.occupied_bins
}
pub fn matches(&self, mh: &KmerMinHash) -> usize {
mh.mins.iter().filter(|x| self.get(**x) == 1).count()
}
pub fn ntables(&self) -> usize {
self.bs.len()
}
pub fn ksize(&self) -> usize {
self.ksize
}
// save
pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
// TODO: if it ends with gz, open a compressed file
// might use get_output here?
self.save_to_writer(&mut File::create(path)?)?;
Ok(())
}
pub fn save_to_writer<W>(&self, wtr: &mut W) -> Result<(), Error>
where
W: io::Write,
{
wtr.write_all(b"OXLI")?;
wtr.write_u8(4)?; // version
wtr.write_u8(2)?; // ht_type
wtr.write_u32::<LittleEndian>(self.ksize as u32)?; // ksize
wtr.write_u8(self.bs.len() as u8)?; // n_tables
wtr.write_u64::<LittleEndian>(self.occupied_bins as u64)?; // n_occupied
for count in &self.bs {
let tablesize = count.len();
wtr.write_u64::<LittleEndian>(tablesize as u64)?;
let byte_size = tablesize / 8 + 1;
let (div, rem) = (byte_size / 4, byte_size % 4);
// Once this issue and PR are solved, this is a one liner:
// https://github.com/BurntSushi/byteorder/issues/155
// https://github.com/BurntSushi/byteorder/pull/166
//wtr.write_u32_from::<LittleEndian>(&count.as_slice()[..div])?;
let slice = &count.as_slice()[..div];
let buf = unsafe {
use std::mem::size_of;
let len = size_of::<u32>() * slice.len();
slice::from_raw_parts(slice.as_ptr() as *const u8, len)
};
wtr.write_all(&buf)?;
// Replace when byteorder PR is released
if rem != 0 {
let mut cursor = [0u8; 4];
LittleEndian::write_u32(&mut cursor, count.as_slice()[div]);
for item in cursor.iter().take(rem) {
wtr.write_u8(*item)?;
}
}
}
Ok(())
}
pub fn from_reader<R>(rdr: &mut R) -> Result<Nodegraph, Error>
where
R: io::Read,
{
let (mut rdr, _format) = niffler::get_reader(Box::new(rdr))?;
let signature = rdr.read_u32::<BigEndian>()?;
assert_eq!(signature, 0x4f58_4c49);
let version = rdr.read_u8()?;
assert_eq!(version, 0x04);
let ht_type = rdr.read_u8()?;
assert_eq!(ht_type, 0x02);
let ksize = rdr.read_u32::<LittleEndian>()?;
let n_tables = rdr.read_u8()?;
let occupied_bins = rdr.read_u64::<LittleEndian>()? as usize;
let mut bs = Vec::with_capacity(n_tables as usize);
for _i in 0..n_tables {
let tablesize: usize = rdr.read_u64::<LittleEndian>()? as usize;
let byte_size = tablesize / 8 + 1;
let rem = byte_size % 4;
let blocks: Vec<u32> = if rem == 0 {
let mut blocks = vec![0; byte_size / 4];
rdr.read_u32_into::<LittleEndian>(&mut blocks)?;
blocks
} else {
let mut blocks = vec![0; byte_size / 4];
rdr.read_u32_into::<LittleEndian>(&mut blocks)?;
let mut values = [0u8; 4];
for item in values.iter_mut().take(rem) {
let byte = rdr.read_u8().expect("error reading bins");
*item = byte;
}
let mut block = vec![0u32; 1];
LittleEndian::read_u32_into(&values, &mut block);
blocks.push(block[0]);
blocks
};
let counts = FixedBitSet::with_capacity_and_blocks(tablesize, blocks);
bs.push(counts);
}
Ok(Nodegraph {
bs,
ksize: ksize as usize,
occupied_bins,
unique_kmers: 0, // This is a khmer issue, it doesn't save unique_kmers
})
}
pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Nodegraph, Error> {
let mut reader = io::BufReader::new(File::open(path)?);
Ok(Nodegraph::from_reader(&mut reader)?)
}
pub fn tablesizes(&self) -> Vec<u64> {
self.bs.iter().map(|x| x.len() as u64).collect()
}
pub fn n_occupied_bins(&self) -> usize {
self.occupied_bins
}
pub fn unique_kmers(&self) -> usize {
self.unique_kmers
}
pub fn similarity(&self, other: &Nodegraph) -> f64 {
let result: usize = self
.bs
.iter()
.zip(&other.bs)
.map(|(bs, bs_other)| bs.intersection(bs_other).count())
.sum();
let size: usize = self
.bs
.iter()
.zip(&other.bs)
.map(|(bs, bs_other)| bs.union(bs_other).count())
.sum();
result as f64 / size as f64
}
pub fn containment(&self, other: &Nodegraph) -> f64 {
let result: usize = self
.bs
.iter()
.zip(&other.bs)
.map(|(bs, bs_other)| bs.intersection(bs_other).count())
.sum();
let size: usize = self.bs.iter().map(|bs| bs.len()).sum();
result as f64 / size as f64
}
}
fn twobit_repr(a: u8) -> HashIntoType {
match a as char {
'A' => 0,
'C' => 2,
'G' => 3,
'T' => 1,
_ => unimplemented!(),
}
}
fn twobit_comp(a: u8) -> HashIntoType {
match a as char {
'A' => 1,
'C' => 3,
'G' => 2,
'T' => 0,
_ => unimplemented!(),
}
}
fn uniqify_rc(f: HashIntoType, r: HashIntoType) -> HashIntoType {
if f < r {
f
} else {
r
}
}
fn _hash(kmer: &[u8]) -> HashIntoType {
let ksize = kmer.len();
let mut hash = 0;
let mut rev = 0;
hash |= twobit_repr(kmer[0]);
rev |= twobit_comp(kmer[ksize - 1]);
let mut i = 1;
let mut j: isize = (ksize - 2) as isize;
while i < ksize {
hash <<= 2;
rev <<= 2;
hash |= twobit_repr(kmer[i]);
rev |= twobit_comp(kmer[j as usize]);
i += 1;
j -= 1;
}
uniqify_rc(hash, rev)
}
#[cfg(test)]
mod test {
use super::*;
use std::io::{BufReader, BufWriter};
use std::path::PathBuf;
use proptest::collection::vec;
use proptest::num::u64;
use proptest::proptest;
// Generate with khmer:
// >>> a = khmer.Nodegraph(3, 23, 6)
// >>> a.count("ACG")
// >>> a.count("TTA")
// >>> a.count("CGA")
// >>> a.save("test.ng")
// and dumping test.ng with xxd:
// $ xxd -i test.ng
static RAW_DATA: &'static [u8] = &[
0x4f, 0x58, 0x4c, 0x49, 0x04, 0x02, 0x03, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x0d, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x08, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21,
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06,
];
static COMPRESSED_RAW_DATA: &'static [u8] = &[
0x1f, 0x8b, 0x08, 0x08, 0x73, 0x88, 0x9f, 0x5e, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x2e,
0x6e, 0x67, 0x00, 0xf3, 0x8f, 0xf0, 0xf1, 0x64, 0x61, 0x62, 0x66, 0x60, 0x60, 0x60, 0x03,
0x11, 0x20, 0x20, 0x0c, 0xa5, 0x19, 0x38, 0x19, 0x05, 0x61, 0x4c, 0x1e, 0x46, 0x5e, 0x28,
0x8b, 0x8b, 0x83, 0x1b, 0xca, 0x52, 0x64, 0x60, 0x87, 0xb2, 0x42, 0x58, 0xa1, 0x0c, 0x36,
0x00, 0x8d, 0xf0, 0xa9, 0x8b, 0x4f, 0x00, 0x00, 0x00,
];
proptest! {
#[test]
fn count_and_get(hashes in vec(u64::ANY, 1..500)) {
let mut ng: Nodegraph = Nodegraph::new(&[1000], 3);
for hash in hashes {
ng.count(hash);
assert_eq!(ng.get(hash), 1);
}
}
}
#[test]
fn load_compressed() {
let mut reader = BufReader::new(&COMPRESSED_RAW_DATA[..]);
let ng: Nodegraph = Nodegraph::from_reader(&mut reader).expect("Loading error");
assert_eq!(ng.tablesizes(), &[19, 17, 13, 11, 7, 5]);
assert_eq!(ng.ksize(), 3);
assert_eq!(ng.get_kmer(b"ACG"), 1);
assert_eq!(ng.get_kmer(b"TTA"), 1);
assert_eq!(ng.get_kmer(b"CGA"), 1);
}
#[test]
fn count_and_get_nodegraph() {
let mut ng: Nodegraph = Nodegraph::new(&[10], 3);
ng.count(801084876663808);
assert_eq!(ng.get(801084876663808), 1);
assert_eq!(ng.unique_kmers(), 1);
}
#[test]
fn load_save_nodegraph() {
let mut datadir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
datadir.push("../../tests/test-data/.sbt.v3/");
for i in 0..=5 {
let mut filename = datadir.clone();
filename.push(format!("internal.{}", i));
let data = std::fs::read(filename).unwrap();
let mut reader = BufReader::new(&data[..]);
let ng: Nodegraph = Nodegraph::from_reader(&mut reader).expect("Loading error");
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
ng.save_to_writer(&mut writer).unwrap();
}
let chunk_size = 8;
for (c1, c2) in data.to_vec().chunks(chunk_size).zip(buf.chunks(chunk_size)) {
assert_eq!(c1, c2);
}
assert_eq!(data.len(), buf.len());
}
}
#[test]
fn binary_repr_load() {
let mut reader = BufReader::new(&RAW_DATA[..]);
let khmer_ng: Nodegraph = Nodegraph::from_reader(&mut reader).expect("Loading error");
assert_eq!(khmer_ng.tablesizes(), &[19, 17, 13, 11, 7, 5]);
assert_eq!(khmer_ng.ksize(), 3);
assert_eq!(khmer_ng.get_kmer(b"ACG"), 1);
assert_eq!(khmer_ng.get_kmer(b"TTA"), 1);
assert_eq!(khmer_ng.get_kmer(b"CGA"), 1);
let mut ng = Nodegraph::with_tables(23, 6, 3);
ng.count_kmer(b"ACG");
ng.count_kmer(b"TTA");
ng.count_kmer(b"CGA");
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
ng.save_to_writer(&mut writer).unwrap();
}
assert_eq!(buf.len(), 79);
assert_eq!(&RAW_DATA, &buf.as_slice());
}
#[test]
fn binary_repr_save() {
let mut ng = Nodegraph::with_tables(23, 6, 3);
ng.count_kmer(b"ACG");
ng.count_kmer(b"TTA");
ng.count_kmer(b"CGA");
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
ng.save_to_writer(&mut writer).unwrap();
}
let mut reader = BufReader::new(&buf[..]);
let new_ng: Nodegraph = Nodegraph::from_reader(&mut reader).expect("Loading error");
assert_eq!(new_ng.tablesizes(), &[19, 17, 13, 11, 7, 5]);
assert_eq!(new_ng.ksize(), 3);
assert_eq!(new_ng.get_kmer(b"ACG"), 1);
assert_eq!(new_ng.get_kmer(b"TTA"), 1);
assert_eq!(new_ng.get_kmer(b"CGA"), 1);
assert_eq!(buf.len(), 79);
assert_eq!(&RAW_DATA, &buf.as_slice());
}
#[test]
fn update_nodegraph() {
let mut filename = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
filename.push("../../tests/test-data/.sbt.v3/internal.0");
let ng_parent: Nodegraph = Nodegraph::from_path(filename).expect("Loading error");
filename = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
filename.push("../../tests/test-data/.sbt.v3/internal.1");
let ng_1: Nodegraph = Nodegraph::from_path(filename).expect("Loading error");
filename = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
filename.push("../../tests/test-data/.sbt.v3/internal.2");
let ng_2: Nodegraph = Nodegraph::from_path(filename).expect("Loading error");
let mut ng_0: Nodegraph = Nodegraph::new(&[99991, 99989, 99971, 99961], 1);
ng_1.update(&mut ng_0).expect("Error in update");
ng_2.update(&mut ng_0).expect("Error in update");
assert_eq!(ng_0.bs, ng_parent.bs);
//assert_eq!(ng_0.occupied_bins, ng_parent.occupied_bins);
}
#[test]
fn update_nodegraph_many() -> Result<(), Box<dyn std::error::Error>> {
let mut leaf1 = Nodegraph::with_tables(100, 3, 5);
for kmer in &["AAAAA", "AAAAT", "AAAAC"] {
leaf1.count(_hash(kmer.as_bytes()));
}
let mut leaf2 = Nodegraph::with_tables(100, 3, 5);
for kmer in &["AAAAA", "AAAAT", "AAAAG"] {
leaf2.count(_hash(kmer.as_bytes()));
}
let mut leaf3 = Nodegraph::with_tables(100, 3, 5);
for kmer in &["AAAAA", "AAAAT", "CAAAA"] {
leaf3.count(_hash(kmer.as_bytes()));
}
let mut leaf4 = Nodegraph::with_tables(100, 3, 5);
for kmer in &["AAAAA", "CAAAA", "GAAAA"] {
leaf4.count(_hash(kmer.as_bytes()));
}
let mut leaf5 = Nodegraph::with_tables(100, 3, 5);
for kmer in &["AAAAA", "AAAAT", "GAAAA"] {
leaf5.count(_hash(kmer.as_bytes()));
}
let h = _hash("AAAAT".as_bytes());
for leaf in &[leaf1, leaf2, leaf3, leaf5] {
assert_eq!(leaf.get(h), 1);
}
assert_eq!(leaf4.get(h), 0);
Ok(())
}
#[test]
fn load_nodegraph() {
let mut filename = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
filename.push("../../tests/test-data/.sbt.v3/internal.0");
//let data = include_bytes!("data/internal.0");
let ng: Nodegraph = Nodegraph::from_path(filename).expect("Loading error");
assert_eq!(ng.tablesizes(), [99991, 99989, 99971, 99961]);
assert_eq!(ng.n_occupied_bins(), 2416);
assert_eq!(ng.get(1877811740), 0);
for h in [
1877811749,
1339603207230,
5641354835174,
10502027926594,
11550845136154,
12183113567732,
14062071191653,
14580861632266,
18722876140337,
20714320729467,
22732389403804,
24134363957219,
30606147678309,
30841792132441,
31130970675642,
32760645340554,
33190965408032,
33960067474598,
35413666412010,
37166860055638,
38008340488610,
38631948370393,
38946626358857,
39177463395973,
39396232170068,
40000457533067,
41548684950793,
42975853122398,
43119393989323,
43377695911881,
49367718187361,
49468277378328,
50266038601832,
51636068122286,
56622962479482,
58428533496606,
58971444597606,
59372670276820,
59452528403612,
61074441390615,
62130354354877,
62702978264830,
64430859773984,
65419869837915,
65663647257358,
67872638217057,
68827108109263,
69134145403133,
70436552236751,
70880519905358,
78004711377952,
81502993782978,
84636365982041,
85239629151685,
94266407193778,
98142256300701,
98837920540443,
99930975216128,
100653760748845,
102082282949673,
102530908835648,
103010972337870,
103329805967682,
103652023867250,
104130252812879,
112760650992638,
114779375695317,
115796389594898,
117864921668170,
119763283100790,
120285237540732,
121866736124647,
122140892054804,
122995254140976,
123065069359489,
123405856681590,
128261346941417,
130618284885748,
131310062444107,
133580282506938,
139762252968300,
148434659896290,
150472163116319,
151610888790844,
151736593364935,
152145317861349,
154119208822262,
154803963303860,
164146490870545,
166146331478050,
166719940886532,
173367021064967,
173503876669758,
173949973069402,
175345218226732,
175559849681044,
177057739236298,
182134979074863,
185526639726849,
186188120396587,
191078441509481,
191784713609488,
196150349451960,
196584209022550,
196853921592387,
197752504251580,
198597053692927,
200567230796156,
201179164742411,
202960515626517,
203378213499023,
210822710165852,
211915017282095,
213613291536686,
215418355892998,
216444054660744,
216772483699428,
218586803538885,
219619606513837,
221322641419906,
221692515333150,
222646058515199,
223103766020907,
223436957406949,
225216425962890,
225962923363564,
227026140769845,
227790244540446,
228251083676258,
231710804058239,
233288106176435,
235385609463388,
235438505061770,
238869764444344,
239420157045937,
241121021240187,
241671335688938,
242838856557679,
244786468497109,
247140303430449,
248336783901894,
250357693564448,
253975323975963,
256375919657769,
259301238714261,
265736169322750,
265781739304017,
266725362494513,
267345873524094,
271342665825792,
274876788032658,
275360996806051,
275711441656065,
276221877341287,
277115529175674,
277862338800417,
280967669495427,
281817613252845,
281897628539431,
282200323162036,
284620358398045,
284881057128884,
285925400570356,
289038917997203,
289724862541255,
290309864993733,
294086384353867,
295503963521838,
296966685834878,
299005107402724,
300199234365396,
300617258525997,
301443933468348,
302667628736144,
305781540735975,
308107503975413,
308473366560206,
311148974624393,
311393227334671,
312856558437716,
314634385460120,
315140251773348,
316147818305256,
317314266550052,
318043998368340,
319121931997971,
324333149672473,
324779561826125,
326855577904572,
327646715321140,
332098363218169,
333944737799563,
334160175766170,
335584394916553,
335971123608722,
336472954791992,
338443948117005,
338762957149102,
341091055062112,
341724341043975,
343240684449173,
344010897833199,
345196014534640,
347580313704916,
348815216366639,
348987115477673,
350399163507829,
357535517122796,
358595265377108,
358821394913517,
359452645935849,
362124977362793,
366354200059782,
366535672236781,
369474755519844,
370249620342175,
372037414685096,
373949557068914,
374319819178480,
374609596539290,
374615513078797,
375780195152331,
379102542404949,
379241504134406,
379468459802010,
379661395441316,
382035531157070,
383008100523152,
383135333541903,
383850900061929,
384049466048679,
386263487549463,
389141313731258,
390332660259608,
393516543506060,
400967959890432,
401487977714282,
403579902131163,
406955472999822,
408962716867059,
409903018669983,
410861197839878,
414355853800959,
416580890530128,
418934773149726,
419642123579295,
421963163293847,
423404494960378,
424303224424616,
424596150389604,
427230335237565,
429952924284227,
430664272577516,
432630098291297,
434623968464695,
435267549331128,
435277763415865,
435874505125675,
437654980371254,
438061138128325,
438738288109196,
439177016005977,
445344075816835,
445802335759252,
446710003143163,
447467518423055,
449641727299803,
450058424424520,
450112320572118,
450125274173050,
452241247094714,
452829154656306,
454813132622585,
456174765596578,
456493632715805,
456717723773303,
461156956524045,
462211497323948,
463604028403361,
465228093393002,
466250095735125,
469687793491358,
471922058927200,
472039595540269,
472566025949945,
472595419353109,
472977022618999,
473018780652067,
473772140307174,
474570287539184,
474912397870603,
476325119891604,
476526896773980,
476855560317170,
480232815782455,
484291524803718,
485278877010947,
487732314724511,
491715999174683,
494276065129917,
495846359323641,
506531113930798,
507871334392190,
508031302306958,
508934816424512,
509939413858428,
510737910464301,
512514768813167,
513350289212553,
517460246914282,
523321188654478,
524296526109332,
525762219690878,
526111205078257,
527062179866457,
527591752682839,
527920198105606,
530316966667021,
532977797373940,
533221992957154,
533383900955463,
537527309474265,
538136383284668,
538939534540869,
539777176029418,
539873986742508,
543935720187395,
545273268128445,
549484636278027,
551381720133873,
553977959695484,
555321949850378,
555828795847874,
557285930201258,
558008777268240,
558433475619762,
558892016080993,
559199414492426,
560748186311107,
561604684739024,
562789967643507,
563343385252253,
563775395645616,
564616206473372,
565020390122451,
568901431510366,
572526115602502,
573767900523468,
573851852316852,
576624529060777,
576874504697497,
578856083248351,
579395263040626,
579656586099131,
584217116139474,
587458649504773,
591009756408904,
592792708776319,
592997432856726,
594482884410814,
596004492939074,
596726606390901,
597875929908982,
600179982751750,
601000534535072,
601440269988372,
601603906866038,
602082770371066,
604883041984487,
605545396594434,
606419362199228,
607833403537880,
609555580824872,
609609500753196,
611579272742038,
612206643585093,
612640334623643,
612821302220884,
617021904160724,
617244669177560,
617309228629787,
618709483466270,
620059729516362,
620849299055244,
621083126852990,
622843084945666,
623088556560813,
627738708322473,
628002002108775,
628967244202734,
630034340392901,
632757066611488,
634340585739407,
634691502028135,
635939425862264,
637603178700210,
637880811482435,
644557275230225,
644935615624623,
645793929303122,
646731502743275,
646973138978211,
647900742708077,
649351154360370,
653652775436966,
655230244020599,
668170744538822,
670595660720839,
671785773373187,
672641554971634,
672821857332020,
673587502056476,
676044446355190,
677295740685782,
679716691783353,
682874745971459,
682963108550465,
683897063771844,
685246440558482,
686035384279530,
687129162879229,
687440351836027,
688990372747831,
690608944213791,
691680901171966,
694851976547107,
694869046270466,
700054088308311,
701010566680671,
701156706346414,
702431887238370,
702728791577749,
703127461004015,
703460523248065,
705302678110381,
707793984897058,
707799855432305,
707962189637436,
707993631271976,
708854130532070,
710403353214581,
710927468728191,
711091480855740,
712661928452840,
715334925158742,
715763419567022,
715896323316677,
717568681000032,
717790011003345,
719139881875323,
722537026567926,
722774506110892,
723332805980528,
724621545164802,
724746920000049,
727030394121071,
727262050490847,
728279662753580,
730854175545196,
731361512976697,
734622692371860,
736290151677476,
737921635760471,
738115824615020,
739389456325310,
742704052187442,
746469097917429,
748064810280445,
749144352424687,
753113822684627,
753423569783277,
755196264392026,
758186007844395,
758543555642030,
759083903793759,
761260029175908,
767230586289375,
770167973924874,
770328708409334,
772165475523258,
772947318346532,
774312511311396,
774365323868051,
774964429534347,
775558532281404,
779330069525835,
781344931111517,
787747218685488,
788027556261557,
790211243959626,
790890494413778,
792003960897692,
792629819473398,
797511060014001,
797622366845781,
799257433888961,
800060479182618,
801084876663808,
802340523858506,
803596407436267,
]
.iter()
{
assert_eq!(ng.get(*h), 1);
}
}
}