docs: public void add(OnLineStatistics B)
     {
         final OnLineStatistics A = this;
         //XXX double compare.
         if(A.n == B.n && B.n == 0)
             return;//nothing to do!
         else if(B.n == 0)
             return;//still nothing!
         else if (A.n == 0)
         {
             this.n = B.n;
             this.mean = B.mean;
             this.m2 = B.m2;
             this.m3 = B.m3;
             this.m4 = B.m4;
             this.min = B.min;
             this.max = B.max;
             return;
         }
         
         double nX = B.n + A.n;
         double nXsqrd = nX*nX;
         double nAnB = B.n*A.n;
         double AnSqrd = A.n*A.n;
         double BnSqrd = B.n*B.n;
         
         double delta = B.mean - A.mean;
         double deltaSqrd = delta*delta;
         double deltaCbd = deltaSqrd*delta;
         double deltaQad = deltaSqrd*deltaSqrd;
         double newMean = (A.n* A.mean + B.n * B.mean)/(A.n + B.n);
         double newM2 = A.m2 + B.m2 + deltaSqrd / nX *nAnB;
         double newM3 = A.m3 + B.m3 + deltaCbd* nAnB*(A.n - B.n) / nXsqrd + 3 * delta * (A.n * B.m2 - B.n * A.m2)/nX;
         double newM4 = A.m4 + B.m4 
                 + deltaQad * (nAnB*(AnSqrd - nAnB + BnSqrd)/(nXsqrd*nX)) 
                 + 6 * deltaSqrd*(AnSqrd*B.m2 + BnSqrd*A.m2)/nXsqrd
                 + 4 * delta *(A.n*B.m3 - B.n*A.m3)/nX;
         
         this.n = nX;
         this.mean = newMean;
         this.m2 = newM2;
         this.m3 = newM3;
         this.m4 = newM4;
         this.min = Math.min(A.min, B.min);
         this.max = Math.max(A.max, B.max);
     }