12.11Sorting. 4tH 4tH Forth compiler
تبلیغات
تبلیغات
CHAPTER 12. STANDARD LIBRARIES
You can also select the required version by calling it by name:
MSRandom . BSDRandom . cr
177
Are these randomizers very good? No, as a matter of fact, they are not. They are sufficient to power your occasional game, but for more serious applications they simply fall short.
That’s why 4tH also provides some very heavy duty randomizers, designed by randomizing expert George Marsaglia
6
. The first is gmkiss.4th. Note that although it provides a similar interface as random.4th, it is not a drop-in replacement, most significantly because it can return the full range of a cell value, including negative numbers. Another difference is that it takes four cell size values to initialize:
1234567890 987654321 12893467 1029384756 seed4!
As a matter of fact, it is built out of three different randomizers, which feed a fourth one.
You can call each and every one of these randomizers and set their registers individually.
R
ANDOMIZER
R
EGISTERS
CONG
SHR3
MWC x y z, w
T
YPE congruential
3-shift shift register multiply with carry
Table 12.2: gmkiss randomizers and their registers
All those randomizers combined results in the KISS random number generator, which is the randomizer that ”RANDOM” calls
7
.
If that still isn’t enough we got even a better one, gmskiss.4th, which is arguably one of the best randomizers in the world. This one uses a large amount of memory, so don’t use it for trivial tasks. It can return the full range of a cell value (including negative numbers) and takes three cell size values to initialize: include lib/gmskiss.4th
987654321 12893467 1029384756 seed3!
." Random number: " kiss . cr
If you don’t want to set the seed yourself, you can always call ”RANDOMIZE” instead.
This ”super KISS” implementation differs from the previous one because the ”multiply with carry” generator has now superlong periods (54767 ∗ 2
1337279
).
12.11
Sorting
Yes, 4tH can do that too. You just have to include qsort.4th (a ”quick sort” implementation) to make it all possible. It works pretty much like the sort routines you’ve seen in
C, which means you have to devise a word to compare two values. Note that qsort.4th
can only sort cell arrays. Setting it up is pretty simple. First you have to include it: include lib/qsort.4th
include lib/random.4th
6 http://en.wikipedia.org/wiki/George_Marsaglia
7
Unless you’ve included random.4th as well.
CHAPTER 12. STANDARD LIBRARIES 178
Then you have to create a word that returns a true flag when the second value on the stack is smaller than the top of the stack. In this example we will just compare two integers, so that is pretty easy:
: MyPrecedes < ; qsort.4th
creates a deferred word
8 called ”PRECEDES”. Now we have to assign our word to ”PRECEDES”, so that it is executed when ”PRECEDES” is called:
’ MyPrecedes is Precedes
That’s it! We’re ready to rock ’n roll now. Let’s set up a simple testing environment:
10 constant #elements
#elements array elements randomize
: InitElements #elements 0 do random elements i th ! loop ;
: ShowElements #elements 0 do elements i th @ . loop cr ;
This creates an array of ten elements, which is filled with random values by ”InitElements”.
”ShowElements” will show on screen what is stored there. The actual sort is straightforward: tell ”SORT” which array and how many elements there are to sort and you’re done:
: SortElements elements #elements sort ;
Now let’s put it all together:
InitElements
ShowElements
SortElements
ShowElements
It will initialize the array, show its contents, sort it and show it again. It will output something like this:
12717 6028 1389 31870 14234 15884 31062 14788 18186 149
149 1389 6028 12717 14234 14788 15884 18186 31062 31870
And what if these were string addresses? Well, ”SORT” would have sorted them too, from the lowest addresses up to the highest addresses, but that’s probably not what you meant.
You wanted to sort the actual strings, not just their addresses. Can 4tH do that too? Sure, you just got to create another ”PRECEDES” word. Something like this:
: SPrecedes >R COUNT R> COUNT COMPARE 0< ;
This will take the two values and treat them as strings. Now the strings are sorted, not just the addresses. Note that the strings themselves will not move in memory. The pointers move, the strings themselves don’t. This is a so-called ”address based sort”.
The 4tH library contains several sorting algorithms. There are two families: ”index based” and ”address based”. The first family can sort any array
9
, the second one only cell arrays, because fetching and exchanging is done within the library member itself.
Another difference is that the ”index based” family allows you to combine several different sorting algorithms within the same program, but also requires you to define your own element exchange word. You can also combine one member of the ”address based” family with the ”index based” family, as long as you handle your ”PRECEDES” definitions properly since they are not compatible.
8
See section 11.7.
9
Since it works with indexes, not addresses. Consequently, it is a bit slower in general.
دانلود
تبلیغات