1

Calling a * pow(10.0, n), in any C derived language, results in two rounding errors, but I require only one rounding error as can be provided by a single fused instruction.

For example a=39762108874335653 n=-297 should give 3.9762108874335653E-281 (as can be validated by parsing the string "3.9762108874335653E-281" or using arbitrary precision arithmetic, and outputting a floating point number) but the quoted code returns 3.976210887433566E-281.

That leads back to the question: is there a fused instruction (or C function) that can perform this calculation to the highest possible precision for the machine?

I am only concerned with the case where a and n are integers, and the result is a double precision floating point number. Note that a may not be exactly representable as a floating point number.

Converting to a string and parsing is not an acceptable solution (it's far too slow), nor is using an arbitrary precision library (such as Java's BigDecimal, also because it's too slow).

Note that there is a similar C stdlib function, ldexp (related to scalbn) which uses base2 and therefore calculates a * 2^n as a single fused instruction.

I am aware of the instructions listed in https://en.wikipedia.org/wiki/C_mathematical_functions

Not a dupe of Is floating point math broken? this is not about trying to understand how rounding works. It is just asking: does this function exist anywhere, ideally in a CPU fused instruction for maximum performance? Obviously the workaround in the absense of such a thing is to use arbitrary precision, but that is quite heavyweight.

fommil
  • 5,757
  • 8
  • 41
  • 81
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/216262/discussion-on-question-by-fommil-is-there-a-fused-instruction-that-can-perform-a). – Samuel Liew Jun 19 '20 at 09:56

1 Answers1

0

The answer is "no" there is not a single instruction that can perform this operation, as answered by @eric-postpischil in chat and the evidence for this can be backed up by the fact that standard libraries would use it if it were available, e.g. glibc strtod

However, although there is no single CPU instruction, it is possible to extract the strtod implementation to operate on the integer input as requested in this question, as was done by Alex Huszagh in Rust. The algorithms discussed here effectively use a * pow(10.0, n) when the significand is estimated to be small enough (preferring division for negative n) and falling back to converge algorithms to eliminate the rounding errors.

fommil
  • 5,757
  • 8
  • 41
  • 81