Commit fad01857 authored by Alexis  CRISCUOLO's avatar Alexis CRISCUOLO
Browse files

1.0

parent 0c783056
This diff is collapsed.
# AlienRemover
Fast removal of alien reads (contaminant, host, ...) from FASTQ file(s)
\ No newline at end of file
_AlienRemover_ is a command line program written in [Java](https://docs.oracle.com/en/java/) that quickly removes alien (i.e. undesirable) high-throughtput sequencing (HTS) reads from FASTQ files.
An HTS reads is considered as an alien one when it likely arises from specified alien sequences (e.g. host genome, cloning vectors, ΦX174, ...).
## Installation
Clone this repository with the following command line:
```bash
git clone https://gitlab.pasteur.fr/GIPhy/AlienRemover.git
```
## Compilation and execution
The source code of _AlienRemover_ is inside the _src_ directory. It requires **Java 13** (or higher) to be be compiled.
#### Building an executable jar file
On computers with [Oracle JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html) (**13** or higher) installed, a Java executable jar file can be created by typing the following command lines inside the _src_ directory:
```bash
javac LHBF.java AlienRemover.java
echo Main-Class: AlienRemover > MANIFEST.MF
jar -cmvf MANIFEST.MF AlienRemover.jar AlienRemover.class LHBF.class
rm MANIFEST.MF AlienRemover.class LHBF.class
```
This will create the executable jar file `AlienRemover.jar` that can be run with the following command line model:
```bash
java -jar AlienRemover.jar [options]
```
## Usage
Run _AlienRemover_ without option to read the following documentation:
```
AlienRemover
Fast removal of alien reads (contaminant, host, ...) from FASTQ file(s)
USAGE:
AlienRemover -a <alienfile> [-b <modelfile>] [-o <basename>] [-k <int>]
AlienRemover -a <alienfile> -i <FASTQ> [-o <basename>] [-k <int>] [-c <float>] [-p <float>] [...]
AlienRemover -a <alienfile> -1 <FASTQ> -2 <FASTQ> [-o <basename>] [-k <int>] [-c <float>] [-p <float>] [...]
OPTIONS:
-a <infile> FASTA file containing alien sequence(s); filename should end with .gz when gzipped
-a <infile> input file containing alien k-mers generated by AlienRemover from FASTA-formatted alien
sequence(s); filename should end with .kmr or .kmz
-i <infile> [SE] FASTQ-formatted input file; filename should end with .gz when gzipped
-1 <infile> [PE] FASTQ-formatted R1 input file; filename should end with .gz when gzipped
-2 <infile> [PE] FASTQ-formatted R2 input file; filename should end with .gz when gzipped
-o <name> outfile basename; output files have the following extensions:
+ alien k-mers: <name>.km<r|z>
+ SE reads: <name>.fastq[.gz] (.gz is added when using option -z)
+ PE reads: <name>.1.fastq[.gz] <name>.2.fastq[.gz] (.gz is added when using option -z)
-k [10-31] k-mer length for alien sequence occurence searching; must lie between 10 and 31 (default: 25)
-p <float> Bloom filter false positive probability cutoff (default: 0.05)
-n <integer> expected number of canonical k-mers (default: estimated from the alien file size)
-l use less bits and more hashing functions, whenever possible (default: not set)
-c <float> criterion to remove a read (default: 0.15)
-s compute Bloom filter statistics (default: not set)
-w write Bloom filter into output file (default: not set)
-r write removed reads into output file(s) (default: not set)
-z gzipped output files (default: not set)
EXAMPLES:
AlienRemover -a alien.fasta -o alien -k 30
AlienRemover -a alien.kmr -i reads.fastq -o flt_reads --p64 -z
AlienRemover -a alien.kmr -1 r1.fq -2 r2.fq -c 0.3 -r
```
## Notes
* In brief, _AlienRemover_ first stores every alien _k_-mer into a (less-hash) Bloom filter. Next, _AlienRemover_ determines the alien _k_-mer content of each HTS read by querying the Bloom filter, and removes those made up by a large proportion of alien _k_-mer (as ruled by option `-c`).
* When the alien (genome) sequence is short (e.g. \< 2Mb), it can be directly set via the option `-a` without affecting the overall running times. For larger alien sequences, it is recommended to first build and save the set of alien _k_-mers (i.e. the Bloom filter) via the option `-w`; such an alien _k_-mer file (\<name\>.kmr, or \<name\>.kmz when using the option `-z`) can next be directly used via the option `-a` for faster running times.
* When creating an alien _k_-mer file (option `-w`), it is highly recommended to set the (approximate) total number of canonical _k_-mers shared by the alien sequences. For instance, the programs [_KMC_](https://github.com/refresh-bio/KMC) or [_KmerStream_](https://github.com/pmelsted/KmerStream) (F0) can be used to quickly approximate this number. _AlienRemover_ will use such a number (option `-n`) to efficiently compute a (less-hash) Bloom filter with optimal dimensions for storing every alien _k_-mer.
* To obtain faster running times, a simple trick is to force _AlienRemover_ to use only one hashing function (at the cost of a larger memory footprint) by setting option `-n` with some large value. In practice, for dealing with a total of _x_ canonical _k_-mers with only one hashing function (while keeping false positive probability _FPP_ < 5%), use the lowest integer value (if any) that is greater than _x_ from the table below:
<div align="center">
| int | `-n` | memory footprint |
|:------------- | --------------:| ------------------:|
| 220,000,000 | 220000000 | 0.5 Gb |
| 440,000,000 | 440000000 | 1 Gb |
| 880,000,000 | 880000000 | 2 Gb |
| 1,700,000,000 | 1700000000 | 4 Gb |
| 3,500,000,000 | 3500000000 | 8 Gb |
</div>
* Inversely, to reduce the overall memory footprint, use the option `-l` to (try to) increase the number of hashing functions.
* Default options are expected to give accurate results in most cases, especially the _k_-mer length (i.e. 25) and the removal criterion cutoff (i.e. 0.15). Increasing the removal criterion cutoff (option `-c`; e.g. 0.25) ensures that the True Positive Rate (TPR; i.e. the proportion of non-alien reads that are not removed) will be very close to 100%, but at the cost of a significant increase of the False Positive Rate (FPR; i.e. the proportion of alien reads that are not removed). Decreasing the removal criterion cutoff (e.g. \< 0.15) is not recommended as this enables a rapid decrease of the TPR.
This diff is collapsed.
import java.io.*;
import java.util.zip.*;
public final class LHBF {
//## constants
private static final byte B0 = (byte) 0;
private static final byte B1 = (byte) 1;
private static final byte B2 = (byte) 2;
private static final byte B3 = (byte) 3;
private static final byte B4 = (byte) 4;
private static final byte B5 = (byte) 5;
private static final byte B6 = (byte) 6;
private static final byte B7 = (byte) 7;
private static final byte B19 = (byte) 19;
private static final byte B21 = (byte) 21;
private static final byte B23 = (byte) 23;
private static final byte B25 = (byte) 25;
private static final byte B27 = (byte) 27;
private static final byte B28 = (byte) 28;
private static final byte B29 = (byte) 29;
private static final byte B30 = (byte) 30;
private static final byte B31 = (byte) 31;
private static final byte B32 = (byte) 32;
private static final byte B33 = (byte) 33;
private static final byte B34 = (byte) 34;
private static final byte B35 = (byte) 35;
private static final byte B36 = (byte) 36;
private static final byte B37 = (byte) 37;
private static final byte MIN_B = B31; //## NOTE: min value of b
private static final byte MAX_B = B36; //## NOTE: max value of b
private static final byte MIN_H = B1; //## NOTE: min value of h
private static final byte MAX_H = B6; //## NOTE: max value of h
private static final int SIZE31 = 33554432; //## NOTE: = ((1<<31)+63)/64
private static final int SIZE32 = 67108864; //## NOTE: = ((1<<32)+63)/64
private static final int SIZE33 = 134217728; //## NOTE: = ((1<<33)+63)/64
private static final int SIZE34 = 268435456; //## NOTE: = ((1<<34)+63)/64
private static final int SIZE35 = 536870912; //## NOTE: = ((1<<35)+63)/64
private static final int SIZE36 = 1073741824; //## NOTE: = ((1<<36)+63)/64
private static final int SIZE37 = 2147483647; //## NOTE: = ((1<<37)+63)/64 = 2,147,483,649; rounded to 2147483647 (Integer.MAX_VALUE)
private static final int MASK31 = 0x7fffffff; //## NOTE: = (1<<31)-1 = 2,147,483,647
private static final long MASK32 = 0xffffffffL; //## NOTE: = (1<<32)-1 = 4,294,967,295
private static final long MASK33 = 0x1ffffffffL; //## NOTE: = (1<<33)-1 = 8,589,934,591
private static final long MASK34 = 0x3ffffffffL; //## NOTE: = (1<<34)-1 = 17,179,869,183
private static final long MASK35 = 0x7ffffffffL; //## NOTE: = (1<<35)-1 = 34,359,738,367
private static final long MASK36 = 0xfffffffffL; //## NOTE: = (1<<36)-1 = 68,719,476,735
private static final long MASK37 = 0x1fffffffffL; //## NOTE: = (1<<37)-1 = 137,438,953,471
private static final long F21212 = 0x5db92d5764105e5dL; //## NOTE: = 6,753,478,969,582,968,413 (X14)
private static final long F21211 = 0x5dfe35e13df556d7L; //## NOTE: = 6,772,910,131,135,207,127 (X10)
private static final long F21112 = 0x613bc0f2dd182425L; //## NOTE: = 7,006,405,794,628,903,973 (X9)
private static final long F21111 = 0x61c8864680b583ebL; //## NOTE: = 7,046,029,254,386,353,131 (X6)
private static final long F21122 = 0x62f74d57b54ec7bdL; //## NOTE: = 7,131,253,574,063,802,301 (X13)
private static final long F21121 = 0x6337ca73c40aaa15L; //## NOTE: = 7,149,405,532,033,034,773 (X8)
private static final long F22211 = 0x69cafdefd6caab73L; //## NOTE: = 7,623,184,525,820,603,251 (X12)
private static final long F22111 = 0x6b79682822d839d5L; //## NOTE: = 7,744,335,555,832,854,997 (X7)
private static final long F22121 = 0x6c257e88e6f7d5c9L; //## NOTE: = 7,792,773,856,690,165,193 (X11)
private static final long F11211 = -F22111; //## NOTE: ~ 10,702,408,517,876,696,623 (X5 ~ -X7)
private static final long F11112 = -F21121; //## NOTE: ~ 11,297,338,541,676,516,841 (X4 ~ -X8)
private static final long F11111 = -F21111; //## NOTE: ~ 11,400,714,819,323,198,485 (X1 ~ -X6)
private static final long F11121 = -F21211; //## NOTE: ~ 11,673,833,942,574,344,489 (X3 ~ -X10)
private static final int BUFFER_SIZE = 1<<16;
private static final Deflater DEFLAT = new Deflater(Deflater.BEST_SPEED); static { DEFLAT.setStrategy(Deflater.HUFFMAN_ONLY); }
//## attributes
private final byte b; // log_2 size
private final byte h; // no. hashing
private final byte k; // k-mer length
private final long m; // no. bits
private final long[] w; // bitset
private final byte r64_b; // Fibok hashing right shift
//## empty LHBF
public LHBF () {
this.b = B0;
this.h = B0;
this.k = B0;
this.m = B0;
this.r64_b = B0;
this.w = new long[B0];
}
//## LHBF of size m=2^b with h hashing function(s) to store k-mers of length k
public LHBF (final byte b, final byte h, final byte k) {
this.b = ( b < MIN_B ) ? MIN_B : ( b > MAX_B ) ? MAX_B : b; //## NOTE: b, the log_2 size of the BF
this.h = ( h < MIN_H ) ? MIN_H : ( h > MAX_H ) ? MAX_H : h; //## NOTE: h, the no. hashing functions
this.k = k; //## NOTE: k, the k-mer length (always odd)
this.m = 1L << b; //## NOTE: m = 2^b, the size of the BF
switch ( b ) { //## NOTE: r64_b, the fibok hashing right shift
case B31: this.w = new long[SIZE31]; r64_b = B33; break;
case B32: this.w = new long[SIZE32]; r64_b = B32; break;
case B33: this.w = new long[SIZE33]; r64_b = B31; break;
case B34: this.w = new long[SIZE34]; r64_b = B30; break;
case B35: this.w = new long[SIZE35]; r64_b = B29; break;
default: this.w = new long[SIZE36]; r64_b = B28; break;
}
}
//## LHBF with dimensions (b,h) estimated from the expected number n of element with specified false positive probability
public LHBF (final long n, final double fp, final byte k) {
final byte[] dim = computeDimension(n, fp);
this.b = ( dim[0] < MIN_B ) ? MIN_B : ( dim[0] > MAX_B ) ? MAX_B : dim[0]; //## NOTE: b, the log_2 size of the BF
this.h = ( dim[1] < MIN_H ) ? MIN_H : ( dim[1] > MAX_H ) ? MAX_H : dim[1]; //## NOTE: h, the no. hashing functions
this.k = k; //## NOTE: k, the k-mer length (always odd)
this.m = 1L << b; //## NOTE: m = 2^b, the size of the BF
switch ( b ) { //## NOTE: r64_b, the fibok hashing right shift
case B31: this.w = new long[SIZE31]; r64_b = B33; break;
case B32: this.w = new long[SIZE32]; r64_b = B32; break;
case B33: this.w = new long[SIZE33]; r64_b = B31; break;
case B34: this.w = new long[SIZE34]; r64_b = B30; break;
case B35: this.w = new long[SIZE35]; r64_b = B29; break;
default: this.w = new long[SIZE36]; r64_b = B28; break;
}
}
public LHBF (final long n, final double fp, final byte k, final boolean lessBitMoreHash) {
final byte[] dim = computeDimension(n, fp, lessBitMoreHash);
this.b = ( dim[0] < MIN_B ) ? MIN_B : ( dim[0] > MAX_B ) ? MAX_B : dim[0]; //## NOTE: b, the log_2 size of the BF
this.h = ( dim[1] < MIN_H ) ? MIN_H : ( dim[1] > MAX_H ) ? MAX_H : dim[1]; //## NOTE: h, the no. hashing functions
this.k = k; //## NOTE: k, the k-mer length (always odd)
this.m = 1L << b; //## NOTE: m = 2^b, the size of the BF
switch ( b ) { //## NOTE: r64_b, the fibok hashing right shift
case B31: this.w = new long[SIZE31]; r64_b = B33; break;
case B32: this.w = new long[SIZE32]; r64_b = B32; break;
case B33: this.w = new long[SIZE33]; r64_b = B31; break;
case B34: this.w = new long[SIZE34]; r64_b = B30; break;
case B35: this.w = new long[SIZE35]; r64_b = B29; break;
default: this.w = new long[SIZE36]; r64_b = B28; break;
}
}
//## LHBF from file written using save()
public LHBF (final String filename, final boolean zip) throws ClassNotFoundException, IOException {
final ObjectInputStream ois = (zip)
? new ObjectInputStream(new BufferedInputStream(new InflaterInputStream(new FileInputStream(filename), new Inflater(), BUFFER_SIZE), BUFFER_SIZE))
: new ObjectInputStream(new BufferedInputStream( new FileInputStream(filename), BUFFER_SIZE));
k = (byte) ois.readObject();
b = (byte) ois.readObject();
switch ( b ) {
case B31: r64_b = B33; break;
case B32: r64_b = B32; break;
case B33: r64_b = B31; break;
case B34: r64_b = B30; break;
case B35: r64_b = B29; break;
default: r64_b = B28; break;
}
m = 1L << b;
h = (byte) ois.readObject();
w = (long[]) ois.readObject();
ois.close();
}
//## saving into file
public final void save (final String filename, final boolean zip) throws IOException {
final ObjectOutputStream oos = (zip)
? new ObjectOutputStream(new BufferedOutputStream(new DeflaterOutputStream(new FileOutputStream(filename), DEFLAT, BUFFER_SIZE), BUFFER_SIZE))
: new ObjectOutputStream(new BufferedOutputStream( new FileOutputStream(filename), BUFFER_SIZE));
oos.writeObject(k);
oos.writeObject(b);
oos.writeObject(h);
oos.writeObject(w);
oos.close();
}
//## estimating optimal dimensions (h,b) from the specified no. elements n and false positive proba. fp
//## when ties, the lesser h wins
public final static byte[] computeDimension(final long n, final double fp) {
final byte[] bh = new byte[2]; bh[0] = MAX_B; bh[1] = MAX_H;
byte h_, b_ = MIN_B; --b_;
while ( ++b_ <= MAX_B ) {
h_ = B0;
while ( ++h_ <= MAX_H ) {
if ( computeFP(b_, h_, n) > fp ) continue;
if ( (1L<<bh[0]) * bh[1] >= (1L<<b_) * h_ ) { bh[0] = b_; bh[1] = h_; }
}
}
return bh;
}
//## estimating optimal dimensions (h,b) from the specified no. elements n and false positive proba. fp
//## when ties and lessBitMoreHash=true, the lesser b wins
public final static byte[] computeDimension(final long n, final double fp, final boolean lessBitMoreHash) {
if ( ! lessBitMoreHash ) return computeDimension(n, fp);
final byte[] bh = new byte[2]; bh[0] = MAX_B; bh[1] = MAX_H;
byte h_, b_ = MIN_B; --b_;
while ( ++b_ <= MAX_B ) {
h_ = B0;
while ( ++h_ <= MAX_H ) {
if ( computeFP(b_, h_, n) > fp ) continue;
if ( (1L<<bh[0]) * bh[1] > (1L<<b_) * h_ ) { bh[0] = b_; bh[1] = h_; }
}
}
return bh;
}
//## estimating the false positive probability of a BFK with specified dimensions (b,h) containing the specified number n of elements
public final static double computeFP(final byte b_, final byte h_, final long n_) { return Math.pow( -Math.expm1(-h_*(double)n_/(1L<<b_)) , h_ ); }
//## estimating the size of a BF2 in Mb
public final static int computeSizeMb(final long m_) { return (int) (m_ >> 23); }
public final static int computeSizeMb(final byte b_) { return computeSizeMb(1L<<b_); }
//## no. hashing
public final byte nHash() { return h; }
//## no. bits
public final long nBits() { return m; }
//## log_2(no. bits)
public final byte l2nBits() { return b; }
//## k-mer length
public final byte k() { return k; }
//## no. set bits
public final long cardinality() { long c = 0; for (final long l: w) c += Long.bitCount(l); return c; }
//## estimated no. elements (from Swamidass & Baldi, 2007; doi:10.1021/ci600526a)
public final long nElements() { return (long) Math.floor(- m * Math.log1p( -cardinality() / (double) m ) / h); }
//## estimated false positive probability
public final double fp() { return Math.pow(cardinality()/(double)m, h); }
//## set (kmr,krc)
public final void set (final long kmr, final long krc) {
switch ( h ) {
case B1: set(hash1(kmr,krc,r64_b)); return;
case B2: set(hash1(kmr,krc,r64_b)); set(hash2(kmr,krc,r64_b)); return;
case B3: set(hash1(kmr,krc,r64_b)); set(hash2(kmr,krc,r64_b)); set(hash3(kmr,krc,r64_b)); return;
case B4: set(hash1(kmr,krc,r64_b)); set(hash2(kmr,krc,r64_b)); set(hash3(kmr,krc,r64_b)); set(hash4(kmr,krc,r64_b)); return;
case B5: set(hash1(kmr,krc,r64_b)); set(hash2(kmr,krc,r64_b)); set(hash3(kmr,krc,r64_b)); set(hash4(kmr,krc,r64_b)); set(hash5(kmr,krc,r64_b)); return;
default: set(hash1(kmr,krc,r64_b)); set(hash2(kmr,krc,r64_b)); set(hash3(kmr,krc,r64_b)); set(hash4(kmr,krc,r64_b)); set(hash5(kmr,krc,r64_b)); set(hash6(kmr,krc,r64_b)); return;
}
}
//## get (kmr,krc)
public final boolean get (final long kmr, final long krc) {
switch ( h ) {
case B1: return get(hash1(kmr,krc,r64_b));
case B2: return get(hash1(kmr,krc,r64_b)) && get(hash2(kmr,krc,r64_b));
case B3: return get(hash1(kmr,krc,r64_b)) && get(hash2(kmr,krc,r64_b)) && get(hash3(kmr,krc,r64_b));
case B4: return get(hash1(kmr,krc,r64_b)) && get(hash2(kmr,krc,r64_b)) && get(hash3(kmr,krc,r64_b)) && get(hash4(kmr,krc,r64_b));
case B5: return get(hash1(kmr,krc,r64_b)) && get(hash2(kmr,krc,r64_b)) && get(hash3(kmr,krc,r64_b)) && get(hash4(kmr,krc,r64_b)) && get(hash5(kmr,krc,r64_b));
default: return get(hash1(kmr,krc,r64_b)) && get(hash2(kmr,krc,r64_b)) && get(hash3(kmr,krc,r64_b)) && get(hash4(kmr,krc,r64_b)) && get(hash5(kmr,krc,r64_b)) && get(hash6(kmr,krc,r64_b));
}
}
//## getset: if get, returns true; otherwise, set and returns false
public final boolean getset (final long kmr, final long krc) {
boolean bool = true;
long x = hash1(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
switch ( h ) {
case B1: return bool;
case B2:
x = hash2(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); } return bool;
case B3:
x = hash2(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash3(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); } return bool;
case B4:
x = hash2(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash3(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash4(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); } return bool;
case B5:
x = hash2(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash3(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash4(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash5(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); } return bool;
default:
x = hash2(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash3(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash4(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash5(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); }
x = hash6(kmr,krc,r64_b); if ( ! get(x) ) { bool = false; set(x); } return bool;
}
}
//## bitset get/set
private final void set (final long i) { w[div64(i)] |= lshft(i); }
private final boolean get (final long i) { return (w[div64(i)] & lshft(i)) != B0; }
private final static int div64 (final long x) { return (int) (x >> B6); }
private final static long lshft (final long x) { return 1L << x; }
//## hashing canonical k-mer
private final static long hash1 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F22211, F22121, F11211, rshft) : fibok(krc, kmr, F22211, F22121, F11211, rshft); }
private final static long hash2 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F21211, F22211, F11211, rshft) : fibok(krc, kmr, F21211, F22211, F11211, rshft); }
private final static long hash3 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F22121, F22211, F22111, rshft) : fibok(krc, kmr, F22121, F22211, F22111, rshft); }
private final static long hash4 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F21121, F21121, F11121, rshft) : fibok(krc, kmr, F21121, F21121, F11121, rshft); }
private final static long hash5 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F21112, F21211, F21121, rshft) : fibok(krc, kmr, F21112, F21211, F21121, rshft); }
private final static long hash6 (final long kmr, final long krc, final byte rshft) { return (kmr > krc) ? fibok(kmr, krc, F21111, F21121, F21211, rshft) : fibok(krc, kmr, F21111, F21121, F21211, rshft); }
private final static long fibok (final long kmax, final long kmin, final long aw, final long bw, final long cw, final byte rshft) { return (aw * ((bw * kmax) ^ (cw * kmin))) >>> rshft; }
public static void main(String[] args) {
// , , ,
int nn = 1234567890;
System.out.println("optimal dimension: b=" + LHBF.computeDimension(nn, 0.01)[0] + " h=" + LHBF.computeDimension(nn, 0.01)[1]);
LHBF lhbf = new LHBF(B33, B4, B25);
System.out.println("b=" + lhbf.l2nBits() + " m=" + lhbf.nBits() + " h=" + lhbf.nHash() + " size=" + LHBF.computeSizeMb(lhbf.l2nBits()) + "Mb");
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment