//#pragma once
//#include <cstdlib>
//#include <cstring>
//#include <cassert>
//#include <new>
//#include <utility>
//#include <algorithm>
//#include <type_traits>
//
//#ifndef FV_ASSERT
//#define FV_ASSERT(cond) assert(cond)
//#endif
//
//template<typename T, size_t SBO_CAP = 16>
//class FastVector {
//    using StorageT = typename std::aligned_storage<sizeof(T), alignof(T)>::type;
//
//    StorageT sbo_[SBO_CAP];
//    T* data_ = reinterpret_cast<T*>(sbo_);
//    size_t size_ = 0;
//    size_t capacity_ = SBO_CAP;
//    bool heapAllocated_ = false;
//
//    inline void reallocate(size_t newCap) {
//        T* newData = reinterpret_cast<T*>(std::malloc(newCap * sizeof(T)));
//        if (!newData) std::abort();
//
//        if constexpr (std::is_trivially_copyable_v<T>) {
//            std::memcpy(newData, data_, size_ * sizeof(T));
//        } else {
//            std::uninitialized_copy(data_, data_ + size_, newData);
//            std::destroy(data_, data_ + size_);
//        }
//
//        if (heapAllocated_) std::free(data_);
//        data_ = newData;
//        capacity_ = newCap;
//        heapAllocated_ = true;
//    }
//
//public:
//    inline FastVector() = default;
//
//    inline ~FastVector() {
//        std::destroy(data_, data_ + size_);
//        if (heapAllocated_) std::free(data_);
//    }
//
//    // Copy constructor
//    FastVector(const FastVector& other) {
//        reserve(other.size_);
//        if constexpr (std::is_trivially_copyable_v<T>) {
//            std::memcpy(data_, other.data_, other.size_ * sizeof(T));
//        } else {
//            std::uninitialized_copy(other.data_, other.data_ + other.size_, data_);
//        }
//        size_ = other.size_;
//    }
//
//    // Move constructor
//    FastVector(FastVector&& other) noexcept {
//        if (other.heapAllocated_) {
//            data_ = other.data_;
//            size_ = other.size_;
//            capacity_ = other.capacity_;
//            heapAllocated_ = true;
//        } else {
//            std::uninitialized_move(other.data_, other.data_ + other.size_, data_);
//        }
//        other.data_ = reinterpret_cast<T*>(other.sbo_);
//        other.size_ = 0;
//        other.capacity_ = SBO_CAP;
//        other.heapAllocated_ = false;
//    }
//
//    // Copy assignment
//    FastVector& operator=(const FastVector& other) {
//        if (this != &other) {
//            clear();
//            reserve(other.size_);
//            if constexpr (std::is_trivially_copyable_v<T>) {
//                std::memcpy(data_, other.data_, other.size_ * sizeof(T));
//            } else {
//                std::uninitialized_copy(other.data_, other.data_ + other.size_, data_);
//            }
//            size_ = other.size_;
//        }
//        return *this;
//    }
//
//    // Move assignment
//    FastVector& operator=(FastVector&& other) noexcept {
//        if (this != &other) {
//            clear();
//            if (heapAllocated_) std::free(data_);
//
//            if (other.heapAllocated_) {
//                data_ = other.data_;
//                size_ = other.size_;
//                capacity_ = other.capacity_;
//                heapAllocated_ = true;
//            } else {
//                std::uninitialized_move(other.data_, other.data_ + other.size_, data_);
//            }
//
//            other.data_ = reinterpret_cast<T*>(other.sbo_);
//            other.size_ = 0;
//            other.capacity_ = SBO_CAP;
//            other.heapAllocated_ = false;
//        }
//        return *this;
//    }
//
//    inline void push_back(const T& val) {
//        if (size_ == capacity_) reallocate(capacity_ * 2);
//        new (data_ + size_) T(val);
//        ++size_;
//    }
//
//    inline void push_back(T&& val) {
//        if (size_ == capacity_) reallocate(capacity_ * 2);
//        new (data_ + size_) T(std::move(val));
//        ++size_;
//    }
//
//    inline void pop_back() {
//        FV_ASSERT(size_ > 0);
//        --size_;
//        std::destroy_at(data_ + size_);
//    }
//
//    inline void clear() {
//        std::destroy(data_, data_ + size_);
//        size_ = 0;
//    }
//
//    inline void reserve(size_t newCap) {
//        if (newCap > capacity_) reallocate(newCap);
//    }
//
//    inline void resize(size_t newSize) {
//        if (newSize > capacity_) reallocate(newSize);
//        if (newSize > size_) {
//            std::uninitialized_value_construct(data_ + size_, data_ + newSize);
//        } else {
//            std::destroy(data_ + newSize, data_ + size_);
//        }
//        size_ = newSize;
//    }
//
//    inline T& operator[](size_t i) {
//        FV_ASSERT(i < size_);
//        return data_[i];
//    }
//
//    inline const T& operator[](size_t i) const {
//        FV_ASSERT(i < size_);
//        return data_[i];
//    }
//
//    inline T* data() { return data_; }
//    inline const T* data() const { return data_; }
//
//    inline size_t size() const { return size_; }
//    inline size_t capacity() const { return capacity_; }
//    inline bool empty() const { return size_ == 0; }
//};
