<commit_before>#pragma once

#include "altruct/structure/math/polynom.h"

namespace altruct {
namespace math {

// series storage type

namespace series_storage {
    enum type { INSTANCE, STATIC, CONSTANT };
}

template<typename T, int ID, int STORAGE_TYPE>
struct series_members;

template<typename T, int ID>
struct series_members<T, ID, series_storage::INSTANCE> {
    int _N;
    series_members(int _N = 0) : _N(_N) {}
    int N() const { return _N; }
    int& refN() { return _N; }
};

template<typename T, int ID>
struct series_members<T, ID, series_storage::STATIC> {
    static int _N;
    series_members(int _N = 0) {}
    static int N() { return _N; }
    static int& refN() { return _N; }
};

template<typename T, int ID>
struct series_members<T, ID, series_storage::CONSTANT> {
    series_members(int _N = 0) {}
    static int N() { return ID; }
    static int& refN() { static int _N = 0; return _N; }
};

/**
 * A formal power series
 *
 * `s(x) = p(x) + O(x^N)`, where p(x) is a polynomial of degree N-1
 *
 * @param T - the underlying type
 * @param ID - ID of the series type (useful with series_storage::CONSTANT)
 * @param STORAGE_TYPE - whether N is a constant, static or instance member
 *   See `STORAGE_TYPE` in the `modulo` class for details.
 */
template<typename T, int ID, int STORAGE_TYPE = series_storage::CONSTANT>
class series : public series_members<T, ID, STORAGE_TYPE> {
    typedef series_members<T, ID, STORAGE_TYPE> my_series_members;
public:
    // s(x) = p(x) + O(x^N)
    polynom<T> p;

    series(const T& c0 = T(0)) : my_series_members(1), p(c0) { p.reserve(this->N()); }
    // construct from int, but only if T is not integral to avoid constructor clashing
    template <typename I = T, typename = std::enable_if_t<!std::is_integral<I>::value>>
    series(int c0) : my_series_members(1) , p(c0) { p.reserve(this->N()); } // to allow constructing from 0 and 1
    series(series&& rhs) : my_series_members(rhs.N()), p(std::move(rhs.p)) { p.reserve(this->N()); }
    series(const series& rhs) : my_series_members(rhs.N()), p(rhs.p) { p.reserve(this->N()); }
    series(polynom<T>&& rhs, int _N) : my_series_members(_N), p(std::move(rhs)) { p.reserve(this->N()); }
    series(const polynom<T>& rhs, int _N) : my_series_members(_N), p(rhs) { p.reserve(this->N()); }
    series(polynom<T>&& rhs) : my_series_members(rhs.size()), p(std::move(rhs)) { p.reserve(this->N()); }
    series(const polynom<T>& rhs) : my_series_members(rhs.size()), p(rhs) { p.reserve(this->N()); }
    series(std::vector<T>&& c) : my_series_members((int)c.size()), p(std::move(c)) { p.reserve(this->N()); }
    series(const std::vector<T>& c) : my_series_members((int)c.size()), p(c) { p.reserve(this->N()); }
    template<typename It> series(It begin, It end) : my_series_members((int)std::distance(begin, end)), p(begin, end) { p.reserve(this->N()); }
    series(std::initializer_list<T> list) : my_series_members((int)list.size()), p(list) { p.reserve(this->N()); }
    series& operator = (series&& rhs) { this->refN() = rhs.N(), this->p = std::move(rhs.p); return *this; }
    series& operator = (const series& rhs) { this->refN() = rhs.N(), this->p = rhs.p; return *this; }

    series& swap(series& rhs) { p.swap(rhs.p); std::swap(this->refN(), rhs.refN()); return *this; }

    series& resize(int _N) { this->refN() = _N; p.resize(_N); return *this; }
    int size() const { return this->N(); }
    const T& at(int index) const { return p.at(index); }
    const T& operator [] (int index) const { return p[index]; }
    T& operator [] (int index) { return p[index]; }

    bool operator == (const series& rhs) const { return p == rhs.p; }
    bool operator != (const series& rhs) const { return p != rhs.p; }
    bool operator <  (const series& rhs) const { return p <  rhs.p; }
    bool operator >  (const series& rhs) const { return p >  rhs.p; }
    bool operator <= (const series& rhs) const { return p <= rhs.p; }
    bool operator >= (const series& rhs) const { return p >= rhs.p; }

    series  operator +  (const series &rhs) const { series t(*this); t += rhs; return t; }
    series  operator -  (const series &rhs) const { series t(*this); t -= rhs; return t; }
    series  operator -  ()                  const { return series(-p, this->N()); }
    series  operator *  (const series& rhs) const { series t(*this); t *= rhs; return t; }
    series  operator /  (const series& rhs) const { series t(*this); t /= rhs; return t; }

    series  operator *  (const T &val) const { series t(*this); t *= val; return t; }
    series  operator /  (const T &val) const { series t(*this); t /= val; return t; }

    series& operator += (const series &rhs) { p += rhs.p; p.reserve(this->N()); return *this; }
    series& operator -= (const series &rhs) { p -= rhs.p; p.reserve(this->N()); return *this; }
    series& operator *= (const series& rhs) { polynom<T>::mul(p, p, rhs.p, this->N() - 1); return *this; }
    series& operator /= (const series& rhs) { return *this *= rhs.inverse(); }

    series& operator *= (const T &val) { p *= val; p.reserve(this->N()); return *this; }
    series& operator /= (const T &val) { p /= val; p.reserve(this->N()); return *this; }

    series derivative() const { return series(p.derivative(), this->N()); }
    series integral() const { return integral(p.ZERO_COEFF); }
    series integral(const T& c0) const { auto pi = p.integral(c0); pi.resize(this->N()); return series(std::move(pi), this->N()); }

    // pointwise multiplication of the coefficients
    series pointwise_mul(const series& rhs) const {
        series s = *this;
        for (int i = 0; i < this->N(); i++) {
            s[i] *= rhs[i];
        }
        return s;
    }

    // s(x)*x^l - shifts coefficients of s(x) by l places
    series shift(int l) const {
        if (l < 0) {
            polynom<T> t{ p.c.begin() - l, p.c.end() };
            t.c.insert(t.c.end(), -l, p.ZERO_COEFF);<commit_msg>series: reserve -> resize<commit_after>#pragma once

#include "altruct/structure/math/polynom.h"

namespace altruct {
namespace math {

// series storage type

namespace series_storage {
    enum type { INSTANCE, STATIC, CONSTANT };
}

template<typename T, int ID, int STORAGE_TYPE>
struct series_members;

template<typename T, int ID>
struct series_members<T, ID, series_storage::INSTANCE> {
    int _N;
    series_members(int _N = 0) : _N(_N) {}
    int N() const { return _N; }
    int& refN() { return _N; }
};

template<typename T, int ID>
struct series_members<T, ID, series_storage::STATIC> {
    static int _N;
    series_members(int _N = 0) {}
    static int N() { return _N; }
    static int& refN() { return _N; }
};

template<typename T, int ID>
struct series_members<T, ID, series_storage::CONSTANT> {
    series_members(int _N = 0) {}
    static int N() { return ID; }
    static int& refN() { static int _N = 0; return _N; }
};

/**
 * A formal power series
 *
 * `s(x) = p(x) + O(x^N)`, where p(x) is a polynomial of degree N-1
 *
 * @param T - the underlying type
 * @param ID - ID of the series type (useful with series_storage::CONSTANT)
 * @param STORAGE_TYPE - whether N is a constant, static or instance member
 *   See `STORAGE_TYPE` in the `modulo` class for details.
 */
template<typename T, int ID, int STORAGE_TYPE = series_storage::CONSTANT>
class series : public series_members<T, ID, STORAGE_TYPE> {
    typedef series_members<T, ID, STORAGE_TYPE> my_series_members;
public:
    // s(x) = p(x) + O(x^N)
    polynom<T> p;

    series(const T& c0 = T(0)) : my_series_members(1), p(c0) { p.resize(this->N()); }
    // construct from int, but only if T is not integral to avoid constructor clashing
    template <typename I = T, typename = std::enable_if_t<!std::is_integral<I>::value>>
    series(int c0) : my_series_members(1) , p(c0) { p.resize(this->N()); } // to allow constructing from 0 and 1
    series(series&& rhs) : my_series_members(rhs.N()), p(std::move(rhs.p)) { p.resize(this->N()); }
    series(const series& rhs) : my_series_members(rhs.N()), p(rhs.p) { p.resize(this->N()); }
    series(polynom<T>&& rhs, int _N) : my_series_members(_N), p(std::move(rhs)) { p.resize(this->N()); }
    series(const polynom<T>& rhs, int _N) : my_series_members(_N), p(rhs) { p.resize(this->N()); }
    series(polynom<T>&& rhs) : my_series_members(rhs.size()), p(std::move(rhs)) { p.resize(this->N()); }
    series(const polynom<T>& rhs) : my_series_members(rhs.size()), p(rhs) { p.resize(this->N()); }
    series(std::vector<T>&& c) : my_series_members((int)c.size()), p(std::move(c)) { p.resize(this->N()); }
    series(const std::vector<T>& c) : my_series_members((int)c.size()), p(c) { p.resize(this->N()); }
    template<typename It> series(It begin, It end) : my_series_members((int)std::distance(begin, end)), p(begin, end) { p.resize(this->N()); }
    series(std::initializer_list<T> list) : my_series_members((int)list.size()), p(list) { p.resize(this->N()); }
    series& operator = (series&& rhs) { this->refN() = rhs.N(), this->p = std::move(rhs.p); return *this; }
    series& operator = (const series& rhs) { this->refN() = rhs.N(), this->p = rhs.p; return *this; }

    series& swap(series& rhs) { p.swap(rhs.p); std::swap(this->refN(), rhs.refN()); return *this; }

    series& resize(int _N) { this->refN() = _N; p.resize(_N); return *this; }
    int size() const { return this->N(); }
    const T& at(int index) const { return p.at(index); }
    const T& operator [] (int index) const { return p[index]; }
    T& operator [] (int index) { return p[index]; }

    bool operator == (const series& rhs) const { return p == rhs.p; }
    bool operator != (const series& rhs) const { return p != rhs.p; }
    bool operator <  (const series& rhs) const { return p <  rhs.p; }
    bool operator >  (const series& rhs) const { return p >  rhs.p; }
    bool operator <= (const series& rhs) const { return p <= rhs.p; }
    bool operator >= (const series& rhs) const { return p >= rhs.p; }

    series  operator +  (const series &rhs) const { series t(*this); t += rhs; return t; }
    series  operator -  (const series &rhs) const { series t(*this); t -= rhs; return t; }
    series  operator -  ()                  const { return series(-p, this->N()); }
    series  operator *  (const series& rhs) const { series t(*this); t *= rhs; return t; }
    series  operator /  (const series& rhs) const { series t(*this); t /= rhs; return t; }

    series  operator *  (const T &val) const { series t(*this); t *= val; return t; }
    series  operator /  (const T &val) const { series t(*this); t /= val; return t; }

    series& operator += (const series &rhs) { p += rhs.p; p.resize(this->N()); return *this; }
    series& operator -= (const series &rhs) { p -= rhs.p; p.resize(this->N()); return *this; }
    series& operator *= (const series& rhs) { polynom<T>::mul(p, p, rhs.p, this->N() - 1); return *this; }
    series& operator /= (const series& rhs) { return *this *= rhs.inverse(); }

    series& operator *= (const T &val) { p *= val; p.resize(this->N()); return *this; }
    series& operator /= (const T &val) { p /= val; p.resize(this->N()); return *this; }

    series derivative() const { return series(p.derivative(), this->N()); }
    series integral() const { return integral(p.ZERO_COEFF); }
    series integral(const T& c0) const { auto pi = p.integral(c0); pi.resize(this->N()); return series(std::move(pi), this->N()); }

    // pointwise multiplication of the coefficients
    series pointwise_mul(const series& rhs) const {
        series s = *this;
        for (int i = 0; i < this->N(); i++) {
            s[i] *= rhs[i];
        }
        return s;
    }

    // s(x)*x^l - shifts coefficients of s(x) by l places
    series shift(int l) const {
        if (l < 0) {
            polynom<T> t{ p.c.begin() - l, p.c.end() };
            t.c.insert(t.c.end(), -l, p.ZERO_COEFF);
{'fraction_non_alphanumeric': 0.18133535660091046, 'fraction_numerical': 0.0032035069971337042, 'mean_word_length': 3.411677203421346, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 118, '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': '353886', 'n_tokens_mistral': 4160, 'n_tokens_neox': 4142, 'n_words': 1199}