I came here to comment that I think the problem is poorly posed and algorithm chosen to implement it is "backwards".
But I also see that StehpenCannon has spoken :-); there is going to be very little chance he is wrong when it comes to arguing about floating point! He also notes the following, but not quite so explicitly...
The problem is poorly posed because the question is, which mantissas, exponents and sign bits fit into a long.
The algorithm is backwards because simple comparisons in integer space cannot compute this; but I think the algorithm should be,
int fits_long(double value) {
unsigned int trailingZeros = countOfTrailingZeros(mantissaOf(value));
bool fits = (bitsInAMantissa + 2 - trailingZeros + exponentOf(value) < bitsInALong);
return fits;
}
[Notes:
if double is always > 0 and going to an unsigned long, the 2 above would be 1. The 2 represents the sign bit in the double. Given that sizeof(double) == sizeof(long) all bits in the two representations are accounted for, so there is no information loss.
checking:
mantissa = 0 (with a hidden msb of 1) means, trailingZeros = bitsInAMantissa -> fits will be true when the exponent value can be 0..62. So this represents each of the +/- 2^exponent values
mantissa = 1 x bitsInAMantissa means, trailingZeros = 0 -> fits will be true when the exponent value can be 0..(bitsInALong-BitsInAMantissa-2). So, +/- (all ones) * 2^exponent value.
The representation for going from double to long is not "smooth".
]
countOfTrailingZeros() is a favorite of bit twiddlers. "Hackers Delight" or "bithacks" https://graphics.stanford.edu/~seander/bithacks.html
[edited to improve readability]