Skip to content

Commit

Permalink
Apply different scaling computation
Browse files Browse the repository at this point in the history
  • Loading branch information
lehins committed Dec 23, 2024
1 parent 1859217 commit 71af49e
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/System/Random.hs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ class Random a where
-- independently:
--
-- >>> fst $ randomR (('a', 5.0), ('z', 10.0)) $ mkStdGen 26
-- ('z',7.27305019146949)
-- ('z',7.72694980853051)
--
-- In case when a lawful range is desired `uniformR` should be used
-- instead.
Expand Down
25 changes: 20 additions & 5 deletions src/System/Random/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,13 +1394,16 @@ instance UniformRange Double where
| l == h = return l
| isInfinite l || isInfinite h =
-- Optimisation exploiting absorption:
-- (-Infinity) + (anything but +Infinity) = -Infinity
-- (anything but -Infinity) + (+Infinity) = +Infinity
-- (-Infinity) + (+Infinity) = NaN
-- (+Infinity) + (-Infinity) = NaN
-- (-Infinity) + (+Infinity) = NaN
-- (+Infinity) + _ = +Infinity
-- (-Infinity) + _ = -Infinity
-- _ + (+Infinity) = +Infinity
-- _ + (-Infinity) = -Infinity
return $! h + l
| otherwise = do
x <- uniformDouble01M g
return $! x * l + (1 - x) * h
pure $! scaleFloating l h x
{-# INLINE uniformRM #-}
isInRange = isInRangeOrd

Expand Down Expand Up @@ -1437,13 +1440,25 @@ instance UniformRange Float where
uniformRM (l, h) g
| l == h = return l
| isInfinite l || isInfinite h =
-- Optimisation exploiting absorption:
-- Optimisation exploiting absorption:
-- (+Infinity) + (-Infinity) = NaN
-- (-Infinity) + (+Infinity) = NaN
-- (+Infinity) + _ = +Infinity
-- (-Infinity) + _ = -Infinity
-- _ + (+Infinity) = +Infinity
-- _ + (-Infinity) = -Infinity
return $! h + l
| otherwise = do
x <- uniformFloat01M g
return $! x * l + (1 - x) * h
pure $! scaleFloating l h x
{-# INLINE uniformRM #-}
isInRange = isInRangeOrd

scaleFloating :: (Ord a, Num a) => a -> a -> a -> a
scaleFloating l h x = if abs l < abs h then l + x * (h - l) else h + x * (l - h)
{-# INLINE scaleFloating #-}

-- | Generates uniformly distributed 'Float' in the range \([0, 1]\).
-- Numbers are generated by generating uniform 'Word32' and dividing
-- it by \(2^{32}\). It's used to implement 'UniformRange' instance for 'Float'.
Expand Down

0 comments on commit 71af49e

Please # to comment.