<commit_before>#ifndef units_hh_INCLUDED
#define units_hh_INCLUDED

#include "hash.hh"

#include <type_traits>

namespace Kakoune
{

template<typename RealType, typename ValueType = int>
class StronglyTypedNumber
{
public:
    [[gnu::always_inline]]
    explicit constexpr StronglyTypedNumber(ValueType value)
        : m_value(value)
    {
        static_assert(std::is_base_of<StronglyTypedNumber, RealType>::value,
                     "RealType is not derived from StronglyTypedNumber");
    }

    [[gnu::always_inline]]
    constexpr RealType operator+(RealType other) const
    { return RealType(m_value + other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator-(RealType other) const
    { return RealType(m_value - other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator*(RealType other) const
    { return RealType(m_value * other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator/(RealType other) const
    { return RealType(m_value / other.m_value); }

    [[gnu::always_inline]]
    RealType& operator+=(RealType other)
    { m_value += other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator-=(RealType other)
    { m_value -= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator*=(RealType other)
    { m_value *= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator/=(RealType other)
    { m_value /= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator++()
    { ++m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator--()
    { --m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType operator++(int)
    { RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; }

    [[gnu::always_inline]]
    RealType operator--(int)
    { RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; }

    [[gnu::always_inline]]
    constexpr RealType operator-() const { return RealType(-m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator%(RealType other) const
    { return RealType(m_value % other.m_value); }

    [[gnu::always_inline]]
    RealType& operator%=(RealType other)
    { m_value %= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    constexpr bool operator==(RealType other) const
    { return m_value == other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator!=(RealType other) const
    { return m_value != other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator<(RealType other) const
    { return m_value < other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator<=(RealType other) const
    { return m_value <= other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator>(RealType other) const
    { return m_value > other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator>=(RealType other) const
    { return m_value >= other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator!() const
    { return !m_value; }

    [[gnu::always_inline]]
    explicit constexpr operator ValueType() const { return m_value; }
    [[gnu::always_inline]]
    explicit constexpr operator bool() const { return m_value; }

    friend size_t hash_value(RealType val) { return hash_value(val.m_value); }

private:
    ValueType m_value;
};

struct LineCount : public StronglyTypedNumber<LineCount, int>
{
    [[gnu::always_inline]]
    constexpr LineCount(int value = 0) : StronglyTypedNumber<LineCount>(value) {}
};

[[gnu::always_inline]]
inline constexpr LineCount operator"" _line(unsigned long long int value)
{
    return LineCount(value);
}

struct ByteCount : public StronglyTypedNumber<ByteCount, int>
{
    [[gnu::always_inline]]
    constexpr ByteCount(int value = 0) : StronglyTypedNumber<ByteCount>(value) {}
};
<commit_msg>Add a 'abs' friend function to StronglyTypedNumber<commit_after>#ifndef units_hh_INCLUDED
#define units_hh_INCLUDED

#include "hash.hh"

#include <type_traits>

namespace Kakoune
{

template<typename RealType, typename ValueType = int>
class StronglyTypedNumber
{
public:
    [[gnu::always_inline]]
    explicit constexpr StronglyTypedNumber(ValueType value)
        : m_value(value)
    {
        static_assert(std::is_base_of<StronglyTypedNumber, RealType>::value,
                     "RealType is not derived from StronglyTypedNumber");
    }

    [[gnu::always_inline]]
    constexpr RealType operator+(RealType other) const
    { return RealType(m_value + other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator-(RealType other) const
    { return RealType(m_value - other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator*(RealType other) const
    { return RealType(m_value * other.m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator/(RealType other) const
    { return RealType(m_value / other.m_value); }

    [[gnu::always_inline]]
    RealType& operator+=(RealType other)
    { m_value += other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator-=(RealType other)
    { m_value -= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator*=(RealType other)
    { m_value *= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator/=(RealType other)
    { m_value /= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator++()
    { ++m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType& operator--()
    { --m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    RealType operator++(int)
    { RealType backup(static_cast<RealType&>(*this)); ++m_value; return backup; }

    [[gnu::always_inline]]
    RealType operator--(int)
    { RealType backup(static_cast<RealType&>(*this)); --m_value; return backup; }

    [[gnu::always_inline]]
    constexpr RealType operator-() const { return RealType(-m_value); }

    [[gnu::always_inline]]
    constexpr RealType operator%(RealType other) const
    { return RealType(m_value % other.m_value); }

    [[gnu::always_inline]]
    RealType& operator%=(RealType other)
    { m_value %= other.m_value; return static_cast<RealType&>(*this); }

    [[gnu::always_inline]]
    constexpr bool operator==(RealType other) const
    { return m_value == other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator!=(RealType other) const
    { return m_value != other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator<(RealType other) const
    { return m_value < other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator<=(RealType other) const
    { return m_value <= other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator>(RealType other) const
    { return m_value > other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator>=(RealType other) const
    { return m_value >= other.m_value; }

    [[gnu::always_inline]]
    constexpr bool operator!() const
    { return !m_value; }

    [[gnu::always_inline]]
    explicit constexpr operator ValueType() const { return m_value; }
    [[gnu::always_inline]]
    explicit constexpr operator bool() const { return m_value; }

    friend size_t hash_value(RealType val) { return hash_value(val.m_value); }
    friend size_t abs(RealType val) { return abs(val.m_value); }

private:
    ValueType m_value;
};

struct LineCount : public StronglyTypedNumber<LineCount, int>
{
    [[gnu::always_inline]]
    constexpr LineCount(int value = 0) : StronglyTypedNumber<LineCount>(value) {}
};

[[gnu::always_inline]]
inline constexpr LineCount operator"" _line(unsigned long long int value)
{
    return LineCount(value);
}

struct ByteCount : public StronglyTypedNumber<ByteCount, int>
{
    [[gnu::always_inline]]
    constexpr ByteCount(int value = 0) : StronglyTypedNumber<ByteCount>(value) {}
};

{'fraction_non_alphanumeric': 0.1356382978723404, 'fraction_numerical': 0.00048355899419729207, 'mean_word_length': 4.209697732997481, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 43, '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': '2167637', 'n_tokens_mistral': 2647, 'n_tokens_neox': 2599, 'n_words': 556}