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:
James Gregory 2013-12-30 12:50:32 +11:00
commit 500e7f5654
353 changed files with 5091 additions and 5091 deletions

View file

@ -37,11 +37,11 @@
</CENTER>
<P><BR></P>
<H3><A NAME="Heading4"></A><FONT COLOR="#000077">Table-Driven Magic</FONT></H3>
<P>David Stafford won my first Optimization Challenge by means of a huge look-up table and an incredible state machine driven by that table. The table didn&#146;t cause David&#146;s entry to exceed the line limit because David&#146;s submission included code to generate the table on the fly as part of the build process. David has done himself one better this time with his QLIFE program; not only does his build process generate a 64K table, but it also generates virtually all his code, consisting of 17,000-plus lines of assembly language spanning another 64K. What David has done is write the equivalent of a bitblt compiler for the Game of Life; one might in fact call it a Life compiler. What David&#146;s code generates is still a general-purpose program; it takes arbitrary seed values, and can run for an arbitrary number of generations, so it&#146;s not as if David simply hardwired the instructions to draw each successive screen. However, it&#146;s a general-purpose program that is exquisitely tailored to the task it needs to perform.
<P>David Stafford won my first Optimization Challenge by means of a huge look-up table and an incredible state machine driven by that table. The table didn&rsquo;t cause David&rsquo;s entry to exceed the line limit because David&rsquo;s submission included code to generate the table on the fly as part of the build process. David has done himself one better this time with his QLIFE program; not only does his build process generate a 64K table, but it also generates virtually all his code, consisting of 17,000-plus lines of assembly language spanning another 64K. What David has done is write the equivalent of a bitblt compiler for the Game of Life; one might in fact call it a Life compiler. What David&rsquo;s code generates is still a general-purpose program; it takes arbitrary seed values, and can run for an arbitrary number of generations, so it&rsquo;s not as if David simply hardwired the instructions to draw each successive screen. However, it&rsquo;s a general-purpose program that is exquisitely tailored to the task it needs to perform.
</P>
<P>All the pieces of QLIFE are shown in Listings 18.1 through 18.5, as follows: Listing 18.1 is BUILD.BAT, the batch file used to build QLIFE; Listing 18.2 is LCOMP.C, the program used to generate the assembler code and data file QLIFE.ASM; Listing 18.3 is MAIN.C, the main program for QLIFE; Listing 18.4 is VIDEO.C, the video-related functions, and Listing 18.5 is LIFE.H, the header file. The following sidebar contains David&#146;s build instructions, exactly as he wrote them. I certainly won&#146;t have room to discuss all the marvelous intricacies of David&#146;s code; I suggest you look over these listings until you understand them thoroughly (it took me a day to pick them apart) because there&#146;s a lot of neat stuff in there, and it&#146;s an approach to performance programming that operates at a more efficient, tightly integrated level than you may ever see again. One hint: It helps a <I>lot</I> to build and run LCOMP.C, redirect its output to QLIFE.ASM, and look at the assembly code in that file. This code is the entirety of David&#146;s generation engine, and it&#146;s almost impossible to visualize its operation without actually seeing it.</P>
<P>All the pieces of QLIFE are shown in Listings 18.1 through 18.5, as follows: Listing 18.1 is BUILD.BAT, the batch file used to build QLIFE; Listing 18.2 is LCOMP.C, the program used to generate the assembler code and data file QLIFE.ASM; Listing 18.3 is MAIN.C, the main program for QLIFE; Listing 18.4 is VIDEO.C, the video-related functions, and Listing 18.5 is LIFE.H, the header file. The following sidebar contains David&rsquo;s build instructions, exactly as he wrote them. I certainly won&rsquo;t have room to discuss all the marvelous intricacies of David&rsquo;s code; I suggest you look over these listings until you understand them thoroughly (it took me a day to pick them apart) because there&rsquo;s a lot of neat stuff in there, and it&rsquo;s an approach to performance programming that operates at a more efficient, tightly integrated level than you may ever see again. One hint: It helps a <I>lot</I> to build and run LCOMP.C, redirect its output to QLIFE.ASM, and look at the assembly code in that file. This code is the entirety of David&rsquo;s generation engine, and it&rsquo;s almost impossible to visualize its operation without actually seeing it.</P>
<BLOCKQUOTE>
<P><FONT SIZE="-1"><HR>How To Build Qlife<P>QLIFE is written for Borland C<SMALL>&#43;&#43;</SMALL>, but it shouldn&#146;t be too difficult to convert it to work with Microsoft C<SMALL>&#43;&#43;</SMALL>. To build QLIFE, run the BUILD.BAT batch file with the size of the life grid on the command line (see below). The command-line options are:</P>
<P><FONT SIZE="-1"><HR>How To Build Qlife<P>QLIFE is written for Borland C<SMALL>++</SMALL>, but it shouldn&rsquo;t be too difficult to convert it to work with Microsoft C<SMALL>++</SMALL>. To build QLIFE, run the BUILD.BAT batch file with the size of the life grid on the command line (see below). The command-line options are:</P>
<TABLE WIDTH="100%"><TD WIDTH="3%">
<TD WIDTH="15%" ALIGN="LEFT" VALIGN="TOP"><SMALL>WIDTH 32</SMALL>
<TD ALIGN="LEFT" VALIGN="TOP"><SMALL>Sets the width of the life grid to 96 cells (divided by 3)</SMALL>.
@ -62,11 +62,11 @@
<TD ALIGN="LEFT" VALIGN="TOP"><SMALL>GEN 1000</SMALL>
<TD ALIGN="LEFT" VALIGN="TOP"><SMALL>Calculates 1,000 generations (optional)</SMALL>.
</TABLE>
<P>These <I>must</I> be in uppercase. For example, the minimum you really need is &#147;WIDTH 40 HEIGHT 120.&#148; I used &#147;WIDTH 46 HEIGHT 138 NOCOUNTER NODRAW GEN 7000&#148; during testing.</P>
<P>If you have selected the GEN option, you will have to press a key to exit QLIFE when it is finished. This is so I could visually compare the result of N generations under QLIFE with N generations under Abrash&#146;s original life program. You should be aware that the program from the listing contains a small bug, which may make it appear that they do not generate identical results. The original program does not display a cell until it changes, so if a cell is alive on the first generation and never dies, then it will never be displayed. This bug is not present in QLIFE.</P>
<P>You should have no trouble running QLIFE with cell grids up to 210&#215;200.</P>
<P>You <I>must</I> have a VGA and at least a 386 to run QLIFE. The 386 features that it uses are not integral to the algorithm (they&#146;re a convenience for the code), so feel free to modify QLIFE to run on earlier CPUs if you wish. QLIFE works best if you have a large CPU cache (256K is recommended).</P>
<P>&#151;<I>David Stafford</I></P>
<P>These <I>must</I> be in uppercase. For example, the minimum you really need is &ldquo;WIDTH 40 HEIGHT 120.&rdquo; I used &ldquo;WIDTH 46 HEIGHT 138 NOCOUNTER NODRAW GEN 7000&rdquo; during testing.</P>
<P>If you have selected the GEN option, you will have to press a key to exit QLIFE when it is finished. This is so I could visually compare the result of N generations under QLIFE with N generations under Abrash&rsquo;s original life program. You should be aware that the program from the listing contains a small bug, which may make it appear that they do not generate identical results. The original program does not display a cell until it changes, so if a cell is alive on the first generation and never dies, then it will never be displayed. This bug is not present in QLIFE.</P>
<P>You should have no trouble running QLIFE with cell grids up to 210x200.</P>
<P>You <I>must</I> have a VGA and at least a 386 to run QLIFE. The 386 features that it uses are not integral to the algorithm (they&rsquo;re a convenience for the code), so feel free to modify QLIFE to run on earlier CPUs if you wish. QLIFE works best if you have a large CPU cache (256K is recommended).</P>
<P>&mdash;<I>David Stafford</I></P>
</FONT><HR>
</BLOCKQUOTE>
<P>