/// <summary>
        /// A convenient way to combine the observations of two Stats objects
        /// into a new Stats object.
        /// </summary>
        /// <param name="a">The first operand</param>
        /// <param name="b">The second operand</param>
        /// <returns></returns>
        public static SummaryStatistics operator +(SummaryStatistics a, SummaryStatistics b)
        {
            SummaryStatistics result = new SummaryStatistics();

            result.Add(a);
            result.Add(b);
            return(result);
        }
        public override bool Equals(object obj)
        {
            if (!base.Equals(obj))
            {
                return(false);
            }
            SummaryStatistics s = obj as SummaryStatistics;

            if (s == null)
            {
                return(false);
            }
            return(s._m3 == _m3 && s._m4 == _m4);
        }
        /// <summary>
        /// Adds a stats object with another type of stats object. The result
        /// should be equivalent, up to the effects of numerical imprecision,
        /// as if in addition to all the values this object has seen, it has
        /// also seen the values added to the other object.
        /// </summary>
        /// <param name="s"></param>
        public void Add(SummaryStatistics s)
        {
            double delta = s.Mean - Mean;
            double na    = Count;
            double nb    = s.Count;
            double nx    = na + nb;

            if (nb == 0.0)
            {
                return; // No-op.
            }
            _m4 += s._m4 + delta *
                   (delta * (delta * delta * na * nb * (na * na - na * nb + nb * nb) / nx +
                             6 * (na * na * s.M2 + nb * nb * M2)) / nx +
                    4 * (na * s._m3 - nb * _m3)) / nx;
            _m3 += s._m3 + delta * (delta * delta * na * nb * (na - nb) / nx + 3 * (na * s.M2 - nb * M2)) / nx;

            base.Add(s);
        }