Clean flaky code

(1) Whether char is signed or unsigned is not defined, so it makes more sense to use int8_t to get sign values.

(2) signbit returns a non-zero value when the sign bit is set, and we can't implicitly assume that it will be 1. This will cause problem when we directly assign it to e.g. a float value. Need to static cast the value to bool first.

(3) Explicit instantiation is not needed when the whole function is defined in the header file.

(4) Don't do EXPECT_EQ for float values. Always assume that there is numerical instability.