On Thu, 24 Nov 2022 18:51:12 +0000
"J. Gareth Moreton via fpc-devel" <fpc-devel@lists.freepascal.org> wrote:

> Hi everyone,
> 
> I just need to touch on the knowledge base.  What tests exist that test 
> the functionality of rtl/inc/sortbase.pp?  As Olly suggested, I'm 
> looking at creating Introsort for this unit as well, but I need to know 
> if such a unit already exists or if I need to make my own.

Some times ago I wrote a couple of merge sort routines to use in BWT,
the project never goes further so they remain at level of numerical
values input only.
They should have a good worst case scenario.
In the merge.pas the parameter nrm has to be false when the dimension
of the array is not a power of two.
There also is a check head-tail of the blocks to move in a single pass
the smaller one.
The natural.pas is recursive in the initial division in blocks and allow
for adaptation for inputs already sorted.
If you find them useful, you are free to made anything you want.
Marco

-- 
Simplex sigillum veri
PROGRAM Sort;
CONST
  len=20;
VAR
  a:ARRAY[0..2*len-1] OF Byte;
  i,j:Word;
  src:Boolean;

PROCEDURE MergeSort(VAR src:Boolean;nrm:Boolean);
VAR
  dbl,sub,i,j,k,l,m,n,dst,lim:Word;
  x,y,z:Integer;
BEGIN
  dbl:=len SHL 1;
  sub:=1;
  WHILE sub<len DO
    BEGIN
      i:=0;
      j:=sub;
      IF src THEN
        BEGIN
          Inc(i,len);
          Inc(j,len);
          k:=dbl;
          dst:=0;
        END
      ELSE
        BEGIN
          k:=len;
          dst:=len;
        END;
      n:=sub SHL 1;
      WHILE i<k DO
        BEGIN
          l:=i+sub;
          m:=j+sub;
          lim:=dst+n;
          IF nrm THEN
            BEGIN
              x:=sub;
              y:=sub;
              z:=n;
            END
          ELSE
            BEGIN
              IF src THEN
                BEGIN
                  IF l>dbl THEN
                    l:=dbl;
                  IF m>dbl THEN
                    m:=dbl;
                  IF lim>len THEN
                    lim:=len;
                END
              ELSE
                BEGIN
                  IF l>len THEN
                    l:=len;
                  IF m>len THEN
                    m:=len;
                  IF lim>dbl THEN
                    lim:=dbl;
                END;
              x:=l-i;
              y:=m-j;
              z:=m-i;
            END;
          IF a[l-1]<=a[j] THEN
            BEGIN
              IF z>0 THEN
                Move(a[i],a[dst],z);
              i:=l;
              j:=m;
              dst:=lim;
            END
          (* Solo < per avere un metodo stabile *)
          ELSE IF a[m-1]<a[i] THEN
            BEGIN
              IF y>0 THEN
                Move(a[j],a[dst],y)
              ELSE
                y:=0;
              IF x>0 THEN
                Move(a[i],a[dst+y],x);
              i:=l;
              j:=m;
              dst:=lim;
            END;
          WHILE dst<lim DO
            BEGIN
              x:=a[i];
              y:=a[j];
              IF (j>=m) OR ((i<l) AND (x<=y)) THEN
                BEGIN
                  a[dst]:=x;
                  Inc(i);
                END
              ELSE
                BEGIN
                  a[dst]:=y;
                  Inc(j);
                END;
              Inc(dst);
            END;
          Inc(i,sub);
          Inc(j,sub);
        END;
      sub:=n;
      src:=NOT src;
    END;
END;

BEGIN
  Randomize;
  FOR i:=0 TO len-1 DO
    BEGIN
      a[i]:=Random(256);
      Write(' ',a[i]);
    END;
  WriteLn;
  src:=False;
  MergeSort(src,False);
  IF NOT src THEN
    j:=0
  ELSE
    j:=len;
  FOR i:=j TO j+len-1 DO
    Write(' ',a[i]);
END.
PROGRAM Sort;
CONST
  len=20;
VAR
  a,b:ARRAY[0..len-1] OF Byte;
  h,t,idx:Word;

PROCEDURE NaturalSort(i,j,k:Word;run:Byte);
VAR
  l,m:Word;
BEGIN
  l:=i;
  m:=j;
  IF run<>2 THEN
    BEGIN
      t:=a[i];
      Inc(i);
      h:=a[i];
      WHILE (i<=m) AND (h>=t) DO
        BEGIN
          t:=h;
          Inc(i);
          h:=a[i];
      END;
      Dec(i);
    END
  ELSE
    i:=k;
  IF i<m THEN
    BEGIN
      IF run<>1 THEN
        BEGIN
          h:=a[j];
          Dec(j);
          t:=a[j];
          WHILE (j>=l) AND (h>=t) DO
            BEGIN
              h:=t;
              Dec(j);
              t:=a[j];
            END;
          Inc(j);
        END
      ELSE
        j:=k;
      IF i-l>=m-j THEN
        BEGIN
          k:=i+1;
          NaturalSort(k,m,j,1);
          j:=k;
        END
      ELSE
        BEGIN
          k:=j-1;
          NaturalSort(l,k,i,2);
          i:=k;
        END;
    END
  ELSE
    k:=len;
  IF k<len THEN
    BEGIN
      h:=0;
      t:=0;
      WHILE l<=m DO
        IF h=t THEN
          IF (l>i) OR (a[l]<=a[j]) THEN
            Inc(l)
          ELSE
            BEGIN
              b[h]:=a[l];
              Inc(h);
              a[l]:=a[j];
              Inc(l);
              Inc(j);
            END
        ELSE
          BEGIN
            IF l<=i THEN
              BEGIN
                b[h]:=a[l];
                Inc(h);
              END;
            IF (j>m) OR (b[t]<=a[j]) THEN
              BEGIN
                a[l]:=b[t];
                Inc(l);
                Inc(t);
              END
            ELSE
              BEGIN
                a[l]:=a[j];
                Inc(l);
                Inc(j);
              END;
          END;
    END;
END;

BEGIN
  Randomize;
  FOR idx:=0 TO len-1 DO
    BEGIN
      a[idx]:=Random(256);
      Write(' ',a[idx]);
    END;
  WriteLn;
  NaturalSort(0,len-1,len,0);
  FOR idx:=0 TO len-1 DO
    Write(' ',a[idx]);
END.
_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to