<commit_before>#ifndef IMPL_AX_VECTOR_HPP
#define IMPL_AX_VECTOR_HPP

#include <cstddef>
#include <algorithm>
#include <vector>
#include <memory>

#include "prelude.hpp"

namespace ax
{
    // A vector with small size optimization.
    template<typename T, typename A = std::allocator<T>, std::size_t N = 4>
    class vector
    {
    public:

        CONSTRAINT(vector);
        using value_type = T;
        using size_type = std::size_t;
        using iterator = T*;
        using const_iterator = const T*;
        using allocator = A; // TODO: see if this is a meaningful trait name
        template<typename T2, typename A2, std::size_t N2>
        using reify = ax::vector<T2, A2, N2>;

        vector() : vector({ }) { }

        vector(std::initializer_list<T> il) :
            vector(il.begin(), il.end()) { }

        vector(const T* begin, const T* end)
        {
            VAR size = static_cast<std::size_t>(end - begin);
            if (size > N)
            {
                small_end = small_begin - 1;
                big_vector.insert(big_vector.begin(), begin, end);
            }
            else
            {
                small_end = small_begin;
                for (VAR i = 0_z; i < N && begin != end; ++i)
                {
                    *small_end = *begin;
                    ++small_end;
                    ++begin;
                }
            }
        }

        vector(const ax::vector<T, A, N>& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = that.big_vector;
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        vector(ax::vector<T, A, N>&& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = std::move(that.big_vector);
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        ~vector() = default;

        ax::vector<T, A, N>& operator=(const ax::vector<T, A, N>& that)
        {
            big_vector = that.big_vector;
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        ax::vector<T, A, N>& operator=(ax::vector<T, A, N>&& that)
        {
            big_vector = std::move(that.big_vector);
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        bool operator==(const ax::vector<T, A, N>& that) const
        {
            VAL size = this->size();
            if (size > N) return big_vector == that.big_vector;
            VAR result = true;
            for (VAR i = 0_z; result && i < size; ++i)
                result = small_begin[i] == that.small_begin[i];
            return result;
        }

        bool operator!=(const ax::vector<T, A, N>& that) const
        {
            return !(*this == that);
        }

        T* begin() { return big() ? big_vector.data() : small_begin; }
        T* end() { return big() ? big_vector.data() + big_vector.size() : small_end; }
        const T* cbegin() const { return const_cast<ax::vector<T, A, N>*>(this)->begin(); }
        const T* cend() const { return const_cast<ax::vector<T, A, N>*>(this)->end(); }
        const T* begin() const { return cbegin(); }
        const T* end() const { return cend(); }

        void push_back(const T& item)
        {
            if (big())
            {
                if (size() == N) big_vector.insert(big_vector.begin(), small_begin, small_end);
                big_vector.push_back(item);
                small_end = small_begin - 1;
            }
            else
            {
                new (small_end) T(item);
                ++small_end;
            }
        }

        void pop_back()
        {
            if (big()) return big_vector.pop_back();
            if (size() != 0)
            {
                (small_end - 1)->~T();
                --small_end;
                return;
            }
            throw std::range_error("Cannot pop_back empty ax::vector.");
        }

        T* erase(const T* iter)
        {
            if (big())<commit_msg>Intermediate commit.<commit_after>#ifndef IMPL_AX_VECTOR_HPP
#define IMPL_AX_VECTOR_HPP

#include <cstddef>
#include <algorithm>
#include <vector>
#include <memory>

#include "prelude.hpp"

namespace ax
{
    // A vector with small size optimization.
    template<typename T, typename A = std::allocator<T>, std::size_t N = 4>
    class vector
    {
    public:

        CONSTRAINT(vector);
        using value_type = T;
        using size_type = std::size_t;
        using iterator = T*;
        using const_iterator = const T*;
        using allocator = A; // TODO: see if this is a meaningful trait name
        template<typename T2, typename A2, std::size_t N2>
        using reify = ax::vector<T2, A2, N2>;

        vector() : vector({ }) { }

        vector(std::initializer_list<T> il) :
            vector(il.begin(), il.end()) { }

        vector(const T* begin, const T* end)
        {
            VAR size = static_cast<std::size_t>(end - begin);
            if (size > N)
            {
                small_end = small_begin - 1;
                big_vector.insert(big_vector.begin(), begin, end);
            }
            else
            {
                small_end = small_begin;
                for (VAR i = 0_z; i < N && begin != end; ++i)
                {
                    *small_end = *begin;
                    ++small_end;
                    ++begin;
                }
            }
        }

        vector(const ax::vector<T, A, N>& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = that.big_vector;
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        vector(ax::vector<T, A, N>&& that)
        {
            if (that.small_end < that.small_begin)
            {
                small_end = small_begin - 1;
                big_vector = std::move(that.big_vector);
            }
            else
            {
                small_end = small_begin;
                VAL size = that.size();
                for (VAR i = 0_z; i < size; ++i)
                {
                    *small_end = that.small_begin[i];
                    ++small_end;
                }
            }
        }

        ~vector() = default;

        ax::vector<T, A, N>& operator=(const ax::vector<T, A, N>& that)
        {
            big_vector = that.big_vector;
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        ax::vector<T, A, N>& operator=(ax::vector<T, A, N>&& that)
        {
            big_vector = std::move(that.big_vector);
            VAL size = that.size();
            for (VAR i = 0_z; i < size; ++i)
            {
                *small_end = that.small_begin[i];
                ++small_end;
            }
            return *this;
        }

        bool operator==(const ax::vector<T, A, N>& that) const
        {
            VAL size = this->size();
            if (size > N) return big_vector == that.big_vector;
            VAR result = true;
            for (VAR i = 0_z; result && i < size; ++i)
                result = small_begin[i] == that.small_begin[i];
            return result;
        }

        bool operator!=(const ax::vector<T, A, N>& that) const
        {
            return !(*this == that);
        }

        T* begin() { return big() ? big_vector.data() : small_begin; }
        T* end() { return big() ? big_vector.data() + big_vector.size() : small_end; }
        const T* cbegin() const { return const_cast<ax::vector<T, A, N>*>(this)->begin(); }
        const T* cend() const { return const_cast<ax::vector<T, A, N>*>(this)->end(); }
        const T* begin() const { return cbegin(); }
        const T* end() const { return cend(); }

        void push_back(const T& item)
        {
            if (big())
            {
                big_vector.push_back(item);
            }
            else if (size() == N)
            {
                big_vector.insert(big_vector.begin(), small_begin, small_end);
                big_vector.push_back(item);
                small_end = small_begin - 1;
            }
            else
            {
                new (small_end) T(item);
                ++small_end;
            }
        }

        void pop_back()
        {
            if (big()) return big_vector.pop_back();
            if (size() != 0)
            {
                (small_end - 1)->~T();
                --small_end;
                return;
            }
            throw std::range_error("Cannot pop_back empty ax::vector.");
        }

        T* erase(const T* iter)
        {
            if (big())
{'fraction_non_alphanumeric': 0.1262767875025035, 'fraction_numerical': 0.0038053274584418186, 'mean_word_length': 1.2332289803220036, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2103391', 'n_tokens_mistral': 3035, 'n_tokens_neox': 2889, 'n_words': 696}