/*
 * Copyright (c) 2016 Swift Navigation Inc.
 * Contact: engineering@swiftnav.com
 *
 * This source is subject to the license found in the file 'LICENSE' which must
 * be be distributed together with this source. All other rights reserved.
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
 */

// Typescript declaration file for TDigest, a Javascript implementation of
// Dunning's T-Digest for streaming quantile approximation. API and
// documentation are sourced from the library at
// https://github.com/welch/tdigest/blob/master/tdigest.js.

declare module "tdigest" {


  class TDigest {

    // Allocate a TDigest structure: approximates distribution percentiles from
    // a stream of reals.
    //
    // delta is the compression factor, the max fraction of mass that
    // can be owned by one centroid (bigger, up to 1.0, means more
    // compression). delta=false switches off TDigest behavior and treats
    // the distribution as discrete, with no merging and exact values
    // reported.
    //
    // K is a size threshold that triggers recompression as the TDigest
    // grows during input.  (Set it to 0 to disable automatic recompression)
    //
    // CX specifies how often to update cached cumulative totals used
    // for quantile estimation during ingest (see cumulate()).  Set to
    // 0 to use exact quantiles for each new point.
    constructor(delta?: number, K?: number, CX?: number);

    // Prepare to digest new points
    reset();

    size(): number;

    // Return {mean,n} of centroids as an array ordered by mean.
    toArray(): Array<number>;

    summary(): string;

    // Incorporate value or array of values x, having count n into the
    // TDigest. n defaults to 1.
    push(x: number | Array<number>, n?: number): void;

    // Incorporate centroid or array of centroids c
    push_centroid(c: Array<number>): void;

    // Find the centroid closest to x. The assumption of unique means and a
    // unique nearest centroid departs from the paper, see _digest().
    find_nearest(x: number): number;

    // Find centroids lower and upper such that lower.mean < x < upper.mean or
    // lower.mean === x === upper.mean. Don't call this for x out of bounds.
    bound_mean(x: number): [number, number];

    // Return approximate percentile-ranks (0..1) for data value x.  or list of
    // x.  calculated according to https://en.wikipedia.org/wiki/Percentile_rank
    //
    // (Note that in continuous mode, boundary sample values will report half
    // their centroid weight inward from 0/1 as the percentile-rank. X values
    // outside the observed range return 0/1)
    p_rank(x_or_xlist): Array<number> | number;

    // Find centroids lower and upper such that lower.mean_cumn < x <
    // upper.mean_cumn or lower.mean_cumn === x === upper.mean_cumn. Don't call
    // this for cumn out of bounds.
    bound_mean_cumn(cumn: number): [number, number];

    // For percentage p (0..1), or for each p in a list of ps, return the
    // smallest data value q at which at least p percent of the observations <=
    // q.
    //
    // for discrete distributions, this selects q using the Nearest Rank Method
    // (https://en.wikipedia.org/wiki/Percentile#The_Nearest_Rank_method) (in
    // scipy, same as percentile(...., interpolation='higher')
    //
    // For continuous distributions, interpolates data values between
    // count-weighted bracketing means.
    //
    // This triggers cumulate() if cumn's are out of date.
    //
    percentile(p_or_plist: Array<number>): Array<number>;

    // TDigests experience worst case compression (none) when input increases
    // monotonically.  Improve on any bad luck by reconsuming digest centroids
    // as if they were weighted points while shuffling their order (and hope for
    // the best).
    compress(): void;
  }

  class Digest {

    // Allocate a distribution digest structure. This is an extension of a
    // TDigest structure that starts in exact histogram (discrete) mode, and
    // automatically switches to TDigest mode for large samples that appear to
    // be from a continuous distribution.
    constructor(config: Object);


    push(x_or_xlist: number | Array<number>): void;

    // While in 'auto' mode, if there are many unique elements, assume they are
    // from a continuous distribution and switch to 'cont' mode (tdigest
    // behavior). Return true on transition from disctete to continuous.
    check_continuous(): boolean;

  }
}
