performancehaskellrandomfloating-pointbranchless

Change (0, 1] to (0, 1) without branching


I have a random number generator that outputs values from (0, 1], but I need to give the output to a function that returns infinity at 0 or 1. How can I post-process the generated number to be in (0, 1) without any branches, as this is intended to execute on a GPU?

I suppose one way is to add a tiny constant and then take the value mod 1. In other words, generate from (ɛ, 1 + ɛ], which gets turned into [ɛ, 1). Is there a better way? What should the ɛ be?


Solution

  • Update 1

    In Haskell, you can find ɛ by using floatRange. The C++ portion below applies otherwise.


    Note: The answer below was written before the OP expressed the answer should be for Haskell

    You don't state the implementation language in the question, so I'm going to assume C++ here.

    Take a look at std::nextafter.

    This will allow you to get the next possible value which you can add to the upper limit, which will result in your code acting as if it was inclusive.

    As for the branching, you could overload the function to avoid the branch. However, this leads to code duplication.

    I'd recommend allowing the branch and letting the compiler make such micro-optimizations unless you really need the performance and can provide a more specialised implementation than the standard one (see Pascal Cuoq's comment).