Do not assume that enum are signed

Clang 3.5 issues warning on constructs like: `abs(f1 - f2)`. The thing is that
`f1` and `f2` are enum types, and the range given (all positive) allows the
compiler to choose an unsigned type (efficiency being one reason to prefer
unsigned arithmetic). If `f1 < f2` are unsigned, then `f1 - f2` wraps around zero
and the `abs()` becomes a no-op. It's the reinterpretation of the unsigned
result (large value) as a signed int that happens to give the correct result,
thanks to 2's complement. In other words, despite Clang's complaints, the
Clang copile is functionally correct. But this is all tricky and dangerous!

In the spirit of the standard, we assume nothing on the signedness of enums,
and simply calculate the rank and file distances, so as to not wrap around zero:
- `rank_dist(r1, r2) = r1 < r2 ? r2 - r1 : r1 - r2`
- `file_dist(f1, f2) = f1 < f2 ? f2 - f1 : f1 - f2`

this logic can in fact be applied to any enum we may use, so for better
generality and to avoid code duplication, we use a template function `diff()`
here.

No functional change.