#ifndef _EBPPS_SAMPLE_HPP_
#define _EBPPS_SAMPLE_HPP_
#include "common_defs.hpp"
#include "optional.hpp"
#include "serde.hpp"
#include <memory>
#include <vector>
namespace datasketches {
template<
typename T,
typename A = std::allocator<T>
>
class ebpps_sample {
public:
explicit ebpps_sample(uint32_t k, const A& allocator = A());
class items_deleter;
ebpps_sample(std::vector<T, A>&& data, optional<T>&& partial_item, double c, const A& allocator = A());
template<typename TT>
void replace_content(TT&& item, double theta);
void reset();
void downsample(double theta);
template<typename FwdSample>
void merge(FwdSample&& other);
using result_type = std::vector<T, A>;
result_type get_sample() const;
double get_c() const;
result_type get_full_items() const;
bool has_partial_item() const;
T get_partial_item() const;
string<A> to_string() const;
inline uint32_t get_num_retained_items() const;
template<typename TT = T, typename SerDe = serde<T>, typename std::enable_if<std::is_arithmetic<TT>::value, int>::type = 0>
inline size_t get_serialized_size_bytes(const SerDe& sd = SerDe()) const;
template<typename TT = T, typename SerDe = serde<T>, typename std::enable_if<!std::is_arithmetic<TT>::value, int>::type = 0>
inline size_t get_serialized_size_bytes(const SerDe& sd = SerDe()) const;
using vector_bytes = std::vector<uint8_t, typename std::allocator_traits<A>::template rebind_alloc<uint8_t>>;
template<typename SerDe = serde<T>>
size_t serialize(uint8_t* ptr, const uint8_t* end_ptr, const SerDe& sd = SerDe()) const;
template<typename SerDe = serde<T>>
void serialize(std::ostream& os, const SerDe& sd = SerDe()) const;
template<typename SerDe = serde<T>>
static std::pair<ebpps_sample, size_t> deserialize(const uint8_t* ptr, size_t size, const SerDe& sd = SerDe(), const A& allocator = A());
template<typename SerDe = serde<T>>
static ebpps_sample deserialize(std::istream& is, const SerDe& sd = SerDe(), const A& allocator = A());
class const_iterator;
const_iterator begin() const;
const_iterator end() const;
private:
A allocator_;
double c_; optional<T> partial_item_; std::vector<T, A> data_;
template<typename FwdItem>
inline void set_partial(FwdItem&& item);
void swap_with_partial();
void move_one_to_partial();
void subsample(uint32_t num_samples);
static inline uint32_t random_idx(uint32_t max);
static inline double next_double();
friend class const_iterator;
};
template<typename T, typename A>
class ebpps_sample<T, A>::const_iterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = const T&;
using difference_type = void;
using pointer = const return_value_holder<value_type>;
using reference = value_type;
const_iterator(const const_iterator& other);
const_iterator& operator++();
const_iterator& operator++(int);
bool operator==(const const_iterator& other) const;
bool operator!=(const const_iterator& other) const;
reference operator*() const;
pointer operator->() const;
private:
static const size_t PARTIAL_IDX = static_cast<size_t>(-1);
const_iterator(const ebpps_sample<T, A>* sample);
const ebpps_sample<T, A>* sample_;
size_t idx_;
bool use_partial_;
friend class ebpps_sample;
};
}
#include "ebpps_sample_impl.hpp"
#endif