[SPARK-3250] Implement Gap Sampling optimization for random sampling

More efficient sampling, based on Gap Sampling optimization:
http://erikerlandson.github.io/blog/2014/09/11/faster-random-samples-with-gap-sampling/

The purpose of `fractionEpsilon` is to avoid taking the logarithm of zero.  It doesn't really have any bearing on the interface contract.   I can rename it to something like `logEpsilon`, that might be more clear.