I’m writing the maths functions for a small LLVM-based programming language,
and I’m currently stumped by how to implement the common rounding functions floor, ceil and round (to even). Firstly because I haven’t found any algorithm descriptions for these functions, secondly because I’m not familiar with what capabilities LLVM has w. rounding.
Being able to round negative numbers correctly is a must, rounding to a specific precision is not. Rounding to an integral value will do. Simply being pointed to any existing implementations that can be used from LLVM bitcode will also work.
You’re going to want to start with the LLVM language reference manual.
You might start by implementing
trunc( )like something along these lines (warning, don’t actually use this; it’s intended as an example, and isn’t correct. See discussion below):The
fptosi ... to ...instruction is documented as rounding a floating-point value to an integer value according to the round-to-zero rounding mode. Thesitofp ... to ...instruction converts that value back into a floating-point value to return.However, there is a problem with this implementation; reading the language reference that I linked to, “the behavior of
fptosi ... to ...is undefined if the result of rounding to the nearest integer cannot fit in the destination type.”This is pretty easy to work around, though, because all sufficiently large floating-point numbers are already integers, and don’t need to be rounded; if the absolute value of
xis greater than or equal to 2^23, you can just return x itself.(This is all for single precision; for double, you will likely want to use
i64, and you will need to use a threshold of 2^52)For the other operations, like
floorandround, you can begin withtrunc, then check the residualx - trunc(x)and adjust the result accordingly.Alternatively, you could call out to your host platform’s C library, which already includes these functions. This is an approach taken by many programming languages.