peterk@cbmger.UUCP (Peter Kittel GERMANY) (05/02/91)
Anybody read the April Byte and the article about the new Combsort algorithm? Recommended to everyone. Not only that it's a pure miracle how one can achieve such a performance with such a little beastie (you take bubble sort and *add two lines* and *change one other line*). ABSOLUTELY INCREDIBLE. But, for the best, if you look closely into one of the explanation boxes, you find all this research (they obviously did an awful lot) was done on an A2000. I also thought at first, be careful it's the April issue, but I immediately tested it and it seems to work, flawlessly and blindingly fast. It looks as if it will replace my old loved heapsort that I used the last years (I hate recursive algorithms like quicksort), because Combsort beats Heapsort by a factor of 33 % on my machine (e.g. 12 s against 16 s). -- Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Commodore Frankfurt, Germany \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk
rrmorris@uokmax.ecn.uoknor.edu (Rodney Raym Morrison) (05/03/91)
In article <1193@cbmger.UUCP> peterk@cbmger.UUCP (Peter Kittel GERMANY) writes: >Anybody read the April Byte and the article about the new Combsort >algorithm? Recommended to everyone. Not only that it's a pure miracle >how one can achieve such a performance with such a little beastie >(you take bubble sort and *add two lines* and *change one other line*). >ABSOLUTELY INCREDIBLE. >But, for the best, if you look closely into one of the explanation >boxes, you find all this research (they obviously did an awful lot) >was done on an A2000. > >I also thought at first, be careful it's the April issue, but I >immediately tested it and it seems to work, flawlessly and blindingly >fast. It looks as if it will replace my old loved heapsort that I used >the last years (I hate recursive algorithms like quicksort), because >Combsort beats Heapsort by a factor of 33 % on my machine (e.g. 12 s >against 16 s). > >-- >Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Could you post your combsort code or email it to me? rrmorris@uokmax.ecn.uoknor.edu
ccplumb@rose.waterloo.edu (Colin Plumb) (05/04/91)
I saw it briefly and was thrilled that BYTE had finally discovered shellsort. If it beats heapsort, though, I may be wrong. How does it work? -- -Colin
peterk@cbmger.UUCP (Peter Kittel GERMANY) (05/06/91)
In article <1991May3.201243.7959@watdragon.waterloo.edu> ccplumb@rose.waterloo.edu (Colin Plumb) writes: >I saw it briefly and was thrilled that BYTE had finally discovered shellsort. >If it beats heapsort, though, I may be wrong. How does it work? In the article, they explicitly mention shellsort. They say that their combsort may look very similar, but is quite a different thing then. -- Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Commodore Frankfurt, Germany \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk
xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) (05/06/91)
ccplumb@rose.waterloo.edu (Colin Plumb) writes: > I saw it briefly and was thrilled that BYTE had finally discovered > shellsort. If it beats heapsort, though, I may be wrong. How does it > work? Much like shell-sort, but instead of decreasing the span by a factor of 1.7 or so per loop, and then repeating each loop until no swaps are seen, the span is decreased by only 1.3 per loop, but each loop runs just once until the span one loop, which is run until no swaps occur. There seems also to be some special casing that a span of 9 or 10 is replaced by a span of 11 for reasons worth reading the article to puzzle out. I did the same about 1967, as I'm sure did thousands of others; the authors' biggest contribution is to run thorough tests to pick the "ideal" span divisor from loop to loop, and to detail performance. While it does (barely) beat heapsort, it takes almost twice as long as quicksort, so it is still not a choice you'd make except in a small sort, quick hack application. As a recent net posting showing quicksort in ML proved, there is nothing inherently complex about quicksort, our notation for programming just makes it look complex with a lanugage as weak as C. In such a procedural language, though, the comb-sort _looks_ much simpler, and is surely simpler to write, than either quicksort or heapsort. Kent, the man from xanth. <xanthian@Zorch.SF-Bay.ORG> <xanthian@well.sf.ca.us>
peterk@cbmger.UUCP (Peter Kittel GERMANY) (05/07/91)
In article <1991May3.165222.31097@uokmax.ecn.uoknor.edu> rrmorris@uokmax.ecn.uoknor.edu (Rodney Raym Morrison) writes: >In article <1193@cbmger.UUCP> peterk@cbmger.UUCP (Peter Kittel GERMANY) writes: >>Anybody read the April Byte and the article about the new Combsort >>algorithm? Recommended to everyone. >>But, for the best, if you look closely into one of the explanation >>boxes, you find all this research (they obviously did an awful lot) >>was done on an A2000. >> ^^^^^^^^^^^^^^^^ >>I also thought at first, be careful it's the April issue, but I >>immediately tested it and it seems to work, flawlessly and blindingly >>fast. It looks as if it will replace my old loved heapsort that I used >>the last years (I hate recursive algorithms like quicksort), because >>Combsort beats Heapsort by a factor of 33 % on my machine (e.g. 12 s >>against 16 s). > >Could you post your combsort code or email it to me? I got some more similar requests, so here we go. Naturally, we speak AmigaBASIC (-: for the not BASIC literates there is also a C version in the Byte article :-) : rem Combsort, by Richard Box and Stephen Lacey, Byte 4/91, p.315 rem Sort Array a(1) to a(size), start index 0 no problem (change FOR) gap=size flag=-1:rem this is a boolean flag while flag or gap<>1 gap=int(gap/1.3):if gap<1 then gap=1 if gap=9 or gap=10 then gap=11 flag=0 for i=1 to size-gap j=i+gap if a(i)>a(j) then ah=a(i):a(i)=a(j):a(j)=ah flag=-1 end if next wend Well, originally they use a "DO ... UNTIL flag=0 and gap" in TrueBasic, which is not available in AmigaBASIC. You may well do it that way in assembler. (I hope my WHILE does indeed exactly the same.) The only place where you had to change something to work on an array starting with index 0 is the FOR loop. For the assembler gurus: The crucial part is that divisor 1.3. If you are going fixed point in assembler, you need not use it to 12 digits precision, values between 1.28 and 1.31 are nearly as good. So you may choose some value that shows some easy-to-divide bit pattern. (They show a diagram made up of 20,000 test arrays and different gap values, showing the sort time depending on gap. The curve shows a definite minimum at 1.3, leading into chaos for bigger values, and steadily rising for lower values.) The special treatment of gap=9 or 10 is already a refinement of 2nd stage, not needed vitally, but reportedly optimizing the performance and really easy to implement. Have fun and tell me about your results! -- Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Commodore Frankfurt, Germany \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk
peter@cbmvax.commodore.com (Peter Cherna) (05/07/91)
In article <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes: >While it does (barely) beat heapsort, it takes almost twice as long >as quicksort, so it is still not a choice you'd make except in a small >sort, quick hack application. As a recent net posting showing >quicksort in ML proved, there is nothing inherently complex about >quicksort, our notation for programming just makes it look complex >with a lanugage as weak as C. Quicksort is even easier to "write" when you find it has already been implemented in a link-library. SAS/C comes with a quicksort that has several interfaces (one for integers, one for strings, etc.) Other compilers may have the same. (It's worth reading through the section of the manual on the link libraries -- there are a really rich set of functions available.) >Kent, the man from xanth. Peter -- Peter Cherna, Operating Systems Development Group, Commodore-Amiga, Inc. {uunet|rutgers}!cbmvax!peter peter@cbmvax.commodore.com My opinions do not necessarily represent the opinions of my employer. "If all you have is a hammer, everything looks like a nail."
231b3678@fergvax.unl.edu (Phil Dietz) (05/08/91)
In <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes: >While it does (barely) beat heapsort, it takes almost twice as long >as quicksort, so it is still not a choice you'd make except in a small >sort, quick hack application. As a recent net posting showing >quicksort in ML proved, there is nothing inherently complex about >quicksort, our notation for programming just makes it look complex >with a lanugage as weak as C. I was VERY amazed at the comb-sorts results. I ran the test on my system, and you know what, comb-sort beat qsort by a heinous time! I sorted a list of ints (100000 of them). I used the comb-sort routine directly from the article, and I used qsort routine that comes with Lattice. sorting the same list of 100000 elements: qsort 165.3 secs comb 53.2 secs This either shows that the comb-sort is FAST, or the Lattice Qsort is SLOW! Yes 3 times faster! Here is the source code to compile on your system: Keep in mind that I just threw this together....(wnat some spaghetti ? :-) Compile lc -Lm -O comb.c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> void main(int argc, char **argv) { void combsort(int *list,int size); int sortfunct(int *a, int *b); int i,*list,size; unsigned int clock[2],clock2[2]; if (argc<3) { printf("combsort [ 1 | 2 ] [# of elements]\n 1 = comb\n 2 = qsort\n\n"); exit(1); } size=atoi(argv[2]); if (size<10) exit(1); list=(int *)calloc(size,sizeof(int)); if (!list) { printf(" Ran out of memory!\n"); exit(1); } for (i=0;i<size;i++) list[i]=(rand() % size); /* Get random list */ for (i=0;i<10;i++) printf("%d: %d\n",i,list[i]); /* Print some of them */ timer(clock); if (atoi(argv[1])==1) { printf("Comb Sorting:\n"); combsort(list,size); } else { printf("Q-Sorting\n"); qsort(list,size,sizeof(int),sortfunct); } timer(clock2); printf("\nSorted:\n"); for (i=0;i<10;i++) printf("%d: %d\n",i,list[i]); printf("Time 1: %d.%d\n",clock[0],clock[1]); printf("Time 2: %d.%d\n",clock2[0],clock2[1]); if (clock[1]>clock2[1]) printf("Total time: %d.%d secs\n",(clock2[0]-clock[0]),(clock[1]-clock2[1])); else printf("Total time: %d.%d secs\n",(clock2[0]-clock[0]),(clock2[1]-clock[1])); } void combsort(int *list,int size) { int switches, hold, i, j, top, gap; gap=size; do { gap=(int)((float)gap/1.3); switch(gap) { case 0: gap=1; break; case 9: case 10: break; default: break; } switches=0; top=size - gap; for(i=0;i<top;++i) { j=i+gap; if (list[i] > list[j]) { hold=list[i]; list[i]=list[j]; list[j]=hold; ++switches; } } } while (switches || (gap>1)); } int sortfunct(int *a, int *b) { if (*a>*b) return 1; if (*a<*b) return -1; return 0; } --- I don't like to flame! Phil Dietz You know what? 231b3678@fergvax.unl.edu Newton and Leibniz suck big time! Univ. of Nebraska
mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (05/08/91)
In article <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes:
While it does (barely) beat heapsort, it takes almost twice as long
as quicksort, so it is still not a choice you'd make except in a small
sort, quick hack application.
Actually, for that kind of application, I use sort(). What's the point
of having libraries of tools if you don't use them for the quick
hacks. In fact, even for non-quick hacks, it's probably worthwhile
using sort(), and replacing it if it proves to be unsuitable for some
reason.
<mike
--
I know the world is flat. Mike Meyer
Don't try tell me that it's round. mwm@pa.dec.com
I know the world stands still. decwrl!mwm
Don't try to make it turn around.
peterk@cbmger.UUCP (Peter Kittel GERMANY) (05/08/91)
In article <231b3678.673637576@fergvax> 231b3678@fergvax.unl.edu (Phil Dietz) writes: > >void combsort(int *list,int size) > { > ... > switch(gap) > { > case 0: gap=1; break; > case 9: case 10: break; ^^^^^ I miss something here: gap=11; ??? > default: break; > } > switches=0; > .... > if (list[i] > list[j]) > { > hold=list[i]; > list[i]=list[j]; > list[j]=hold; > ++switches; ^^ Why do they do this? Why not just set the flag? Or is a "++switches;" faster than a "switches=1;" (done by MOVEQ in assembler)? -- Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Commodore Frankfurt, Germany \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk
dac@prolix.pub.uu.oz.au (Andrew Clayton) (05/08/91)
In article <MWM.91May7111453@raven.pa.dec.com>, Mike (My Watch Has Windows writes: > In article <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes: > While it does (barely) beat heapsort, it takes almost twice as long > as quicksort, so it is still not a choice you'd make except in a small > sort, quick hack application. > > Actually, for that kind of application, I use sort(). What's the point > of having libraries of tools if you don't use them for the quick > hacks. In fact, even for non-quick hacks, it's probably worthwhile > using sort(), and replacing it if it proves to be unsuitable for some > reason. If you want a sad laugh; Mickeysoft C V6.00 for the MSDOS platform has a sort() library function, all very well and good. Microsoft Windows (V3) has listboxes that can be flagged as 'sorted'. Fine. Unfortunately, Windows doesn't use the sort() library - it has its OWN completely incompatible collating sequence that places all punctuation and special symbols BEFORE letters, and all the numerals AFTER letters. It's truly spasticated, and a real bitch to work with. Grr. > I know the world is flat. Mike Meyer Dac --
mjl@alison.at (Martin J. Laubach) (05/09/91)
| In article <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes: | While it does (barely) beat heapsort, it takes almost twice as long | as quicksort Pardon me -- I don't want to start a "my sort is better than your sort" thread, I just want to find out whether the stuff we learnt is correct or not... Following my docs, heapsort always does O(N ld N), while quicksort is N ld N (best), N^2/2 (worst case), and 1.4 N ld N (average). Doesn't this mean that heap and quick are about the same, but the possibility of an anomaly in quicksort? mjl
mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (05/09/91)
In article <231b3678.673637576@fergvax> 231b3678@fergvax.unl.edu (Phil Dietz) writes: In <1991May6.155148.1201@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes: >While it does (barely) beat heapsort, it takes almost twice as long >as quicksort, so it is still not a choice you'd make except in a small >sort, quick hack application. I was VERY amazed at the comb-sorts results. I ran the test on my system, and you know what, comb-sort beat qsort by a heinous time! I sorted a list of ints (100000 of them). I used the comb-sort routine directly from the article, and I used qsort routine that comes with Lattice. sorting the same list of 100000 elements: qsort 165.3 secs comb 53.2 secs This either shows that the comb-sort is FAST, or the Lattice Qsort is SLOW! No, it shows what happens when you compare a general sort utility to one tailored for the problem at hand. Your comb-sort got to use a direct comparisons and assignments instead of a function calls. That makes each comparison and exchange an order of magnitude (or more) more expensive for SAS qsort than for your coomb-sort. A closer-to-fair comparison would be to write your own quicksort for sorting a fixed-size array of known object types. I cheated, and tweaked your comb-sort to call sortfunct for the comparison, and memcpy for the assignments, whicih should have roughly the same effect. I got: comb-sort of 100000 elements: 42.46 seconds qsort of 100000 elements: 27.12 seconds I.e. - the quicksort is roughly twice as fast for this case. Note: what I did - or even what I suggested doing - doesn't constitute a serious study of the problem. It just points out the flaws in what was presented earlier. In reality, I'll continue using qsort(), even though I can get faster results by handcoded routines. When a profiled run of the code shows that the serious delays are caused by the qsort, I'll change it to something faster, and chosen for the problem at hand. Meanwhile, I'm waiting to see what BSD is going to do with Bernsten's combinatorial sort, which sorts things in order(total_keysize). And there's a thing called "fusion sort" that might be the same thing in another guise.... <mike -- Take a magic carpet to the olden days Mike Meyer To a mythical land where everybody lays mwm@pa.dec.com Around in the clouds in a happy daze decwrl!mwm In Kizmiaz ... Kizmiaz
Charlie_Gibbs@mindlink.bc.ca (Charlie Gibbs) (05/09/91)
In article <191c1d82.ARN1dba@prolix.pub.uu.oz.au> dac@prolix.pub.uu.oz.au (Andrew Clayton) writes: >Unfortunately, Windows doesn't use the sort() library - it has >its OWN completely incompatible collating sequence that places >all punctuation and special symbols BEFORE letters, and all the >numerals AFTER letters. It's truly spasticated, and a real bitch >to work with. Grr. My God! That's just like EBCDIC! IBM is everywhere! Charlie_Gibbs@mindlink.bc.ca "I'm cursed with hair from HELL!" -- Night Court
limonce@pilot.njin.net (Tom Limoncelli +1 201 408 5389) (05/09/91)
In article <MWM.91May8182512@raven.pa.dec.com> mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes: > A closer-to-fair comparison would be to write your own quicksort for > sorting a fixed-size array of known object types. I cheated, and >[...] > comb-sort of 100000 elements: 42.46 seconds > qsort of 100000 elements: 27.12 seconds If you want to be even more closer-to-fair you wouldn't give results for only sorting one amount of numbers. You should really show a graph of how they work on 1000, 2000, 3000, 5000, 10000, 15000... (note the logorithmic increase) elements. Of course, if you want to be the most accurate (by computer theory standards) you wouldn't even run the program! You'd just figure the O() of the function. > In reality, I'll continue using qsort(), even though I can get faster > results by handcoded routines. When a profiled run of the code shows > that the serious delays are caused by the qsort, I'll change it to > something faster, and chosen for the problem at hand. I now do just about all my programming like that. I don't think I've written a new line of code in years. :-) -- Tom Limoncelli tlimonce@drew.edu tlimonce@drew.bitnet 201-408-5389 Three witches making a potion. One asks, "A Liza Minnelli record, light beer, poppers, Frye boots; what's this spell for anyway?"
bombadil@diku.dk (Kristian Nielsen) (05/09/91)
231b3678@fergvax.unl.edu (Phil Dietz) writes: >I was VERY amazed at the comb-sorts results. I ran the test on my system, and >you know what, comb-sort beat qsort by a heinous time! I sorted >a list of ints (100000 of them). I used the comb-sort routine directly >from the article, and I used qsort routine that comes with Lattice. > > sorting the same list of 100000 elements: qsort 165.3 secs > comb 53.2 secs > >This either shows that the comb-sort is FAST, or the Lattice Qsort is SLOW! >Yes 3 times faster! Here is the source code to compile on your system: >Keep in mind that I just threw this together....(wnat some spaghetti ? :-) > >Compile lc -Lm -O comb.c > if (atoi(argv[1])==1) > { > printf("Comb Sorting:\n"); > combsort(list,size); > } > else > { > printf("Q-Sorting\n"); > qsort(list,size,sizeof(int),sortfunct); > } > >int sortfunct(int *a, int *b) > { > if (*a>*b) return 1; > if (*a<*b) return -1; > return 0; > } Though this is not a claim of qsort being better that compsort (I really wouldn't know), it should be remarked that the above isn't really a fair way to compare the two algorithms. The reason is that the qsort function used is much more general than the compsort, being able to sort elements of any size and ordering. This introduces rather large overheads in the inner loops, since qsort has to make a function call for each compare, and perhaps also for each element swap (memcpy?). Combsort does all of this inline, optimised for a fixed size. How about rewriting compsort to be as general as qsort (caller-specified size and ordering-function), and posting the results? - Kristian.
hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) (05/10/91)
> In article <MWM.91May8182512@raven.pa.dec.com> mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes: > > > A closer-to-fair comparison would be to write your own quicksort for > > sorting a fixed-size array of known object types. I cheated, and > >[...] > > comb-sort of 100000 elements: 42.46 seconds > > qsort of 100000 elements: 27.12 seconds > > If you want to be even more closer-to-fair you wouldn't give results > for only sorting one amount of numbers. You should really show a > graph of how they work on 1000, 2000, 3000, 5000, 10000, 15000... (note > the logorithmic increase) elements. > > Of course, if you want to be the most accurate (by computer theory > standards) you wouldn't even run the program! You'd just figure the > O() of the function. ^^^^^^ Perhaps you know, that there is a computer-theory-theorey proof, that no comparision-based sorting algorithm can run faster than O(n log n) which is a lower bound for sorting. Which bucket-sort you can even achieve O(n)! For details on this subject see U.Manber : 'Introduction to Algorithms' (Addison-Wesley ISBN 0-201-12037-2) Chapter 6.4.6 and D.E.Knuth : 'The Art of computer programming - sorting and searching' (Addison-Wesley ISBN unknown) In the articles you will see, that Quicksort ist the fastest comparision- based sorting algorithm on the average, but it may take O(n*n) in the worst case. Heapsort on the other side is guaranteed to sort in O(n log n), but in the average case it is slower than Quicksort. Quicksort's running time depends on the input an on it's implementation. Hope that helps ... -Heiko -- Heiko W.Rupp, Gerwigstr.5, D-7500 Karlsruhe 1 | hwr@pilhuhn.ka.sub.org Tel: +49 7021 693642 (voice only) | uk85@dkauni2.bitnet All opinions expressed are my own, but sometimes I don't know what I say Gruesse -Heiko -- Heiko W.Rupp, Gerwigstr.5, D-7500 Karlsruhe 1 | hwr@pilhuhn.ka.sub.org Tel: +49 7021 693642 (voice only) | uk85@dkauni2.bitnet All opinions expressed are my own, but sometimes I don't know what I say
allbery@NCoast.ORG (Brandon S. Allbery KB8JRR/AA) (05/10/91)
As quoted from <231b3678.673637576@fergvax> by 231b3678@fergvax.unl.edu (Phil Dietz): +--------------- | you know what, comb-sort beat qsort by a heinous time! I sorted | a list of ints (100000 of them). I used the comb-sort routine directly | from the article, and I used qsort routine that comes with Lattice. | | sorting the same list of 100000 elements: qsort 165.3 secs | comb 53.2 secs | | This either shows that the comb-sort is FAST, or the Lattice Qsort is SLOW! +--------------- If Lattice's qsort() is anything like the one in the Unix standard C library, it's a pretty good proof that any algorithm can be implemented to run as slow as you like. :-) :-( ++Brandon -- Me: Brandon S. Allbery Ham: KB8JRR/AA 10m,6m,2m,220,440,1.2 Internet: allbery@NCoast.ORG (restricted HF at present) Delphi: ALLBERY AMPR: kb8jrr.AmPR.ORG [44.70.4.88] uunet!usenet.ins.cwru.edu!ncoast!allbery KB8JRR @ WA8BXN.OH
pds@quintus.UUCP (Peter Schachte) (05/11/91)
In article <mjl.8698@alison.at> mjl@alison.at writes: > Following my docs, heapsort always does O(N ld N), while quicksort >is N ld N (best), N^2/2 (worst case), and 1.4 N ld N (average). There are lots of N log N sorts, so the constant factors start getting important in choosing. Also note that you need to consider both the number of comparisons as well as the number of exchanges. In fact, if you sort an array of pointers to records, exchanges are pretty cheap. And if your keys are strings rather than integers, comparisons are much more expensive. It's often more important to minimize the numer of comparisons rather than the number of exchanges. -- -Peter Schachte pds@quintus.com ...!{uunet,sun}!quintus!pds
krsear02@ulkyvx.bitnet (Kendall 'Opusii' Sears) (05/13/91)
[oh for a real reader!] >I saw it briefly and was thrilled that BYTE had finally discovered shellsort. >If it beats heapsort, though, I may be wrong. How does it work? > > -Colin This is exactly what I thought when I saw the article. It was sad though, I remember a time when BYTE was one of the first mags to publish new algs but now they seem to be re-publishing other peoples' articles; the 'shell-sort' was in a Compute! or Compute!'s Gazette (I don't remember which) way back when... Geez am I *THAT* old? Kendall. -- Kendall "Opusii" Sears KRSEAR02@ULKYVX.bitnet Programmer /// Child Development Unit /// Amiga Department of Pediatrics \\\/// Currently running AmigaOS 2.0 University of Louisville \XX/ And Supporting Unix Sys V Rev 4. --------------------------------------------------------------------------- "Numbness is bliss... I can't feel a thing." -me.
dvljrt@cs.umu.se (Joakim Rosqvist) (05/13/91)
In article <191d6f59.ARN12eb@pilhuhn.ka.sub.org> hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) writes: >> In article <MWM.91May8182512@raven.pa.dec.com> mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes: >> >> > A closer-to-fair comparison would be to write your own quicksort for >> > sorting a fixed-size array of known object types. I cheated, and >> >[...] >> > comb-sort of 100000 elements: 42.46 seconds >> > qsort of 100000 elements: 27.12 seconds >> >In the articles you will see, that Quicksort ist the fastest comparision- >based sorting algorithm on the average, but it may take O(n*n) in the Has anybody timed Quicksort in assembler? I just made a comb-sort that will sort 100000 integers in 18.5 sec /$DR.HEX$
peterk@cbmger.UUCP (Peter Kittel GERMANY) (05/14/91)
In article <1991May13.073134.330@ulkyvx.bitnet> krsear02@ulkyvx.bitnet (Kendall 'Opusii' Sears) writes: >[oh for a real reader!] > >>I saw it briefly and was thrilled that BYTE had finally discovered shellsort. >>If it beats heapsort, though, I may be wrong. How does it work? >> >> -Colin >This is exactly what I thought when I saw the article. It was sad though, >I remember a time when BYTE was one of the first mags to publish new algs >but now they seem to be re-publishing other peoples' articles; the >'shell-sort' was in a Compute! or Compute!'s Gazette (I don't remember which) >way back when... Geez am I *THAT* old? But if you read the article thoroughly, you'll find that the authors indeed know sell-sort and compare their algorithm to it, finding out that the two are more different than from first sight. Combsort appears to be much faster than shell-sort. -- Best regards, Dr. Peter Kittel // E-Mail to \\ Only my personal opinions... Commodore Frankfurt, Germany \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk
ttobler@unislc.uucp (Trent Tobler) (05/16/91)
From article <191d6f59.ARN12eb@pilhuhn.ka.sub.org>, by hwr@pilhuhn.ka.sub.org (Heiko W.Rupp): > >> Of course, if you want to be the most accurate (by computer theory >> standards) you wouldn't even run the program! You'd just figure the >> O() of the function. > ^^^^^^ > Perhaps you know, that there is a computer-theory-theorey proof, that no > comparision-based sorting algorithm can run faster than O(n log n) which > is a lower bound for sorting. That is correct. He was saying to calculate the time function of the comb sort compared to the quick sort. I believe the article stated that the comb-sort algorithem appeared to be an O(n*ln n) sort. In other words, as more elements are sorted, the ratio of time(quicksort)/time(combsort) remains constant. > Which bucket-sort you can even achieve O(n)! ^^^ is this suppost to be 'With'? And anyway, who can afford the memory with a bucket sort on any generic data? (Isn't the bucket sort the one where for each element, an integer is calculated which has the property such that A<B for items A and B, f(A) < f(B) holds; and then to do the sort, you simply increment the count of C[f(X)], and then reconstructing the list based on C?) > > In the articles you will see, that Quicksort ist the fastest comparision- > based sorting algorithm on the average, but it may take O(n*n) in the > worst case. No, there are sorts which are faster. > Heapsort on the other side is guaranteed to sort in O(n log n), > but in the average case it is slower than Quicksort. Quicksort's running > time depends on the input an on it's implementation. > Quicksort also uses additional memory. As N gets larger, the amount of memory above that contained in the array to sort grows by ln(N). Heapsort and combsort are both iteritive sorts, which means they use a constant amount of memory for any N. I have an algorithem based on the merge sort that runs about the same as quick sort on random lists, and runs even faster on near-sorted lists. It's problem is that its memory requirements grow by N/2. Of the sorts that I have tested, Quicksort tends to minimize the number of moves on elements, but requires. Combsort did about twice the number of moves as quicksort, and about the same number of compares. The m-sort I tested tended to minimize the number of comparisions, about 50% of that quicksort required, but required 100% more moves. Here is a table I constructed showing various sort statistics: Random Sorted Backward-Sorted 10 100 1000 10 100 1000 10 100 1000 bubble-sort compares 45 4872 499455 9 99 999 45 4950 499500 moves 78 7413 722256 0 0 0 135 14850 1498446 comb-sort compares 32 1096 19706 32 1096 19706 32 1096 19706 moves 30 801 12612 0 0 0 21 348 4596 heap-sort compares 39 1030 16878 41 1081 17570 35 944 15966 moves 62 1041 13920 74 1134 14677 53 910 12314 m-sort compares 29 603 9403 15 316 4932 28 455 6047 moves 34 777 12942 0 0 0 49 988 14887 quick-sort compares 35 861 14878 45 4950 499500 50 5000 500000 moves 24 365 5066 18 198 1998 23 248 2498 shell-sort compares 32 704 13985 15 342 5457 21 500 8541 moves 52 1089 19883 30 684 10914 43 914 14825 The algorithems used were bubble: compare neighbors, swap if out of order. comb: described in Byte, April 1991 heap: vanilla heap sort m-sort: 1) divide list in half. 2) If size of either half > 2, recursively sort it. 3) merge sort each half (they are each in order because of (2)) quick: vanilla quicksort shell-sort: 3n+1 shell sort --- Trent Tobler - ttobler@csulx.weber.edu
mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (05/18/91)
In article <1991May15.220144.27507@unislc.uucp> ttobler@unislc.uucp (Trent Tobler) writes: > Which bucket-sort you can even achieve O(n)! ^^^ is this suppost to be 'With'? And anyway, who can afford the memory with a bucket sort on any generic data? (Isn't the bucket sort the one where for each element, an integer is calculated which has the property such that A<B for items A and B, f(A) < f(B) holds; and then to do the sort, you simply increment the count of C[f(X)], and then reconstructing the list based on C?) Well, that's one form of bucket sort. For sorting generic data, it's probably better to do a multi-pass bucket sort, where you sort on one byte of the key on each pass. Net result is a sort that is O(keysize), for the total size of the keys (it can't be expressed cleanly in terms of the number of keys). With equal-size objects, this can be done in place. <mike -- Don't tell me how to live my life Mike Meyer Don't tell me what to do mwm@pa.dec.com Repression is always brought about decwrl!mwm by people with politics and attitudes like you.
andand@cia.docs.uu.se (Anders Andersson) (05/31/91)
In <1991May15.220144.27507@unislc.uucp> ttobler@unislc.uucp (Trent Tobler) writes: >From article <191d6f59.ARN12eb@pilhuhn.ka.sub.org>, by hwr@pilhuhn.ka.sub.org (Heiko W.Rupp): >> >>> Of course, if you want to be the most accurate (by computer theory >>> standards) you wouldn't even run the program! You'd just figure the >>> O() of the function. >> ^^^^^^ >> Perhaps you know, that there is a computer-theory-theorey proof, that no >> comparision-based sorting algorithm can run faster than O(n log n) which >> is a lower bound for sorting. >That is correct. He was saying to calculate the time function of the comb >sort compared to the quick sort. I believe the article stated that >the comb-sort algorithem appeared to be an O(n*ln n) sort. In other >words, as more elements are sorted, the ratio of time(quicksort)/time(combsort) >remains constant. Yes, I made a quick calculation that suggested that quicksort is 1.9 times faster. I tried to tell the world (or rather this newsgroup) but my message bounced. >> Which bucket-sort you can even achieve O(n)! > ^^^ is this suppost to be 'With'? >And anyway, who can afford the memory with a bucket sort on any generic data? >(Isn't the bucket sort the one where for each element, an integer is calculated > which has the property such that A<B for items A and B, f(A) < f(B) holds; and > then to do the sort, you simply increment the count of C[f(X)], and then > reconstructing the list based on C?) I'm not sure what bucket sort is, but radix sort is O(n) and it 'only' requires twice the memory (i.e. it needs a extra copy of the data). In a general application, you only sort pointers to data objects, so this isn't too bad. >> >> In the articles you will see, that Quicksort ist the fastest comparision- >> based sorting algorithm on the average, but it may take O(n*n) in the >> worst case. >No, there are sorts which are faster. It all depends on what data you are sorting. Quicksort usually beets other sorts hands down in tests, mostly because it has a extremly short inner loop. This is a great advantage when sorting an array of integers or something, but not equally important in practice when each compare is associated with some overhead. [stuff deleted] >Of the sorts that I have tested, Quicksort tends to minimize the number of >moves on elements, but requires. Combsort did about twice the number of >moves as quicksort, and about the same number of compares. The m-sort I ^^^^^^^^^^^^^^^^^^^^^^^ >tested tended to minimize the number of comparisions, about 50% of that >quicksort required, but required 100% more moves. That's strange. Acording to my sources on quicksort and my own calculations of combsort, combsort should require 1.9 times as many compares. I might have missed something, but I can't imagine what. I should be able to count my way through nested loops... [stuff deleted] -Anders Andersson (andand@cia.docs.uu.se)
hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) (06/04/91)
In article <andand.675707397@cia.docs.uu.se>, Anders Andersson writes: > In <1991May15.220144.27507@unislc.uucp> ttobler@unislc.uucp (Trent Tobler) writes: > > >From article <191d6f59.ARN12eb@pilhuhn.ka.sub.org>, by hwr@pilhuhn.ka.sub.org (Heiko W.Rupp): > > [..] > >> Which bucket-sort you can even achieve O(n)! > > ^^^ is this suppost to be 'With'? Yup ! > > > I'm not sure what bucket sort is, but radix sort is O(n) and it 'only' requires > twice the memory (i.e. it needs a extra copy of the data). In a general application, > you only sort pointers to data objects, so this isn't too bad. Bucketsort: Imagine that You have 50 States. Bucket sort means now sorting the letters according to the name of the State in one of 50 Boxes (or Buckets) labeled with the name of the State. Going once through the data costs O(n); adding an element to the head of the list costs O(1) -> You get linear (O(n)) running time. Gruesse -Heiko -- Heiko W.Rupp, Gerwigstr.5, D-7500 Karlsruhe 1 | hwr@pilhuhn.ka.sub.org Tel: +49 7021 693642 (voice only) | uk85@dkauni2.bitnet They say that killing a shopkeeper brings bad luck.
ttobler@unislc.uucp (Trent Tobler) (06/04/91)
From article <andand.675707397@cia.docs.uu.se>, by andand@cia.docs.uu.se (Anders Andersson): >>No, there are sorts which are faster. > > It all depends on what data you are sorting. Quicksort usually beets > other sorts hands down in tests, mostly because it has a extremly short inner > loop. This is a great advantage when sorting an array of integers or something, > but not equally important in practice when each compare is associated with some > overhead. There are actually sorts that beat quicksort on all data of a certain size of greater (they are quite complex, can't remember there names right now.) >>Of the sorts that I have tested, Quicksort tends to minimize the number of >>moves on elements, but requires. Combsort did about twice the number of >>moves as quicksort, and about the same number of compares. The m-sort I > ^^^^^^^^^^^^^^^^^^^^^^^ >>tested tended to minimize the number of comparisions, about 50% of that >>quicksort required, but required 100% more moves. > > That's strange. Acording to my sources on quicksort and my own calculations > of combsort, combsort should require 1.9 times as many compares. I might have Well, combsort requires about twice the moves, and about the same number of compares, so if q-sort requires 15000 compares, and 5000 moves, then that is 20000 operations. The corresponding comb-sort would require 20000 compares, and would require 13000 moves, so that would mean 33000 operations; comb-sort is slower by about 1.65 times if compares and moves take about the same amount of time. Again, the main advantage (as I see it) of the comb-sort is that it's memory requirements are constant for ANY array. (true, quick-sort only requires ln(N)+C units of additional memory, which is not a lot) > -Anders Andersson (andand@cia.docs.uu.se) -- Trent Tobler - ttobler@csulx.weber.edu
tdsmith@oasys.dt.navy.mil (Timothy Smith) (06/07/91)
In article <193e8efd.ARN1453@pilhuhn.ka.sub.org> hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) writes: >Imagine that You have 50 States. Bucket sort means now sorting the letters >according to the name of the State in one of 50 Boxes (or Buckets) labeled >with the name of the State. Going once through the data costs O(n); adding >an element to the head of the list costs O(1) -> You get linear (O(n)) running >time. What? Start with an unsorted list of n objects (or pointers to objects, same thing...) Is there a sort algorithm which is o(n)? If so, use it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! Tim
tdsmith@oasys.dt.navy.mil (Timothy Smith) (06/07/91)
>it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! er, with only 7 "reads". Sorry about the second posting. >Tim
231b3678@fergvax.unl.edu (Phil Dietz) (06/07/91)
In <8236@oasys.dt.navy.mil> tdsmith@oasys.dt.navy.mil (Timothy Smith) writes: >>it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! >er, with only 7 "reads". Sorry about the second posting. >>Tim Simply use a hash function of f(x) = x The only way a bucket sort can work is to know ahead of schedule, how many buckets will be needed. From the example above, I'm assuming that there are at least 55 buckets...all initialized to some null value. When you get 23, simply toggle bit 23 or set array[23] to 1 etc. etc. When you hit 10, you are done with the list and they are all sorted (you must skip NULLS when printing). Hash functions are very nice, but they many limitations... ---- Quote #4 Phil Dietz " " 231b3678@fergvax.unl.edu -- Invisible Man University of Nebraska
staale@stud.cs.uit.no (Staale Schwenke) (06/07/91)
In article <8235@oasys.dt.navy.mil>, tdsmith@oasys.dt.navy.mil (Timothy Smith) writes: |> In article <193e8efd.ARN1453@pilhuhn.ka.sub.org> hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) writes: |> >Imagine that You have 50 States. Bucket sort means now sorting the letters |> >according to the name of the State in one of 50 Boxes (or Buckets) labeled |> >with the name of the State. Going once through the data costs O(n); adding |> >an element to the head of the list costs O(1) -> You get linear (O(n)) running |> >time. |> |> What? Start with an unsorted list of n objects (or pointers to objects, |> same thing...) Is there a sort algorithm which is o(n)? If so, use |> it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! |> ^^^^^ |> Tim Hm.. Reads Assuming , like in the original example, you have a finite number of different keys e.g. 0-100, this could be done by going once through the data. Based on the value each number would be moved into a bucket. (F.ex. an array [0..100] if identical keys were not allowed). -- ------------------------------------------------------------------------ Staale Schwenke E-mail: staale@stud.cs.uit.no ------------------------------------------------------------------------
ttobler@unislc.uucp (Trent Tobler) (06/14/91)
From article <8235@oasys.dt.navy.mil>, by tdsmith@oasys.dt.navy.mil (Timothy Smith): > In article <193e8efd.ARN1453@pilhuhn.ka.sub.org> hwr@pilhuhn.ka.sub.org (Heiko W.Rupp) writes: >>Imagine that You have 50 States. Bucket sort means now sorting the letters >>according to the name of the State in one of 50 Boxes (or Buckets) labeled >>with the name of the State. Going once through the data costs O(n); adding >>an element to the head of the list costs O(1) -> You get linear (O(n)) running >>time. > > What? Start with an unsorted list of n objects (or pointers to objects, > same thing...) Is there a sort algorithm which is o(n)? If so, use > it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! > Except than o(n) does not mean n moves. o(n) means it takes exactly k*n with k constant. In your example, suppose the numbers are in the range of 0-255. One o(n) sort that I can think of goes like this. We have an array of 256 elements labeled A(x) which can hold a range of 0 up to the maximum size of an array we wish to sort. To sort, simply initialize this array to all 0, then for each item to sort, increment to corresponding element. For the example you give, A(x) would be A(0)=0, A(1)=0, ..., A(9)=1, A(10)=1, A(11)=1, ... A(254)=0, A(255)=0 Then, go though this array, starting from 0 and working to 256, and store A(x) x's into the original array, ie.. no 0's, no 1's, ..., one 9, one 10, one 11, ... no 254's, no 255's. and you have the original array, sorted. ( 9 10 11 12 23 41 55 ) This method takes 2 * 256 + 2 * n steps. In otherwords, it is o(n) -- Trent Tobler - ttobler@csulx.weber.edu
tdsmith@oasys.dt.navy.mil (Timothy Smith) (06/14/91)
In article <1991Jun13.175106.6902@unislc.uucp> ttobler@unislc.uucp (Trent Tobler) writes: >From article <8235@oasys.dt.navy.mil>, by tdsmith@oasys.dt.navy.mil (Timothy Sm >ith): >> >> Start with an unsorted list of n objects (or pointers to objects, >> same thing...) Is there a sort algorithm which is o(n)? If so, use >> it to sort (23 41 55 12 11 9 10) with only 7 moves. I'm skeptical! >> >Except than o(n) does not mean n moves. o(n) means it takes exactly >k*n with k constant. Oops! Guess I was typing a bit too quickly. In your example, suppose the numbers are in the range >of 0-255. One o(n) sort that I can think of goes like this. > > We have an array of 256 elements labeled A(x) which can hold a range of >0 up to the maximum size of an array we wish to sort... {...stuff...} >Then, go though this array, starting from 0 and working to 256, and >store A(x) x's into the original array, ie.. {...more stuff...} >This method takes 2 * 256 + 2 * n steps. In otherwords, it is o(n) > >-- > Trent Tobler - ttobler@csulx.weber.edu Let m be the number of buckets. I get O(2*m+2*n) => O(m+n) => O(max(m,n)) => max(O(n),O(m)) The problem as I see it is that the bucket range has to be defined ahead of time. For reccuring problems this is fine, since m can be fixed. But for arbitrary problems it is not so clear. For example, sorting (3 1 2) can be done with 3 buckets, but (10,000 1 2) requires 10,000 buckets. Are both problems O(3)? In theory, yes. In practice, no. A key variable has been neglected. For real numbers m is infinite. I conclude combsort is not a general purpose sorting algorithm, just a special case integer sort over a finite set of input possibilities. In THEORY combsort is O(n), but theory sometimes has little relation to practicality. If m is O(n) then the sort is O(n), otherwise the analysis is misleading. If m >> n then combsort is O(1)! AND, if m >> n^2 then selection sort wil beat it, even though selection sort is O(n^2)! I bring this up because this isn't comp.theory, so O(n) could be taken out of context. - Complexity is not a quantitative measure of utility between algorithms, it is a qualitatively estimate of the time for different sized runs with the same algorithm. - Two algorithms with the same complexity may have run times that differ by orders of magnitude. - Complexity claims are sensitive to how the problem is posed. Sometimes the worst case complexity is quoted, sometimes the average, and sometimes the most likely. This becomes a problem when the worst case for one is compared with the average for another. - There are no general purpose sorts which do better than O(n*logn). - There are some special purpose integer sorts that are O(n). - If the input domain is restricted to n << m combsort becomes O(1), i.e. runs in constant time. It also becomes a very inefficient algorithm. (for the above example, bubblesort uses aprox 4 moves to sort (10,000 2 1), combsort uses aprox 20,000 moves. On (10,000 5,000 4 3 2 1), a problem which is twice as big, bublesort uses aprox 25 moves, combsort 20,000.) Tim Smith
mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (06/16/91)
In article <8454@oasys.dt.navy.mil> tdsmith@oasys.dt.navy.mil (Timothy Smith) writes:
The problem as I see it is that the bucket range has to be defined
ahead of time. For reccuring problems this is fine, since m can be
fixed. But for arbitrary problems it is not so clear.
Yup, but there's a way around that. Choose some convenient size chunk,
and combsort the high-order chunk of that size in each key. You've
just partitioned the elements so that each element is in the partition
it will be in when correctly sorted. Sort each bucket by the second
chunk in the keys, producing a second level of buckets. Continue down
the keys until either the buckets are singleton sets, or you run out
of key (at which time all the keys in any bucket will be equal). The
net result is that you've looked at each chunk a fixed number of times
(once if you do it BFI, a few more if you finesse it).
For real numbers m is infinite. I conclude combsort is not a general
purpose sorting algorithm, just a special case integer sort over a finite
set of input possibilities.
Well, the above outlines a variant of combsort that applies to
arbitrary keys. It's generally known as a "radix sort". For most
computers (like an Amiga), "bytes" are the obvious convenient size
chunk. That's what the implementation I've got uses.
IN THEORY combsort is O(n), but theory sometimes has little relation to
practicality.
In theory, a radix sort is O(c), where c is the number of chunks. A
combsort is a radixsort where c is the key size. This isn't practical
for all keys. However, choosing a practical chunk size is always
possible, and the resulting implementation works.
- There are no general purpose sorts which do better than O(n*logn).
False. See the above. It's a general purpose algorithm, and it's
always better (in the theoretical sense) than O(n*logn).
<mike
--
Kiss me with your mouth. Mike Meyer
Your love is better than wine. mwm@pa.dec.com
But wine is all I have. decwrl!mwm
Will your love ever be mine?
GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) (06/18/91)
>> - There are no general purpose sorts which do better than O(n*logn). >False. See the above. It's a general purpose algorithm, and it's >always better (in the theoretical sense) than O(n*logn). We have seen this year (I just did my exam for it last week) that there is no GENERAL sorting algorithm which is better than O(n*logn) We have also seen the proof to this theorem but I'm not going to repeat it here since I forgot it :-) It has something to do with sort trees. By GENERAL I mean that the algorithm must be able to sort anything (including things with variable length (which can of course be forced if you extend all items to the same maximum length)).
nj@magnolia.Berkeley.EDU (Narciso Jaramillo) (06/19/91)
In article <91169.133303GUTEST8@cc1.kuleuven.ac.be> GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) writes:
We have seen this year (I just did my exam for it last week) that there
is no GENERAL sorting algorithm which is better than O(n*logn)
By GENERAL I mean that the algorithm must be able to sort anything
(including things with variable length (which can of course be
forced if you extend all items to the same maximum length)).
To be more precise, the theorem holds only for algorithms which sort
by comparing keys to each other. These algorithms rely only on the
keys being linearly ordered, and the ability to do one comparison in
O(1) time. Algorithms like Radix Sort make extra assumptions about
the keys (in this case, that they are numbers and can be broken up
into digits), and thus can achieve better worst case complexity (but
at the cost of extra space utilization in this case).
nj
mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (06/19/91)
In article <NJ.91Jun18111231@magnolia.Berkeley.EDU> nj@magnolia.Berkeley.EDU (Narciso Jaramillo) writes: In article <91169.133303GUTEST8@cc1.kuleuven.ac.be> GUTEST8@cc1.kuleuven.ac.be (Ives Aerts) writes: We have seen this year (I just did my exam for it last week) that there is no GENERAL sorting algorithm which is better than O(n*logn) By GENERAL I mean that the algorithm must be able to sort anything (including things with variable length (which can of course be forced if you extend all items to the same maximum length)). To be more precise, the theorem holds only for algorithms which sort by comparing keys to each other. These algorithms rely only on the keys being linearly ordered, and the ability to do one comparison in O(1) time. Algorithms like Radix Sort make extra assumptions about the keys (in this case, that they are numbers and can be broken up into digits), and thus can achieve better worst case complexity (but at the cost of extra space utilization in this case). Actually, the radix sort assumption is slightly more general than that. It assumes that you can address "subkeys" that are small enough to be bucket sorted on your machine. This assumption is true for any octet addressable machine with more than a few K octets of ram. Note that a fully general implementation inside of those constraints requires that you allow specification of the order to sort subkeys (e.g. - byte 3, then byte 1, then byte 2, then byte 0), as well as an ordering on each subkey (e.g. - for each subkey, you provide a lookup table that gives the sort order for that subkey). <mike -- And then up spoke his own dear wife, Mike Meyer Never heard to speak so free. mwm@pa.dec.com "I'd rather a kiss from dead Matty's lips, decwrl!mwm Than you or your finery."