anchor.diff:  { CONSTANTS }
   
   const
  +  EPSILON : Double = 0.00001;
     MillisPerSecond = 1000;
     MillisPerMinute = 60 * MillisPerSecond;
     MillisPerHour = 60 * MillisPerMinute;
  
positive.code:     class function GetLogicalCPUCount(): Int32; static;
    end;
  
  resourcestring
    sNotImplemented = 'Not implemented';
    sInvalidParameter_OutOfBounds = 'Invalid Parameter: %s out of bounds';
  
negative.code: {$ENDIF FPC}
  end;
  
  { TStatistics }
  
  constructor TStatistics.Create;
  begin
    Reset;
  end;
  
  function TStatistics.Mean : Double;
  begin
    Result := NaN;
    if SampleCount > 0 then
      Result := Sum / SampleCount;
  end;
  
  function TStatistics.PopulationStandardDeviation : Double;
  begin
    Result := Sqrt(PopulationVariance);
  end;
  
  function TStatistics.PopulationVariance : Double;
  begin
    if SampleCount > 0 then
      Result :=  ((SampleCount * SquaredSum) - Sum * Sum) / (SampleCount * SampleCount)
    else
      Result := Nan;
  end;
  
  function TStatistics.PopulationVariationCoefficient : Double;
  begin
    if SampleCount > 0 then
      Result :=  (PopulationVariance / Mean) * 100
    else
      Result := Nan;
  end;
  
  function TStatistics.GeometricMean : Double;
  begin
    if SampleCount > 0 then
      Result :=  Power(Product, 1.0 / SampleCount)
    else
      Result := Nan;
  end;
  
  function TStatistics.HarmonicMean : Double;
  begin
    if SampleCount > 0 then
      Result := SampleCount / ReciprocalSum
    else
      Result := Nan;
  end;
  
  function TStatistics.MinimumError : Double;
  begin
    if (Mean * Mean) > (EPSILON * EPSILON) then
      Result := 100.0 * (Minimum - Mean) / Mean
    else
      Result := Nan;
  end;
  
  function TStatistics.MaximumError : Double;
  begin
    if (Mean * Mean) > (EPSILON * EPSILON) then
      Result := 100.0 * (Maximum - Mean) / Mean
    else
      Result := Nan;
  end;
  
  function TStatistics.SampleStandardDeviation : Double;
  begin
    if SampleCount >= 2 then
      Result := Sqrt(SampleVariance)
    else
      Result := Nan;
  end;
  
  function TStatistics.SampleVariance : Double;
  begin
    if SampleCount > 0 then
      Result := ((SampleCount * SquaredSum) - Sum * Sum) / ((SampleCount - 1) * (SampleCount - 1))
    else
      Result := Nan;
  end;
  
  function TStatistics.SampleVariationCoefficient : Double;
  begin
    if SampleCount >= 2 then
      Result := 100 * (SampleStandardDeviation / Mean)
    else
      Result := Nan;
  end;
  
  procedure TStatistics.Reset;
  begin
    FCount := 0;
    FMin := 0.0;
    FMax := 0.0;
    FTotal := 0.0;
    FTotal2 := 0.0;
    FRecip := 0.0;
    FProduct := 1.0;
  end;
  
  procedure TStatistics.AddDatum(ADatum : Double);
  begin
    Inc(FCount);
    FTotal := FTotal + ADatum;
    FTotal2 := FTotal + ADatum * ADatum;
    if IsNaN(FRecip) OR ((ADatum * ADatum) < (EPSILON * EPSILON)) then
      FRecip := double.NaN
    else
      FRecip := FRecip + (1.0 / ADatum);
    FProduct := FProduct * ADatum;
    if (FCount = 1) then begin
      // first data so set _min/_max
      FMin := ADatum;
      FMax := ADatum;
    end else begin
      // adjust _min/_max boundaries if necessary
      if (ADatum < FMin) then
        FMin := ADatum;
      if (ADatum > FMax) then
        FMax := ADatum;
    end;
  end;
  
  procedure TStatistics.AddDatum(ADatum : Double; ANumTimes : UInt32);
  begin
    FCount := FCount + ANumTimes;
    FTotal := FTotal + ADatum * ANumTimes;
    FTotal2 := FTotal2 + ADatum * ADatum * ANumTimes;
    if IsNaN(FRecip) OR ((ADatum * ADatum) < (EPSILON * EPSILON)) then
      FRecip := NaN
    else
      FRecip := FRecip + (1.0 / ADatum) * ANumTimes;
    FProduct := FProduct * Power(ADatum, ANumTimes);
    if (FCount = 1) then begin
      // first data so set _min/_max
      FMin := ADatum;
      FMax := ADatum;
    end else begin
      // adjust _min/_max boundaries if necessary
      if ADatum < FMin then
          FMin := ADatum;
      if ADatum > FMax then
          FMax := ADatum;
    end;
  end;
  
  procedure TStatistics.RemoveDatum(ADatum : Double);
  begin
      Dec(FCount);
      FTotal := FTotal - ADatum;
      FTotal2 := FTotal2 - ADatum * ADatum;
      FRecip := FRecip - (1.0 / ADatum);
      if ABS(ADatum) > EPSILON then
       FProduct := FProduct / ADatum;
  end;
  
  initialization
    MinTimeStampDateTime:= StrToDateTime('1980-01-01 00:00:000', IntlDateTimeFormat);
    VarTrue := True;
  