Replace invalid characters with HTML entities
— with — ’ with ’ + with + × with x ç with ç “ with “ ” with ” ‘ with ‘ • with • – with - µ with µ † with † Fix C++ θ with θ Yen symbol instead of times Fix broken apos Bullet again E-circumflex
This commit is contained in:
parent
9e52de9586
commit
500e7f5654
353 changed files with 5091 additions and 5091 deletions
60
17-04.html
60
17-04.html
|
|
@ -36,16 +36,16 @@
|
|||
</TABLE>
|
||||
</CENTER>
|
||||
<P><BR></P>
|
||||
<P>There’s a kicker here, though, and that’s the counting of neighbors for cells at the edge of the cellmap. When cellmap wrapping is enabled (so that the cellmap becomes essentially a toroid, with each edge joined seamlessly to the opposite edge, as opposed to having a border of off-cells), neighbors that reside on the other edge of the cellmap can’t be accessed by the standard fixed offset, as shown in Figure 17.1. So, in general, we could improve performance by hard-wiring our neighbor-counting for the bit-per-cell cellmap format, but it seems we’d need a lot of conditional code to handle wrapping, and that would slow things back down again.
|
||||
<P>There’s a kicker here, though, and that’s the counting of neighbors for cells at the edge of the cellmap. When cellmap wrapping is enabled (so that the cellmap becomes essentially a toroid, with each edge joined seamlessly to the opposite edge, as opposed to having a border of off-cells), neighbors that reside on the other edge of the cellmap can’t be accessed by the standard fixed offset, as shown in Figure 17.1. So, in general, we could improve performance by hard-wiring our neighbor-counting for the bit-per-cell cellmap format, but it seems we’d need a lot of conditional code to handle wrapping, and that would slow things back down again.
|
||||
</P>
|
||||
<P><A NAME="Fig1"><!-- </A><A HREF="javascript:displayWindow('images/17-01.jpg',408,258 )"> --><IMG SRC="images/17-01.jpg"><BR><!-- </A>
|
||||
<BR><A HREF="javascript:displayWindow('images/17-01.jpg',408,258)"> --><FONT COLOR="#000077"><B>Figure 17.1</B></FONT></A> <I>Edge-wrapping complications.</I>
|
||||
</P>
|
||||
<P>When a problem doesn’t lend itself well to optimization, make it a practice to see if you can change the problem definition to one that allows for greater efficiency. In this case, we’ll change the problem by putting padding bytes around the edge of the cellmap, and duplicating each edge of the cellmap in the padding bytes at the opposite side, as shown in Figure 17.2. That way, a hard-wired neighbor count will find exactly what it should—the opposite edge—without any special code at all.
|
||||
<P>When a problem doesn’t lend itself well to optimization, make it a practice to see if you can change the problem definition to one that allows for greater efficiency. In this case, we’ll change the problem by putting padding bytes around the edge of the cellmap, and duplicating each edge of the cellmap in the padding bytes at the opposite side, as shown in Figure 17.2. That way, a hard-wired neighbor count will find exactly what it should—the opposite edge—without any special code at all.
|
||||
</P>
|
||||
<P>But doesn’t that extra copying of the edges take time? Sure, but only a little; we can build it into the cellmap copying function, and then frankly we won’t even notice it. Avoiding tens or hundreds of thousands of calls to <B>cell_state(),</B> on the other hand, will be <I>very</I> noticeable. Listing 17.3 shows the alterations to Listing 17.1 required to implement a hard-wired neighbor-counting function. This is a minor change, in truth, implemented in about half an hour and not making the code significantly larger—but Listing 17.3 is 3.6 times faster than Listing 17.1, as shown in Table 17.1. We’re up to about 10 generations per second on a 486; not where we want to be, but it is a vast improvement.</P>
|
||||
<P>But doesn’t that extra copying of the edges take time? Sure, but only a little; we can build it into the cellmap copying function, and then frankly we won’t even notice it. Avoiding tens or hundreds of thousands of calls to <B>cell_state(),</B> on the other hand, will be <I>very</I> noticeable. Listing 17.3 shows the alterations to Listing 17.1 required to implement a hard-wired neighbor-counting function. This is a minor change, in truth, implemented in about half an hour and not making the code significantly larger—but Listing 17.3 is 3.6 times faster than Listing 17.1, as shown in Table 17.1. We’re up to about 10 generations per second on a 486; not where we want to be, but it is a vast improvement.</P>
|
||||
<P><A NAME="Fig2"><!-- </A><A HREF="javascript:displayWindow('images/17-02.jpg',407,260 )"> --><IMG SRC="images/17-02.jpg"><BR><!-- </A>
|
||||
<BR><A HREF="javascript:displayWindow('images/17-02.jpg',407,260)"> --><FONT COLOR="#000077"><B>Figure 17.2</B></FONT></A> <I>The “padding cells” solution.</I>
|
||||
<BR><A HREF="javascript:displayWindow('images/17-02.jpg',407,260)"> --><FONT COLOR="#000077"><B>Figure 17.2</B></FONT></A> <I>The “padding cells” solution.</I>
|
||||
</P>
|
||||
<P><B>LISTING 17.3 L17-3.CPP</B></P>
|
||||
<!-- CODE //-->
|
||||
|
|
@ -78,16 +78,16 @@ public:
|
|||
cellmap::cellmap(unsigned int h, unsigned int w)
|
||||
{
|
||||
width = w;
|
||||
width_in_bytes = ((w + 7) / 8) + 2; // pad each side with
|
||||
width_in_bytes = ((w + 7) / 8) + 2; // pad each side with
|
||||
// 1 extra byte
|
||||
height = h;
|
||||
length_in_bytes = width_in_bytes * (h + 2); // pad top/bottom
|
||||
length_in_bytes = width_in_bytes * (h + 2); // pad top/bottom
|
||||
// with 1 extra byte
|
||||
cells = new unsigned char[length_in_bytes]; // cell storage
|
||||
memset(cells, 0, length_in_bytes); // clear all cells, to start
|
||||
}
|
||||
|
||||
/* Copies one cellmap’s cells to another cellmap. If wrapping is
|
||||
/* Copies one cellmap’s cells to another cellmap. If wrapping is
|
||||
enabled, copies edge (wrap) bytes into opposite padding bytes in
|
||||
source first, so that the padding bytes off each edge have the
|
||||
same values as would be found by wrapping around to the opposite
|
||||
|
|
@ -99,17 +99,17 @@ void cellmap::copy_cells(cellmap &sourcemap)
|
|||
|
||||
#if WRAP_EDGES
|
||||
// Copy left and right edges into padding bytes on right and left
|
||||
cell_ptr = sourcemap.cells + width_in_bytes;
|
||||
for (i=0; i<height; i++) {
|
||||
*cell_ptr = *(cell_ptr + width_in_bytes - 2);
|
||||
*(cell_ptr + width_in_bytes - 1) = *(cell_ptr + 1);
|
||||
cell_ptr += width_in_bytes;
|
||||
cell_ptr = sourcemap.cells + width_in_bytes;
|
||||
for (i=0; i<height; i++) {
|
||||
*cell_ptr = *(cell_ptr + width_in_bytes - 2);
|
||||
*(cell_ptr + width_in_bytes - 1) = *(cell_ptr + 1);
|
||||
cell_ptr += width_in_bytes;
|
||||
}
|
||||
// Copy top and bottom edges into padding bytes on bottom and top
|
||||
memcpy(sourcemap.cells, sourcemap.cells + length_in_bytes -
|
||||
memcpy(sourcemap.cells, sourcemap.cells + length_in_bytes -
|
||||
(width_in_bytes * 2), width_in_bytes);
|
||||
memcpy(sourcemap.cells + length_in_bytes - width_in_bytes,
|
||||
sourcemap.cells + width_in_bytes, width_in_bytes);
|
||||
memcpy(sourcemap.cells + length_in_bytes - width_in_bytes,
|
||||
sourcemap.cells + width_in_bytes, width_in_bytes);
|
||||
#endif
|
||||
// Copy all cells to the destination
|
||||
memcpy(cells, sourcemap.cells, length_in_bytes);
|
||||
|
|
@ -120,7 +120,7 @@ padding bytes around the cellmap. */
|
|||
void cellmap::set_cell(unsigned int x, unsigned int y)
|
||||
{
|
||||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
*(cell_ptr) |= 0x80 >> (x & 0x07);
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ to compensate for the padding bytes around the cell map. */
|
|||
void cellmap::clear_cell(unsigned int x, unsigned int y)
|
||||
{
|
||||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
*(cell_ptr) &= ~(0x80 >> (x & 0x07));
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ compensate for the padding bytes around
|
|||
int cellmap::cell_state(int x, int y)
|
||||
{
|
||||
unsigned char *cell_ptr =
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
cells + ((y + 1) * width_in_bytes) + ((x / 8) + 1);
|
||||
|
||||
return (*cell_ptr & (0x80 >> (x & 0x07))) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -154,36 +154,36 @@ int cellmap::count_neighbors(int x, int y)
|
|||
unsigned int neighbor_count;
|
||||
|
||||
// Point to upper left neighbor
|
||||
cell_ptr = cells + ((y * width_in_bytes) + ((x + 7) / 8));
|
||||
cell_ptr = cells + ((y * width_in_bytes) + ((x + 7) / 8));
|
||||
mask = 0x80 >> ((x - 1) & 0x07);
|
||||
// Count upper left neighbor
|
||||
neighbor_count = (*cell_ptr & mask) ? 1 : 0;
|
||||
// Count left neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower left neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
// Point to upper neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
cell_ptr++;
|
||||
}
|
||||
// Count upper neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count lower neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
// Point to upper right neighbor
|
||||
if ((mask >>= 1) == 0) {
|
||||
mask = 0x80;
|
||||
cell_ptr++;
|
||||
cell_ptr++;
|
||||
}
|
||||
// Count upper right neighbor
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
if ((*cell_ptr & mask)) neighbor_count++;
|
||||
// Count right neighbor
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + width_in_bytes) & mask)) neighbor_count++;
|
||||
// Count lower right neighbor
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
if ((*(cell_ptr + (width_in_bytes * 2)) & mask)) neighbor_count++;
|
||||
|
||||
return neighbor_count;
|
||||
}
|
||||
|
|
@ -194,8 +194,8 @@ void cellmap::next_generation(cellmap& next_map)
|
|||
{
|
||||
unsigned int x, y, neighbor_count;
|
||||
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
for (y=0; y<height; y++) {
|
||||
for (x=0; x<width; x++) {
|
||||
neighbor_count = count_neighbors(x, y);
|
||||
if (cell_state(x, y) == 1) {
|
||||
if ((neighbor_count != 2) && (neighbor_count != 3)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue