#ifndef ARRAY_TUPLE_SKETCH_HPP_
#define ARRAY_TUPLE_SKETCH_HPP_
#include <vector>
#include <memory>
#include "serde.hpp"
#include "tuple_sketch.hpp"
namespace datasketches {
template<typename T, typename Allocator = std::allocator<T>>
class array {
public:
using value_type = T;
using allocator_type = Allocator;
explicit array(uint8_t size, T value, const Allocator& allocator = Allocator()):
allocator_(allocator), size_(size), array_(allocator_.allocate(size_)) {
std::fill(array_, array_ + size_, value);
}
array(const array& other):
allocator_(other.allocator_),
size_(other.size_),
array_(allocator_.allocate(size_))
{
std::copy(other.array_, other.array_ + size_, array_);
}
array(array&& other) noexcept:
allocator_(std::move(other.allocator_)),
size_(other.size_),
array_(other.array_)
{
other.array_ = nullptr;
}
~array() {
if (array_ != nullptr) allocator_.deallocate(array_, size_);
}
array& operator=(const array& other) {
array copy(other);
std::swap(allocator_, copy.allocator_);
std::swap(size_, copy.size_);
std::swap(array_, copy.array_);
return *this;
}
array& operator=(array&& other) {
std::swap(allocator_, other.allocator_);
std::swap(size_, other.size_);
std::swap(array_, other.array_);
return *this;
}
T& operator[](size_t index) { return array_[index]; }
T operator[](size_t index) const { return array_[index]; }
uint8_t size() const { return size_; }
T* data() { return array_; }
const T* data() const { return array_; }
bool operator==(const array& other) const {
for (uint8_t i = 0; i < size_; ++i) if (array_[i] != other.array_[i]) return false;
return true;
}
private:
Allocator allocator_;
uint8_t size_;
T* array_;
};
template<typename Array, typename Allocator = typename Array::allocator_type>
class default_array_tuple_update_policy {
public:
default_array_tuple_update_policy(uint8_t num_values = 1, const Allocator& allocator = Allocator()):
allocator_(allocator), num_values_(num_values) {}
Array create() const {
return Array(num_values_, 0, allocator_);
}
template<typename InputArray> void update(Array& array, const InputArray& update) const {
for (uint8_t i = 0; i < num_values_; ++i) array[i] += update[i];
}
uint8_t get_num_values() const {
return num_values_;
}
private:
Allocator allocator_;
uint8_t num_values_;
};
template<typename Array, typename Allocator> class compact_array_tuple_sketch;
template<
typename Array,
typename Policy = default_array_tuple_update_policy<Array>,
typename Allocator = typename Array::allocator_type
>
class update_array_tuple_sketch: public update_tuple_sketch<Array, Array, Policy, Allocator> {
public:
using Base = update_tuple_sketch<Array, Array, Policy, Allocator>;
using resize_factor = typename Base::resize_factor;
class builder;
compact_array_tuple_sketch<Array, Allocator> compact(bool ordered = true) const;
uint8_t get_num_values() const;
private:
update_array_tuple_sketch(uint8_t lg_cur_size, uint8_t lg_nom_size, resize_factor rf, float p, uint64_t theta,
uint64_t seed, const Policy& policy, const Allocator& allocator);
};
template<typename Array, typename Policy, typename Allocator>
class update_array_tuple_sketch<Array, Policy, Allocator>::builder: public tuple_base_builder<builder, Policy, Allocator> {
public:
builder(const Policy& policy = Policy(), const Allocator& allocator = Allocator());
update_array_tuple_sketch build() const;
};
template<
typename Array,
typename Allocator = typename Array::allocator_type
>
class compact_array_tuple_sketch: public compact_tuple_sketch<Array, Allocator> {
public:
using Base = compact_tuple_sketch<Array, Allocator>;
using Entry = typename Base::Entry;
using AllocEntry = typename Base::AllocEntry;
using AllocU64 = typename Base::AllocU64;
using vector_bytes = typename Base::vector_bytes;
static const uint8_t SERIAL_VERSION = 1;
static const uint8_t SKETCH_FAMILY = 9;
static const uint8_t SKETCH_TYPE = 3;
enum flags { UNUSED1, UNUSED2, IS_EMPTY, HAS_ENTRIES, IS_ORDERED };
template<typename Sketch>
compact_array_tuple_sketch(const Sketch& other, bool ordered = true);
uint8_t get_num_values() const;
void serialize(std::ostream& os) const;
vector_bytes serialize(unsigned header_size_bytes = 0) const;
static compact_array_tuple_sketch deserialize(std::istream& is, uint64_t seed = DEFAULT_SEED, const Allocator& allocator = Allocator());
static compact_array_tuple_sketch deserialize(const void* bytes, size_t size, uint64_t seed = DEFAULT_SEED,
const Allocator& allocator = Allocator());
private:
uint8_t num_values_;
template<typename Ar, typename P, typename Al> friend class array_tuple_union;
template<typename Ar, typename P, typename Al> friend class array_tuple_intersection;
template<typename Ar, typename Al> friend class array_tuple_a_not_b;
compact_array_tuple_sketch(bool is_empty, bool is_ordered, uint16_t seed_hash, uint64_t theta, std::vector<Entry, AllocEntry>&& entries, uint8_t num_values);
compact_array_tuple_sketch(uint8_t num_values, Base&& base);
};
}
#include "array_tuple_sketch_impl.hpp"
#endif