Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

COBOL SORT command 3

Status
Not open for further replies.

delugir

Programmer
Mar 26, 2009
4
US
We have a coding standard that we are not supposed to use the SORT command in COBOL programs (we're using Enterprise COBOL).

I've asked around as to why we have this standard and the only reply is that they heard it used a lot of CPU time and cost a lot. Does anyone know if this is true?

Is there a difference if you want to sort a whole file in a program versus sorting just a working-storage table (10 occurrences). I need to sort up to 10 occurrences of a working storage table for each record that is processed in the program.

I have read about the bubble sorts that we can use to do this. But wanted to know why that would be better than just using the SORT command in this case.
 
IMHO, I guess COBOL's SORT is only for sorting physical files (tables), not for sorting working storage tables. Some years ago I had to sort a working storage table, but it worked not with COBOL's SORT, so I wrote rather my own bubble sort.

Perhaps I'm wrong - correct me please - but maybe it's depending from COBOL standard or COBOL compiler - I'm using ILE COBOL on iSeries.
 
It depends on your Cobol dialect whether SORT can sort the contents of a WS array. At least MF can sort that, and that's the only dialect I've ever used (and it seems to have a lot of extensions), so I can't speak for other Cobol brands.

HTH
TonHu
 
your standard is obsolete now. COBOL Sort will use the same sort engine as a normal SORT on a JCL. Speed is the same really.

But to sort a array, Enterprise COBOL does not do it yet as far as I know. but you can look on the manuals online at IBM.

In any case there are plenty of samples of sort algorithms in COBOL on the web. search for them.

Regards

Frederico Fonseca
SysSoft Integrated Ltd

FAQ219-2884
FAQ181-2886
 
Mainframe COBOL has used the same sort engine for many years (always as far as I know). Nevertheless, many mainframe shops do not allow internal COBOL sorts because they are much more inefficient than standalone sorts. THe reason is that DFHSORT (and other sort products like SYNCSORT) is optimized to do IO very quickly (large CCW chains). COBOL internal sorts rely on COBOL or LE to do the input procedure and output procedure IO and do not take advantage of the tricks that the standalone sort uses.

Some time ago, IBM introduced the FASTSRT CBL option that improves COBOL Sorts when either USING or GIVING (or both) is used with the SORT verb. I'm not sure what the option does to improve performance, but apparently it does.

I've argued with my peers that a blanket prohibition on internal sorting is not a good thing. There are many situations where the overall time required to produce a report or perform processing is no slower using an internal sort than with separate COBOL programs and an intermediate standalone sort and there are fewer programs to maintain.

Glenn
 
I have SHELL SORT copybooks that will sort a WS table many times faster than a bubble sort. Anyone interested?
 
I personally had a Shell-Metzner sort routine before we use MF.
 
Thanks to all for your responses!

I have done a little more looking around on the IBM web site and I think you are correct that you can't use the SORT command to sort a working storage table (which is what I need to do). It's only for sorting files.

Looks like I'll have to use a bubble sort or something similar.
 
While the COBOL SORT may not be designed to sort a WS table, you could make it work. Create an INPUT PROCEDURE to cycle thru the table and RELEASE a record to the SORT. The OUTPUT PROCEDURE could clear out the table and then RETURN the sorted records and fill the table in sequence.
 
It's very small. I shall post it.
Working Storage:
Code:
01.  *> Shell Sort indices.                     
    05  INDEX-1                 Pic 9(4) Comp-5.
    05  INDEX-2                 Pic 9(4) Comp-5.
    05  INTERVAL                Pic 9(4) Comp-5.
    05  GAP                     Pic 9(4) Comp-5.
Procedure:
Code:
 *>                                                          
 *> Shell Sort with initial compression of table.            
 *>                                                          
 Move Zero                         to NUMBER-OF-ENTRIES      
 Perform Varying INDEX-1 from 1 by 1 Until INDEX-1 > MAX-ENTR
   If TABLE-ENTRY(INDEX-1) not = NULL-ENTRY                  
     Add 1                         to NUMBER-OF-ENTRIES      
     If NUMBER-OF-ENTRIES < INDEX-1                          
       Move TABLE-ENTRY(INDEX-1)   to TABLE-ENTRY(NUMBER-OF-E
       Move NULL-ENTRY             to TABLE-ENTRY(INDEX-1)   
     End-If                                                  
   End-If                                                    
 End-Perform                                                 
 Move NUMBER-OF-ENTRIES            to GAP                    
 Perform Until GAP < 2                                       
   Divide 2                      into GAP                    
   Move GAP                        to INTERVAL               
   Perform Until INTERVAL not < NUMBER-OF-ENTRIES            
     Add 1                         to INTERVAL               
     Move INTERVAL                 to INDEX-2                
     Compute INDEX-1 = INTERVAL - GAP                        
     If TABLE-KEY(INDEX-1) > TABLE-KEY(INDEX-2)              
       Move TABLE-ENTRY(INDEX-2)   to HOLD-ENTRY             
       Perform Until INDEX-2 not > GAP                       
                 or HOLD-KEY not < TABLE-KEY(INDEX-1)        
         Move TABLE-ENTRY(INDEX-1) to TABLE-ENTRY(INDEX-2)   
         Subtract GAP            from INDEX-1                
         Subtract GAP            from INDEX-2                
       End-Perform                                           
       Move HOLD-ENTRY             to TABLE-ENTRY(INDEX-2)   
     End-If                                                  
   End-Perform                                               
End-Perform
Use COPY ... REPLACING as appropriate.
 
Thanx webrabbit for posting the shell sort copybooks.

Coboldeke,
Can you post an example how to use sort for sorting a working storage table using input/output procedures as you suggested?
 
Some samples:
Code:
  CBL SSRANGE
 IDENTIFICATION DIVISION.
 PROGRAM-ID. TSORT.
 ENVIRONMENT DIVISION.
 INPUT-OUTPUT SECTION.
* DEMONSTRATE A WS TABLE SORT USING SORT VERB.
 FILE-CONTROL.
     SELECT SORTTEST ASSIGN TO SORTTEMP.
 DATA DIVISION.
 FILE SECTION.
 SD  SORTTEST.
 01  SORT-REC                    PIC 9(5).

 WORKING-STORAGE SECTION.
* The table to be sorted.
 01  SORT-TABLE-ITEMS.
     04  SORT-TABLE PIC 9(5) OCCURS 1000 TIMES
                    INDEXED BY I SWAP-NUMBER.

 01  WS-VARS.
     04  TABLE-VAL        PIC 9(5).
     04  SORT-COUNT       PIC S9(4) COMP-5.
 01  TIMING-PROC.
     04  Start-Time       Pic 99/99/99/99.
     04  End-Time         Pic 99/99/99/99.

 PROCEDURE DIVISION.
 0000-MAIN SECTION.
     MOVE FUNCTION CURRENT-DATE (9:8) TO START-TIME.
* PERFORM SORT 1000 TIMES.
     PERFORM VARYING SORT-COUNT FROM 1 BY 1 UNTIL SORT-COUNT > 1000
* FILL TABLE WITH INVERSE SORTED VALUES.
       MOVE 1000 TO TABLE-VAL
       PERFORM VARYING I FROM 1 BY 1
               UNTIL I > 1000
          MOVE TABLE-VAL TO SORT-TABLE (I)
          SUBTRACT 1 FROM TABLE-VAL
       END-PERFORM
* DO SORT
       SORT SORTTEST
           ASCENDING SORT-REC
           INPUT PROCEDURE IS 1000-INPUT
           OUTPUT PROCEDURE IS 2000-OUTPUT
     END-PERFORM.
* REPORT RESULTS
     MOVE FUNCTION CURRENT-DATE (9:8) TO END-TIME.
*    PERFORM 0600-DISPLAY.

     DISPLAY "  END: " END-TIME.
     DISPLAY "START: " START-TIME.
     GOBACK.

 0600-DISPLAY SECTION.
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > 1000
        DISPLAY SORT-TABLE (I)
     END-PERFORM.

 1000-INPUT SECTION.
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > 1000
       RELEASE SORT-REC FROM SORT-TABLE (I)
     END-PERFORM.

 2000-OUTPUT SECTION.
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > 1000
       RETURN SORTTEST INTO SORT-TABLE (I)
          AT END CONTINUE
       END-RETURN
     END-PERFORM.

Code:
  CBL SSRANGE
 IDENTIFICATION DIVISION.
 PROGRAM-ID. COMBSORT.
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* COMB SORT WITH INDEXED TABLE ACCESS
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ENVIRONMENT DIVISION.
 DATA DIVISION.
 WORKING-STORAGE SECTION.

* The table to be sorted.
 01  SORT-TABLE-ITEMS.
     04  SORT-TABLE PIC 9(5) OCCURS 1000 TIMES INDEXED BY I SWAP-NUMBER.

 01  TEST-VARS.
     04  Start-Time       Pic 99/99/99/99.
     04  End-Time         Pic 99/99/99/99.
     04  GEN-COUNTER      PIC S9(5) COMP-5.
     04  COUNTER-1        PIC S9(5) COMP-5.

 01  SORT-PROC-VARS.
     04  SWAP-VALUE        PIC 9(5).
     04  JUMP-SIZE         PIC S9(5) COMP-5.
     04  TABLE-SIZE        PIC S9(5) COMP-5.
     04  UPPER-LIMIT       PIC S9(5) COMP-5.
     04  SWAP              PIC X.         
 
*----------------------------------------------------------------
 PROCEDURE DIVISION.
 0000-START-SECTION.
* Rudimentary timing
     MOVE FUNCTION CURRENT-DATE (9:8) TO START-TIME.

* perform the sort 1000 times on the table
     PERFORM VARYING GEN-COUNTER FROM 1 BY 1 UNTIL GEN-COUNTER > 1000
* load the table - inverse sorted order
        MOVE 1000 TO COUNTER-1
        PERFORM VARYING I FROM 1 BY 1 UNTIL I > 1000
            MOVE COUNTER-1 TO SORT-TABLE (I)
            SUBTRACT 1 FROM COUNTER-1
        END-PERFORM
* sort the table.
        PERFORM 1000-COMBSORT
     END-PERFORM.
* after - display the timing results & display the table
     MOVE FUNCTION CURRENT-DATE (9:8) TO END-TIME.

*    PERFORM 0600-DISPLAY.
     DISPLAY "  END: " END-TIME.
     DISPLAY "START: " START-TIME.
     GOBACK.

 0600-DISPLAY SECTION.
     PERFORM VARYING GEN-COUNTER FROM 1 BY 1 UNTIL GEN-COUNTER > 1000
        DISPLAY GEN-COUNTER ': ' SORT-TABLE (GEN-COUNTER)
     END-PERFORM.

 1000-COMBSORT SECTION.
     MOVE 1000 TO JUMP-SIZE TABLE-SIZE
     PERFORM 1100-SORT1 UNTIL (SWAP = 'Y') AND (JUMP-SIZE < 2).

 1100-SORT1 SECTION.
     COMPUTE JUMP-SIZE = (10 * JUMP-SIZE + 3) / 13.
     COMPUTE UPPER-LIMIT = TABLE-SIZE - JUMP-SIZE.
     MOVE 'Y' TO SWAP.
     PERFORM 1200-SORT2 VARYING I FROM 1 BY 1 UNTIL I > UPPER-LIMIT.

 1200-SORT2 SECTION.
     SET SWAP-NUMBER TO I.
     SET SWAP-NUMBER UP BY JUMP-SIZE.
     IF SORT-TABLE (I) > SORT-TABLE (SWAP-NUMBER)
        MOVE SORT-TABLE (I) TO SWAP-VALUE
        MOVE SORT-TABLE (SWAP-NUMBER) TO SORT-TABLE (I)
        MOVE SWAP-VALUE TO SORT-TABLE (SWAP-NUMBER)
        MOVE 'N' TO SWAP
     END-IF.

Code:
  CBL SSRANGE
 IDENTIFICATION DIVISION.
 PROGRAM-ID. BBLESORT.
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* BUBBLE SORT WITH INDEXES
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ENVIRONMENT DIVISION.
 DATA DIVISION.
 WORKING-STORAGE SECTION.

 01  SORT-TABLE-ITEMS.
     04  SORT-TABLE PIC 9(5) OCCURS 1000 TIMES INDEXED BY STEP I DISP-INDEX.

 01  TEST-VARS.
     04  Start-Time       Pic 99/99/99/99.
     04  End-Time         Pic 99/99/99/99.

     04  GEN-COUNTER      PIC S9(5) COMP-3.
     04  COUNTER-1        PIC S9(5) COMP-3.
     04  COUNTER-2        PIC S9(5) COMP-3.

 01  sort-proc-vars.
     04  temp-swap-value  pic 9(5).

*----------------------------------------------------------------
 PROCEDURE DIVISION.
 0000-START-SECTION.
     MOVE FUNCTION CURRENT-DATE (9:8) TO START-TIME.
     PERFORM VARYING GEN-COUNTER FROM 1 BY 1 UNTIL GEN-COUNTER > 1000
        MOVE 1 TO COUNTER-1
        PERFORM VARYING COUNTER-2 FROM 1000
               BY -1 UNTIL COUNTER-2 < 1
           MOVE COUNTER-2 TO SORT-TABLE (COUNTER-1)
           ADD 1 TO COUNTER-1
        END-PERFORM
        PERFORM 1000-BUBBLE-SORT
     END-PERFORM.
     MOVE FUNCTION CURRENT-DATE (9:8) TO END-TIME.
     DISPLAY "  END: " END-TIME.
     DISPLAY "START: " START-TIME.
     PERFORM 0600-DISPLAY.
     GOBACK.

 0600-DISPLAY SECTION.
     PERFORM VARYING GEN-COUNTER FROM 1 BY 1 UNTIL GEN-COUNTER > 1000
        DISPLAY GEN-COUNTER ': ' SORT-TABLE (GEN-COUNTER)
     END-PERFORM.

 1000-BUBBLE-SORT SECTION.
     PERFORM VARYING STEP FROM 1 BY 1 UNTIL STEP > 1000
        SET DISP-INDEX TO STEP
        SET DISP-INDEX UP BY 1
        PERFORM VARYING I FROM DISP-INDEX BY 1 UNTIL I > 1000
           IF SORT-TABLE (STEP) > SORT-TABLE (I)
              MOVE SORT-TABLE (STEP) TO TEMP-SWAP-VALUE
              MOVE SORT-TABLE (I) TO SORT-TABLE(STEP)
              MOVE TEMP-SWAP-VALUE TO SORT-TABLE (I)
           END-IF
        END-PERFORM
     END-PERFORM.



Measurement is not management.
 
Hi Glenn9999,

Thank you very much for the great comprehensive examples !

But I have a question to the the first example - i.e. usage of COBOL's SORT:

How it's with the physical file SORTTEMP which is declared in
Code:
 FILE-CONTROL.
     SELECT SORTTEST ASSIGN TO SORTTEMP.
 DATA DIVISION.
 FILE SECTION.
 SD  SORTTEST.
 01  SORT-REC                    PIC 9(5).
Must be this temporary file SORTTEMP created before usage in the program?
So if want to use COBOL's SORT for sorting a working storage table I need first to create for my working storage table a temporary physical file (table)?



 
I'm using Fujitsu COBOL 3.0 on testing those. One of its requirements is that you define a temporary working area on disk for it. If I were to not, it would return a severe compiler error. As for testing, it's definitely fast enough that it's not going to disk, so I would guess that it's required in case the SORT routines there would need it.

But I would think for IBM COBOL for this-and-that that you could just follow whatever requirements it holds. I'm sure that includes any definitions of temporary sort working areas.

Measurement is not management.
 
I have done a little more looking around on the IBM web site and I think you are correct that you can't use the SORT command to sort a working storage table (which is what I need to do). It's only for sorting files."

Quite incorrect. . . .

The internal sort in cobol can sort anything precicely because it is not "only for sorting files". Data to be sorted can be RELEASEd to the sort and the source of the data can be anything. . . This includes data from vsam files, db2 tables, internal arrays, etc and data taken from multiple sources in the same program. Note that the program controls what is released to the sort - it is not as restricted as an external sort that typically requires a "sortin".
 
The internal sort in cobol can sort anything precicely because it is not "only for sorting files".

This is a very good observation.

For example, when one thinks that a SORT must sort a working-storage table, think about how the data arrived in the table. Was it read in from a file? Obviously, there must be a reason for the unsorted order of the table.

So, use SORT, RELEASE the data elements to be tabled in the INPUT PROCEDURE and fill the table elements in the OUTPUT PROCEDURE.

It might seem 'inefficient' and it very well may not be the absolute in efficiency, but it is easy to code. And, most decent SORT algorithms will 'short circuit' sorted data from the in-memory sort tournament area to the RETURN statement if the sort tournament area is large enough to contain all the data (as it well might be if all the data fit in a table), never writing data to a temp file.

Tom Morrison
 
The key here is what papadi and Tom have said. THe internal SORT is not restricted to having a sort file that matches either an input or output file in layout.

You can define the SORT file to be any group of data fields you like. Then in the input PROCEDURE, you create each of those records and RELEASE them to the SORT. It may be that you read an input file and only select certain records, and certain pieces of data from those records. You might even create some new pieces of data using the information from the input record. All of this is moved into your sort record record layout and RELEASEd.

In the output PROCEDURE when you RETURN those records you have sorted, you can put the information in your WS table. You can use as much or as little of the sorted record's data as you like. You are not required to have your WS table to be defined exactly as your sort record.

That's one of the benefits of the COBOL internal SORT. You're not restricted to sorting just the information coming in from an input record.

If your input record had a 1 letter code for the day of the week... S=Sun, M=Mon, T=Tue, W=Wed, H=Thu, F=Fri, A=Sat and you needed to get the data sorted in ascending order by day, you couldn't easily do it if you were only allowed to sort the data you were given. But in the input procedure you could change a "S" to "1", "M" to "2", etc. You could save that code as well as the original code if you needed it later and now get the data sorted in day sequence.
 
In at least one application (many programs), multiple selections are accepted from the user. To simplify the subsequent selection process, the selections are sorted. No input files!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top