Improvements to std.math floor() / ceil()

Some changes are going on here:

1. Uses union instead to ensure that compiler doesn't emit any library calls here (seen a small speed up in benchmarking code).
2. Add float/double overloads, improvements might be negligible because isNaN and isInfinity checks perform (heavy?) conversions to long double.
3. Move common code in floor into floorImpl
4. Converted isNaN and isInfinity into generic functions.  This final change resulted in a substantial improvement of codegen.

> From my experience I've only seen it to be a problem if you are accessing data outside the range of the peek type.

(Not that it matters now)

Second experience, type punning an lvalue *always* breaks under optimisations.

Here we are pretty much safe because it's only read, not written to.  floorImpl() needs a union because the bits are written to.