<commit_before>clockSkew = require('./clockSkew');

function Accumulator(properties) {
    this.t_0 = Date.now();
    this.k = [0];
    for (var i in properties) {
        this[i] = properties[i];
    }
}

// default values
Accumulator.prototype.trustClientClock = false;
Accumulator.prototype.discrete = true;
Accumulator.prototype.batched = false;
Accumulator.prototype.scale = 1000;
Accumulator.prototype.max = Infinity;
Accumulator.prototype.min = 0;

// number of widgets at time t = evaluate(poly, t, 0)
// number of widget factories at time t = evaluate(poly, t, 1)
// number of manually-bought factories = poly[1]
// these equivalences still hold after first-order translation,
// but not higher-order translation.
Accumulator.prototype.evaluate = function(x, i) {
    i = i || 0;
    if (i >= this.k.length) {
        return 0;
    }
    if (this.batched) {
        x = Math.floor(x);
    }
    var j = i + 1;
    var k_j = this.evaluate(x, j);
    var k_i = this.k[i] + k_j*x;
    if (this.discrete && i != 0) {
        // fractional amounts are useful for translation, so keep them at the very end
        k_i = Math.floor(k_i);
    }
    if (i == 0) {
        if (this.max == null) {
            this.max = Infinity;
        }
        if (this.min == null) {
            this.min = -Infinity;
        }
        return Math.max(Math.min(k_i, this.max), this.min);
    }
    else {
        return k_i;
    }
};

// TODO: handle skew here so consumers don't have to
Accumulator.prototype.evaluateAtTime = function(t_1, i) {
    var t = (t_1-this.t_0)/this.scale;
    value = this.evaluate(t, i);
    return Math.min(this.max, value);
};

// first derivative of value
Accumulator.prototype.rateAtTime = function(t_1) {
    var t = (t_1-this.t_0)/this.scale;
    return this.evaluate(t, 1);
};

// For 'batched' accumulators, the progress until the next batch is complete.
Accumulator.prototype.progressAtTime = function(t_1) {
    if (this.isConstant()) {
        return NaN;
    }
    var t = (t_1-this.t_0)/this.scale;
    return t - Math.floor(t);
};

Accumulator.prototype.degree = function() {
    var degree = 0;
    for (var i = 0; i < this.k.length; i++) {
        var k_i = this.k[i];
        if (k_i) {
            degree = i;
        }
    }
    return degree;
};

Accumulator.prototype.isConstant = function() {
    return (this.degree() == 0);
};

// general-purpose function to translate a polynomial from t_0 to t_1
// TODO: determine whether this method can accommodate higher-order polynomials
// f(t) = a * t^2 + b * t + c
// f(t-t_0) = a*(t-t_0)^2 + b*(t-t_0) + c
//          = a*(t^2 - 2*t_0*t + t_0^2) + b*t - b*t_0 + c
//          = a*t^2 - (2*a*t_0 + b)*t + a*t_0^2 - b*t_0 + c
// is t_0^2 meaningful?
Accumulator.prototype.translate = function(t_1) {
    var newPoly = [];
    for (var i = 0; i < this.k.length; i++) {
        // TODO: support higher order translation
        newPoly[i] = this.k[i];
    }
    newPoly[0] = this.evaluateAtTime(t_1);
    this.k = newPoly;
    this.t_0 = t_1;
};

// would like to support negative mods with floors
// eg consume materials to produce products,
// without going below zero
Accumulator.prototype.addPolynomial = function(mod) {
    var self = this;
    if (mod.length == 1) { // bypass clock for constants<commit_msg>higher-order translation method<commit_after>clockSkew = require('./clockSkew');

function Accumulator(properties) {
    this.t_0 = Date.now();
    this.k = [0];
    for (var i in properties) {
        this[i] = properties[i];
    }
}

// default values
Accumulator.prototype.trustClientClock = false;
Accumulator.prototype.discrete = true;
Accumulator.prototype.batched = false;
Accumulator.prototype.scale = 1000;
Accumulator.prototype.max = Infinity;
Accumulator.prototype.min = 0;

// number of widgets at time t = evaluate(poly, t, 0)
// number of widget factories at time t = evaluate(poly, t, 1)
// number of manually-bought factories = poly[1]
// these equivalences still hold after first-order translation,
// but not higher-order translation.
Accumulator.prototype.evaluate = function(x, i) {
    i = i || 0;
    if (i >= this.k.length) {
        return 0;
    }
    if (this.batched) {
        x = Math.floor(x);
    }
    var j = i + 1;
    var k_j = this.evaluate(x, j);
    var k_i = this.k[i] + k_j*x;
    if (this.discrete && i != 0) {
        // fractional amounts are useful for translation, so keep them at the very end
        k_i = Math.floor(k_i);
    }
    if (i == 0) {
        if (this.max == null) {
            this.max = Infinity;
        }
        if (this.min == null) {
            this.min = -Infinity;
        }
        return Math.max(Math.min(k_i, this.max), this.min);
    }
    else {
        return k_i;
    }
};

// TODO: handle skew here so consumers don't have to
Accumulator.prototype.evaluateAtTime = function(t_1, i) {
    var t = (t_1-this.t_0)/this.scale;
    value = this.evaluate(t, i);
    return Math.min(this.max, value);
};

// first derivative of value
Accumulator.prototype.rateAtTime = function(t_1) {
    var t = (t_1-this.t_0)/this.scale;
    return this.evaluate(t, 1);
};

// For 'batched' accumulators, the progress until the next batch is complete.
Accumulator.prototype.progressAtTime = function(t_1) {
    if (this.isConstant()) {
        return NaN;
    }
    var t = (t_1-this.t_0)/this.scale;
    return t - Math.floor(t);
};

Accumulator.prototype.degree = function() {
    var degree = 0;
    for (var i = 0; i < this.k.length; i++) {
        var k_i = this.k[i];
        if (k_i) {
            degree = i;
        }
    }
    return degree;
};

Accumulator.prototype.isConstant = function() {
    return (this.degree() == 0);
};

// general-purpose function to translate a polynomial from t_0 to t_1
// this discards information about manually-entered values.
Accumulator.prototype.translate = function(t_1) {
    var t = (t_1-this.t_0)/this.scale;
    var newK = [];
    for (var i = 0; i < this.k.length; i++) {
        newK[i] = this.evaluate(t, i);
    }
    this.k = newK;
    this.t_0 = t_1;
};

// would like to support negative mods with floors
// eg consume materials to produce products,
// without going below zero
Accumulator.prototype.addPolynomial = function(mod) {
    var self = this;
    if (mod.length == 1) { // bypass clock for constants
{'fraction_non_alphanumeric': 0.14143331751305174, 'fraction_numerical': 0.014712861888941622, 'mean_word_length': 2.5005537098560353, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, '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': '3580021', 'n_tokens_mistral': 2264, 'n_tokens_neox': 2190, 'n_words': 590}