// !!! DO NOT EDIT - THIS IS AN AUTO-GENERATED FILE !!!
// Created by amalgamation.sh on 2023-12-16T02:52:00Z

/*
 * The CRoaring project is under a dual license (Apache/MIT).
 * Users of the library may choose one or the other license.
 */
/*
 * Copyright 2016-2022 The CRoaring authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
/*
 * MIT License
 *
 * Copyright 2016-2022 The CRoaring authors
 *
 * Permission is hereby granted, free of charge, to any
 * person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the
 * Software without restriction, including without
 * limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software
 * is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice
 * shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
 * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
 * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * SPDX-License-Identifier: MIT
 */

#define ROARING_API_NOT_IN_GLOBAL_NAMESPACE  // see remarks in roaring.h
#include "roaring.h"
#undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE
/* begin file cpp/roaring.hh */
/*
A C++ header for Roaring Bitmaps.
*/
#ifndef INCLUDE_ROARING_HH_
#define INCLUDE_ROARING_HH_

#include <cstdarg>

#include <algorithm>
#include <initializer_list>
#include <new>
#include <stdexcept>
#include <string>

#if !defined(ROARING_EXCEPTIONS)
// __cpp_exceptions is required by C++98 and we require C++11 or better.
#ifndef __cpp_exceptions
#error "__cpp_exceptions should be defined"
#endif
# if __cpp_exceptions
#  define ROARING_EXCEPTIONS 1
# else
#  define ROARING_EXCEPTIONS 0
# endif
#endif

#ifndef ROARING_TERMINATE
# if ROARING_EXCEPTIONS
#  define ROARING_TERMINATE(_s) throw std::runtime_error(_s)
# else
#  define ROARING_TERMINATE(_s) std::terminate()
# endif
#endif

#define ROARING_API_NOT_IN_GLOBAL_NAMESPACE  // see remarks in roaring.h
#undef ROARING_API_NOT_IN_GLOBAL_NAMESPACE


namespace paimon::roaring {

class RoaringSetBitForwardIterator;

/**
 * A bit of context usable with `*Bulk()` functions.
 *
 * A context may only be used with a single bitmap, and any modification to a bitmap
 * (other than modifications performed with `Bulk()` functions with the context
 * passed) will invalidate any contexts associated with that bitmap.
 */
class BulkContext {
   public:
    friend class Roaring;
    using roaring_bitmap_bulk_context_t = internal::roaring_bulk_context_t;
    BulkContext() : context_{nullptr, 0, 0, 0} {}

    BulkContext(const BulkContext&) = delete;
    BulkContext& operator=(const BulkContext&) = delete;
    BulkContext(BulkContext&&) noexcept = default;
    BulkContext& operator=(BulkContext&&) noexcept = default;

   private:
    roaring_bitmap_bulk_context_t context_;
};

class Roaring {
    typedef internal::roaring_bitmap_t roaring_bitmap_t;  // class-local name alias

public:
    /**
     * Create an empty bitmap in the existing memory for the class.
     * The bitmap will be in the "clear" state with no auxiliary allocations.
     */
    Roaring() : roaring{} {
        // The empty constructor roaring{} silences warnings from pedantic static analyzers.
        internal::roaring_bitmap_init_cleared(&roaring);
    }

    /**
     * Construct a bitmap from a list of 32-bit integer values.
     */
    Roaring(size_t n, const uint32_t *data) : Roaring() {
        internal::roaring_bitmap_add_many(&roaring, n, data);
    }

    /**
     * Construct a bitmap from an initializer list.
     */
    Roaring(std::initializer_list<uint32_t> l) : Roaring() {
        addMany(l.size(), l.begin());
    }

    /**
     * Copy constructor.
     * It may throw std::runtime_error if there is insufficient memory.
     */
    Roaring(const Roaring &r) : Roaring() {
        if (!internal::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
            ROARING_TERMINATE("failed roaring_bitmap_overwrite in constructor");
        }
        internal::roaring_bitmap_set_copy_on_write(
            &roaring,
            internal::roaring_bitmap_get_copy_on_write(&r.roaring));
    }

    /**
     * Move constructor. The moved-from object remains valid but empty, i.e.
     * it behaves as though it was just freshly constructed.
     */
    Roaring(Roaring &&r) noexcept : roaring(r.roaring) {
        //
        // !!! This clones the bits of the roaring structure to a new location
        // and then overwrites the old bits...assuming that this will still
        // work.  There are scenarios where this could break; e.g. if some of
        // those bits were pointers into the structure memory itself.  If such
        // things were possible, a roaring_bitmap_move() API would be needed.
        //
        internal::roaring_bitmap_init_cleared(&r.roaring);
    }

    /**
     * Construct a roaring object by taking control of a malloc()'d C struct.
     *
     * Passing a NULL pointer is unsafe.
     * The pointer to the C struct will be invalid after the call.
     */
    explicit Roaring(roaring_bitmap_t *s) noexcept : roaring (*s) {
        roaring_free(s);  // deallocate the passed-in pointer
    }

    /**
     * Construct a bitmap from a list of uint32_t values.
     */
    static Roaring bitmapOf(size_t n, ...) {
        Roaring ans;
        va_list vl;
        va_start(vl, n);
        for (size_t i = 0; i < n; i++) {
            ans.add(va_arg(vl, uint32_t));
        }
        va_end(vl);
        return ans;
    }

    /**
     * Construct a bitmap from a list of uint32_t values.
     * E.g., bitmapOfList({1,2,3}).
     */
    static Roaring bitmapOfList(std::initializer_list<uint32_t> l) {
        Roaring ans;
        ans.addMany(l.size(), l.begin());
        return ans;
    }

    /**
     * Add value x
     */
    void add(uint32_t x) noexcept { internal::roaring_bitmap_add(&roaring, x); }

    /**
     * Add value x
     * Returns true if a new value was added, false if the value was already
     * existing.
     */
    bool addChecked(uint32_t x) noexcept {
        return internal::roaring_bitmap_add_checked(&roaring, x);
    }

    /**
     * Add all values in range [min, max)
     */
    void addRange(const uint64_t min, const uint64_t max) noexcept {
        return internal::roaring_bitmap_add_range(&roaring, min, max);
    }

    /**
     * Add all values in range [min, max]
     */
    void addRangeClosed(const uint32_t min, const uint32_t max) noexcept {
        return internal::roaring_bitmap_add_range_closed(&roaring, min, max);
    }

    /**
     * Add value n_args from pointer vals
     */
    void addMany(size_t n_args, const uint32_t *vals) noexcept {
        internal::roaring_bitmap_add_many(&roaring, n_args, vals);
    }

    /**
     * Add value val, using context from a previous insert for speed
     * optimization.
     *
     * `context` will be used to store information between calls to make bulk
     * operations faster. `context` should be default-initialized before the
     * first call to this function.
     */
    void addBulk(BulkContext &context, uint32_t x) noexcept {
        internal::roaring_bitmap_add_bulk(&roaring, &context.context_, x);
    }

    /**
     * Check if item x is present, using context from a previous insert or search
     * for speed optimization.
     *
     * `context` will be used to store information between calls to make bulk
     * operations faster. `context` should be default-initialized before the
     * first call to this function.
     */
    bool containsBulk(BulkContext& context, uint32_t x) const noexcept {
        return internal::roaring_bitmap_contains_bulk(&roaring, &context.context_, x);
    }

    /**
     * Remove value x
     */
    void remove(uint32_t x) noexcept { internal::roaring_bitmap_remove(&roaring, x); }

    /**
     * Remove value x
     * Returns true if a new value was removed, false if the value was not
     * existing.
     */
    bool removeChecked(uint32_t x) noexcept {
        return internal::roaring_bitmap_remove_checked(&roaring, x);
    }

    /**
     * Remove all values in range [min, max)
     */
    void removeRange(uint64_t min, uint64_t max) noexcept {
        return internal::roaring_bitmap_remove_range(&roaring, min, max);
    }

    /**
     * Remove all values in range [min, max]
     */
    void removeRangeClosed(uint32_t min, uint32_t max) noexcept {
        return internal::roaring_bitmap_remove_range_closed(&roaring, min, max);
    }

    /**
     * Return the largest value (if not empty)
     */
    uint32_t maximum() const noexcept { return internal::roaring_bitmap_maximum(&roaring); }

    /**
     * Return the smallest value (if not empty)
     */
    uint32_t minimum() const noexcept { return internal::roaring_bitmap_minimum(&roaring); }

    /**
     * Check if value x is present
     */
    bool contains(uint32_t x) const noexcept {
        return internal::roaring_bitmap_contains(&roaring, x);
    }

    /**
     * Check if all values from x (included) to y (excluded) are present
     */
    bool containsRange(const uint64_t x, const uint64_t y) const noexcept {
        return internal::roaring_bitmap_contains_range(&roaring, x, y);
    }

    /**
     * Destructor.  By contract, calling roaring_bitmap_clear() is enough to
     * release all auxiliary memory used by the structure.
     */
    ~Roaring() {
        if (!(roaring.high_low_container.flags & ROARING_FLAG_FROZEN)) {
            internal::roaring_bitmap_clear(&roaring);
        } else {
            // The roaring member variable copies the `roaring_bitmap_t` and
            // nested `roaring_array_t` structures by value and is freed in the
            // constructor, however the underlying memory arena used for the
            // container data is not freed with it. Here we derive the arena
            // pointer from the second arena allocation in
            // `roaring_bitmap_frozen_view` and free it as well.
            roaring_bitmap_free(
                (roaring_bitmap_t *)((char *)
                                     roaring.high_low_container.containers -
                                     sizeof(roaring_bitmap_t)));
        }
    }

    /**
     * Copies the content of the provided bitmap, and
     * discard the current content.
     * It may throw std::runtime_error if there is insufficient memory.
     */
    Roaring &operator=(const Roaring &r) {
        if (!internal::roaring_bitmap_overwrite(&roaring, &r.roaring)) {
            ROARING_TERMINATE("failed memory alloc in assignment");
        }
        internal::roaring_bitmap_set_copy_on_write(
            &roaring,
            internal::roaring_bitmap_get_copy_on_write(&r.roaring));
        return *this;
    }

    /**
     * Moves the content of the provided bitmap, and
     * discard the current content.
     */
    Roaring &operator=(Roaring &&r) noexcept {
        internal::roaring_bitmap_clear(&roaring);  // free this class's allocations

        // !!! See notes in the Move Constructor regarding roaring_bitmap_move()
        //
        roaring = r.roaring;
        internal::roaring_bitmap_init_cleared(&r.roaring);

        return *this;
    }

    /**
     * Assignment from an initializer list.
     */
    Roaring &operator=(std::initializer_list<uint32_t> l) {
        // Delegate to move assignment operator
        *this = Roaring(l);
        return *this;
    }

    /**
     * Compute the intersection between the current bitmap and the provided
     * bitmap, writing the result in the current bitmap. The provided bitmap
     * is not modified.
     *
     * Performance hint: if you are computing the intersection between several
     * bitmaps, two-by-two, it is best to start with the smallest bitmap.
     */
    Roaring &operator&=(const Roaring &r) noexcept {
        internal::roaring_bitmap_and_inplace(&roaring, &r.roaring);
        return *this;
    }

    /**
     * Compute the difference between the current bitmap and the provided
     * bitmap, writing the result in the current bitmap. The provided bitmap
     * is not modified.
     */
    Roaring &operator-=(const Roaring &r) noexcept {
        internal::roaring_bitmap_andnot_inplace(&roaring, &r.roaring);
        return *this;
    }

    /**
     * Compute the union between the current bitmap and the provided bitmap,
     * writing the result in the current bitmap. The provided bitmap is not
     * modified.
     *
     * See also the fastunion function to aggregate many bitmaps more quickly.
     */
    Roaring &operator|=(const Roaring &r) noexcept {
        internal::roaring_bitmap_or_inplace(&roaring, &r.roaring);
        return *this;
    }

    /**
     * Compute the symmetric union between the current bitmap and the provided
     * bitmap, writing the result in the current bitmap. The provided bitmap
     * is not modified.
     */
    Roaring &operator^=(const Roaring &r) noexcept {
        internal::roaring_bitmap_xor_inplace(&roaring, &r.roaring);
        return *this;
    }

    /**
     * Exchange the content of this bitmap with another.
     */
    void swap(Roaring &r) noexcept { std::swap(r.roaring, roaring); }

    /**
     * Get the cardinality of the bitmap (number of elements).
     */
    uint64_t cardinality() const noexcept {
        return internal::roaring_bitmap_get_cardinality(&roaring);
    }

    /**
     * Returns true if the bitmap is empty (cardinality is zero).
     */
    bool isEmpty() const noexcept { return internal::roaring_bitmap_is_empty(&roaring); }

    /**
     * Returns true if the bitmap is subset of the other.
     */
    bool isSubset(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_is_subset(&roaring, &r.roaring);
    }

    /**
     * Returns true if the bitmap is strict subset of the other.
     */
    bool isStrictSubset(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_is_strict_subset(&roaring, &r.roaring);
    }

    /**
     * Convert the bitmap to an array. Write the output to "ans", caller is
     * responsible to ensure that there is enough memory allocated
     * (e.g., ans = new uint32[mybitmap.cardinality()];)
     */
    void toUint32Array(uint32_t *ans) const noexcept {
        internal::roaring_bitmap_to_uint32_array(&roaring, ans);
    }
    /**
     * To int array with pagination
     */
    void rangeUint32Array(uint32_t *ans, size_t offset, size_t limit) const noexcept {
        internal::roaring_bitmap_range_uint32_array(&roaring, offset, limit, ans);
    }

    /**
     * Return true if the two bitmaps contain the same elements.
     */
    bool operator==(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_equals(&roaring, &r.roaring);
    }

    /**
     * Compute the negation of the roaring bitmap within the half-open interval
     * [range_start, range_end). Areas outside the interval are unchanged.
     */
    void flip(uint64_t range_start, uint64_t range_end) noexcept {
        internal::roaring_bitmap_flip_inplace(&roaring, range_start, range_end);
    }

    /**
     * Compute the negation of the roaring bitmap within the closed interval
     * [range_start, range_end]. Areas outside the interval are unchanged.
     */
    void flipClosed(uint32_t range_start, uint32_t range_end) noexcept {
        internal::roaring_bitmap_flip_inplace(
            &roaring, range_start, uint64_t(range_end) + 1);
    }

    /**
     * Remove run-length encoding even when it is more space efficient.
     * Return whether a change was applied.
     */
    bool removeRunCompression() noexcept {
        return internal::roaring_bitmap_remove_run_compression(&roaring);
    }

    /**
     * Convert array and bitmap containers to run containers when it is more
     * efficient; also convert from run containers when more space efficient.
     * Returns true if the result has at least one run container.  Additional
     * savings might be possible by calling shrinkToFit().
     */
    bool runOptimize() noexcept { return internal::roaring_bitmap_run_optimize(&roaring); }

    /**
     * If needed, reallocate memory to shrink the memory usage. Returns
     * the number of bytes saved.
     */
    size_t shrinkToFit() noexcept { return internal::roaring_bitmap_shrink_to_fit(&roaring); }

    /**
     * Iterate over the bitmap elements. The function iterator is called once
     * for all the values with ptr (can be NULL) as the second parameter of
     * each call.
     *
     * roaring_iterator is simply a pointer to a function that returns bool
     * (true means that the iteration should continue while false means that it
     * should stop), and takes (uint32_t,void*) as inputs.
     */
    void iterate(internal::roaring_iterator iterator, void *ptr) const {
        internal::roaring_iterate(&roaring, iterator, ptr);
    }

    /**
     * Selects the value at index rnk in the bitmap, where the smallest value
     * is at index 0.
     *
     * If the size of the roaring bitmap is strictly greater than rank, then
     * this function returns true and sets element to the element of given rank.
     * Otherwise, it returns false.
     */
    bool select(uint32_t rnk, uint32_t *element) const noexcept {
        return internal::roaring_bitmap_select(&roaring, rnk, element);
    }

    /**
     * Computes the size of the intersection between two bitmaps.
     */
    uint64_t and_cardinality(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_and_cardinality(&roaring, &r.roaring);
    }

    /**
     * Check whether the two bitmaps intersect.
     */
    bool intersect(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_intersect(&roaring, &r.roaring);
    }

    /**
     * Computes the Jaccard index between two bitmaps. (Also known as the
     * Tanimoto distance,
     * or the Jaccard similarity coefficient)
     *
     * The Jaccard index is undefined if both bitmaps are empty.
     */
    double jaccard_index(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_jaccard_index(&roaring, &r.roaring);
    }

    /**
     * Computes the size of the union between two bitmaps.
     */
    uint64_t or_cardinality(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_or_cardinality(&roaring, &r.roaring);
    }

    /**
     * Computes the size of the difference (andnot) between two bitmaps.
     */
    uint64_t andnot_cardinality(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_andnot_cardinality(&roaring, &r.roaring);
    }

    /**
     * Computes the size of the symmetric difference (andnot) between two
     * bitmaps.
     */
    uint64_t xor_cardinality(const Roaring &r) const noexcept {
        return internal::roaring_bitmap_xor_cardinality(&roaring, &r.roaring);
    }

    /**
     * Returns the number of integers that are smaller or equal to x.
     * Thus the rank of the smallest element is one.  If
     * x is smaller than the smallest element, this function will return 0.
     * The rank and select functions differ in convention: this function returns
     * 1 when ranking the smallest value, but the select function returns the
     * smallest value when using index 0.
     */
    uint64_t rank(uint32_t x) const noexcept {
        return internal::roaring_bitmap_rank(&roaring, x);
    }

    /**
     * Get `rank()` values in bulk. The values in `[begin .. end)` must be in Ascending order.
     * possible implementation: for(auto* iter = begin; iter != end; ++iter) *(ans++) = rank(*iter);
     */
    void rank_many(const uint32_t* begin, const uint32_t* end, uint64_t* ans) const noexcept {
        return internal::roaring_bitmap_rank_many(&roaring, begin, end, ans);
    }

    /**
     * Returns the index of x in the set, index start from 0.
     * If the set doesn't contain x , this function will return -1.
     * The difference with rank function is that this function will return -1
     * when x isn't in the set, but the rank function will return a
     * non-negative number.
     */
    int64_t getIndex(uint32_t x) const noexcept {
        return internal::roaring_bitmap_get_index(&roaring, x);
    }

    /**
     * Write a bitmap to a char buffer. This is meant to be compatible with
     * the Java and Go versions. Returns how many bytes were written which
     * should be getSizeInBytes().
     *
     * Setting the portable flag to false enable a custom format that
     * can save space compared to the portable format (e.g., for very
     * sparse bitmaps).
     *
     * Boost users can serialize bitmaps in this manner:
     *
     *       BOOST_SERIALIZATION_SPLIT_FREE(Roaring)
     *       namespace boost {
     *       namespace serialization {
     *
     *       template <class Archive>
     *       void save(Archive& ar, const Roaring& bitmask,
     *          const unsigned int version) {
     *         std::size_t expected_size_in_bytes = bitmask.getSizeInBytes();
     *         std::vector<char> buffer(expected_size_in_bytes);
     *         std::size_t       size_in_bytes = bitmask.write(buffer.data());
     *
     *         ar& size_in_bytes;
     *         ar& boost::serialization::make_binary_object(buffer.data(),
     *             size_in_bytes);
     *      }
     *      template <class Archive>
     *      void load(Archive& ar, Roaring& bitmask,
     *          const unsigned int version) {
     *         std::size_t size_in_bytes = 0;
     *         ar& size_in_bytes;
     *         std::vector<char> buffer(size_in_bytes);
     *         ar&  boost::serialization::make_binary_object(buffer.data(),
     *            size_in_bytes);
     *         bitmask = Roaring::readSafe(buffer.data(), size_in_bytes);
     *      }
     *      }  // namespace serialization
     *      }  // namespace boost
     */
    size_t write(char *buf, bool portable = true) const noexcept {
        if (portable) {
            return internal::roaring_bitmap_portable_serialize(&roaring, buf);
        } else {
            return internal::roaring_bitmap_serialize(&roaring, buf);
        }
    }

    /**
     * Read a bitmap from a serialized version. This is meant to be compatible
     * with the Java and Go versions.
     *
     * Setting the portable flag to false enable a custom format that
     * can save space compared to the portable format (e.g., for very
     * sparse bitmaps).
     *
     * This function is unsafe in the sense that if you provide bad data,
     * many, many bytes could be read. See also readSafe.
     *
     * The function may throw std::runtime_error if a bitmap could not be read. Not that even
     * if it does not throw, the bitmap could still be unusable if the loaded
     * data does not match the portable Roaring specification: you should
     * ensure that the data you load come from a serialized bitmap.
     */
    static Roaring read(const char *buf, bool portable = true) {
        roaring_bitmap_t * r = portable
            ? internal::roaring_bitmap_portable_deserialize(buf)
            : internal::roaring_bitmap_deserialize(buf);
        if (r == NULL) {
            ROARING_TERMINATE("failed alloc while reading");
        }
        return Roaring(r);
    }

    /**
     * Read a bitmap from a serialized version, reading no more than maxbytes
     * bytes.  This is meant to be compatible with the Java and Go versions.
     * The function itself is safe in the sense that it will not cause buffer overflows.
     * However, for correct operations, it is assumed that the bitmap read was once
     * serialized from a valid bitmap. If you provided an incorrect input (garbage), then the
     * bitmap read may not be in a valid state and following operations may not lead
     * to sensible results. It is your responsability to ensure that the input bytes
     * follow the format specification if you want a usable bitmap:
     * https://github.com/RoaringBitmap/RoaringFormatSpec
     * In particular, the serialized array containers need to be in sorted order, and the
     * run containers should be in sorted non-overlapping order. This is is guaranteed to
     * happen when serializing an existing bitmap, but not for random inputs.
     * Note that this function assumes that your bitmap was serialized in *portable* mode
     * (which is the default with the 'write' method).
     *
     * The function may throw std::runtime_error if a bitmap could not be read. Not that even
     * if it does not throw, the bitmap could still be unusable if the loaded
     * data does not match the portable Roaring specification: you should
     * ensure that the data you load come from a serialized bitmap.
     */
    static Roaring readSafe(const char *buf, size_t maxbytes) {
        roaring_bitmap_t * r =
            internal::roaring_bitmap_portable_deserialize_safe(buf,maxbytes);
        if (r == NULL) {
            ROARING_TERMINATE("failed alloc while reading");
        }
        return Roaring(r);
    }

    /**
     * How many bytes are required to serialize this bitmap (meant to be
     * compatible with Java and Go versions)
     *
     * Setting the portable flag to false enable a custom format that
     * can save space compared to the portable format (e.g., for very
     * sparse bitmaps).
     */
    size_t getSizeInBytes(bool portable = true) const noexcept {
        if (portable) {
            return internal::roaring_bitmap_portable_size_in_bytes(&roaring);
        } else {
            return internal::roaring_bitmap_size_in_bytes(&roaring);
        }
    }

    /**
     * For advanced users.
     * This function may throw std::runtime_error.
     */
    static const Roaring frozenView(const char *buf, size_t length) {
        const roaring_bitmap_t *s =
            internal::roaring_bitmap_frozen_view(buf, length);
        if (s == NULL) {
            ROARING_TERMINATE("failed to read frozen bitmap");
        }
        Roaring r;
        r.roaring = *s;
        return r;
    }

    /**
     * For advanced users.
     */
    void writeFrozen(char *buf) const noexcept {
        roaring_bitmap_frozen_serialize(&roaring, buf);
    }

    /**
     * For advanced users.
     */
    size_t getFrozenSizeInBytes() const noexcept {
        return roaring_bitmap_frozen_size_in_bytes(&roaring);
    }

    /**
     * Computes the intersection between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     *
     * Performance hint: if you are computing the intersection between several
     * bitmaps, two-by-two, it is best to start with the smallest bitmap.
     * Consider also using the operator &= to avoid needlessly creating
     * many temporary bitmaps.
     * This function may throw std::runtime_error.
     */
    Roaring operator&(const Roaring &o) const {
        roaring_bitmap_t *r = internal::roaring_bitmap_and(&roaring, &o.roaring);
        if (r == NULL) {
            ROARING_TERMINATE("failed materalization in and");
        }
        return Roaring(r);
    }

    /**
     * Computes the difference between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     * This function may throw std::runtime_error.
     */
    Roaring operator-(const Roaring &o) const {
        roaring_bitmap_t *r = internal::roaring_bitmap_andnot(&roaring, &o.roaring);
        if (r == NULL) {
            ROARING_TERMINATE("failed materalization in andnot");
        }
        return Roaring(r);
    }

    /**
     * Computes the union between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     * This function may throw std::runtime_error.
     */
    Roaring operator|(const Roaring &o) const {
        roaring_bitmap_t *r = internal::roaring_bitmap_or(&roaring, &o.roaring);
        if (r == NULL) {
            ROARING_TERMINATE("failed materalization in or");
        }
        return Roaring(r);
    }

    /**
     * Computes the symmetric union between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     * This function may throw std::runtime_error.
     */
    Roaring operator^(const Roaring &o) const {
        roaring_bitmap_t *r = internal::roaring_bitmap_xor(&roaring, &o.roaring);
        if (r == NULL) {
            ROARING_TERMINATE("failed materalization in xor");
        }
        return Roaring(r);
    }

    /**
     * Whether or not we apply copy and write.
     */
    void setCopyOnWrite(bool val) noexcept {
        internal::roaring_bitmap_set_copy_on_write(&roaring, val);
    }

    /**
     * Print the content of the bitmap
     */
    void printf() const noexcept { internal::roaring_bitmap_printf(&roaring); }

    /**
     * Print the content of the bitmap into a string
     */
    std::string toString() const noexcept {
        struct iter_data {
            std::string str{}; // The empty constructor silences warnings from pedantic static analyzers.
            char first_char = '{';
        } outer_iter_data;
        if (!isEmpty()) {
            iterate(
                [](uint32_t value, void *inner_iter_data) -> bool {
                    ((iter_data *)inner_iter_data)->str +=
                        ((iter_data *)inner_iter_data)->first_char;
                    ((iter_data *)inner_iter_data)->str +=
                        std::to_string(value);
                    ((iter_data *)inner_iter_data)->first_char = ',';
                    return true;
                },
                (void *)&outer_iter_data);
        } else
            outer_iter_data.str = '{';
        outer_iter_data.str += '}';
        return outer_iter_data.str;
    }

    /**
     * Whether or not copy and write is active.
     */
    bool getCopyOnWrite() const noexcept {
        return internal::roaring_bitmap_get_copy_on_write(&roaring);
    }

    /**
     * Computes the logical or (union) between "n" bitmaps (referenced by a
     * pointer).
     * This function may throw std::runtime_error.
     */
    static Roaring fastunion(size_t n, const Roaring **inputs) {
        const roaring_bitmap_t **x =
            (const roaring_bitmap_t **)roaring_malloc(n * sizeof(roaring_bitmap_t *));
        if (x == NULL) {
            ROARING_TERMINATE("failed memory alloc in fastunion");
        }
        for (size_t k = 0; k < n; ++k) x[k] = &inputs[k]->roaring;

        roaring_bitmap_t *c_ans = internal::roaring_bitmap_or_many(n, x);
        if (c_ans == NULL) {
            roaring_free(x);
            ROARING_TERMINATE("failed memory alloc in fastunion");
        }
        Roaring ans(c_ans);
        roaring_free(x);
        return ans;
    }

    typedef RoaringSetBitForwardIterator const_iterator;

    /**
     * Returns an iterator that can be used to access the position of the set
     * bits. The running time complexity of a full scan is proportional to the
     * number of set bits: be aware that if you have long strings of 1s, this
     * can be very inefficient.
     *
     * It can be much faster to use the toArray method if you want to retrieve
     * the set bits.
     */
    const_iterator begin() const;

    /**
     * A bogus iterator that can be used together with begin()
     * for constructions such as for (auto i = b.begin(); * i!=b.end(); ++i) {}
     */
    const_iterator &end() const;

    roaring_bitmap_t roaring;
};

/**
 * Used to go through the set bits. Not optimally fast, but convenient.
 */
class RoaringSetBitForwardIterator final {
public:
    typedef std::forward_iterator_tag iterator_category;
    typedef uint32_t *pointer;
    typedef uint32_t &reference_type;
    typedef uint32_t value_type;
    typedef int32_t difference_type;
    typedef RoaringSetBitForwardIterator type_of_iterator;

    /**
     * Provides the location of the set bit.
     */
    value_type operator*() const { return i.current_value; }

    bool operator<(const type_of_iterator &o) const {
        if (!i.has_value) return false;
        if (!o.i.has_value) return true;
        return i.current_value < *o;
    }

    bool operator<=(const type_of_iterator &o) const {
        if (!o.i.has_value) return true;
        if (!i.has_value) return false;
        return i.current_value <= *o;
    }

    bool operator>(const type_of_iterator &o)  const {
        if (!o.i.has_value) return false;
        if (!i.has_value) return true;
        return i.current_value > *o;
    }

    bool operator>=(const type_of_iterator &o)  const {
        if (!i.has_value) return true;
        if (!o.i.has_value) return false;
        return i.current_value >= *o;
    }

    /**
     * Move the iterator to the first value >= val.
     */
    void equalorlarger(uint32_t val) {
        internal::roaring_move_uint32_iterator_equalorlarger(&i,val);
    }

    type_of_iterator &operator++() {  // ++i, must returned inc. value
        internal::roaring_advance_uint32_iterator(&i);
        return *this;
    }

    type_of_iterator operator++(int) {  // i++, must return orig. value
        RoaringSetBitForwardIterator orig(*this);
        internal::roaring_advance_uint32_iterator(&i);
        return orig;
    }

    type_of_iterator& operator--() { // prefix --
        internal::roaring_previous_uint32_iterator(&i);
        return *this;
    }

    type_of_iterator operator--(int) { // postfix --
        RoaringSetBitForwardIterator orig(*this);
        internal::roaring_previous_uint32_iterator(&i);
        return orig;
    }

    bool operator==(const RoaringSetBitForwardIterator &o) const {
        return i.current_value == *o && i.has_value == o.i.has_value;
    }

    bool operator!=(const RoaringSetBitForwardIterator &o) const {
        return i.current_value != *o || i.has_value != o.i.has_value;
    }

    explicit RoaringSetBitForwardIterator(const Roaring &parent,
                                          bool exhausted = false) {
        if (exhausted) {
            i.parent = &parent.roaring;
            i.container_index = INT32_MAX;
            i.has_value = false;
            i.current_value = UINT32_MAX;
        } else {
            internal::roaring_init_iterator(&parent.roaring, &i);
        }
    }

    internal::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
};

inline RoaringSetBitForwardIterator Roaring::begin() const {
    return RoaringSetBitForwardIterator(*this);
}

inline RoaringSetBitForwardIterator &Roaring::end() const {
    static RoaringSetBitForwardIterator e(*this, true);
    return e;
}

}  // namespace paimon::roaring

#endif /* INCLUDE_ROARING_HH_ */
/* end file cpp/roaring.hh */
/* begin file cpp/roaring64map.hh */
/**
 * A C++ header for 64-bit Roaring Bitmaps,
 * implemented by way of a map of many
 * 32-bit Roaring Bitmaps.
 *
 * Reference (format specification) :
 * https://github.com/RoaringBitmap/RoaringFormatSpec#extention-for-64-bit-implementations
*/
#ifndef INCLUDE_ROARING_64_MAP_HH_
#define INCLUDE_ROARING_64_MAP_HH_

#include <algorithm>
#include <cinttypes> // PRIu64 macro
#include <cstdarg>  // for va_list handling in bitmapOf()
#include <cstdio>  // for std::printf() in the printf() method
#include <cstring>  // for std::memcpy()
#include <functional>
#include <initializer_list>
#include <limits>
#include <map>
#include <new>
#include <numeric>
#include <queue>
#include <stdexcept>
#include <string>
#include <utility>


namespace paimon::roaring {

using roaring::Roaring;

class Roaring64MapSetBitForwardIterator;
class Roaring64MapSetBitBiDirectionalIterator;

class Roaring64Map {
    typedef internal::roaring_bitmap_t roaring_bitmap_t;

public:
    /**
     * Create an empty bitmap
     */
    Roaring64Map() = default;

    /**
     * Construct a bitmap from a list of 32-bit integer values.
     */
    Roaring64Map(size_t n, const uint32_t *data) { addMany(n, data); }

    /**
     * Construct a bitmap from a list of 64-bit integer values.
     */
    Roaring64Map(size_t n, const uint64_t *data) { addMany(n, data); }

    /**
     * Construct a bitmap from an initializer list.
     */
    Roaring64Map(std::initializer_list<uint64_t> l) {
        addMany(l.size(), l.begin());
    }

    /**
     * Construct a 64-bit map from a 32-bit one
     */
    explicit Roaring64Map(const Roaring &r) { emplaceOrInsert(0, r); }

    /**
     * Construct a 64-bit map from a 32-bit rvalue
     */
    explicit Roaring64Map(Roaring &&r) { emplaceOrInsert(0, std::move(r)); }

    /**
     * Construct a roaring object from the C struct.
     *
     * Passing a NULL point is unsafe.
     */
    explicit Roaring64Map(roaring_bitmap_t *s) {
        emplaceOrInsert(0, Roaring(s));
    }

    Roaring64Map(const Roaring64Map& r) = default;

    Roaring64Map(Roaring64Map&& r) noexcept = default;

    /**
     * Copy assignment operator.
     */
    Roaring64Map &operator=(const Roaring64Map &r) = default;

    /**
     * Move assignment operator.
     */
    Roaring64Map &operator=(Roaring64Map &&r) noexcept = default;

    /**
     * Assignment from an initializer list.
     */
    Roaring64Map &operator=(std::initializer_list<uint64_t> l) {
        // Delegate to move assignment operator
        *this = Roaring64Map(l);
        return *this;
    }

    /**
     * Construct a bitmap from a list of uint64_t values.
     */
    static Roaring64Map bitmapOf(size_t n...) {
        Roaring64Map ans;
        va_list vl;
        va_start(vl, n);
        for (size_t i = 0; i < n; i++) {
            ans.add(va_arg(vl, uint64_t));
        }
        va_end(vl);
        return ans;
    }

    /**
     * Construct a bitmap from a list of uint64_t values.
     * E.g., bitmapOfList({1,2,3}).
     */
    static Roaring64Map bitmapOfList(std::initializer_list<uint64_t> l) {
        Roaring64Map ans;
        ans.addMany(l.size(), l.begin());
        return ans;
    }

    /**
     * Adds value x.
     */
    void add(uint32_t x) {
        lookupOrCreateInner(0).add(x);
    }

    /**
     * Adds value x.
     */
    void add(uint64_t x) {
        lookupOrCreateInner(highBytes(x)).add(lowBytes(x));
    }

    /**
     * Adds value x.
     * Returns true if a new value was added, false if the value was already
     * present.
     */
    bool addChecked(uint32_t x) {
        return lookupOrCreateInner(0).addChecked(x);
    }

    /**
     * Adds value x.
     * Returns true if a new value was added, false if the value was already
     * present.
     */
    bool addChecked(uint64_t x) {
        return lookupOrCreateInner(highBytes(x)).addChecked(lowBytes(x));
    }

    /**
     * Adds all values in the half-open interval [min, max).
     */
    void addRange(uint64_t min, uint64_t max) {
        if (min >= max) {
            return;
        }
        addRangeClosed(min, max - 1);
    }

    /**
     * Adds all values in the closed interval [min, max].
     */
    void addRangeClosed(uint32_t min, uint32_t max) {
        lookupOrCreateInner(0).addRangeClosed(min, max);
    }

    /**
     * Adds all values in the closed interval [min, max]
     */
    void addRangeClosed(uint64_t min, uint64_t max) {
        if (min > max) {
            return;
        }
        uint32_t start_high = highBytes(min);
        uint32_t start_low = lowBytes(min);
        uint32_t end_high = highBytes(max);
        uint32_t end_low = lowBytes(max);

        // We put std::numeric_limits<>::max in parentheses to avoid a
        // clash with the Windows.h header under Windows.
        const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();

        // Fill in any nonexistent slots with empty Roarings. This simplifies
        // the logic below, allowing it to simply iterate over the map between
        // 'start_high' and 'end_high' in a linear fashion.
        auto current_iter = ensureRangePopulated(start_high, end_high);

        // If start and end land on the same inner bitmap, then we can do the
        // whole operation in one call.
        if (start_high == end_high) {
            auto &bitmap = current_iter->second;
            bitmap.addRangeClosed(start_low, end_low);
            return;
        }

        // Because start and end don't land on the same inner bitmap,
        // we need to do this in multiple steps:
        // 1. Partially fill the first bitmap with values from the closed
        //    interval [start_low, uint32_max]
        // 2. Fill intermediate bitmaps completely: [0, uint32_max]
        // 3. Partially fill the last bitmap with values from the closed
        //    interval [0, end_low]
        auto num_intermediate_bitmaps = end_high - start_high - 1;

        // Step 1: Partially fill the first bitmap.
        {
            auto &bitmap = current_iter->second;
            bitmap.addRangeClosed(start_low, uint32_max);
            ++current_iter;
        }

        // Step 2. Fill intermediate bitmaps completely.
        if (num_intermediate_bitmaps != 0) {
            auto &first_intermediate = current_iter->second;
            first_intermediate.addRangeClosed(0, uint32_max);
            ++current_iter;

            // Now make (num_intermediate_bitmaps - 1) copies of this.
            for (uint32_t i = 1; i != num_intermediate_bitmaps; ++i) {
                auto &next_intermediate = current_iter->second;
                next_intermediate = first_intermediate;
                ++current_iter;
            }
        }

        // Step 3: Partially fill the last bitmap.
        auto &bitmap = current_iter->second;
        bitmap.addRangeClosed(0, end_low);
    }

    /**
     * Adds 'n_args' values from the contiguous memory range starting at 'vals'.
     */
    void addMany(size_t n_args, const uint32_t *vals) {
        lookupOrCreateInner(0).addMany(n_args, vals);
    }

    /**
     * Adds 'n_args' values from the contiguous memory range starting at 'vals'.
     */
    void addMany(size_t n_args, const uint64_t *vals) {
        // Potentially reduce outer map lookups by optimistically
        // assuming that adjacent values will belong to the same inner bitmap.
        Roaring *last_inner_bitmap = nullptr;
        uint32_t last_value_high = 0;
        for (size_t lcv = 0; lcv < n_args; lcv++) {
            auto value = vals[lcv];
            auto value_high = highBytes(value);
            auto value_low = lowBytes(value);
            if (last_inner_bitmap == nullptr || value_high != last_value_high) {
                last_inner_bitmap = &lookupOrCreateInner(value_high);
                last_value_high = value_high;
            }
            last_inner_bitmap->add(value_low);
        }
    }

    /**
     * Removes value x.
     */
    void remove(uint32_t x) {
        auto iter = roarings.begin();
        // Since x is a uint32_t, highbytes(x) == 0. The inner bitmap we are
        // looking for, if it exists, will be at the first slot of 'roarings'.
        if (iter == roarings.end() || iter->first != 0) {
            return;
        }
        auto &bitmap = iter->second;
        bitmap.remove(x);
        eraseIfEmpty(iter);
    }

    /**
     * Removes value x.
     */
    void remove(uint64_t x) {
        auto iter = roarings.find(highBytes(x));
        if (iter == roarings.end()) {
            return;
        }
        auto &bitmap = iter->second;
        bitmap.remove(lowBytes(x));
        eraseIfEmpty(iter);
    }

    /**
     * Removes value x
     * Returns true if a new value was removed, false if the value was not
     * present.
     */
    bool removeChecked(uint32_t x) {
        auto iter = roarings.begin();
        // Since x is a uint32_t, highbytes(x) == 0. The inner bitmap we are
        // looking for, if it exists, will be at the first slot of 'roarings'.
        if (iter == roarings.end() || iter->first != 0) {
            return false;
        }
        auto &bitmap = iter->second;
        if (!bitmap.removeChecked(x)) {
            return false;
        }
        eraseIfEmpty(iter);
        return true;
    }

    /**
     * Remove value x
     * Returns true if a new value was removed, false if the value was not
     * present.
     */
    bool removeChecked(uint64_t x) {
        auto iter = roarings.find(highBytes(x));
        if (iter == roarings.end()) {
            return false;
        }
        auto &bitmap = iter->second;
        if (!bitmap.removeChecked(lowBytes(x))) {
            return false;
        }
        eraseIfEmpty(iter);
        return true;
    }

    /**
     * Removes all values in the half-open interval [min, max).
     */
    void removeRange(uint64_t min, uint64_t max) {
        if (min >= max) {
            return;
        }
        return removeRangeClosed(min, max - 1);
    }

    /**
     * Removes all values in the closed interval [min, max].
     */
    void removeRangeClosed(uint32_t min, uint32_t max) {
        auto iter = roarings.begin();
        // Since min and max are uint32_t, highbytes(min or max) == 0. The inner
        // bitmap we are looking for, if it exists, will be at the first slot of
        // 'roarings'.
        if (iter == roarings.end() || iter->first != 0) {
            return;
        }
        auto &bitmap = iter->second;
        bitmap.removeRangeClosed(min, max);
        eraseIfEmpty(iter);
    }

    /**
     * Removes all values in the closed interval [min, max].
     */
    void removeRangeClosed(uint64_t min, uint64_t max) {
        if (min > max) {
            return;
        }
        uint32_t start_high = highBytes(min);
        uint32_t start_low = lowBytes(min);
        uint32_t end_high = highBytes(max);
        uint32_t end_low = lowBytes(max);

        // We put std::numeric_limits<>::max in parentheses to avoid a
        // clash with the Windows.h header under Windows.
        const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();

        // If the outer map is empty, end_high is less than the first key,
        // or start_high is greater than the last key, then exit now because
        // there is no work to do.
        if (roarings.empty() || end_high < roarings.cbegin()->first ||
            start_high > (roarings.crbegin())->first) {
            return;
        }

        // If we get here, start_iter points to the first entry in the outer map
        // with key >= start_high. Such an entry is known to exist (i.e. the
        // iterator will not be equal to end()) because start_high <= the last
        // key in the map (thanks to the above if statement).
        auto start_iter = roarings.lower_bound(start_high);
        // end_iter points to the first entry in the outer map with
        // key >= end_high, if such a key exists. Otherwise, it equals end().
        auto end_iter = roarings.lower_bound(end_high);

        // Note that the 'lower_bound' method will find the start and end slots,
        // if they exist; otherwise it will find the next-higher slots.
        // In the case where 'start' landed on an existing slot, we need to do a
        // partial erase of that slot, and likewise for 'end'. But all the slots
        // in between can be fully erased. More precisely:
        //
        // 1. If the start point falls on an existing entry, there are two
        //    subcases:
        //    a. if the end point falls on that same entry, remove the closed
        //       interval [start_low, end_low] from that entry and we are done.
        //    b. Otherwise, remove the closed interval [start_low, uint32_max]
        //       from that entry, advance start_iter, and fall through to step 2.
        // 2. Completely erase all slots in the half-open interval
        //    [start_iter, end_iter)
        // 3. If the end point falls on an existing entry, remove the closed
        //    interval [0, end_high] from it.

        // Step 1. If the start point falls on an existing entry...
        if (start_iter->first == start_high) {
            auto &start_inner = start_iter->second;
            // 1a. if the end point falls on that same entry...
            if (start_iter == end_iter) {
                start_inner.removeRangeClosed(start_low, end_low);
                eraseIfEmpty(start_iter);
                return;
            }

            // 1b. Otherwise, remove the closed range [start_low, uint32_max]...
            start_inner.removeRangeClosed(start_low, uint32_max);
            // Advance start_iter, but keep the old value so we can check the
            // bitmap we just modified for emptiness and erase if it necessary.
            auto temp = start_iter++;
            eraseIfEmpty(temp);
        }

        // 2. Completely erase all slots in the half-open interval...
        roarings.erase(start_iter, end_iter);

        // 3. If the end point falls on an existing entry...
        if (end_iter != roarings.end() && end_iter->first == end_high) {
            auto &end_inner = end_iter->second;
            end_inner.removeRangeClosed(0, end_low);
            eraseIfEmpty(end_iter);
        }
    }

    /**
     * Clears the bitmap.
     */
    void clear() {
        roarings.clear();
    }

    /**
     * Return the largest value (if not empty)
     */
    uint64_t maximum() const {
        for (auto roaring_iter = roarings.crbegin();
             roaring_iter != roarings.crend(); ++roaring_iter) {
            if (!roaring_iter->second.isEmpty()) {
                return uniteBytes(roaring_iter->first,
                                  roaring_iter->second.maximum());
            }
        }
        // we put std::numeric_limits<>::max/min in parentheses
        // to avoid a clash with the Windows.h header under Windows
        return (std::numeric_limits<uint64_t>::min)();
    }

    /**
     * Return the smallest value (if not empty)
     */
    uint64_t minimum() const {
        for (auto roaring_iter = roarings.cbegin();
             roaring_iter != roarings.cend(); ++roaring_iter) {
            if (!roaring_iter->second.isEmpty()) {
                return uniteBytes(roaring_iter->first,
                                  roaring_iter->second.minimum());
            }
        }
        // we put std::numeric_limits<>::max/min in parentheses
        // to avoid a clash with the Windows.h header under Windows
        return (std::numeric_limits<uint64_t>::max)();
    }

    /**
     * Check if value x is present
     */
    bool contains(uint32_t x) const {
        return roarings.count(0) == 0 ? false : roarings.at(0).contains(x);
    }
    bool contains(uint64_t x) const {
        return roarings.count(highBytes(x)) == 0
            ? false
            : roarings.at(highBytes(x)).contains(lowBytes(x));
    }

    /**
     * Compute the intersection of the current bitmap and the provided bitmap,
     * writing the result in the current bitmap. The provided bitmap is not
     * modified.
     *
     * Performance hint: if you are computing the intersection between several
     * bitmaps, two-by-two, it is best to start with the smallest bitmap.
     */
    Roaring64Map &operator&=(const Roaring64Map &other) {
        if (this == &other) {
            // ANDing *this with itself is a no-op.
            return *this;
        }

        // Logic table summarizing what to do when a given outer key is
        // present vs. absent from self and other.
        //
        // self     other    (self & other)  work to do
        // --------------------------------------------
        // absent   absent   empty           None
        // absent   present  empty           None
        // present  absent   empty           Erase self
        // present  present  empty or not    Intersect self with other, but
        //                                   erase self if result is empty.
        //
        // Because there is only work to do when a key is present in 'self', the
        // main for loop iterates over entries in 'self'.

        decltype(roarings.begin()) self_next;
        for (auto self_iter = roarings.begin(); self_iter != roarings.end();
             self_iter = self_next) {
            // Do the 'next' operation now, so we don't have to worry about
            // invalidation of self_iter down below with the 'erase' operation.
            self_next = std::next(self_iter);

            auto self_key = self_iter->first;
            auto &self_bitmap = self_iter->second;

            auto other_iter = other.roarings.find(self_key);
            if (other_iter == other.roarings.end()) {
                // 'other' doesn't have self_key. In the logic table above,
                // this reflects the case (self.present & other.absent).
                // So, erase self.
                roarings.erase(self_iter);
                continue;
            }

            // Both sides have self_key. In the logic table above, this reflects
            // the case (self.present & other.present). So, intersect self with
            // other.
            const auto &other_bitmap = other_iter->second;
            self_bitmap &= other_bitmap;
            if (self_bitmap.isEmpty()) {
                // ...but if intersection is empty, remove it altogether.
                roarings.erase(self_iter);
            }
        }
        return *this;
    }

    /**
     * Compute the difference between the current bitmap and the provided
     * bitmap, writing the result in the current bitmap. The provided bitmap
     * is not modified.
     */
    Roaring64Map &operator-=(const Roaring64Map &other) {
        if (this == &other) {
            // Subtracting *this from itself results in the empty map.
            roarings.clear();
            return *this;
        }

        // Logic table summarizing what to do when a given outer key is
        // present vs. absent from self and other.
        //
        // self     other    (self - other)  work to do
        // --------------------------------------------
        // absent   absent   empty           None
        // absent   present  empty           None
        // present  absent   unchanged       None
        // present  present  empty or not    Subtract other from self, but
        //                                   erase self if result is empty
        //
        // Because there is only work to do when a key is present in both 'self'
        // and 'other', the main while loop ping-pongs back and forth until it
        // finds the next key that is the same on both sides.

        auto self_iter = roarings.begin();
        auto other_iter = other.roarings.cbegin();

        while (self_iter != roarings.end() &&
               other_iter != other.roarings.cend()) {
            auto self_key = self_iter->first;
            auto other_key = other_iter->first;
            if (self_key < other_key) {
                // Because self_key is < other_key, advance self_iter to the
                // first point where self_key >= other_key (or end).
                self_iter = roarings.lower_bound(other_key);
                continue;
            }

            if (self_key > other_key) {
                // Because self_key is > other_key, advance other_iter to the
                // first point where other_key >= self_key (or end).
                other_iter = other.roarings.lower_bound(self_key);
                continue;
            }

            // Both sides have self_key. In the logic table above, this reflects
            // the case (self.present & other.present). So subtract other from
            // self.
            auto &self_bitmap = self_iter->second;
            const auto &other_bitmap = other_iter->second;
            self_bitmap -= other_bitmap;

            if (self_bitmap.isEmpty()) {
                // ...but if subtraction is empty, remove it altogether.
                self_iter = roarings.erase(self_iter);
            } else {
                ++self_iter;
            }
            ++other_iter;
        }
        return *this;
    }

    /**
     * Compute the union of the current bitmap and the provided bitmap,
     * writing the result in the current bitmap. The provided bitmap is not
     * modified.
     *
     * See also the fastunion function to aggregate many bitmaps more quickly.
     */
    Roaring64Map &operator|=(const Roaring64Map &other) {
        if (this == &other) {
            // ORing *this with itself is a no-op.
            return *this;
        }

        // Logic table summarizing what to do when a given outer key is
        // present vs. absent from self and other.
        //
        // self     other    (self | other)  work to do
        // --------------------------------------------
        // absent   absent   empty           None
        // absent   present  not empty       Copy other to self and set flags
        // present  absent   unchanged       None
        // present  present  not empty       self |= other
        //
        // Because there is only work to do when a key is present in 'other',
        // the main for loop iterates over entries in 'other'.

        for (const auto &other_entry : other.roarings) {
            const auto &other_bitmap = other_entry.second;

            // Try to insert other_bitmap into self at other_key. We take
            // advantage of the fact that std::map::insert will not overwrite an
            // existing entry.
            auto insert_result = roarings.insert(other_entry);
            auto self_iter = insert_result.first;
            auto insert_happened = insert_result.second;
            auto &self_bitmap = self_iter->second;

            if (insert_happened) {
                // Key was not present in self, so insert was performed above.
                // In the logic table above, this reflects the case
                // (self.absent | other.present). Because the copy has already
                // happened, thanks to the 'insert' operation above, we just
                // need to set the copyOnWrite flag.
                self_bitmap.setCopyOnWrite(copyOnWrite);
                continue;
            }

            // Both sides have self_key, and the insert was not performed. In
            // the logic table above, this reflects the case
            // (self.present & other.present). So OR other into self.
            self_bitmap |= other_bitmap;
        }
        return *this;
    }

    /**
     * Compute the XOR of the current bitmap and the provided bitmap, writing
     * the result in the current bitmap. The provided bitmap is not modified.
     */
    Roaring64Map &operator^=(const Roaring64Map &other) {
        if (this == &other) {
            // XORing *this with itself results in the empty map.
            roarings.clear();
            return *this;
        }

        // Logic table summarizing what to do when a given outer key is
        // present vs. absent from self and other.
        //
        // self     other    (self ^ other)  work to do
        // --------------------------------------------
        // absent   absent   empty           None
        // absent   present  non-empty       Copy other to self and set flags
        // present  absent   unchanged       None
        // present  present  empty or not    XOR other into self, but erase self
        //                                   if result is empty.
        //
        // Because there is only work to do when a key is present in 'other',
        // the main for loop iterates over entries in 'other'.

        for (const auto &other_entry : other.roarings) {
            const auto &other_bitmap = other_entry.second;

            // Try to insert other_bitmap into self at other_key. We take
            // advantage of the fact that std::map::insert will not overwrite an
            // existing entry.
            auto insert_result = roarings.insert(other_entry);
            auto self_iter = insert_result.first;
            auto insert_happened = insert_result.second;
            auto &self_bitmap = self_iter->second;

            if (insert_happened) {
                // Key was not present in self, so insert was performed above.
                // In the logic table above, this reflects the case
                // (self.absent ^ other.present). Because the copy has already
                // happened, thanks to the 'insert' operation above, we just
                // need to set the copyOnWrite flag.
                self_bitmap.setCopyOnWrite(copyOnWrite);
                continue;
            }

            // Both sides have self_key, and the insert was not performed. In
            // the logic table above, this reflects the case
            // (self.present ^ other.present). So XOR other into self.
            self_bitmap ^= other_bitmap;

            if (self_bitmap.isEmpty()) {
                // ...but if intersection is empty, remove it altogether.
                roarings.erase(self_iter);
            }
        }
        return *this;
    }

    /**
     * Exchange the content of this bitmap with another.
     */
    void swap(Roaring64Map &r) { roarings.swap(r.roarings); }

    /**
     * Get the cardinality of the bitmap (number of elements).
     * Throws std::length_error in the special case where the bitmap is full
     * (cardinality() == 2^64). Check isFull() before calling to avoid
     * exception.
     */
    uint64_t cardinality() const {
        if (isFull()) {
#if ROARING_EXCEPTIONS
            throw std::length_error("bitmap is full, cardinality is 2^64, "
                                    "unable to represent in a 64-bit integer");
#else
            ROARING_TERMINATE("bitmap is full, cardinality is 2^64, "
                              "unable to represent in a 64-bit integer");
#endif
        }
        return std::accumulate(
            roarings.cbegin(), roarings.cend(), (uint64_t)0,
            [](uint64_t previous,
               const std::pair<const uint32_t, Roaring> &map_entry) {
                return previous + map_entry.second.cardinality();
            });
    }

    /**
     * Returns true if the bitmap is empty (cardinality is zero).
     */
    bool isEmpty() const {
        return std::all_of(roarings.cbegin(), roarings.cend(),
                           [](const std::pair<const uint32_t, Roaring> &map_entry) {
                               return map_entry.second.isEmpty();
                           });
    }

    /**
     * Returns true if the bitmap is full (cardinality is max uint64_t + 1).
     */
    bool isFull() const {
        // only bother to check if map is fully saturated
        //
        // we put std::numeric_limits<>::max/min in parentheses
        // to avoid a clash with the Windows.h header under Windows
        return roarings.size() ==
            ((uint64_t)(std::numeric_limits<uint32_t>::max)()) + 1
            ? std::all_of(
                roarings.cbegin(), roarings.cend(),
                [](const std::pair<const uint32_t, Roaring> &roaring_map_entry) {
                    // roarings within map are saturated if cardinality
                    // is uint32_t max + 1
                    return roaring_map_entry.second.cardinality() ==
                        ((uint64_t)
                         (std::numeric_limits<uint32_t>::max)()) +
                        1;
                })
            : false;
    }

    /**
     * Returns true if the bitmap is subset of the other.
     */
    bool isSubset(const Roaring64Map &r) const {
        for (const auto &map_entry : roarings) {
            if (map_entry.second.isEmpty()) {
                continue;
            }
            auto roaring_iter = r.roarings.find(map_entry.first);
            if (roaring_iter == r.roarings.cend())
                return false;
            else if (!map_entry.second.isSubset(roaring_iter->second))
                return false;
        }
        return true;
    }

    /**
     * Returns true if the bitmap is strict subset of the other.
     * Throws std::length_error in the special case where the bitmap is full
     * (cardinality() == 2^64). Check isFull() before calling to avoid exception.
     */
    bool isStrictSubset(const Roaring64Map &r) const {
        return isSubset(r) && cardinality() != r.cardinality();
    }

    /**
     * Convert the bitmap to an array. Write the output to "ans",
     * caller is responsible to ensure that there is enough memory
     * allocated
     * (e.g., ans = new uint32[mybitmap.cardinality()];)
     */
    void toUint64Array(uint64_t *ans) const {
        // Annoyingly, VS 2017 marks std::accumulate() as [[nodiscard]]
        (void)std::accumulate(roarings.cbegin(), roarings.cend(), ans,
                              [](uint64_t *previous,
                                 const std::pair<const uint32_t, Roaring> &map_entry) {
                                  for (uint32_t low_bits : map_entry.second)
                                      *previous++ =
                                          uniteBytes(map_entry.first, low_bits);
                                  return previous;
                              });
    }

    /**
     * Return true if the two bitmaps contain the same elements.
     */
    bool operator==(const Roaring64Map &r) const {
        // we cannot use operator == on the map because either side may contain
        // empty Roaring Bitmaps
        auto lhs_iter = roarings.cbegin();
        auto lhs_cend = roarings.cend();
        auto rhs_iter = r.roarings.cbegin();
        auto rhs_cend = r.roarings.cend();
        while (lhs_iter != lhs_cend && rhs_iter != rhs_cend) {
            auto lhs_key = lhs_iter->first, rhs_key = rhs_iter->first;
            const auto &lhs_map = lhs_iter->second, &rhs_map = rhs_iter->second;
            if (lhs_map.isEmpty()) {
                ++lhs_iter;
                continue;
            }
            if (rhs_map.isEmpty()) {
                ++rhs_iter;
                continue;
            }
            if (!(lhs_key == rhs_key)) {
                return false;
            }
            if (!(lhs_map == rhs_map)) {
                return false;
            }
            ++lhs_iter;
            ++rhs_iter;
        }
        while (lhs_iter != lhs_cend) {
            if (!lhs_iter->second.isEmpty()) {
                return false;
            }
            ++lhs_iter;
        }
        while (rhs_iter != rhs_cend) {
            if (!rhs_iter->second.isEmpty()) {
                return false;
            }
            ++rhs_iter;
        }
        return true;
    }

    /**
     * Computes the negation of the roaring bitmap within the half-open interval
     * [min, max). Areas outside the interval are unchanged.
     */
    void flip(uint64_t min, uint64_t max) {
        if (min >= max) {
            return;
        }
        flipClosed(min, max - 1);
    }

    /**
     * Computes the negation of the roaring bitmap within the closed interval
     * [min, max]. Areas outside the interval are unchanged.
     */
    void flipClosed(uint32_t min, uint32_t max) {
        auto iter = roarings.begin();
        // Since min and max are uint32_t, highbytes(min or max) == 0. The inner
        // bitmap we are looking for, if it exists, will be at the first slot of
        // 'roarings'. If it does not exist, we have to create it.
        if (iter == roarings.end() || iter->first != 0) {
            iter = roarings.emplace_hint(iter, std::piecewise_construct,
                                         std::forward_as_tuple(0),
                                         std::forward_as_tuple());
            auto &bitmap = iter->second;
            bitmap.setCopyOnWrite(copyOnWrite);
        }
        auto &bitmap = iter->second;
        bitmap.flipClosed(min, max);
        eraseIfEmpty(iter);
    }

    /**
     * Computes the negation of the roaring bitmap within the closed interval
     * [min, max]. Areas outside the interval are unchanged.
     */
    void flipClosed(uint64_t min, uint64_t max) {
        if (min > max) {
          return;
        }
        uint32_t start_high = highBytes(min);
        uint32_t start_low = lowBytes(min);
        uint32_t end_high = highBytes(max);
        uint32_t end_low = lowBytes(max);

        // We put std::numeric_limits<>::max in parentheses to avoid a
        // clash with the Windows.h header under Windows.
        const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();

        // Fill in any nonexistent slots with empty Roarings. This simplifies
        // the logic below, allowing it to simply iterate over the map between
        // 'start_high' and 'end_high' in a linear fashion.
        auto current_iter = ensureRangePopulated(start_high, end_high);

        // If start and end land on the same inner bitmap, then we can do the
        // whole operation in one call.
        if (start_high == end_high) {
            auto &bitmap = current_iter->second;
            bitmap.flipClosed(start_low, end_low);
            eraseIfEmpty(current_iter);
            return;
        }

        // Because start and end don't land on the same inner bitmap,
        // we need to do this in multiple steps:
        // 1. Partially flip the first bitmap in the closed interval
        //    [start_low, uint32_max]
        // 2. Flip intermediate bitmaps completely: [0, uint32_max]
        // 3. Partially flip the last bitmap in the closed interval
        //    [0, end_low]

        auto num_intermediate_bitmaps = end_high - start_high - 1;

        // 1. Partially flip the first bitmap.
        {
            auto &bitmap = current_iter->second;
            bitmap.flipClosed(start_low, uint32_max);
            auto temp = current_iter++;
            eraseIfEmpty(temp);
        }

        // 2. Flip intermediate bitmaps completely.
        for (uint32_t i = 0; i != num_intermediate_bitmaps; ++i) {
            auto &bitmap = current_iter->second;
            bitmap.flipClosed(0, uint32_max);
            auto temp = current_iter++;
            eraseIfEmpty(temp);
        }

        // 3. Partially flip the last bitmap.
        auto &bitmap = current_iter->second;
        bitmap.flipClosed(0, end_low);
        eraseIfEmpty(current_iter);
    }

    /**
     * Remove run-length encoding even when it is more space efficient
     * return whether a change was applied
     */
    bool removeRunCompression() {
        return std::accumulate(
            roarings.begin(), roarings.end(), true,
            [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
                return map_entry.second.removeRunCompression() && previous;
            });
    }

    /**
     * Convert array and bitmap containers to run containers when it is more
     * efficient; also convert from run containers when more space efficient.
     * Returns true if the result has at least one run container.
     * Additional savings might be possible by calling shrinkToFit().
     */
    bool runOptimize() {
        return std::accumulate(
            roarings.begin(), roarings.end(), true,
            [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
                return map_entry.second.runOptimize() && previous;
            });
    }

    /**
     * If needed, reallocate memory to shrink the memory usage.
     * Returns the number of bytes saved.
     */
    size_t shrinkToFit() {
        size_t savedBytes = 0;
        auto iter = roarings.begin();
        while (iter != roarings.cend()) {
            if (iter->second.isEmpty()) {
                // empty Roarings are 84 bytes
                savedBytes += 88;
                roarings.erase(iter++);
            } else {
                savedBytes += iter->second.shrinkToFit();
                iter++;
            }
        }
        return savedBytes;
    }

    /**
     * Iterate over the bitmap elements in order(start from the smallest one)
     * and call iterator once for every element until the iterator function
     * returns false. To iterate over all values, the iterator function should
     * always return true.
     *
     * The roaring_iterator64 parameter is a pointer to a function that
     * returns bool (true means that the iteration should continue while false
     * means that it should stop), and takes (uint64_t element, void* ptr) as
     * inputs.
     */
    void iterate(internal::roaring_iterator64 iterator, void *ptr) const {
        for (const auto &map_entry : roarings) {
            bool should_continue =
                roaring_iterate64(&map_entry.second.roaring, iterator,
                                  uint64_t(map_entry.first) << 32, ptr);
            if (!should_continue) {
                break;
            }
        }
    }

    /**
     * Selects the value at index 'rank' in the bitmap, where the smallest value
     * is at index 0. If 'rank' < cardinality(), returns true with *element set
     * to the element of the specified rank. Otherwise, returns false and the
     * contents of *element are unspecified.
     */
    bool select(uint64_t rank, uint64_t *element) const {
        for (const auto &map_entry : roarings) {
            auto key = map_entry.first;
            const auto &bitmap = map_entry.second;

            uint64_t sub_cardinality = bitmap.cardinality();
            if (rank < sub_cardinality) {
                uint32_t low_bytes;
                // Casting rank to uint32_t is safe because
                // rank < sub_cardinality and sub_cardinality <= 2^32.
                if (!bitmap.select((uint32_t)rank, &low_bytes)) {
                    ROARING_TERMINATE("Logic error: bitmap.select() "
                        "returned false despite rank < cardinality()");
                }
                *element = uniteBytes(key, low_bytes);
                return true;
            }
            rank -= sub_cardinality;
        }
        return false;
    }

    /**
     * Returns the number of integers that are smaller or equal to x.
     */
    uint64_t rank(uint64_t x) const {
        uint64_t result = 0;
        // Find the first bitmap >= x's bucket. If that is the bucket x would be in, find it's rank in that bucket.
        // Either way, we're left with a range of all buckets strictly smaller than x's bucket, add all their
        // cardinalities together.
        auto end = roarings.lower_bound(highBytes(x));
        if (end != roarings.cend() && end->first == highBytes(x)) {
            result += end->second.rank(lowBytes(x));
        }
        for (auto iter = roarings.cbegin(); iter != end; ++iter) {
            result += iter->second.cardinality();
        }
        return result;
    }

    /**
     * Returns the index of x in the set, index start from 0.
     * If the set doesn't contain x , this function will return -1.
     * The difference with rank function is that this function will return -1
     * when x isn't in the set, but the rank function will return a
     * non-negative number.
     */
    int64_t getIndex(uint64_t x) const {
        int64_t index = 0;
        auto roaring_destination = roarings.find(highBytes(x));
        if (roaring_destination != roarings.cend()) {
            for (auto roaring_iter = roarings.cbegin();
                 roaring_iter != roaring_destination; ++roaring_iter) {
                index += roaring_iter->second.cardinality();
            }
            auto low_idx = roaring_destination->second.getIndex(lowBytes(x));
            if (low_idx < 0) return -1;
            index += low_idx;
            return index;
        }
        return -1;
    }

    /**
     * Write a bitmap to a char buffer. This is meant to be compatible with
     * the Java and Go versions. Returns how many bytes were written which
     * should be getSizeInBytes().
     *
     * Setting the portable flag to false enables a custom format that
     * can save space compared to the portable format (e.g., for very
     * sparse bitmaps).
     */
    size_t write(char *buf, bool portable = true) const {
        const char *orig = buf;
        // push map size
        uint64_t map_size = roarings.size();
        std::memcpy(buf, &map_size, sizeof(uint64_t));
        buf += sizeof(uint64_t);
        std::for_each(
            roarings.cbegin(), roarings.cend(),
            [&buf, portable](const std::pair<const uint32_t, Roaring> &map_entry) {
                // push map key
                std::memcpy(buf, &map_entry.first, sizeof(uint32_t));
                // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is undefined

                buf += sizeof(uint32_t);
                // push map value Roaring
                buf += map_entry.second.write(buf, portable);
            });
        return buf - orig;
    }

    /**
     * Read a bitmap from a serialized version. This is meant to be compatible
     * with the Java and Go versions.
     *
     * Setting the portable flag to false enable a custom format that
     * can save space compared to the portable format (e.g., for very
     * sparse bitmaps).
     *
     * This function is unsafe in the sense that if you provide bad data, many
     * bytes could be read, possibly causing a buffer overflow. See also
     * readSafe.
     */
    static Roaring64Map read(const char *buf, bool portable = true) {
        Roaring64Map result;
        // get map size
        uint64_t map_size;
        std::memcpy(&map_size, buf, sizeof(uint64_t));
        buf += sizeof(uint64_t);
        for (uint64_t lcv = 0; lcv < map_size; lcv++) {
            // get map key
            uint32_t key;
            std::memcpy(&key, buf, sizeof(uint32_t));
            // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined

            buf += sizeof(uint32_t);
            // read map value Roaring
            Roaring read_var = Roaring::read(buf, portable);
            // forward buffer past the last Roaring Bitmap
            buf += read_var.getSizeInBytes(portable);
            result.emplaceOrInsert(key, std::move(read_var));
        }
        return result;
    }

    /**
     * Read a bitmap from a serialized version, reading no more than maxbytes
     * bytes.  This is meant to be compatible with the Java and Go versions.
     *
     * Setting the portable flag to false enable a custom format that can save
     * space compared to the portable format (e.g., for very sparse bitmaps).
     */
    static Roaring64Map readSafe(const char *buf, size_t maxbytes) {
        if (maxbytes < sizeof(uint64_t)) {
            ROARING_TERMINATE("ran out of bytes");
        }
        Roaring64Map result;
        uint64_t map_size;
        std::memcpy(&map_size, buf, sizeof(uint64_t));
        buf += sizeof(uint64_t);
        maxbytes -= sizeof(uint64_t);
        for (uint64_t lcv = 0; lcv < map_size; lcv++) {
            if(maxbytes < sizeof(uint32_t)) {
                ROARING_TERMINATE("ran out of bytes");
            }
            uint32_t key;
            std::memcpy(&key, buf, sizeof(uint32_t));
            // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined

            buf += sizeof(uint32_t);
            maxbytes -= sizeof(uint32_t);
            // read map value Roaring
            Roaring read_var = Roaring::readSafe(buf, maxbytes);
            // forward buffer past the last Roaring Bitmap
            size_t tz = read_var.getSizeInBytes(true);
            buf += tz;
            maxbytes -= tz;
            result.emplaceOrInsert(key, std::move(read_var));
        }
        return result;
    }

    /**
     * Return the number of bytes required to serialize this bitmap (meant to
     * be compatible with Java and Go versions)
     *
     * Setting the portable flag to false enable a custom format that can save
     * space compared to the portable format (e.g., for very sparse bitmaps).
     */
    size_t getSizeInBytes(bool portable = true) const {
        // start with, respectively, map size and size of keys for each map
        // entry
        return std::accumulate(
            roarings.cbegin(), roarings.cend(),
            sizeof(uint64_t) + roarings.size() * sizeof(uint32_t),
            [=](size_t previous,
                const std::pair<const uint32_t, Roaring> &map_entry) {
                // add in bytes used by each Roaring
                return previous + map_entry.second.getSizeInBytes(portable);
            });
    }

    static const Roaring64Map frozenView(const char *buf) {
        // size of bitmap buffer and key
        const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);

        Roaring64Map result;

        // get map size
        uint64_t map_size;
        memcpy(&map_size, buf, sizeof(uint64_t));
        buf += sizeof(uint64_t);

        for (uint64_t lcv = 0; lcv < map_size; lcv++) {
            // pad to 32 bytes minus the metadata size
            while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;

            // get bitmap size
            size_t len;
            memcpy(&len, buf, sizeof(size_t));
            buf += sizeof(size_t);

            // get map key
            uint32_t key;
            memcpy(&key, buf, sizeof(uint32_t));
            buf += sizeof(uint32_t);

            // read map value Roaring
            const Roaring read = Roaring::frozenView(buf, len);
            result.emplaceOrInsert(key, read);

            // forward buffer past the last Roaring Bitmap
            buf += len;
        }
        return result;
    }

    // As with serialized 64-bit bitmaps, 64-bit frozen bitmaps are serialized
    // by concatenating one or more Roaring::write output buffers with the
    // preceeding map key. Unlike standard bitmap serialization, frozen bitmaps
    // must be 32-byte aligned and requires a buffer length to parse. As a
    // result, each concatenated output of Roaring::writeFrozen is preceeded by
    // padding, the buffer size (size_t), and the map key (uint32_t). The
    // padding is used to ensure 32-byte alignment, but since it is followed by
    // the buffer size and map key, it actually pads to `(x - sizeof(size_t) +
    // sizeof(uint32_t)) mod 32` to leave room for the metadata.
    void writeFrozen(char *buf) const {
        // size of bitmap buffer and key
        const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);

        // push map size
        uint64_t map_size = roarings.size();
        memcpy(buf, &map_size, sizeof(uint64_t));
        buf += sizeof(uint64_t);

        for (auto &map_entry : roarings) {
            size_t frozenSizeInBytes = map_entry.second.getFrozenSizeInBytes();

            // pad to 32 bytes minus the metadata size
            while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;

            // push bitmap size
            memcpy(buf, &frozenSizeInBytes, sizeof(size_t));
            buf += sizeof(size_t);

            // push map key
            memcpy(buf, &map_entry.first, sizeof(uint32_t));
            buf += sizeof(uint32_t);

            // push map value Roaring
            map_entry.second.writeFrozen(buf);
            buf += map_entry.second.getFrozenSizeInBytes();
        }
    }

    size_t getFrozenSizeInBytes() const {
        // size of bitmap size and map key
        const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
        size_t ret = 0;

        // map size
        ret += sizeof(uint64_t);

        for (auto &map_entry : roarings) {
            // pad to 32 bytes minus the metadata size
            while ((ret + metadata_size) % 32 != 0) ret++;
            ret += metadata_size;

            // frozen bitmaps must be 32-byte aligned
            ret += map_entry.second.getFrozenSizeInBytes();
        }
        return ret;
    }

    /**
     * Computes the intersection between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     *
     * Performance hint: if you are computing the intersection between several
     * bitmaps, two-by-two, it is best to start with the smallest bitmap.
     * Consider also using the operator &= to avoid needlessly creating
     * many temporary bitmaps.
     */
    Roaring64Map operator&(const Roaring64Map &o) const {
        return Roaring64Map(*this) &= o;
    }

    /**
     * Computes the difference between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     */
    Roaring64Map operator-(const Roaring64Map &o) const {
        return Roaring64Map(*this) -= o;
    }

    /**
     * Computes the union between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     */
    Roaring64Map operator|(const Roaring64Map &o) const {
        return Roaring64Map(*this) |= o;
    }

    /**
     * Computes the symmetric union between two bitmaps and returns new bitmap.
     * The current bitmap and the provided bitmap are unchanged.
     */
    Roaring64Map operator^(const Roaring64Map &o) const {
        return Roaring64Map(*this) ^= o;
    }

    /**
     * Whether or not we apply copy and write.
     */
    void setCopyOnWrite(bool val) {
        if (copyOnWrite == val) return;
        copyOnWrite = val;
        std::for_each(roarings.begin(), roarings.end(),
                      [=](std::pair<const uint32_t, Roaring> &map_entry) {
                          map_entry.second.setCopyOnWrite(val);
                      });
    }

    /**
     * Print the contents of the bitmap to stdout.
     * Note: this method adds a final newline, but toString() does not.
     */
    void printf() const {
        auto sink = [](const std::string &s) {
            fputs(s.c_str(), stdout);
        };
        printToSink(sink);
        sink("\n");
    }

    /**
     * Print the contents of the bitmap into a string.
     */
    std::string toString() const {
        std::string result;
        auto sink = [&result](const std::string &s) {
            result += s;
        };
        printToSink(sink);
        return result;
    }

    /**
     * Whether or not copy and write is active.
     */
    bool getCopyOnWrite() const { return copyOnWrite; }

    /**
     * Computes the logical or (union) between "n" bitmaps (referenced by a
     * pointer).
     */
    static Roaring64Map fastunion(size_t n, const Roaring64Map **inputs) {
        // The strategy here is to basically do a "group by" operation.
        // We group the input roarings by key, do a 32-bit
        // roaring_bitmap_or_many on each group, and collect the results.
        // We accomplish the "group by" operation using a priority queue, which
        // tracks the next key for each of our input maps. At each step, our
        // algorithm takes the next subset of maps that share the same next key,
        // runs roaring_bitmap_or_many on those bitmaps, and then advances the
        // current_iter on all the affected entries and then repeats.

        // There is an entry in our priority queue for each of the 'n' inputs.
        // For a given Roaring64Map, we look at its underlying 'roarings'
        // std::map, and take its begin() and end(). This forms our half-open
        // interval [current_iter, end_iter), which we keep in the priority
        // queue as a pq_entry. These entries are updated (removed and then
        // reinserted with the pq_entry.iterator field advanced by one step) as
        // our algorithm progresses. But when a given interval becomes empty
        // (i.e. pq_entry.iterator == pq_entry.end) it is not returned to the
        // priority queue.
        struct pq_entry {
            roarings_t::const_iterator iterator;
            roarings_t::const_iterator end;
        };

        // Custom comparator for the priority queue.
        auto pq_comp = [](const pq_entry &lhs, const pq_entry &rhs) {
            auto left_key = lhs.iterator->first;
            auto right_key = rhs.iterator->first;

            // We compare in the opposite direction than normal because priority
            // queues normally order from largest to smallest, but we want
            // smallest to largest.
            return left_key > right_key;
        };

        // Create and populate the priority queue.
        std::priority_queue<pq_entry, std::vector<pq_entry>, decltype(pq_comp)> pq(pq_comp);
        for (size_t i = 0; i < n; ++i) {
            const auto &roarings = inputs[i]->roarings;
            if (roarings.begin() != roarings.end()) {
                pq.push({roarings.begin(), roarings.end()});
            }
        }

        // A reusable vector that holds the pointers to the inner bitmaps that
        // we pass to the underlying 32-bit fastunion operation.
        std::vector<const roaring_bitmap_t*> group_bitmaps;

        // Summary of the algorithm:
        // 1. While the priority queue is not empty:
        //    A. Get its lowest key. Call this group_key
        //    B. While the lowest entry in the priority queue has a key equal to
        //       group_key:
        //       1. Remove this entry (the pair {current_iter, end_iter}) from
        //          the priority queue.
        //       2. Add the bitmap pointed to by current_iter to a list of
        //          32-bit bitmaps to process.
        //       3. Advance current_iter. Now it will point to a bitmap entry
        //          with some key greater than group_key (or it will point to
        //          end()).
        //       4. If current_iter != end_iter, reinsert the pair into the
        //          priority queue.
        //    C. Invoke the 32-bit roaring_bitmap_or_many() and add to result
        Roaring64Map result;
        while (!pq.empty()) {
            // Find the next key (the lowest key) in the priority queue.
            auto group_key = pq.top().iterator->first;

            // The purpose of the inner loop is to gather all the inner bitmaps
            // that share "group_key" into "group_bitmaps" so that they can be
            // fed to roaring_bitmap_or_many(). While we are doing this, we
            // advance those iterators to their next value and reinsert them
            // into the priority queue (unless they reach their end).
            group_bitmaps.clear();
            while (!pq.empty()) {
                auto candidate_current_iter = pq.top().iterator;
                auto candidate_end_iter = pq.top().end;

                auto candidate_key = candidate_current_iter->first;
                const auto &candidate_bitmap = candidate_current_iter->second;

                // This element will either be in the group (having
                // key == group_key) or it will not be in the group (having
                // key > group_key). (Note it cannot have key < group_key
                // because of the ordered nature of the priority queue itself
                // and the ordered nature of all the underlying roaring maps).
                if (candidate_key != group_key) {
                    // This entry, and (thanks to the nature of the priority
                    // queue) all other entries as well, are all greater than
                    // group_key, so we're done collecting elements for the
                    // current group. Because of the way this loop was written,
                    // the group will will always contain at least one element.
                    break;
                }

                group_bitmaps.push_back(&candidate_bitmap.roaring);
                // Remove this entry from the priority queue. Note this
                // invalidates pq.top() so make sure you don't have any dangling
                // references to it.
                pq.pop();

                // Advance 'candidate_current_iter' and insert a new entry
                // {candidate_current_iter, candidate_end_iter} into the
                // priority queue (unless it has reached its end).
                ++candidate_current_iter;
                if (candidate_current_iter != candidate_end_iter) {
                    pq.push({candidate_current_iter, candidate_end_iter});
                }
            }

            // Use the fast inner union to combine these.
            auto *inner_result = roaring_bitmap_or_many(group_bitmaps.size(),
                group_bitmaps.data());
            // Insert the 32-bit result at end of the 'roarings' map of the
            // result we are building.
            result.roarings.insert(result.roarings.end(),
                std::make_pair(group_key, Roaring(inner_result)));
        }
        return result;
    }

    friend class Roaring64MapSetBitForwardIterator;
    friend class Roaring64MapSetBitBiDirectionalIterator;

    Roaring &getOrCreateInner(uint32_t high) {
        return lookupOrCreateInner(high);
    }
    typedef Roaring64MapSetBitForwardIterator const_iterator;
    typedef Roaring64MapSetBitBiDirectionalIterator const_bidirectional_iterator;

    /**
     * Returns an iterator that can be used to access the position of the set
     * bits. The running time complexity of a full scan is proportional to the
     * number of set bits: be aware that if you have long strings of 1s, this
     * can be very inefficient.
     *
     * It can be much faster to use the toArray method if you want to
     * retrieve the set bits.
     */
    const_iterator begin() const;

    /**
     * A bogus iterator that can be used together with begin()
     * for constructions such as: for (auto i = b.begin(); * i!=b.end(); ++i) {}
     */
    const_iterator end() const;

private:
    typedef std::map<uint32_t, Roaring> roarings_t;
    roarings_t roarings{}; // The empty constructor silences warnings from pedantic static analyzers.
    bool copyOnWrite{false};
    static constexpr uint32_t highBytes(const uint64_t in) { return uint32_t(in >> 32); }
    static constexpr uint32_t lowBytes(const uint64_t in) { return uint32_t(in); }
    static constexpr uint64_t uniteBytes(const uint32_t highBytes,
                                         const uint32_t lowBytes) {
        return (uint64_t(highBytes) << 32) | uint64_t(lowBytes);
    }
    // this is needed to tolerate gcc's C++11 libstdc++ lacking emplace
    // prior to version 4.8
    void emplaceOrInsert(const uint32_t key, const Roaring &value) {
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
        roarings.insert(std::make_pair(key, value));
#else
        roarings.emplace(std::make_pair(key, value));
#endif
    }

    void emplaceOrInsert(const uint32_t key, Roaring &&value) {
#if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
        roarings.insert(std::make_pair(key, std::move(value)));
#else
        roarings.emplace(key, std::move(value));
#endif
    }

    /*
     * Look up 'key' in the 'roarings' map. If it does not exist, create it.
     * Also, set its copyOnWrite flag to 'copyOnWrite'. Then return a reference
     * to the (already existing or newly created) inner bitmap.
     */
    Roaring &lookupOrCreateInner(uint32_t key) {
        auto &bitmap = roarings[key];
        bitmap.setCopyOnWrite(copyOnWrite);
        return bitmap;
    }

    /**
     * Prints the contents of the bitmap to a caller-provided sink function.
     */
    void printToSink(const std::function<void(const std::string &)> &sink) const {
        sink("{");

        // Storage for snprintf. Big enough to store the decimal representation
        // of the largest uint64_t value and trailing \0.
        char buffer[32];
        const char *separator = "";
        // Reusable, and therefore avoids many repeated heap allocations.
        std::string callback_string;
        for (const auto &entry : roarings) {
            auto high_bits = entry.first;
            const auto &bitmap = entry.second;
            for (const auto low_bits : bitmap) {
                auto value = uniteBytes(high_bits, low_bits);
                snprintf(buffer, sizeof(buffer), "%" PRIu64, value);
                callback_string = separator;
                callback_string.append(buffer);
                sink(callback_string);
                separator = ",";
            }
        }
        sink("}");
    }

    /**
     * Ensures that every key in the closed interval [start_high, end_high]
     * refers to a Roaring bitmap rather being an empty slot. Inserts empty
     * Roaring bitmaps if necessary. The interval must be valid and non-empty.
     * Returns an iterator to the bitmap at start_high.
     */
    roarings_t::iterator ensureRangePopulated(uint32_t start_high,
                                              uint32_t end_high) {
        if (start_high > end_high) {
            ROARING_TERMINATE("Logic error: start_high > end_high");
        }
        // next_populated_iter points to the first entry in the outer map with
        // key >= start_high, or end().
        auto next_populated_iter = roarings.lower_bound(start_high);

        // Use uint64_t to avoid an infinite loop when end_high == uint32_max.
        roarings_t::iterator start_iter{};  // Definitely assigned in loop.
        for (uint64_t slot = start_high; slot <= end_high; ++slot) {
            roarings_t::iterator slot_iter;
            if (next_populated_iter != roarings.end() &&
                next_populated_iter->first == slot) {
                // 'slot' index has caught up to next_populated_iter.
                // Note it here and advance next_populated_iter.
                slot_iter = next_populated_iter++;
            } else {
                // 'slot' index has not yet caught up to next_populated_iter.
                // Make a fresh entry {key = 'slot', value = Roaring()}, insert
                // it just prior to next_populated_iter, and set its copy
                // on write flag. We take pains to use emplace_hint and
                // piecewise_construct to minimize effort.
                slot_iter = roarings.emplace_hint(
                    next_populated_iter, std::piecewise_construct,
                    std::forward_as_tuple(uint32_t(slot)),
                    std::forward_as_tuple());
                auto &bitmap = slot_iter->second;
                bitmap.setCopyOnWrite(copyOnWrite);
            }

            // Make a note of the iterator of the starting slot. It will be
            // needed for the return value.
            if (slot == start_high) {
                start_iter = slot_iter;
            }
        }
        return start_iter;
    }

    /**
     * Erases the entry pointed to by 'iter' from the 'roarings' map. Warning:
     * this invalidates 'iter'.
     */
    void eraseIfEmpty(roarings_t::iterator iter) {
        const auto &bitmap = iter->second;
        if (bitmap.isEmpty()) {
            roarings.erase(iter);
        }
    }
};

/**
 * Used to go through the set bits. Not optimally fast, but convenient.
 */
class Roaring64MapSetBitForwardIterator {
public:
    typedef std::forward_iterator_tag iterator_category;
    typedef uint64_t *pointer;
    typedef uint64_t &reference;
    typedef uint64_t value_type;
    typedef int64_t difference_type;
    typedef Roaring64MapSetBitForwardIterator type_of_iterator;

    /**
     * Provides the location of the set bit.
     */
    value_type operator*() const {
        return Roaring64Map::uniteBytes(map_iter->first, i.current_value);
    }

    bool operator<(const type_of_iterator &o) const {
        if (map_iter == map_end) return false;
        if (o.map_iter == o.map_end) return true;
        return **this < *o;
    }

    bool operator<=(const type_of_iterator &o) const {
        if (o.map_iter == o.map_end) return true;
        if (map_iter == map_end) return false;
        return **this <= *o;
    }

    bool operator>(const type_of_iterator &o) const {
        if (o.map_iter == o.map_end) return false;
        if (map_iter == map_end) return true;
        return **this > *o;
    }

    bool operator>=(const type_of_iterator &o) const {
        if (map_iter == map_end) return true;
        if (o.map_iter == o.map_end) return false;
        return **this >= *o;
    }

    type_of_iterator &operator++() {  // ++i, must returned inc. value
        if (i.has_value == true) roaring_advance_uint32_iterator(&i);
        while (!i.has_value) {
            map_iter++;
            if (map_iter == map_end) return *this;
            roaring_init_iterator(&map_iter->second.roaring, &i);
        }
        return *this;
    }

    type_of_iterator operator++(int) {  // i++, must return orig. value
        Roaring64MapSetBitForwardIterator orig(*this);
        roaring_advance_uint32_iterator(&i);
        while (!i.has_value) {
            map_iter++;
            if (map_iter == map_end) return orig;
            roaring_init_iterator(&map_iter->second.roaring, &i);
        }
        return orig;
    }

    bool move(const value_type& x) {
        map_iter = p.lower_bound(Roaring64Map::highBytes(x));
        if (map_iter != p.cend()) {
            roaring_init_iterator(&map_iter->second.roaring, &i);
            if (map_iter->first == Roaring64Map::highBytes(x)) {
                if (roaring_move_uint32_iterator_equalorlarger(&i, Roaring64Map::lowBytes(x)))
                    return true;
                map_iter++;
                if (map_iter == map_end) return false;
                roaring_init_iterator(&map_iter->second.roaring, &i);
            }
            return true;
        }
        return false;
    }

    bool operator==(const Roaring64MapSetBitForwardIterator &o) const {
        if (map_iter == map_end && o.map_iter == o.map_end) return true;
        if (o.map_iter == o.map_end) return false;
        return **this == *o;
    }

    bool operator!=(const Roaring64MapSetBitForwardIterator &o) const {
        if (map_iter == map_end && o.map_iter == o.map_end) return false;
        if (o.map_iter == o.map_end) return true;
        return **this != *o;
    }

    Roaring64MapSetBitForwardIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
        map_iter = r.map_iter;
        map_end = r.map_end;
        i = r.i;
        return *this;
    }

    Roaring64MapSetBitForwardIterator(const Roaring64MapSetBitForwardIterator& r)
        : p(r.p),
          map_iter(r.map_iter),
          map_end(r.map_end),
          i(r.i)
    {}

    Roaring64MapSetBitForwardIterator(const Roaring64Map &parent,
                                      bool exhausted = false)
        : p(parent.roarings), map_end(parent.roarings.cend()) {
        if (exhausted || parent.roarings.empty()) {
            map_iter = parent.roarings.cend();
        } else {
            map_iter = parent.roarings.cbegin();
            roaring_init_iterator(&map_iter->second.roaring, &i);
            while (!i.has_value) {
                map_iter++;
                if (map_iter == map_end) return;
                roaring_init_iterator(&map_iter->second.roaring, &i);
            }
        }
    }

protected:
    const std::map<uint32_t, Roaring>& p;
    std::map<uint32_t, Roaring>::const_iterator map_iter{}; // The empty constructor silences warnings from pedantic static analyzers.
    std::map<uint32_t, Roaring>::const_iterator map_end{}; // The empty constructor silences warnings from pedantic static analyzers.
    internal::roaring_uint32_iterator_t i{}; // The empty constructor silences warnings from pedantic static analyzers.
};

class Roaring64MapSetBitBiDirectionalIterator final :public Roaring64MapSetBitForwardIterator {
public:
    explicit Roaring64MapSetBitBiDirectionalIterator(const Roaring64Map &parent,
                                                     bool exhausted = false)
        : Roaring64MapSetBitForwardIterator(parent, exhausted), map_begin(parent.roarings.cbegin())
    {}

    Roaring64MapSetBitBiDirectionalIterator &operator=(const Roaring64MapSetBitForwardIterator& r) {
        *(Roaring64MapSetBitForwardIterator*)this = r;
        return *this;
    }

    Roaring64MapSetBitBiDirectionalIterator& operator--() { //  --i, must return dec.value
        if (map_iter == map_end) {
            --map_iter;
            roaring_init_iterator_last(&map_iter->second.roaring, &i);
            if (i.has_value) return *this;
        }

        roaring_previous_uint32_iterator(&i);
        while (!i.has_value) {
            if (map_iter == map_begin) return *this;
            map_iter--;
            roaring_init_iterator_last(&map_iter->second.roaring, &i);
        }
        return *this;
    }

    Roaring64MapSetBitBiDirectionalIterator operator--(int) {  // i--, must return orig. value
        Roaring64MapSetBitBiDirectionalIterator orig(*this);
        if (map_iter == map_end) {
            --map_iter;
            roaring_init_iterator_last(&map_iter->second.roaring, &i);
            return orig;
        }

        roaring_previous_uint32_iterator(&i);
        while (!i.has_value) {
            if (map_iter == map_begin) return orig;
            map_iter--;
            roaring_init_iterator_last(&map_iter->second.roaring, &i);
        }
        return orig;
    }

protected:
    std::map<uint32_t, Roaring>::const_iterator map_begin;
};

inline Roaring64MapSetBitForwardIterator Roaring64Map::begin() const {
    return Roaring64MapSetBitForwardIterator(*this);
}

inline Roaring64MapSetBitForwardIterator Roaring64Map::end() const {
    return Roaring64MapSetBitForwardIterator(*this, true);
}

}  // namespace paimon::roaring

#endif /* INCLUDE_ROARING_64_MAP_HH_ */
/* end file cpp/roaring64map.hh */
