Reconcile This

July 18th, 2010

One of the reasons I’ve used Quicken so consistently to track our finances is that it so often saves me money. In a typical year, I used to catch $75 to $150 worth of bank errors, usually with credit card charges. These erroneous transactions are things that I would have missed with a visual inspection of the monthly statement, but are easy to nail when reconciling my records against the bank’s.

Common errors I catch:

  • Transposed digits. That $34 dollar meal is mistakenly entered as $43 by the hurried waiter. Small enough that I’d never notice, but easy to catch in Quicken. I got pretty good at contesting these.
  • Double charges. When you charge a meal at a restaurant, the waiter enters the pre-tip total and brings you the receipt. On the receipt, you enter the tip amount and sign. The waiter then enters a second charge for the total with the tip, and reverses the original charge. But sometimes, the reversal doesn’t work, and you’ll end up paying for your meal twice.
  • Charges at the statement cutoff. Twice I’ve had a charge show up as the last transaction of my monthly statement, and again as the first charge of the next monthly statement.

Mistakes like these are one of the main reasons I’ve stuck with an older version of Quicken that emphasizes reconciling over downloading.

Over the past few years, I’ve noticed a change in the types of errors I catch. There are fewer and fewer of those common charge errors in the vendor’s favor and more and more in my favor. In fact, the most common type of error I see now is the transaction that never posts to the account.

For example, I have a charge slip (actual ink on a physical piece of paper) showing that I paid our veterinarian $77.64 with our Visa card last December, but that charge has never appeared on our credit card statement. And it’s not just small vendors like the local vet clinic. TJ Maxx, Crate & Barrel, H&M, Target and other big name retailers sometimes fail to get a charge through.

I wonder who is losing out. Are these vendors not getting paid or is the bank failing to bill me? The first few times this happened, I called the bank. I gave specific information about the time, place, and amount of receipts that I had that didn’t post to my account. The rep said they didn’t have a record of any of those charges, and suggested that I called the vendors—if I cared. I called a couple of smaller ones, like the local vet clinic. They were uncertain how to verify payment for a specific credit card charge. In general, they seemed unconcerned—they didn’t think the credit card companies were underpaying them.

Ignorance is bliss, I guess.

In the past, the paper trail was king. A printed receipt was the final arbiter of the transaction. If the charge on the statement didn’t match the receipt, you sent a copy of the receipt to the bank, and the bank fixed their records. But today, it seems, the bank’s database is the final authority—reality be damned.

If the bank is happy and the vendors are satisfied, I guess I’m the only one with a problem. Sure, I’m ahead a couple hundred dollars, but my statements don’t reconcile. To a hardcore Quicken user, that’s torture.

Counting to a Billion

April 24th, 2010

[This blog post is reconstructed from the Internet Archive's copy of my original article posted on April 7th, 2007. The original post was lost.]

Let’s count to a billion.

#include <iostream>

void Count(const unsigned long limit) {
  DWORD ticStart = ::GetTickCount();
  unsigned long counter = 0;
  for (unsigned long i = 0; i < limit; ++i) {
    ++counter;
  }
  DWORD ticStop = ::GetTickCount();

  std::cout << "Counting took "
            << ticStop − ticStart
            << "milliseconds."
            << std::endl;
}

int main() {
  Count(1000 * 1000 * 1000);
  return 0;
}

Computers are pretty fast. With optimization turned off, my computer reports that it took a mere 2547 milliseconds (or about 2.5 seconds) to count to a billion. With optimization turned on, the compiler realizes there are no side effects in the loop, so it replaces the loop with an assignment: counter = limit;, taking virtually no time.

In the ray tracer, I want to keep statistics. How many intersection tests were performed? How many rays per seconds were traced? How many of those were shadow rays? Essentially, this boils down to counting how many times certain operations are performed. From this experiment, I can see that incrementing a few counters won’t be a significant performance hit.

But the ray tracer is multithreaded. To keep n cores cranking, I’ve got n threads rendering different parts of the picture. So if I want an accurate count of how many times something happens, I’m going to have to put some sort of synchronization on the accesses to the counter.

void CountWithCriticalSection(const unsigned long limit) {
  CRITICAL_SECTION cs;
  ::InitializeCriticalSection(&cs);

  DWORD ticStart = ::GetTickCount();
  unsigned long counter = 0;
  for (unsigned long i = 0; i < limit; ++i) {
    ::EnterCriticalSection(&cs);
    ++counter;
    ::LeaveCriticalSection(&cs);
  }
  DWORD ticStop = ::GetTickCount();
  ::DeleteCriticalSection(&cs);

  std::cout << "Critical section counting took "
            << ticStop − ticStart
            << " milliseconds."
            << std::endl;
}

The example is still single threaded, but the code is now thread safe. The critical section prevents two threads from corrupting the counter by trying to modify it at the same time.

The bad news is that this example, optimized or not, took 73,719 milliseconds. Ouch. Thread safety has a price. And this is without any contention for the critical section. It would be worse with two threads incrementing the counter. Imagine how bad it would have been if we had used a mutex and had to make a billion round trips to kernel mode!

Fortunately, Windows provides a set of interlocked functions which can help us do simple, thread-safe operations like counting without the overhead of a critical section. One more version:

void CountInterlocked(const unsigned long limit) {
  DWORD ticStart = ::GetTickCount();
  volatile long counter = 0;
  for (unsigned long i = 0; i < limit; ++i) {
    ::InterlockedIncrement(&counter);
  }
  DWORD ticStop = ::GetTickCount();

  std::cout << "Interlocked counting took "
            << ticStop − ticStart
            << " milliseconds."
            << endl;
}

This version scores significantly better at 37,390 milliseconds, just over half the time of the uncontested critical section. But that’s still a lot of overhead to take on while rendering.

And a little back-of-the-envelope calculation delivers even more bad news. Suppose one of the counters is supposed to be the number of intersection tests performed in the rendering job. If were computing images at hi-def resolution (1920 by 1080), that’s about 2 million pixels. If, for anti-aliasing, we oversample with say 16 rays per pixel, we’re up to about 32 million primary rays. Each primary might spawn a secondary reflection or refraction ray. Each of those 64 million rays might require, say, 10 shadow rays for shading. With a good acceleration structure, we might get away with as few as 4 intersections per ray. Next thing you know, we’ve exceeded the capacity of a 32-bit unsigned integer. If not for a single frame, then certainly once we start animating at 24 or 30 frames per second. So it looks like we’ll need 64 bits for at least some of our counters.

But, unless you’re on a 64-bit architecture, there aren’t 64-bit versions of the interlocked APIs. That means we’re back to critical sections for making the counters thread-safe. Obviously, we need to rethink this.

The key to good performance with multiple threads is to eliminate shared data as much as possible. Suppose instead of one counter, each thread had its own. Each thread would be able to increment its own counter without any synchronization concerns. Then, when the render is done, the independent counters could be summed to determine the total count. This adds a small amount of complexity and coordination, but not much, and the benefit should be worth it.

And this brings me back to my singleton post. I’m now paying the price for not taking my own advice. The ray tracer’s statistics are based on a set of counters kept in a singleton, so now I have to do some extra refactoring to distribute the counters among thread-specific objects.

105% Complete

March 14th, 2010

One of my UI pet peeves is misleading progress indicators.

This morning, I’m running a disk drive diagnostic program. The first test claimed it would take 200 seconds. After only 10 seconds, the display said “10% done”. Huh? Last time I checked, 10 ÷ 200 was 0.05, or 5%. Near the end of the test, the display said “100% done” about 10 seconds before it actually completed.

To a user, incorrect progress bars are annoying and useless. I don’t know about you, but when something is “100% done”, I think of it as, well, done. Not close to done. Those eternal seconds between “100% done” and actually done are immensely frustrating. People have even done research papers on designing progress bars to improve the user’s perception of a program’s progress. But this kind of research is light years ahead of real life, where we can’t even get a decent linear progress bar to work.

From my programmer’s perspective, misleading progress indicators are especially perplexing. You have to write extra code to get it wrong. Since programmers are lazy, nobody should be writing extra code, and all of our progress bars should just work.

Consider the disk drive diagnostic. You’d expect a plain jane linear progress indicator to be computed something like this:

indicator_value = work_done / total_work

Pretty simple, right? Ten seconds into a 200 second test should give us 0.05.

Now it’s likely that the calculation is done with integer arithmetic, and the final result will be presented as a percentage. So we have to scale up the numbers like so:

indicator_value = 100 * work_done / total_work

Now, 100 * 10 seconds ÷ 200 seconds gives us 5. So why in the world would the disk diagnostic claim 10%? Because somebody decided to do more work than was necessary.

Somebody apparently decided to have the indicator display progress in 10 percentage point increments (10%, 20%, 30%, etc.). Fine, you have to draw the line somewhere. So we revise our code to something like this:

indicator_value = 100 * work_done / total_work / 10 * 10

Mathematicians unfamiliar with integer arithmetic in most programming languages are now scratching their heads. The salient detail is that there’s an implicit floor function on the result of each division operation when working with integers. Conceptually, the above is equivalent to:

indicator_value = floor(floor(100 * work_done / total_work) / 10) * 10

Any programmer who find him- or herself at this point should stop, take a breath, and check off the progress indicator feature as complete.

But many programmers don’t stop there. Something bothers them. They instinctively worry about the “rounding down” that the integer division does. They want to fix it. They want to round up. Next thing you know, they’ve written an expression like this:

indicator_value = (100 * work_done / total_work + 5) / 10 * 10

Adding 5 (which is half of the 10 percentage point interval) will bias the number up. In many cases, this is the right thing to do. If you’re writing code to credit frequent flier miles to my account, I want you to round up. But we’re talking about code for a progress indicator. Don’t over-promise. Manage the user’s expectations.

It’s true that, 10 seconds into a 200 second operation, we’re closer to 10% than we are to 0%. But we’re not 10% done. We’re not even close. And, at the other end, you’ll show 100% done 10 seconds before we’re actually done. That’s an outright lie. User interfaces shouldn’t lie to users.

Don’t round up on progress indicators. Ever!

“But now users will panic,” some of you are sure to complain, “because it’ll seem like nothing is happening for 20 whole seconds!”

Perhaps so. Maybe it’s time to revisit the decision to show progress in 10 percentage point increments. You could have done even less work.

[Happy Pi Day!]

Review: Writing and Selling Your Mystery Novel

October 10th, 2009

I’m at a stage where the best thing I could do to improve my writing would simply be to practice more. But every now and then, when I’m looking for some motivation to get back to my work in progress, I pick up one of those “how-to-write” books. There are some excellent ones (like Self-Editing for Fiction Writers and Writing the Breakout Novel) and some not-so-excellent ones. There are also some that are probably pretty good but whose advice is too intangible for me to incorporate into my skillset (e.g., Creating Character Emotions). Nowadays, I don’t have high expectations for these books. I just use them as a way to get back into the writing mood.

Cover of Writing and Selling Your Mystery Novel by Hallie Ephron

Writing and Selling Your Mystery Novel by Hallie Ephron

It was with this mindset that I picked up Writing and Selling Your Mystery Novel by Hallie Ephron, and boy was I pleasantly surprised. It’s easy for these books to overreach by trying to touch on all aspects of becoming a published author. Covering both writing and selling in a single book is ambitious, so my hopes for depth were low. Nevertheless, Ephron manages to pack a lot of great ideas into less than 250 pages. I found the portions specific to mysteries (e.g., tips on plotting, building suspense, and pacing) to be especially helpful.

Many of her specific suggestions I’d not read anywhere else before (and I’ve read a lot of these books). And while she doesn’t plunge into any of the ideas in great depth, in many cases depth wasn’t necessary. Many of her tools will go into my toolbox. Other tidbits immediately sparked several ideas that I am already applying to my work in progress. I look forward to revisiting her chapters on revision—if I ever get this first draft done.

The book is well organized. You can read your way through it pretty quickly (even if you do the exercises along the away). You can also use it as a reference by returning to individual chapters for a refresher as you move through the stages of writing your own story. Most of the chapters are short and cover very specific topics with thought-provoking discussion, concrete examples, worksheets, and checklists.

Ephron also interviewed several well-known mystery writers and let them contribute some of their own tips. For example, Lee Child offers tricks on how to avoid getting bogged down in description while writing what should be a fast-paced action sequence.

If you’re working on a mystery, or even a thriller, I’d easily recommend Writing and Selling your Mystery Novel. It won’t replace Self-Editing or Breakout Novel—you still need those (and fantastic blogs like Edittorrent). But you will get tangible, actionable ideas from Ephron’s work that you won’t find in the more general writing advisers.

Claiming My Chase Account

September 16th, 2009

I had a long-term CD account at Washington Mutual, which was bought by Chase during the econopocalypse. In my latest quarterly statement (which Chase has managed to bloat into two pages), there was a note that I had to “claim” my account or they would be forced to turn it over to the FDIC. I called the number and here is roughly what transpired.

Recording: Thanks for calling Chase to claim your account. You can claim your account by executing a transaction on it.

Me: No, I can’t, not without incurring an interest penalty. It’s a long term CD that doesn’t mature until 2010.

Recording: Or by visiting a branch.

Me: I haven’t been inside a bank branch in years.

Recording: Or by logging into your Washington Mutual online banking account.

Me: I don’t have one of those.

Recording: Or by remaining on the line to talk to a banker.

Me: Now we’re getting somewhere.

Recording: If you’d like to participate in a customer satisfaction survey, please stay on the line after the banker disconnects, and you’ll be automatically connected to the survey.

Banker: Thanks for calling Chase. How can I help you?

Me: I got a note in my statement that I have to claim the CD account I had with Washington Mutual.

Banker: No problem. What’s the account number?

Me: [reads number from the statement]

Banker: Hmm. I don’t see an account with that number.

Me: It’s the number right from the statement.

Banker: Did you open this account in California?

Me: Yes. I opened it with Great Western Savings in California. After the savings and loan melt-down, Great Western Savings became Great Western Bank, which was bought by Washington Mutual, which closed my branch without notice, and now they’ve been bought by you.

Banker: Wow, you’ve had that CD for quite a while.

Me: Yes, and this is the most work I’ve ever had to put into maintaining it.

Banker: Maybe I can look it up by your name.

Me: [gives name, address, date-of-birth, and full Social Security number, and hopes that this isn't some scam]

Banker: Oh, OK, here it is. I see it was opened in 2002.

Me: Quicken says I’ve had it since at least 1992. I think that was after Great Western switch from an S&L to a bank.

Banker: Let me confirm the balance with you then. [tells me the balance]

Me: Yeah, that’s right.

Banker: OK, you’ve now claimed your account.

Me: Gee, that’s a relief, because it seems like you didn’t have it there for a minute. And I don’t really understand why I had to claim it. Every bank account I’ve ever had has changed hands at least once before, and I’ve never had to claim any of those.

Banker: It’s just a regulation, sir.

Me: Then it’s a regulation no other bank follows.

Banker: Is there anything else I can do for you?

Me: No, just keep my money safe, thanks.

Banker: Thanks for calling Chase. Goodbye.

Me: [waits on the line for the promised customer satisfaction survey]

Me: [… and waits]

Me: [… and waits]

Click. Dial tone.

Me: Note to self, move the CD when it matures next year.

Test-Driven Development

September 5th, 2009

On a C++ programming forum, somebody asked a relatively simple question: How do you write a function that counts the number of lines in a text file? Most of the answers were friendly and helpful, but flawed.

As programmers, we often think of a problem as so trivial that we don’t take the time to think through the answers or to appreciate the subtlety of corner cases. In one of my favorite books, Programming Pearls, Jon Bentley talks about how hard it is for programmers to get fairly simple and routine problems correct on the first try. He writes:

I’ve assigned this [binary search] problem in courses at Bell Labs and IBM. Professional programmers had a couple hours to [implement a binary search] in the language of their choice; a high-level pseudocode was fine. At the end of the specified time, almost all the programmers reported that they had the correct code for the task. We would then take thirty minutes to examine their code, which the programmers did with test cases. In several classes and with over a hundred programmers, the results were varied little; ninety percent of the programmers found bugs in their programs (and I wasn’t always convinced of the correctness of the code in which no bugs were found). [p. 36]

Remember, these are professional programmers, in the language of their choice, with hours of time, messing up a binary search.

Notice the oh-so-common pattern here:

  1. Write code.
  2. Declare that it works.
  3. Test it and discover it’s broken.

It’s enough to make you wonder if there’s a better way. Many people in the extreme programming and agile crowds would say that we’re doing it all out of order. Not only should “declare it works” come after testing, but probably so should writing code. So let’s take this seemingly trivial line-counting problem and apply a little test-driven development in C++.

First, let’s agree on an interface. I propose:

template <typename InputIt>
size_t CountLines(InputIt begin, InputIt end);

That is, we’ll give the function a pair of iterators pointing to the beginning and end of the text we want examined, and the function will return the number of lines. (If you want to count the lines in a file, read the file into a std::string and call the function.) I’ve used size_t for the return type, as that’s typically unsigned (after all, the count will be 0 or more—it can’t be negative), and it’s generally as large an integer type as your platform will comfortably handle, so we shouldn’t have to worry about text consisting of too many lines. If you’re not a fan of the template parameters for the iterator types, feel free to re-write it with const char pointers.

Now that we know the interface, we will write the test function—even before we discuss how we’ll count lines. This function will iterate through a set of test cases, feed the input to CountLines, and check the return.

bool Test_CountLines() {
  struct TestCase {
    std::string input;
    size_t output;
  };

  const TestCase tests[] = {
    {"Hello\nWorld\n", 2}
  };

  const size_t cTests = sizeof(tests) / sizeof(tests[0]);

  size_t cPassed = 0;
  size_t cFailed = 0;
  for (size_t i = 0; i < cTests; ++i) {
    const TestCase &test = tests[i];
    size_t cLines = CountLines(test.input.begin(), test.input.end());
    if (cLines == test.output) {
      ++cPassed;
    } else {
      std::cerr << "FAILURE" << std::endl
                << "Input \"" << test.input << '"' << std::endl
                << "Output " << cLines << " instead of " << test.output << std::endl;
      ++cFailed;
    }
  }

  return cPassed == cTests && cFailed == 0;
}

I’ve started us with one test case, and we can add more as we develop the function. Just to make sure our testing framework is solid, let’s stub out CountLines and a little main function to make sure it all compiles and runs.

template <typename InputIt>
size_t CountLines(InputIt /* begin */, InputIt /* end */) {
  size_t cLines = 0;
  return cLines;
}

I commented out the parameter names to avoid the “unused parameter” warnings. These will come into play shortly.

int main() {
  assert(Test_CountLines());
  return 0;
}

If you put all this together and run it, you’ll see that the test fails as expected. This is good, as we want to make sure we exercise the failure case of our test function to know that it works.

Some of you are probably saying that you could have already written a correct CountLines function by now. Maybe. Remember all those “helpful” answers on the programming forum? Remember all those professional developers attempting a binary search? Besides, it really didn’t take long to build this test infrastructure. If a bug ever does crop up in the function, we can easily debug it. When we fix a bug, we can immediately verify that we didn’t create a regression by re-checking every test case we’ve ever come up with. And you can add that new test case so that it never breaks again. If you change something fundamental, like the compiler or OS you’re using one, you can know with certainty whether or not it affects the behavior of your function.

Next we need test cases. Off the top of my head, here are some interesting cases we’ll have to design for:

  • An empty string should have zero lines.
  • The count of a string with blank lines or empty lines (e.g., “Hello\n\nWorld!\n”) should include those blank lines.

Doesn’t seem too hard yet, so let’s add those test cases.

const TestCase tests[] = {
  {"", 0},
  {"Hello\nWorld\n", 2},
  {"Hello\n\nWorld\n", 3}
};

It seems pretty “obvious” that the way to count the lines is to count the number of newline (‘\n’) characters in the string:

template <typename InputIt>
size_t CountLines(InputIt begin, InputIt end) {
  return std::count(begin, end, '\n');
}

Ta da! Test-driven development has led us directly to one of the common—but incorrect—answers given on the programming forum.

Consider the string “Hello”. That has zero newline characters, but most people would consider it to be one line long. Too bad we didn’t think of that while coming up with our test cases. Now that we have thought of it, the first thing to do is to add it to our test code.

const TestCase tests[] = {
  …
  {"Hello", 1},
  …
};

We might be tempted to treat this new string as a special case.

// Ugly -- don't do this!
template <typename InputIt>
size_t CountLines(InputIt begin, InputIt end) {
  size_t cLines = std::count(begin, end, '\n');
  if (cLines == 0 && begin != end) {
    cLines = 1;
  }
  return cLines;
}

While this hack will pass our tests, it’s ugly and still wrong. We’ve failed to realize that the “Hello” string is just a special case of not having a newline character on the last line in the string. (This is an extremely common bug in the wild. Many parsers choke if the last line of the input doesn’t end with a newline.) So we add another test case:

const TestCase tests[] = {
  …
  {"Hello\nWorld", 2},
  …
};

When adding a test case, it’s good to think of counter-examples. For instance, if the last line of the string does end with a newline, that shouldn’t trigger an extra line. Fortunately, we’ve already got a test case for that.

Now our original approach is starting to look bad. Simply counting the newline characters, even with some hacky fix-ups for “corner cases”, isn’t going to work.

All is not lost. Yes, we have to completely re-think how we’re going to implement CountLines, but none of that invalidates the test framework we’ve built. When we come up with our new solution, we can immediately check to see if it solves the new test cases as well as the others we’ve already made. Suddenly it looks like the time we’ve put into the test framework is going to pay off.

There are a few ways to solve the line counting problem, but they all boil down to a state machine. Here’s my solution:

template <typename InputIt>
size_t CountLines(InputIt begin, InputIt end) {
  size_t cLines = 0;
  bool bStartOfLine = true;
  for ( ; begin != end; ++begin) {
    if (bStartOfLine) {
      ++cLines;
    }
    bStartOfLine = *begin == '\n';
  }
  return cLines;
}

In this case, there’s not much state—just a boolean. If we’re at the beginning of a line, and there’s anything on it (even a ‘\n’), then we need to count the line. After that, we simply need to figure out if the next character will be at the start of a line or not. This solution passes all five of our test cases.

Some say that you shouldn’t “waste time” on the corner cases, since, well, they’re corner cases. In my experience, though, if you get the corner cases right, then the mainstream cases generally just work. After all, the corner cases should just be degenerate versions of the mainstream case—or vice versa.

Uh oh, another bug. We’ve been considering ‘\n’ to be the newline character. Text files on Multics-derived operating systems use a single ASCII line feed character (LF) to indicate a line break, but that’s far from universal. CP/M, DOS, Windows and a lot of Internet protocols require a carriage return (CR) followed by LF to mark a line break. C and C++ file i/o routines will translate whichever convention your platform uses to and from ‘\n’. Most compilers give ‘\n’ the value 0×0A, which happens to be the same as an ASCII LF. On Unix systems, the compiler’s i/o routines have to do no translation. On others, when you write ‘\n’, the output routine actually writes CR-LF, and when the input routine reads CR-LF, it returns ‘\n’. (Read all about newlines on Wikipedia.)

But if we were to read in the data in binary mode (which could be faster), then we’ll see the actual bytes used in the file. So we have to add test cases. First, we’ll add the CR+LF cases. Then we’ll conditionally add ones with explicit LFs in case our compiler doesn’t use LF for ‘\n’.

const TestCase tests[] = {
  …
  {"Hello\x0D\x0AWorld", 2},
  {"Hello\x0D\x0AWorld\x0D\x0A", 2},
  {"Hello\x0D\x0A\x0D\x0AWorld\x0D\x0A", 3},
#if '\n' != '\x0A'
  {"Hello\x0AWorld", 2},
  {"Hello\x0AWorld\x0A", 2},
  {"Hello\x0A\x0AWorld\x0A", 3}
#endif
};

Happily, our latest version of CountLines works with these new examples. Essentially, the CR characters aren’t important to the algorithm, and our compiler does assign LF for ‘\n’.

If you did read the Wikipedia article, you know that there are several more newline conventions that we might want to support. Old Mac and Amiga files use just a CR, old IBM mainframes used NEL from the EBCDIC character set, Unicode introduced LINE SEPARATOR and PARAGRAPH SEPARATOR code points, etc. I’m sure you could imagine refining CountLines to handle these additional cases. Essentially, the state machine grows in complexity.

Conclusion

OK, this has been a long blog post, mostly because I’ve shown the iterative process necessary to solve the problem. What we’ve seen is that even the simplest problems might be more complex than we anticipate. The more thought we put into coming up with test cases, the more robust an implementation we were able to write. And when we had to start the implementation over from scratch, having a unit test framework helped us quickly ensure that the new implementation was at least as correct as the previous one.

One Tap or Two?

August 22nd, 2009

[This blog post is reconstructed from a draft dated April 5, 2006. The original post was lost.]

If you ever took a typing class, you were probably taught to press the space bar twice between sentences. Lately, more and more blogs have declared this to be wrong-headed advice. Today, they claim, with proportional fonts and improving electronic typography (even on computer screens), you should use just one space between sentences. But the debate rages on. So what’s a poor keyboardist to do?

If you’re a serious author, you should be writing rather than surfing, so I’ll give you an early out: prepare your manuscript whichever way your agent, editor, and publisher want. Period. Now close your browser and get back to work.

Still with me? Good. The rest of us will now debate this trivial point with a religious fervor that rivals operating system wars.

On a typewriter, or with a monospace font on a computer screen, there is only one type of a space: a simple gap the same width as any of the other characters in the font. If you need more space, you can line up several of these simple spaces. In fine typesetting, however, spaces are much more flexible. If you justify both margins of your text, spaces are stretched (and sometimes even squished) to make the lines come out to equal lengths. Printers have all sorts of spaces, from the interword space we all know and love, to em spaces and quad spaces and probably zillions of others. The sizes of these gaps are dictated by the font face and font size.

The debate, therefore, is not one-space-or-two. This oversimplification of the question is the root of much of the disagreement. Nobody thinks that, in a proportional font, intersentence spaces should be twice as wide as a regular space. We have to stop conflating these two ideas. First, should the spaces between sentences be any different than the ones between words? Second, how many times should you, as a keyboardist, hit the space bar between sentences?

Should there be a difference?

Donald Knuth, a professor of mathematics and computer science, pioneered fine electronic typesetting by developing TeX and Metafont, tools which many technical publications still use for producing high-quality documents. (I believe Metafont was the first application of scalable outline fonts.) If you know Knuth, you know he doesn’t do things halfway. From his writings on the subject, it seems he has studied the entire history of putting ink on paper.

According to Knuth’s design, whether and how much extra space goes between sentences should be determined by the font designer. Therefore, there is a distinction.

TeX’s model of a space is not just its natural size, but also how it can stretch or squish when it is being adjusted during justification. In TeX’s default mode with the Computer Modern fonts, spaces between sentences are fractionally wider than ones between words. The difference is so small, you can barely tell. When justifying the text, those intersentence spaces are stretchier than the interword ones. In fact, TeX also makes spaces after punctuation marks like commas, which don’t end sentences, stretch faster than interword spaces (though not as fast as intersentence spaces).

TeX also offers a mode, called French spacing, that lets you override the font designer by eliminating these spacing distinctions and makes all the spaces the same size and stretchiness.

I should let the typographers and font designers battle over whether it’s right to make a distinction, but I have my opinions.

Personally, I prefer to read material that adds a little extra space between sentences (and, no the open space above a period doesn’t do it for me). I’ve been noticing that fewer and fewer new books are typeset this way. I find myself stumbling and re-reading a lot more, especially in fiction with lots of dialogue. Although the extra space is a tiny, subtle cue, it’s something I notice. Please God, when e-books finally catch on, please give us a choice to read them in either mode.

Apparently I’m not the only one who stumbles without longer spaces between sentences. This comment on screenwriter John August’s blog points out that actors reading aloud stumble less when there’s extra space between sentences. This isn’t a totally fair comparison, because he’s talking about a typewritten (monospaced) script. Nevertheless, it supports the idea that the spacing between sentences should be distinct from the spacing between words to help the reader.

Another reason to distinguish is to eliminate ambiguity. These two lines have slightly different meanings:

"Run!" I gasped.

"Run!"  I gasped.

I’ve used a monospace font to make it clear. The first example is a single sentence (and a good example of bad dialogue). The second one is two distinct sentences (and avoids using a cheesy dialogue attribution). Yes, it’s contrived, but I stumble across a few of these in every novel I read. And even when the spacing isn’t the sole clue to the sentence boundaries, it can help the reader by being a redundant clue.

The font designers and typographers may now proceed to argue over “color” and “rivers” until their hearts burst. For the rest of us, it’s enough to know that at least some reliable sources do make a distinction between interword and intersentence spaces.

What should you type?

My keyboard, and I assume yours, has only one space bar, so how can we distinguish these spaces when we type?

Well, that all depends on which rendering method you’d like to use. And, as it turns out, most rendering methods suck.

If you’re typing plain text, in a monospace font, use two spaces between sentences. There seems to be little debate over that.

If you’re composing an email, be aware that the reader might see it as plain text, even if you try to format it with HTML or rich text. Reading incoming mail as plain text is an excellent defense against web beacons and browser exploits in all that spam that slips by the filters. If your text can’t make the point without the fancy formatting, then you should probably be spending more time on content.

If you’re writing for the Web in HTML or XML, it doesn’t matter how many spaces you type, because (with a few exceptions), it’s going to treat any number of consecutive spaces as a single space. That’s good news for those of you who have a hard time changing your typing habits, but it sucks for readers who want a little more room between sentences.

If you’re using TeX or LaTeX, it doesn’t matter how many spaces you type. No really. Go ahead, put 42 spaces between your next two sentences. Trust me. It’ll be fine. TeX can usually figure out all by itself which spaces are between sentences. Unfortunately, the algorithm isn’t perfect, so occasionally you do have to give it a hint, especially in dialogue and after certain kinds of abbreviations.

I’m not sure about troff.

I had a colleague

who would write

in short phrases

like this.

He found it

easier

to edit and proofread.

troff then turned his text into normal type. Nobody else ever knew how strange his source files were.

Let’s see. What else. Oh yeah, Word. If you write in Word, I’m sorry. Word is schizophrenic when it comes to how many spaces you type. On the one hand, since it’s a WYSIWYG editor (WYSIWYG is the wrong paradigm for composing text), every space you type becomes a space on the page. If you type two spaces between sentences, you’ll end up with intersentence spaces that are twice as wide as a regular space. And, if you justify the text, that gap will stretch twice as fast. We all agreed at the beginning that this is bad. And it’s the primary reason why so many people have oversimplified the issue in their blog and described the two-space tap as “100% wrong.” On the other hand, those of you brave enough to leave Word’s grammar checker turned on may have noticed that the grammar checker screws up less often if you put two spaces between sentences. This, in and of itself, isn’t a strong argument for using two spaces.

Still, I cringe every time I see a blog recommending that people use a global search and replace to change all of the space pairs into single spaces. It just doesn’t seem right to throw that information away. What we need is a better rendering method. One that lets writers type however they like and lets readers choose how they want the text displayed.

For the record, I’m an unrepentant double-tapper.

Servo Animation

August 9th, 2009

One of the (far too many) projects I’ve been working on is a video game. You might call it a sports simulations—then again, you might not, depending on your idea of what constitutes a sport. Nevertheless, it involves players waving sticks at balls, trying to get the balls to go in the right direction.

Physics

For the core of the game engine, I’ve built a physics simulator. Back in college, I had a tenuous grasp on Newtonian physics, which came in handy as I was earning my degree in physics. As with many things, you have to use it or lose it, and I haven’t exercised my knowledge of physics much since graduating. So, in addition to the figuring out how to translate conservation of energy into floating point math, I had to relearn some physics and, especially, some calculus. If you find yourself in the same boat, I recommend this series of articles from Chris Hecker as a warm-up:

Those will help you (re-)learn the physics and math necessary to make a nice 2D simulator (think Crayon Physics). With those as inspiration, these heavy-duty tutorials from David Baraff will help you build a nearly-complete 3D simulator:

My simulator is built almost directly from the latter two references. While these are hard-core articles, there is a lot more to this field. Fortunately for me, this was plenty to do the basic bouncing balls simulation that are necessary for my game.

At least, I thought it was. I have the balls bouncing, rolling, and smacking into each other, all under the control of the physical simulation. What I need now is to blend the simulation with canned animations and with input from the user. The question is, how do I handle the interaction of the animation-controlled objects with the simulation-controlled ones?

Consider a canned animation of a 3D character swinging a bat. There’s a ball hurtling toward the player’s avatar. The player presses a button to start the animation. Frame by frame, the bat’s position is updated. If the bat hits the ball, an impulse needs to be imparted to the ball. But since the swing is just a series of positions, we don’t have all the physical values necessary to compute an accurate force to apply to the ball. You could probably guesstimate the change in momentum and send the ball flying off in a plausible way, but what about the bat? If I continue with the animation of the player’s follow-through, you won’t see any recoil on the bat itself. The bat will continue on its trajectory as though the player had missed the ball.

This is a quandary I’ve been pondering off-and-on for a while. But after the MazeBot project, the answer came to me: servo control.

Servo

MazeBot has a compass sensor that gives its orientation in degrees with respect to magnetic north. At any point in time, MazeBot’s software has a desired orientation. The difference between the desired orientation and the measured orientation is the error. The error is used to compute how much power to apply to the left and right motors in order to turn the robot back to the desired heading. This is repeated many times per second in order to keep the robot on track. This is called servo control.

Now here’s the neat part. To execute a turn, the software “animates” the desired heading from its original value to the desired value. For example, if the robot is at heading 18 and it wants to turn 90 degrees, the software changes the desired heading to 19, then to 20, then 21, and so on, until it reaches 108. That’s it. It doesn’t directly issue any commands to the motors.

In the background, the servo controller is always running, trying its darndest to keep the robot aligned to the desired heading—even when the desired heading is a moving target. Thus the robot turns. How closely it follows the animated path depends on how well-tuned the servo controller is and how responsive the mechanism is.

Servo Animation

Suppose we applied the same idea to the animation of the bat. The bat could be just another object that the physics simulator controls. Rather than telling us where the bat is, the animation path tells us where we want the bat to be. We feed that desired position into a servo controller just like the desired heading is given to MazeBot’s servo controller. The servo controller returns the force (and torque) that should be applied to the bat to keep it on the animation path.

Now that the bat is a first-class citizen of the simulation, we have all the physical parameters we need to resolve any ball-bat collisions. The ball experiences a change in momentum and heads away to the outfield. The bat will also experience a recoil impulse causing it to momentarily fall behind the animation path. The servo controller will increase the forces to try to get the bat back on track, resulting in a swing that—while animation-driven—still responds in a realistically different way than if there had been no collision.

I haven’t tried this out yet. Given my project backlog, it might be a while, but I wanted to write up this idea while it was still fresh in my head. What do you think? Will it work?

MazeBot

July 31st, 2009

My brother and I make it a point to get together about four weekends a year to do projects. We started this “tradition” a couple years ago, and it’s become something I look forward to every time.

Last weekend I met him in Southern California. He suggested we do a robotics projects, specifically, to make a small robot that can navigate a maze. First we needed a maze, so we headed to Home Depot with the idea of getting some lumber we could cut into various lengths and layout to make a reconfigurable maze. After settling on some 1×4 pine boards, we discovered some 2×16×6 concrete blocks. They worked beautifully, and were much cheaper than even the cheap wood we had originally selected.

To build the actual robot, which I dubbed MazeBot, we used LEGO (Mindstorms NXT). Working with the NXT, which is the second generation of the LEGO robotics line, was much easier than trying to get the original Mindstorms brick to do much. We used ROBOTC, which is a C compiler from the folks at CMU made especially for robotics projects. We used Bluetooth to transfer the compiled programs from our development PC to the robot. The whole process was a snap, which made it very easy to do lots of iterations.

Adrian with MazeBot

Adrian with MazeBot

Did I say lots of iterations? We made eight major versions of the software (about four pages of C code) in one weekend. In the end, MazeBot could explore and map the maze. The next step would have been to give it more explicit goals, like finding a route to a particular cell in the maze, but we ran out of weekend. This video shows MazeBot in action.

The robot uses a sonar sensor in front to detect the maze walls. It has a compass sensor on a mast to determine its orientation. (The mast is necessary because the magnets in the drive motors interfered with the accuracy of the compass readings. Late in the weekend, we figured out that our mast had to be even taller to get good readings.) The software assumes everything in the maze is at right angles and that the robot begins aligned with one of the walls. The LEGO motors also have feedback, which we used to determine how far the robot has traveled.

MazeBot 8.0 from Adrian on Vimeo.

I certainly learned a lot about PID servo control. Well, PI control anyway—our robot doesn’t use a derivative term.

Rebooting the Blog

July 31st, 2009

Ever since the mishap last year where I destroyed my blog, I’ve been wanting to get it set up again. Every few days it seems I’ve had something I wanted to post, but the work involved in getting set up again was always a roadblock.

My employer surprised me today by giving us the afternoon off. I took advantage of the time to learn more about WordPress. I’ve installed it manually this time, in order to better understand the configuration. So hopefully I can get back to blogging.

If you had registered a user account here before, it’s gone. Though, for now, I’m not requiring people to log in to comment. If you haven’t had a comment approved before, it won’t show up until it’s moderated.