home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 09 / porter.lis < prev    next >
File List  |  1988-08-22  |  18KB  |  807 lines

  1. _THE STATE OF MODULEA-2_ 
  2. by
  3. Kent Porter
  4.  
  5.  
  6.  
  7. Listing One 
  8.  
  9. MODULE dry; 
  10.  
  11.   FROM Storage
  12.     IMPORT ALLOCATE, DEALLOCATE, Available, InstallHeap, RemoveHeap;
  13.   FROM Strings
  14.     IMPORT CompareStr;
  15.  
  16. (*
  17.  *   "DHRYSTONE" Benchmark Program
  18.  *
  19.  *   Version:   Mod2/1
  20.  *   Date:      05/03/86
  21.  *   Author:      Reinhold P. Weicker,  CACM Vol 27, No 10, 10/84 pg. 1013
  22.  *         C version translated from ADA by Rick Richardson
  23.  *         Every method to preserve ADA-likeness has been used,
  24.  *         at the expense of C-ness.
  25.  *         Modula-2 version translated from C by Kevin Northover.
  26.  *         Again every attempt made to avoid distortions of the original.
  27.  *   Machine Specifics:
  28.  *         The time function is system dependant, one is
  29.  *         provided for the Amiga.  Your compiler may be different.
  30.  *         The LOOPS constant is initially set for 50000 loops.
  31.  *         If you have a machine with large integers and is
  32.  *         very fast, please change this number to 500000 to
  33.  *         get better accuracy.
  34.  *         You can also time the program with a stopwatch when it
  35.  *         is lightly loaded (no interlaced 4 bit deep Amiga screens ...).
  36.  *
  37.  **************************************************************************
  38.  *
  39.  *   The following program contains statements of a high-level programming
  40.  *   language (Modula-2) in a distribution considered representative:
  41.  *
  42.  *   assignments         53%
  43.  *   control statements      32%
  44.  *   procedure, function calls   15%
  45.  *
  46.  *   100 statements are dynamically executed.  The program is balanced with
  47.  *   respect to the three aspects:
  48.  *      - statement type
  49.  *      - operand type (for simple data types)
  50.  *      - operand access
  51.  *         operand global, local, parameter, or constant.
  52.  *
  53.  *   The combination of these three aspects is balanced only approximately.
  54.  *
  55.  *   The program does not compute anything meaningfull, but it is
  56.  *   syntactically and semantically correct.
  57.  *
  58.  *) 
  59.  
  60. (* Accuracy of timings and human fatigue controlled by next two lines *) 
  61.  
  62.   CONST 
  63.     LOOPS = 50000;
  64.  
  65.   TYPE 
  66.     Enumeration = (Ident1, Ident2, Ident3, Ident4, Ident5); 
  67.     OneToThirty = CARDINAL; 
  68.     OneToFifty = CARDINAL; 
  69.     CapitalLetter = CHAR; 
  70.     String30 = ARRAY [0..30-1] OF CHAR; 
  71.     Array1Dim = ARRAY [0..50] OF CARDINAL; 
  72.     Array2Dim = ARRAY [0..50], [0..50] OF CARDINAL; 
  73.     RecordPtr = POINTER TO RecordType; 
  74.     RecordType = RECORD 
  75.                    PtrComp: RecordPtr; 
  76.                    Discr: Enumeration; 
  77.                    EnumComp: Enumeration; 
  78.                    IntComp: OneToFifty; 
  79.                    StringComp: String30; 
  80.                  END; 
  81.  
  82.     (* 
  83.      * Package 1
  84.      *) 
  85.  
  86.   VAR 
  87.  
  88.     IntGlob: CARDINAL; 
  89.     BoolGlob: BOOLEAN; 
  90.     Char1Glob: CHAR; 
  91.     Char2Glob: CHAR; 
  92.     Array1Glob: Array1Dim; 
  93.     Array2Glob: Array2Dim; 
  94.     PtrGlb: RecordPtr; 
  95.     PtrGlbNext: RecordPtr; 
  96.  
  97.  
  98.   PROCEDURE Proc7(IntParI1, IntParI2: OneToFifty; 
  99.                   VAR IntParOut: OneToFifty); 
  100.  
  101.     VAR 
  102.  
  103.       IntLoc: OneToFifty; 
  104.   BEGIN 
  105.     IntLoc := IntParI1+2; 
  106.     IntParOut := IntParI2+IntLoc; 
  107.   END Proc7; 
  108.  
  109.  
  110.   PROCEDURE Proc3(VAR PtrParOut: RecordPtr); 
  111.   BEGIN 
  112.     IF (PtrGlb <> NIL) THEN 
  113.  
  114.       PtrParOut := PtrGlb^.PtrComp
  115.     ELSE 
  116.       IntGlob := 100
  117.     END; 
  118.     Proc7(10, IntGlob, PtrGlb^.IntComp); 
  119.   END Proc3; 
  120.  
  121.  
  122.   PROCEDURE Func3(EnumParIn: Enumeration): BOOLEAN; 
  123.  
  124.     VAR 
  125.       EnumLoc: Enumeration; 
  126.     VAR Func3Result: BOOLEAN; 
  127.   BEGIN 
  128.     EnumLoc := EnumParIn; 
  129.     Func3Result := EnumLoc = Ident3; 
  130.     RETURN Func3Result
  131.   END Func3; 
  132.  
  133.  
  134.   PROCEDURE Proc6(EnumParIn: Enumeration; 
  135.                   VAR EnumParOut: Enumeration); 
  136.   BEGIN 
  137.     EnumParOut := EnumParIn; 
  138.     IF ( NOT Func3(EnumParIn)) THEN 
  139.       EnumParOut := Ident4
  140.     END; 
  141.     CASE EnumParIn OF 
  142.         Ident1: 
  143.         EnumParOut := Ident1
  144.       | Ident2: 
  145.         IF (IntGlob > 100) THEN 
  146.  
  147.           EnumParOut := Ident1
  148.         ELSE 
  149.           EnumParOut := Ident4
  150.         END
  151.       | Ident3: 
  152.         EnumParOut := Ident2
  153.       | Ident4: 
  154.       | Ident5: 
  155.         EnumParOut := Ident3
  156.        
  157.       ELSE 
  158.     END; 
  159.   END Proc6; 
  160.  
  161.  
  162.  
  163.   PROCEDURE Proc1(PtrParIn: RecordPtr); 
  164.   BEGIN 
  165.     WITH PtrParIn^ DO 
  166.  
  167.       PtrComp^ := PtrGlb^; 
  168.       IntComp := 5; 
  169.       PtrComp^.IntComp := IntComp; 
  170.       PtrComp^.PtrComp := PtrComp; 
  171.       Proc3(PtrComp^.PtrComp); 
  172.       IF (PtrComp^.Discr = Ident1) THEN 
  173.         PtrComp^.IntComp := 6; 
  174.         Proc6(EnumComp, PtrComp^.EnumComp); 
  175.         PtrComp^.PtrComp := PtrGlb^.PtrComp; 
  176.         Proc7(PtrComp^.IntComp, 10, PtrComp^.IntComp); 
  177.  
  178.  
  179.       ELSE 
  180.         PtrParIn^ := PtrComp^
  181.       END; 
  182.     END; 
  183.   END Proc1; 
  184.  
  185.  
  186.   PROCEDURE Proc2(VAR IntParIO: OneToFifty); 
  187.  
  188.     VAR 
  189.  
  190.       IntLoc: OneToFifty; 
  191.       EnumLoc: Enumeration; 
  192.   BEGIN 
  193.     IntLoc := IntParIO+10; 
  194.     REPEAT 
  195.  
  196.       IF (Char1Glob = 'A') THEN 
  197.  
  198.         DEC(IntLoc, 1); 
  199.         IntParIO := IntLoc-IntGlob; 
  200.         EnumLoc := Ident1; 
  201.       END; 
  202.     UNTIL EnumLoc = Ident1; 
  203.   END Proc2; 
  204.  
  205.  
  206.   PROCEDURE Proc4; 
  207.  
  208.     VAR 
  209.  
  210.       BoolLoc: BOOLEAN; 
  211.   BEGIN 
  212.     BoolLoc := Char1Glob = 'A'; 
  213.     BoolLoc := BoolLoc OR BoolGlob; 
  214.     Char2Glob := 'B'; 
  215.   END Proc4; 
  216.  
  217.  
  218.   PROCEDURE Proc5; 
  219.   BEGIN 
  220.     Char1Glob := 'A'; 
  221.     BoolGlob := FALSE; 
  222.   END Proc5; 
  223.  
  224.  
  225.   PROCEDURE Proc8(VAR Array1Par: Array1Dim; 
  226.                   VAR Array2Par: Array2Dim; 
  227.                   IntParI1, IntParI2: OneToFifty); 
  228.  
  229.     VAR 
  230.  
  231.       IntLoc: OneToFifty; 
  232.       IntIndex: OneToFifty; 
  233.   BEGIN 
  234.     IntLoc := IntParI1+5; 
  235.     Array1Par[IntLoc] := IntParI2; 
  236.     Array1Par[IntLoc+1] := Array1Par[IntLoc]; 
  237.     Array1Par[IntLoc+30] := IntLoc; 
  238.     FOR IntIndex := IntLoc TO (IntLoc+1) DO 
  239.       Array2Par[IntLoc][IntIndex] := IntLoc
  240.     END; 
  241.     Array2Par[IntLoc][IntLoc-1] := Array2Par[IntLoc][IntLoc-1]+1; 
  242.     Array2Par[IntLoc+20][IntLoc] := Array1Par[IntLoc]; 
  243.     IntGlob := 5; 
  244.   END Proc8; 
  245.  
  246.  
  247.   PROCEDURE Func1(CharPar1, CharPar2: CapitalLetter): Enumeration; 
  248.  
  249.     VAR 
  250.  
  251.       CharLoc1, CharLoc2: CapitalLetter; 
  252.     VAR Func1Result: Enumeration; 
  253.   BEGIN 
  254.     CharLoc1 := CharPar1; 
  255.     CharLoc2 := CharLoc1; 
  256.     IF (CharLoc2 <> CharPar2) THEN 
  257.       Func1Result := (Ident1)
  258.     ELSE 
  259.       Func1Result := (Ident2)
  260.     END; 
  261.     RETURN Func1Result
  262.   END Func1; 
  263.  
  264.  
  265.   PROCEDURE Func2(VAR StrParI1, StrParI2: String30): BOOLEAN; 
  266.  
  267.     VAR 
  268.  
  269.       IntLoc: OneToThirty; 
  270.       CharLoc: CapitalLetter; 
  271.     VAR Func2Result: BOOLEAN; 
  272.   BEGIN 
  273.     IntLoc := 2; 
  274.     WHILE (IntLoc <= 2) DO 
  275.       IF (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) = Ident1) THEN 
  276.         CharLoc := 'A'; 
  277.         INC(IntLoc, 1); 
  278.       END; 
  279.     END; 
  280.     IF (CharLoc >= 'W') AND (CharLoc <= 'Z') THEN 
  281.       IntLoc := 7
  282.     END; 
  283.     IF CharLoc = 'X' THEN 
  284.       Func2Result := TRUE
  285.     ELSIF CompareStr (StrParI1, StrParI2) > 0 THEN 
  286.       INC(IntLoc, 7); 
  287.       Func2Result := TRUE
  288.     ELSE 
  289.       Func2Result := FALSE
  290.     END; 
  291.     RETURN Func2Result
  292.   END Func2; 
  293.  
  294.  
  295.  
  296.   PROCEDURE Proc0; 
  297.  
  298.     VAR 
  299.  
  300.       IntLoc1: OneToFifty; 
  301.       IntLoc2: OneToFifty; 
  302.       IntLoc3: OneToFifty; 
  303.       CharLoc: CHAR; 
  304.       CharIndex: CHAR; 
  305.       EnumLoc: Enumeration; 
  306.       String1Loc, String2Loc: String30; 
  307.       i, LoopMax: CARDINAL;
  308.  
  309.  
  310.   BEGIN 
  311.     LoopMax := LOOPS;
  312.     NEW(PtrGlbNext); 
  313.     NEW(PtrGlb); 
  314.     PtrGlb^.PtrComp := PtrGlbNext; 
  315.     PtrGlb^.Discr := Ident1; 
  316.     PtrGlb^.EnumComp := Ident3; 
  317.     PtrGlb^.IntComp := 40; 
  318.     PtrGlb^.StringComp := 'DHRYSTONE PROGRAM, SOME STRING'; 
  319.     String1Loc := "DHRYSTONE PROGRAM, 1'ST STRING"; 
  320.     FOR i := 0 TO LoopMax DO 
  321.  
  322.       Proc5; 
  323.       Proc4; 
  324.       IntLoc1 := 2; 
  325.       IntLoc2 := 3; 
  326.       String2Loc := "DHRYSTONE PROGRAM, 2'ND STRING"; 
  327.       EnumLoc := Ident2; 
  328.       BoolGlob :=  NOT Func2(String1Loc, String2Loc); 
  329.       WHILE (IntLoc1 < IntLoc2) DO 
  330.  
  331.         IntLoc3 := 5*IntLoc1-IntLoc2; 
  332.         Proc7(IntLoc1, IntLoc2, IntLoc3); 
  333.         INC(IntLoc1, 1); 
  334.       END; 
  335.       Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3); 
  336.       Proc1(PtrGlb); 
  337.       CharIndex := 'A'; 
  338.       WHILE CharIndex <= Char2Glob DO 
  339.  
  340.         IF (EnumLoc = Func1(CharIndex, 'C')) THEN 
  341.           Proc6(Ident1, EnumLoc)
  342.         END; 
  343.         CharIndex := VAL(CHAR, ORD(CharIndex)+1); 
  344.       END; 
  345.       IntLoc3 := IntLoc2*IntLoc1; 
  346.       IntLoc2 := IntLoc3 DIV IntLoc1; 
  347.       IntLoc2 := 7*(IntLoc3-IntLoc2)-IntLoc1; 
  348.       Proc2(IntLoc1); 
  349.     END; 
  350.   END Proc0; 
  351.  
  352.  
  353.  
  354.   (* The Main Program is trivial *) 
  355.  
  356. BEGIN 
  357.   Proc0; 
  358. END dry.
  359.  
  360.  
  361. Listing Two
  362.  
  363. MODULE sieve;
  364. (* Eratosthenes sieve prime number program, Byte Magazine *)
  365.  
  366.   CONST size = 8190;
  367.  
  368.   VAR
  369.     psn, k, prime, iter : INTEGER;
  370.     flags : ARRAY [0..size] OF BOOLEAN;
  371.  
  372. BEGIN
  373.   FOR iter := 1 TO 25 DO
  374.     FOR psn := 0 TO size DO
  375.      flags[ psn ] := TRUE;
  376.     END(* for *);
  377.     FOR psn := 0 TO size DO
  378.      IF flags[ psn ]
  379.      THEN  (* prime *)
  380.        prime := psn + psn + 3;
  381.        k := psn + prime;
  382.        WHILE k <= size DO  (* cancel multiples *)
  383.         flags[ k ] := FALSE;
  384.         k := k + prime;
  385.        END(* while *);
  386.      END(* if then *);
  387.     END(* for *);
  388.   END(* for *);
  389. END sieve.
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397. Listing Three
  398.  
  399. MODULE fib; 
  400.  
  401. (* Berkeley standard benchmark *) 
  402. (* Computes largest 16-bit Fibonacci number *) 
  403. (* Tests compiler recursion efficiency and CPU thruput *) 
  404.  
  405.   CONST 
  406.     TIMES = 10; 
  407.     VALUE = 24; 
  408.  
  409.   VAR 
  410.     i: INTEGER; 
  411.     f: CARDINAL; 
  412.     (* ----------------------------------------------------------- *) 
  413.  
  414.   PROCEDURE fibonacci(n: INTEGER): CARDINAL; 
  415.     VAR fibonacciResult: CARDINAL; 
  416.   BEGIN 
  417.     IF n >= 2 THEN 
  418.       fibonacciResult := fibonacci(n-1)+fibonacci(n-2)
  419.     ELSE 
  420.       fibonacciResult := n
  421.     END; 
  422.     RETURN fibonacciResult
  423.   END fibonacci; (* --------------------------- *) 
  424.  
  425.  
  426. BEGIN (* main *) 
  427.   FOR i := 1 TO TIMES DO 
  428.     f := fibonacci(VALUE)
  429.   END; 
  430. END fib.
  431.  
  432.  
  433.  
  434. Listing Four
  435.  
  436.  
  437. MODULE acker; 
  438.  
  439.  
  440.  
  441. (* Berkeley standard benchmark *) 
  442. (* Ackerman's function: ack (2, 4) *) 
  443. (* Tests recursion and integer math *) 
  444. (* Repeats 10,000 times *) 
  445.  
  446.  
  447.  
  448.   VAR 
  449.     loop, r: INTEGER; 
  450.     (* ---------------------------------------------------------- *) 
  451.  
  452.  
  453.  
  454.  
  455.   PROCEDURE ack(x1, x2: INTEGER): INTEGER; 
  456.  
  457.     VAR 
  458.       result: INTEGER; 
  459.  
  460.     VAR ackResult: INTEGER; 
  461.   BEGIN 
  462.     IF x1 = 0 THEN 
  463.  
  464.       result := x2+1
  465.     ELSIF x2 = 0 THEN 
  466.       result := ack(x1-1, 1)
  467.     ELSE 
  468.       result := ack(x1-1, ack(x1, x2-1))
  469.     END; 
  470.     ackResult := result; 
  471.     RETURN ackResult
  472.   END ack; (* --------------------------- *) 
  473.  
  474.  
  475. BEGIN (* main *) 
  476.   FOR loop := 1 TO 10000 DO 
  477.     r := ack(2, 4)
  478.   END; 
  479. END acker.
  480.  
  481.  
  482.  
  483.  
  484.  
  485. Listing Five
  486.  
  487. MODULE FPMath; 
  488. (* Benchmarks floating point math package *)
  489.  
  490.   FROM MathLib0 IMPORT arctan, exp, ln, sin, sqrt;
  491.   FROM InOut    IMPORT Write, WriteLn, WriteString;
  492.  
  493.   CONST
  494.     pi = 3.1415927;
  495.     nloops = 5;
  496.  
  497.   VAR 
  498.     i, j: INTEGER; 
  499.     angle, result, argument: REAL; 
  500.  
  501. BEGIN 
  502.   WriteString('SQUARE ROOTS   '); 
  503.   FOR i := 1 TO nloops DO 
  504.     Write ('.');
  505.     argument := 0.0; 
  506.     WHILE argument <= 1000.0 DO 
  507.       result := sqrt (argument); 
  508.       argument := argument + 1.0
  509.     END; 
  510.   END; (* FOR *) 
  511.  
  512.   WriteLn;
  513.   WriteString('LOGS           '); 
  514.   FOR i := 1 TO nloops DO 
  515.     Write ('.');
  516.     argument := 0.1; 
  517.     WHILE argument <= 1000.1 DO 
  518.       result := ln (argument); 
  519.       argument := argument + 1.0
  520.     END; 
  521.   END; (* FOR *) 
  522.  
  523.   WriteLn;
  524.   WriteString('EXPONENTIALS   '); 
  525.   FOR i := 1 TO nloops DO 
  526.     Write ('.');
  527.     argument := 0.1; 
  528.     WHILE argument <= 10.0 DO 
  529.       result := exp (argument); 
  530.       argument := argument + 0.01
  531.     END; 
  532.   END; (* FOR *) 
  533.  
  534.   WriteLn;
  535.   WriteString('ARCTANS        '); 
  536.   FOR i := 1 TO nloops DO 
  537.     Write ('.');
  538.     argument := 0.1; 
  539.     WHILE argument <= 10.0 DO 
  540.       angle := arctan (argument); 
  541.       argument := argument + 0.01
  542.     END; 
  543.   END; (* FOR *) 
  544.  
  545.   WriteLn;
  546.   WriteString('SINES          '); 
  547.   FOR i := 1 TO nloops DO 
  548.     Write ('.');
  549.     angle := 0.0; 
  550.     WHILE angle <= 2.0 * pi DO 
  551.       result := sin (angle); 
  552.       angle := angle + pi / 360.0
  553.     END; 
  554.   END; (* FOR *)
  555.   WriteLn; 
  556. END FPMath.
  557.  
  558.  
  559. Listing Six
  560.  
  561. MODULE QSort;
  562.  
  563. (* The test uses QuickSort to measure recursion speed *)
  564. (* An ordered array is created by the program and is  *)
  565. (* reverse sorted.  The process is performed 'MAXITER'*)
  566. (* number of times.                                   *)
  567.  
  568. CONST SIZE = 1000;
  569.       MAXITER = 50;
  570.  
  571. TYPE NUMBERS = ARRAY[1..SIZE] OF CARDINAL;
  572.  
  573. VAR Iter, Offset, I, J, Temporary : CARDINAL;
  574.     A : NUMBERS;
  575.  
  576. PROCEDURE InitializeArray ;
  577. (* Procedure to initialize array *)
  578.  
  579. VAR I : CARDINAL;
  580.  
  581. BEGIN
  582.     FOR I := 1 TO SIZE DO
  583.         A[I] := SIZE - I + 1
  584.     END; (* FOR I *)
  585. END InitializeArray;
  586.  
  587. PROCEDURE QuickSort;
  588. (* Procedure to perform a QuickSort *)
  589.  
  590. PROCEDURE Sort(Left, Right : CARDINAL);
  591.  
  592. VAR i, j : CARDINAL;
  593.     Data1, Data2 : CARDINAL;
  594.  
  595. BEGIN
  596.     i := Left; j := Right;
  597.     Data1 := A[(Left + Right) DIV 2];
  598.     REPEAT
  599.         WHILE A[i] < Data1 DO INC(i) END;
  600.         WHILE Data1 < A[j] DO DEC(j) END;
  601.         IF i <= j THEN 
  602.             Data2 := A[i]; A[i] := A[j]; A[j] := Data2;
  603.             INC(i); DEC(j)
  604.         END;
  605.     UNTIL i > j;
  606.     IF Left < j  THEN Sort(Left,j)  END;
  607.     IF i < Right THEN Sort(i,Right) END;
  608. END Sort;
  609.  
  610. BEGIN (* QuickSort *)
  611.     Sort(1,SIZE);
  612. END QuickSort;
  613.  
  614. BEGIN (* Main *)
  615.     FOR Iter := 1 TO MAXITER  DO 
  616.        InitializeArray;    
  617.        QuickSort   
  618.     END; (* FOR Iter  *)
  619. END QSort.
  620.  
  621.  
  622.  
  623. Listing Seven
  624.  
  625. MODULE ShSort;
  626. (* Tests Shell sort speed on an integer array of ARSIZE elements.  *)
  627. (* Creates an array ordered from smaller to larger, then sorts it  *)
  628. (* into reverse order. Repeats NSORTS times.                       *)
  629.  
  630. CONST ARSIZE = 1000;
  631.       NSORTS = 20;
  632.  
  633. TYPE NUMBERS = ARRAY [1..ARSIZE] OF INTEGER;
  634.  
  635. VAR IsInOrder, Ascending : BOOLEAN;
  636.     Iter, Offset, I, J, Temporary : CARDINAL;
  637.     Ch : CHAR;
  638.     A : NUMBERS;
  639.  
  640. PROCEDURE InitializeArray ;
  641.      (* Initialize array *)
  642. BEGIN
  643.     FOR I := 1 TO ARSIZE DO
  644.         A [I] := I
  645.     END; (* FOR I *)
  646. END InitializeArray;
  647.  
  648. PROCEDURE ShellSort ;
  649.      (* Shell-Meztner sort *)
  650.  
  651.     PROCEDURE Swap;
  652.          (* Swap elements A[I] and A[J] *)
  653.     BEGIN
  654.        IsInOrder := FALSE;
  655.        Temporary := A[I];
  656.        A[I] := A[J];
  657.        A[J] := Temporary;
  658.     END Swap;
  659.  
  660. BEGIN
  661.    (* Toggle 'Ascending' flag *)
  662.        Ascending := NOT Ascending;
  663.        Offset := ARSIZE;
  664.        WHILE Offset > 1 DO
  665.            Offset := Offset DIV 2;
  666.            REPEAT
  667.                IsInOrder := TRUE;
  668.                FOR J := 1 TO (ARSIZE - Offset) DO
  669.                    I := J + Offset;
  670.                    IF Ascending 
  671.                        THEN IF A[I] < A[J] THEN Swap END
  672.                        ELSE IF A[I] > A[J] THEN Swap END
  673.                    END; (* IF AscendingOrder *)
  674.                END; (* FOR J *)
  675.            UNTIL IsInOrder;
  676.        END; (* End of while-loop *)
  677. END ShellSort;
  678.  
  679. BEGIN (* Main *)
  680.     InitializeArray;
  681.     Ascending := TRUE;
  682.     FOR Iter := 1 TO NSORTS DO 
  683.        ShellSort   
  684.     END; 
  685. END ShSort.
  686.  
  687.  
  688.  
  689. Listing Eight
  690.  
  691. MODULE cortn;
  692.  
  693. (* Benchmark to test speed of coroutine switching *)
  694. (* Shifts NCHARS characters to upper-case         *)
  695. (* Two transfers per character                    *)
  696.  
  697. FROM SYSTEM IMPORT NEWPROCESS, TRANSFER, ADDRESS, BYTE, ADR;
  698.  
  699. CONST  NCHARS = 50000;
  700.        WorkSize = 1000;
  701.  
  702. VAR    ch : ARRAY [1..NCHARS] OF CHAR;
  703.        ShiftWork, CountWork : ARRAY [1..WorkSize] OF BYTE;
  704.        count, chval, c : CARDINAL;
  705.        main, shifter, counter : ADDRESS;
  706.  
  707. PROCEDURE CountProc;
  708.     (* Increments count *)
  709. BEGIN
  710.   REPEAT
  711.     count := count + 1;
  712.     TRANSFER (counter, shifter);
  713.   UNTIL FALSE;
  714. END CountProc;
  715.  
  716. PROCEDURE ShiftProc;
  717.     (* Shifts char at 'count' to upper case *)
  718. BEGIN
  719.   REPEAT
  720.     IF (ch [count] >= 'a') AND (ch [count] <= 'z') THEN
  721.       ch [count] := CHR (ORD (ch [count]) - 32)
  722.     END;
  723.     TRANSFER (shifter, counter);
  724.   UNTIL count = NCHARS;
  725.   TRANSFER (shifter, main);
  726. END ShiftProc;
  727.  
  728. BEGIN  (* Main program *)
  729.  
  730.   (* Load array with lower-case letters *)
  731.   chval := ORD ('a');
  732.   FOR c := 1 TO NCHARS DO
  733.     ch [c] := CHR (chval);
  734.     chval := chval + 1;
  735.     IF chval > ORD ('z') THEN
  736.       chval := ORD ('a');
  737.     END;
  738.   END;
  739.  
  740.   (* Set up coroutines *)
  741.   NEWPROCESS (CountProc, ADR (CountWork), WorkSize, counter);
  742.   NEWPROCESS (ShiftProc, ADR (ShiftWork), WorkSize, shifter);
  743.  
  744.   (* Dispatch the controlling task *)
  745.   count := 1;
  746.   TRANSFER (main, shifter);
  747. END cortn.
  748.  
  749.  
  750.  
  751.  
  752. Listing Nine
  753.  
  754. MODULE ncortn;
  755.  
  756. (* Does the same thing as CORTN.MOD, but without  *)
  757. (* coroutine switching                            *)
  758. (* Subtract run time for this from time for CORTN *)
  759. (* to find out actual coroutine overhead          *)
  760.  
  761. CONST  NCHARS = 50000;
  762.        WorkSize = 1000;
  763.  
  764. VAR    ch : ARRAY [1..NCHARS] OF CHAR;
  765.        count, chval, c : CARDINAL;
  766.  
  767. PROCEDURE CountProc;
  768.     (* Increments count *)
  769. BEGIN
  770.   count := count + 1;
  771. END CountProc;
  772.  
  773. PROCEDURE ShiftProc;
  774.     (* Shifts all chars in array 'ch' upper case *)
  775. BEGIN
  776.   REPEAT
  777.     IF (ch [count] >= 'a') AND (ch [count] <= 'z') THEN
  778.       ch [count] := CHR (ORD (ch [count]) - 32)
  779.     END;
  780.     CountProc;          (* Substitute call for TRANSFER *)
  781.   UNTIL count = NCHARS;
  782. END ShiftProc;
  783.  
  784. BEGIN  (* Main program *)
  785.  
  786.   (* Load array with lower-case letters *)
  787.   chval := ORD ('a');
  788.   FOR c := 1 TO NCHARS DO
  789.     ch [c] := CHR (chval);
  790.     chval := chval + 1;
  791.     IF chval > ORD ('z') THEN
  792.       chval := ORD ('a');
  793.     END;
  794.   END;
  795.  
  796.   (* Dispatch the controlling task *)
  797.   count := 1;
  798.   ShiftProc;
  799. END ncortn.
  800.  
  801.  
  802.  
  803.  
  804.  
  805.  
  806.  
  807.