/// <summary> /// Convert a <see cref="IInvertibleBloomFilterData{TId, THash, TCount}"/> to a concrete <see cref="InvertibleBloomFilterData{TId, THash, TCount}"/>. /// </summary> /// <typeparam name="TId">The identifier type</typeparam> /// <typeparam name="THash">The entity hash type</typeparam> /// <typeparam name="TCount">The occurence count type</typeparam> /// <param name="filterData">The IBF data</param> /// <param name="configuration"></param> /// <returns></returns> internal static InvertibleBloomFilterData <TId, THash, TCount> ConvertToBloomFilterData <TId, THash, TCount>( this IInvertibleBloomFilterData <TId, THash, TCount> filterData, ICountingBloomFilterConfiguration <TId, THash, TCount> configuration) where TId : struct where TCount : struct where THash : struct { if (filterData == null) { return(null); } var result = filterData as InvertibleBloomFilterData <TId, THash, TCount>; if (result != null) { result.SyncCompressionProviders(configuration); return(result); } var res = new InvertibleBloomFilterData <TId, THash, TCount> { HashFunctionCount = filterData.HashFunctionCount, BlockSize = filterData.BlockSize, HashSums = filterData.HashSumProvider.ToArray(), Counts = filterData.Counts, IdSums = filterData.IdSumProvider.ToArray(), IsReverse = filterData.IsReverse, SubFilter = filterData.SubFilter, Capacity = filterData.Capacity, ItemCount = filterData.ItemCount, ErrorRate = filterData.ErrorRate }; res.SyncCompressionProviders(configuration); return(res); }
/// <summary> /// Create new Bloom filter data based upon the size and the hash function count. /// </summary> /// <typeparam name="TId">Type of the identifier</typeparam> /// <typeparam name="TCount">Type of the counter</typeparam> /// <typeparam name="TEntity"></typeparam> /// <param name="capacity"></param> /// <param name="m">Size per hash function</param> /// <param name="k">The number of hash functions.</param> /// <returns>The Bloom filter data</returns> public InvertibleBloomFilterData <TId, THash, TCount> Create <TEntity, TId, THash, TCount>( IInvertibleBloomFilterConfiguration <TEntity, TId, THash, TCount> configuration, long capacity, long m, uint k) where TId : struct where TCount : struct where THash : struct { if (m < 1) // from overflow in bestM calculation { throw new ArgumentOutOfRangeException( nameof(m), "The provided capacity and errorRate values would result in an array of length > long.MaxValue. Please reduce either the capacity or the error rate."); } var res = new InvertibleBloomFilterData <TId, THash, TCount> { HashFunctionCount = k, BlockSize = m, Counts = new TCount[m], Capacity = capacity, ErrorRate = configuration.ActualErrorRate(m, capacity, k) }; res.SyncCompressionProviders(configuration); return(res); }
/// <summary> /// Initialize the Bloom filter /// </summary> /// <param name="capacity">Capacity</param> /// <param name="m">Size per hash function</param> /// <param name="k">Number of hash functions.</param> public virtual void Initialize(long capacity, long m, uint k) { // validate the params are in range if (!Configuration.Supports(capacity, m)) { throw new ArgumentOutOfRangeException( $"The size {m} of the Bloom filter is not large enough to hold {capacity} items."); } Data = Configuration.DataFactory.Create(Configuration, capacity, m, k); }
/// <summary> /// The given <paramref name="position"/> is not considered relevant when the count for that position equals the identity. /// </summary> /// <param name="configuration"></param> /// <param name="data"></param> /// <param name="position"></param> /// <returns></returns> private static bool IsMember( ICountConfiguration <TCount> configuration, InvertibleBloomFilterData <TId, THash, TCount> data, long position) { return(configuration .Comparer .Compare( configuration.Identity, data.Counts[position]) != 0); }
/// <summary> /// Set the data for this Bloom filter. /// </summary> /// <param name="data">The data to restore</param> public virtual void Rehydrate(IInvertibleBloomFilterData <TId, int, TCount> data) { if (data == null) { return; } if (!data.IsValid()) { throw new ArgumentException( "Invertible Bloom filter data is invalid.", nameof(data)); } Data = data.ConvertToBloomFilterData(Configuration); ValidateData(); }