unit frmFibBurn;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Gauges, StdCtrls, COSBI_Common, ExtCtrls, TeEngine, Series, TeeProcs,
  Chart, Mask;

const
  ARRAY_SIZE = 1000000;
  REPEAT_COUNT = 20;

type
  TBigArray = array[0..ARRAY_SIZE] of Integer;

  TfrmMemLate = class(TForm)
    GaugeProgress: TGauge;
    btnFibGo: TButton;
    edBandwidth: TEdit;
    Edit1: TEdit;
    chartBandwidth: TChart;
    Series1: TLineSeries;
    lblIterations: TLabel;
    cboIterations: TComboBox;
    cboxGraphRealTime: TCheckBox;
    edMinMax: TEdit;
    btnScale: TButton;
    lblN: TLabel;
    cboN: TComboBox;
    procedure btnFibGoClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnScaleClick(Sender: TObject);
  private
    { Private declarations }
    StopWatch: TStopWatch;
  public
    { Public declarations }
  end;

var
  frmMemLate: TfrmMemLate;

implementation

{$R *.DFM}


procedure TfrmMemLate.btnFibGoClick(Sender: TObject);
// We want to be able to read and write to an array section varying the size
// we are working with starting at 1kB (256 integer elements) and increasing
// by 1kB steps until we reach 500 kB.  At each step we are going to push through
// around 100 MB.  We will determine the number of iterations by "div" our
// section size with 100MB (we should allow this number to be user defined).
// We need to report the report bandwidth rate at each step.
var
   l_A            : TBigArray;  // this is our target array

   li_iterate       : integer;
   li_RepeatCount   : integer;
   le_Time          : Extended;
   ld_AvgTime       : Double;
   lb_GraphNow      : Boolean;
   l_Results        : Array[1..500] of double;
   li_n             : integer;

const

  UNROLL_FACTOR = 4;

begin
  edBandwidth.Text := 'Testing...';
  Refresh;
  btnFibGo.Enabled := False;
  btnScale.Enabled := FALSE;

  le_Time := 0;
  chartBandwidth.SeriesList.Series[0].Clear;
  chartBandwidth.LeftAxis.Automatic := TRUE;

  li_RepeatCount := StrToInt( Trim( cboIterations.Text ) );
  li_n := StrToInt( Trim( cboN.Text ) );

  GaugeProgress.MaxValue := li_RepeatCount;
  GaugeProgress.Progress := 0;

  lb_GraphNow := (cboxGraphRealTime.State = cbChecked);
  Application.ProcessMessages;

  StopWatch.Resolution := swresCPU;
  for li_iterate := 1 to li_RepeatCount do
  begin
    StopWatch.StartTimer;

    Fibonacci( li_n );

    StopWatch.StopTimer;
    le_Time := le_Time + StopWatch.ElapsedTime;

    if lb_GraphNow then begin

      GaugeProgress.Progress := GaugeProgress.Progress + 1;

      chartBandwidth.SeriesList.Series[0].Add(StopWatch.ElapsedTime, '', clRed);

      edMinMax.Text := 'Max = ' +
            FloatToStrF(chartBandwidth.SeriesList.Series[0].MaxYValue, ffNumber, 10, 5) +
            ', Min = ' +
            FloatToStrF(chartBandwidth.SeriesList.Series[0].MinYValue, ffNumber, 10, 5);

      Application.ProcessMessages;

    end else begin
      l_Results[ li_iterate ] := StopWatch.ElapsedTime;
    end;

  end;

  GaugeProgress.Progress := GaugeProgress.MaxValue;
  Edit1.Text := 'Total time ' + FloatToStrF((le_Time), ffNumber, 6, 6) + ' s';

  ld_AvgTime := (le_time ) / (li_RepeatCount);
  edBandwidth.Text := 'Avg time: ' +
                      FloatToStrF( ld_AvgTime, ffNumber, 10, 3) + ' s';

  if not lb_GraphNow then begin

    for li_iterate := 1 to li_RepeatCount do begin
      chartBandwidth.SeriesList.Series[0].Add(l_Results[ li_iterate ], '', clRed);
    end;
    edMinMax.Text := 'Max = ' +
                   FloatToStrF(chartBandwidth.SeriesList.Series[0].MaxYValue, ffNumber, 10, 5) +
                   ', Min = ' +
                   FloatToStrF(chartBandwidth.SeriesList.Series[0].MinYValue, ffNumber, 10, 5);

  end;

  btnFibGo.Enabled := TRUE;
  btnScale.Enabled := TRUE;

end;

procedure TfrmMemLate.FormCreate(Sender: TObject);
begin
  StopWatch := TStopWatch.Create;
  cboIterations.ItemIndex := 4;
  cboN.ItemIndex := 13;
end;

procedure TfrmMemLate.FormDestroy(Sender: TObject);
begin
  StopWatch.Free;
end;

procedure TfrmMemLate.btnScaleClick(Sender: TObject);
begin
  if chartBandwidth.LeftAxis.Automatic then begin
    chartBandwidth.LeftAxis.Automatic := FALSE;
    chartBandwidth.LeftAxis.Minimum := 0;
  end else begin
    chartBandwidth.LeftAxis.Automatic := TRUE;
  end;
end;

end.
