<commit_before>/*
 * vector_detail.hpp
 *
 *  Created on: Oct 29, 2014
 *      Author: zmij
 */

#ifndef PUSHKIN_VECTOR_DETAIL_HPP_
#define PUSHKIN_VECTOR_DETAIL_HPP_

#include <type_traits>
#include <utility>

#include <pushkin/math/detail/axis_names.hpp>
#include <pushkin/math/detail/value_traits.hpp>

namespace psst {
namespace math {

namespace detail {

/** Variadic template arguments unwrapping */
template< ::std::size_t Index, typename T >
struct data_holder {
    static constexpr ::std::size_t index = Index;
    using type = T;

    type value;

    constexpr data_holder() = default;
    data_holder(data_holder const&) = default;
    data_holder(data_holder&&) = default;
    data_holder&
    operator = (data_holder const&) = default;
    data_holder&
    operator = (data_holder&&) = default;

    constexpr data_holder(type const& value)
        : value(value) {}

    template< typename Y >
    constexpr data_holder(Y const& value)
        : value(value) {}

    void
    swap(data_holder<Index, T>& rhs)
    {
        using std::swap;
        swap(value, rhs.value);
    }

    template< size_t idx1, typename Y >
    data_holder&
    operator =(const data_holder< idx1, Y >& rhs)
    {
        value = rhs.value;
        return *this;
    }
};

template < typename IndexTuple, typename T >
struct vector_builder;

template < ::std::size_t ... Indexes, typename T >
struct vector_builder< std::index_sequence< Indexes ... >, T > :
    // TODO Replace the data holder with an std::array
    data_holder< Indexes, T > ... {

    static constexpr ::std::size_t size = sizeof ... (Indexes);
    using index_sequence_type   = std::index_sequence< Indexes ... >;
    using this_type             = vector_builder< index_sequence_type, T >;

    using element_type          = T;
    using value_traits          = vector_value_traits<T>;
    using value_type            = typename value_traits::value_type;
    using lvalue_reference      = typename value_traits::lvalue_reference;
    using const_reference       = typename value_traits::const_reference;

    using magnitude_type        = typename value_traits::magnitude_type;

    using pointer               = value_type*;
    using const_pointer         = value_type const*;

    using iterator              = value_type*;
    using const_iterator        = value_type const*;

    constexpr vector_builder() = default;

    /**
     * Single value constructor, for initializing all values to the value
     * @param val
     */
    constexpr vector_builder(T val)
        : data_holder< Indexes, T >(val) ... {}

    /**
     * Construct vector from a vector of larger size
     * @param rhs
     * @param
     */
    template < ::std::size_t ... IndexesR, typename U >
    constexpr vector_builder(
            vector_builder< std::index_sequence< IndexesR ... >, U > const& rhs,
            typename ::std::enable_if< size <= sizeof ... (IndexesR) >::type* = 0 )
        : data_holder< Indexes, T >( rhs.template at< Indexes >() ) ... {}

    template < typename ... E >
    constexpr vector_builder(E const& ... args,
            typename ::std::enable_if< size == sizeof ... (E) >::type* = 0)
        : data_holder< Indexes, T >(args) ... {}

    template < typename ... E >
    constexpr vector_builder(E&& ... args,
            typename ::std::enable_if< size == sizeof ... (E) >::type* = 0)
        : data_holder< Indexes, T >( std::forward<E>(args) ) ... {}

    template < typename U >
    constexpr vector_builder(::std::initializer_list<U> const& args)
        : data_holder< Indexes, T >(*(args.begin() + Indexes))... {}

    constexpr vector_builder(const_pointer p)
        : data_holder< Indexes, T >(*(p + Indexes))... {}

    pointer
    data()
    {
        return &this->data_holder< 0, T >::value;
    }

    constexpr const_pointer
    data() const
    {
        return &this->data_holder< 0, T >::value;
    }

    template < ::std::size_t N >
    lvalue_reference
    at()
    {
        return this->data_holder< N, T >::value;
    }

    template < ::std::size_t N >
    constexpr const_reference
    at() const
    {
        return this->data_holder< N, T >::value;
    }

    iterator
    begin()
    {
        return &this->data_holder< 0, T >::value;
    }

    constexpr const_iterator
    begin() const
    {
        return cbegin();
    }
    constexpr const_iterator
    cbegin() const
    {
        return &this->data_holder< 0, T >::value;
    }

    iterator
    end()
    {
        return begin() + size;
    }

    constexpr const_iterator
    end() const
    {
        return cend();
    }
    constexpr const_iterator
    cend() const
    {
        return begin() + size;
    }

    lvalue_reference
    operator[](::std::size_t idx)
    {
        assert(idx < size);
        return begin()[idx];
    }

    constexpr const_reference
    operator[](::std::size_t idx) const
    {
        assert(idx < size);
        return begin()[idx];
    }
};

template < ::std::size_t L, ::std::size_t R >
struct min : ::std::conditional<
        L < R,
        ::std::integral_constant<::std::size_t, L>,
        ::std::integral_constant<::std::size_t, R>
    >::type {};

template < ::std::size_t N, typename T, typename U >
struct vector_cmp;

template < ::std::size_t N, typename T, typename U,
    ::std::size_t TSize, ::std::size_t USize,
    typename Axes >
struct vector_cmp<N, vector<T, TSize, Axes>, vector<U, USize, Axes>> {
    using left_side     = vector<T, TSize, Axes>;
    using traits_type   = typename left_side::value_traits;
    using right_side    = vector<U, USize, Axes>;
    using prev_elem     = vector_cmp<N - 1, left_side, right_side>;<commit_msg>feat: use std::array for storage of vector data<commit_after>/*
 * vector_detail.hpp
 *
 *  Created on: Oct 29, 2014
 *      Author: zmij
 */

#ifndef PUSHKIN_VECTOR_DETAIL_HPP_
#define PUSHKIN_VECTOR_DETAIL_HPP_

#include <pushkin/math/detail/axis_names.hpp>
#include <pushkin/math/detail/value_traits.hpp>

#include <type_traits>
#include <utility>
#include <array>

namespace psst {
namespace math {

namespace detail {

/** Variadic template arguments unwrapping */
template< ::std::size_t Index, typename T >
struct data_holder {
    static constexpr ::std::size_t index = Index;
    using type = T;

    type value;

    constexpr data_holder() = default;
    data_holder(data_holder const&) = default;
    data_holder(data_holder&&) = default;
    data_holder&
    operator = (data_holder const&) = default;
    data_holder&
    operator = (data_holder&&) = default;

    constexpr data_holder(type const& value)
        : value(value) {}

    template< typename Y >
    constexpr data_holder(Y const& value)
        : value(value) {}

    void
    swap(data_holder<Index, T>& rhs)
    {
        using std::swap;
        swap(value, rhs.value);
    }

    template< size_t idx1, typename Y >
    data_holder&
    operator =(const data_holder< idx1, Y >& rhs)
    {
        value = rhs.value;
        return *this;
    }
};

template <::std::size_t Index, typename T>
struct value_fill {
  T value;
};

template < typename IndexTuple, typename T >
struct vector_builder;

template < ::std::size_t ... Indexes, typename T >
struct vector_builder< std::index_sequence< Indexes ... >, T > {

    static constexpr ::std::size_t size = sizeof ... (Indexes);
    using index_sequence_type   = std::index_sequence< Indexes ... >;
    using this_type             = vector_builder< index_sequence_type, T >;

    using element_type          = T;
    using value_traits          = vector_value_traits<T>;
    using value_type            = typename value_traits::value_type;
    using lvalue_reference      = typename value_traits::lvalue_reference;
    using const_reference       = typename value_traits::const_reference;

    using magnitude_type        = typename value_traits::magnitude_type;

    using pointer               = value_type*;
    using const_pointer         = value_type const*;

    using iterator              = value_type*;
    using const_iterator        = value_type const*;

    constexpr vector_builder() = default;

    /**
     * Single value constructor, for initializing all values to the value
     * @param val
     */
    constexpr vector_builder(T val)
        : data_({value_fill<Indexes, T>{val}.value ...}) {}

    /**
     * Construct vector from a vector of larger size
     * @param rhs
     * @param
     */
    template < ::std::size_t ... IndexesR, typename U >
    constexpr vector_builder(
            vector_builder< std::index_sequence< IndexesR ... >, U > const& rhs,
            typename ::std::enable_if< size <= sizeof ... (IndexesR) >::type* = 0 )
        : data_({rhs.template at< Indexes >()...}) {}

    template < typename ... E >
    constexpr vector_builder(E const& ... args,
            typename ::std::enable_if< size == sizeof ... (E) >::type* = 0)
        : data_({args...}) {}

    template < typename ... E >
    constexpr vector_builder(E&& ... args,
            typename ::std::enable_if< size == sizeof ... (E) >::type* = 0)
        : data_({std::forward<E>(args)...}) {}

    template < typename U >
    constexpr vector_builder(::std::initializer_list<U> const& args)
        : data_({*(args.begin() + Indexes)...}) {}

    constexpr vector_builder(const_pointer p)
        : data_({*(p + Indexes)...}) {}

    pointer
    data() { return data_.data(); }

    constexpr const_pointer
    data() const { return data_.data(); }

    template < ::std::size_t N >
    lvalue_reference
    at() { return ::std::get<N>(data_); }

    template < ::std::size_t N >
    constexpr const_reference
    at() const { return ::std::get<N>(data_); }

    iterator
    begin() { return data_.begin(); }

    constexpr const_iterator
    begin() const { return cbegin(); }
    constexpr const_iterator
    cbegin() const { return data_.cbegin(); }

    iterator
    end() { return data_.end(); }

    constexpr const_iterator
    end() const { return cend(); }
    constexpr const_iterator
    cend() const { return data_.end(); }

    lvalue_reference
    operator[](::std::size_t idx)
    {
        assert(idx < size);
        return data_[idx];
    }

    constexpr const_reference
    operator[](::std::size_t idx) const
    {
        assert(idx < size);
        return data_[idx];
    }
private:
    using data_type = ::std::array<T, size>;
    data_type data_;
};

template < ::std::size_t L, ::std::size_t R >
struct min : ::std::conditional<
        L < R,
        ::std::integral_constant<::std::size_t, L>,
        ::std::integral_constant<::std::size_t, R>
    >::type {};

template < ::std::size_t N, typename T, typename U >
struct vector_cmp;

template < ::std::size_t N, typename T, typename U,
    ::std::size_t TSize, ::std::size_t USize,
    typename Axes >
struct vector_cmp<N, vector<T, TSize, Axes>, vector<U, USize, Axes>> {
    using left_side     = vector<T, TSize, Axes>;
    using traits_type   = typename left_side::value_traits;
    using right_side    = vector<U, USize, Axes>;
    using prev_elem     = vector_cmp<N - 1, left_side, right_side>;
{'fraction_non_alphanumeric': 0.13242585414225186, 'fraction_numerical': 0.0025241143063193003, 'mean_word_length': 2.6338028169014085, 'pattern_counts': {'":': 0, '<': 114, '<?xml version=': 0, '>': 112, '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': '124696', 'n_tokens_mistral': 3613, 'n_tokens_neox': 3434, 'n_words': 884}