コード例 #1
0
        public void Add(T item, int priority = 0)
        {
            int oldPriority;

            if (sub.UpdateOrAdd(item, priority, out oldPriority))
            {
                RemoveMain(oldPriority, item);
            }
            if (reserveList == null)
            {
                reserveList = new HashedLinkedList <T>(cmp);
            }
            var list = reserveList;

            if (!main.FindOrAdd(priority, ref list))
            {
                reserveList = null;
            }
            list.Add(item);
        }
コード例 #2
0
        /// <summary>
        /// Add a new value to the T-Digest. Note that this method is NOT thread safe.
        /// </summary>
        /// <param name="value">The value to add</param>
        /// <param name="weight">The relative weight associated with this value. Default is 1 for all values.</param>
        public void Add(double value, double weight = 1)
        {
            if (weight <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(weight), "must be greater than 0");
            }

            var first = count == 0;

            count += weight;

            if (first)
            {
                oldAvg = value;
                newAvg = value;
                Min    = value;
                Max    = value;
            }
            else
            {
                newAvg = oldAvg + (value - oldAvg) / count;
                oldAvg = newAvg;
                Max    = value > Max ? value : Max;
                Min    = value < Min ? value : Min;
            }

            if (centroids.Count == 0)
            {
                centroids.Add(value, new Centroid(value, weight));
                return;
            }

            var closest = GetClosestCentroids(value);

            var candidates = closest
                             .Select(c => new
            {
                Threshold = GetThreshold(ComputeCentroidQuantile(c)),
                Centroid  = c
            })
                             .Where(c => c.Centroid.Count + weight < c.Threshold)
                             .ToList();

            while (candidates.Count > 0 & weight > 0)
            {
                var cData  = candidates[_rand.Next() % candidates.Count];
                var deltaW = Math.Min(cData.Threshold - cData.Centroid.Count, weight);

                double oldMean;
                if (cData.Centroid.Update(deltaW, value, out oldMean))
                {
                    ReInsertCentroid(oldMean, cData.Centroid);
                }

                weight -= deltaW;
                candidates.Remove(cData);
            }

            if (weight > 0)
            {
                var toAdd = new Centroid(value, weight);

                if (centroids.FindOrAdd(value, ref toAdd))
                {
                    double oldMean;

                    if (toAdd.Update(weight, toAdd.Mean, out oldMean))
                    {
                        ReInsertCentroid(oldMean, toAdd);
                    }
                }
            }

            if (centroids.Count > (CompressionConstant / Accuracy))
            {
                Compress();
            }
        }