textwrap: Integer size and overflow when calculating penalty

When testing the optimal-fit algorithm, I encountered a panic during the cost calculations:

thread 'main' panicked at 'attempt to multiply with overflow', .../textwrap-0.13.0/src/core.rs:710:21

I fixed this by multiplying my mm widths with the factor 100 instead of 1000, which should still be a sufficient precision. But looking at the cost calculations, I have two follow-up questions:

  • Why are the costs stored as a i32 instead of a usize? They are generated by adding positive usize values, positive integer constants and other costs, so usize should work too.
  • How should overflows be handled when calculating the penalty? I changed the i32 type to usize, causing an integer overflow at the same location for the max_width test case that sets the line width to usize::MAX. This is currently working, probably because the huge value target_width - line_width is cropped when casting to i32 before updating the cost. Shouldn’t the cost calculation use saturating additions and multiplications if large line widths are supported?

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17 (13 by maintainers)

Commits related to this issue

Most upvoted comments

What about #289? Wouldn’t it mostly mitigate the problem for realistic use cases? And it should still be possible to detect the overflow case by checking for infinity.

I think it’s even better: there are no infinities because the penalties are scaled up to some maximum value: https://github.com/mgeisler/textwrap/pull/289/commits/93e51143adb061d1b2d7c43a98fbec1c6b8b6131

This approach also has a funny side effect of making the penalties dependent on the line length. That is, a gap of 10 is seen as catastrophic if the line length is 20, but seen as negligible if the line length is 1000. That should be a good feature, and if you know the line length, I believe you can compute suitable penalties (now that they’re adjustable: #389) to get the effect you want.

However, since this is different that the current approach, I recall spending a lot of time with a Jupyter Notebook trying to figure out if I can scale the penalties in a nice way to make them independent of the line width — but now I think I might have tried to solve a non-problem.