function sgg(ys, xs, options = {}) {
        let { windowSize = 9, derivative = 0, polynomial = 3 } = options;
        if (windowSize % 2 === 0 || windowSize < 5 || !Number.isInteger(windowSize)) {
            throw new RangeError('Invalid window size (should be odd and at least 5 integer number)');
        }
        if (!isAnyArray(ys)) {
            throw new TypeError('Y values must be an array');
        }
        if (typeof xs === 'undefined') {
            throw new TypeError('X must be defined');
        }
        if (windowSize > ys.length) {
            throw new RangeError(`Window size is higher than the data length ${windowSize}>${ys.length}`);
        }
        if (derivative < 0 || !Number.isInteger(derivative)) {
            throw new RangeError('Derivative should be a positive integer');
        }
        if (polynomial < 1 || !Number.isInteger(polynomial)) {
            throw new RangeError('Polynomial should be a positive integer');
        }
        if (polynomial >= 6) {
            // eslint-disable-next-line no-console
            console.warn('You should not use polynomial grade higher than 5 if you are' +
                ' not sure that your data arises from such a model. Possible polynomial oscillation problems');
        }
        let half = Math.floor(windowSize / 2);
        let np = ys.length;
        let ans = new Float64Array(np);
        let weights = fullWeights(windowSize, polynomial, derivative);
        let hs = 0;
        let constantH = true;
        if (isAnyArray(xs)) {
            constantH = false;
        }
        else {
            hs = Math.pow(xs, derivative);
        }
        //For the borders
        for (let i = 0; i < half; i++) {
            let wg1 = weights[half - i - 1];
            let wg2 = weights[half + i + 1];
            let d1 = 0;
            let d2 = 0;
            for (let l = 0; l < windowSize; l++) {
                d1 += wg1[l] * ys[l];
                d2 += wg2[l] * ys[np - windowSize + l];
            }
            if (constantH) {
                ans[half - i - 1] = d1 / hs;
                ans[np - half + i] = d2 / hs;
            }
            else {
                hs = getHs(xs, half - i - 1, half, derivative);
                ans[half - i - 1] = d1 / hs;
                hs = getHs(xs, np - half + i, half, derivative);
                ans[np - half + i] = d2 / hs;
            }
        }
        //For the internal points
        let wg = weights[half];
        for (let i = windowSize; i <= np; i++) {
            let d = 0;
            for (let l = 0; l < windowSize; l++) { d += wg[l] * ys[l + i - windowSize]; }
            if (!constantH) {
                hs = getHs(xs, i - half - 1, half, derivative);
            }
            ans[i - half - 1] = d / hs;
        }
        return ans;
    }
Apply Savitzky Golay algorithm
@param [ys] Array of y values
@param [xs] Array of X or deltaX
@return  Array containing the new ys (same length)