Normal quotes
This commit is contained in:
parent
5e10794a24
commit
18011c595a
352 changed files with 6040 additions and 6040 deletions
50
18-05.md
50
18-05.md
|
|
@ -2,21 +2,21 @@
|
|||
[Previous](18-04.html) [Table of Contents](index.html) [Next](19-01.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
“The basic idea is to maintain a ‘change list.’ This is an array of
|
||||
"The basic idea is to maintain a ‘change list.' This is an array of
|
||||
pointers into the cell array. Each change list element points to a word
|
||||
which changes in the next generation. This way we don’t have to waste
|
||||
which changes in the next generation. This way we don't have to waste
|
||||
time scanning every cell since most of them do not change. Two passes
|
||||
are made through the change list. The first pass updates the cell
|
||||
display on the screen, sets the life/death status of each cell for this
|
||||
new generation, and updates the neighbor counts for the adjacent cells.
|
||||
There are some efficiencies gained by using cell triplets rather than
|
||||
individual cells since we usually don’t need to set all eight neighbors.
|
||||
individual cells since we usually don't need to set all eight neighbors.
|
||||
[Again, the neighbor counts for cells in the same word are implied by
|
||||
the states of those cells.] The second pass sets the next-generation
|
||||
states for the cells and their neighbors, and in the process builds the
|
||||
change list for the next generation.
|
||||
|
||||
“Processing each word is a little complex but very fast. A 64K block of
|
||||
"Processing each word is a little complex but very fast. A 64K block of
|
||||
code exists with routines on each 256-byte boundary. Generally speaking,
|
||||
the entry point corresponds to the high byte of the cell word. This byte
|
||||
contains the life/death values and a bit to indicate if this is an edge
|
||||
|
|
@ -27,31 +27,31 @@ to that address. [Therefore, there are 128 possible jump targets on the
|
|||
first pass, and 128 more on the second, all on 256-byte boundaries and
|
||||
all keyed off the high 7 bits of the cell triplet state; because bit 8
|
||||
of the jump index is 0 on the first pass and 1 on the second, there is
|
||||
no conflict. The lower bit isn’t needed for other purposes because only
|
||||
no conflict. The lower bit isn't needed for other purposes because only
|
||||
the edge flag bit and the six life/death state bits matter for jumping
|
||||
into David’s state machine. The other nine bits, the bits used for the
|
||||
into David's state machine. The other nine bits, the bits used for the
|
||||
neighbor counts, are used only in the next step.]
|
||||
|
||||
“Determining which changes must be made to a cell triplet is easy and
|
||||
surprisingly quick. There’s no counting! Instead, I use a 64K lookup
|
||||
"Determining which changes must be made to a cell triplet is easy and
|
||||
surprisingly quick. There's no counting! Instead, I use a 64K lookup
|
||||
table indexed by the cell triplet itself. The value of the lookup table
|
||||
entry is equal to what the high byte should be in the next generation.
|
||||
If this value is equal to the current high byte, then no changes are
|
||||
necessary to the cell. Otherwise it is placed in the change list. Look
|
||||
at the code in the **Test()** and **Fix()** functions to see how this is
|
||||
done.” [This step is as important as it is obscure. David has a 64K
|
||||
done." [This step is as important as it is obscure. David has a 64K
|
||||
table organized so that if you use a word describing a cell triplet as a
|
||||
lookup index, the byte you will read will be the state of the high byte
|
||||
for the next generation. In other words, David’s table is constructed so
|
||||
for the next generation. In other words, David's table is constructed so
|
||||
that the edge flag bit, the life/death states, and the three neighbor
|
||||
count fields form an index to a byte describing the next generation
|
||||
state for that triplet. In practice, only the next generation field of
|
||||
the cell changes. Then, if another change to a nearby cell tries to
|
||||
nudge that cell into changing again, David’s code sees that the desired
|
||||
nudge that cell into changing again, David's code sees that the desired
|
||||
state is already set, and does not add that cell to the change list
|
||||
again.]
|
||||
|
||||
Segment usage in David’s assembly code is summarized in Listing 18.6.
|
||||
Segment usage in David's assembly code is summarized in Listing 18.6.
|
||||
|
||||
**LISTING 18.6 QLIFE Assembly Segment Usage**
|
||||
|
||||
|
|
@ -62,12 +62,12 @@ Segment usage in David’s assembly code is summarized in Listing 18.6.
|
|||
FS : Video segment
|
||||
GS : Unused
|
||||
|
||||
#### A Layperson’s Overview of QLIFE {#Heading6}
|
||||
#### A Layperson's Overview of QLIFE {#Heading6}
|
||||
|
||||
Most likely, you’re scratching your head right now in bemusement. I
|
||||
don’t blame you; I felt the same way myself at first. It’s actually
|
||||
Most likely, you're scratching your head right now in bemusement. I
|
||||
don't blame you; I felt the same way myself at first. It's actually
|
||||
pretty simple, though, once you have the hang of it. Basically, David
|
||||
runs down the change list, visiting every cell that’s due to change in
|
||||
runs down the change list, visiting every cell that's due to change in
|
||||
this generation, setting it to the new state, drawing it in the new
|
||||
state, and adjusting the counts of all its neighbors. David has a
|
||||
separate assembly routine for every possible change of state for a cell
|
||||
|
|
@ -83,8 +83,8 @@ David looks at that triplet and all affected neighbors to see which will
|
|||
change in the next generation. He tests for this condition by using each
|
||||
potentially changed cell triplet word as an index into the
|
||||
aforementioned lookup table of new states. If the current state matches
|
||||
the appropriate state for the next generation, then there’s nothing to
|
||||
do and the cell is not added to the change list. If the states don’t
|
||||
the appropriate state for the next generation, then there's nothing to
|
||||
do and the cell is not added to the change list. If the states don't
|
||||
match, then the cell is added to the change list, and the appropriate
|
||||
state for the next generation is set in the cell triplet. David checks
|
||||
the minimum possible number of cells for change by branching to code
|
||||
|
|
@ -101,18 +101,18 @@ the desired result—just three instructions:
|
|||
|
||||
These suffice to select the proper, minimum-work code to process the
|
||||
next cell triplet that has changed, and all potentially affected
|
||||
neighbors. For all the size of David’s code, it has an astonishing
|
||||
neighbors. For all the size of David's code, it has an astonishing
|
||||
economy of effort, as execution glides through the change list without a
|
||||
wasted instruction.
|
||||
|
||||
Alas, I don’t have the room to discuss Peter Klerings’ equally
|
||||
remarkable Life implementation here. I’ll close this chapter with a
|
||||
Alas, I don't have the room to discuss Peter Klerings' equally
|
||||
remarkable Life implementation here. I'll close this chapter with a
|
||||
quote from Terje Mathisen, one of the finest optimizers it has ever been
|
||||
my pleasure to meet, who, after looking over David’s and Peter’s
|
||||
entries, said, “This has been an eye-opening experience for me. I
|
||||
honestly thought I had the fastest possible approach.” TANSTATFC.
|
||||
my pleasure to meet, who, after looking over David's and Peter's
|
||||
entries, said, "This has been an eye-opening experience for me. I
|
||||
honestly thought I had the fastest possible approach." TANSTATFC.
|
||||
|
||||
There Ain’t No Such Thing As the Fastest Code.
|
||||
There Ain't No Such Thing As the Fastest Code.
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](18-04.html) [Table of Contents](index.html) [Next](19-01.html)
|
||||
|
|
|
|||
Loading…
Reference in a new issue