Skip to content

Commit 68a7427

Browse files
glemaitrejjerphan
andauthored
MAINT remove overflow for RAND_R_MAX (#24955)
Co-authored-by: Julien Jerphanion <[email protected]>
1 parent b9137b4 commit 68a7427

File tree

1 file changed

+7
-11
lines changed

1 file changed

+7
-11
lines changed

sklearn/utils/_random.pxd

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ cdef enum:
1212
# Max value for our rand_r replacement (near the bottom).
1313
# We don't use RAND_MAX because it's different across platforms and
1414
# particularly tiny on Windows/MSVC.
15+
# It corresponds to the maximum representable value for
16+
# 32-bit signed integers (i.e. 2^31 - 1).
1517
RAND_R_MAX = 0x7FFFFFFF
1618

1719
cpdef sample_without_replacement(cnp.int_t n_population,
@@ -30,14 +32,8 @@ cdef inline UINT32_t our_rand_r(UINT32_t* seed) nogil:
3032
seed[0] ^= <UINT32_t>(seed[0] >> 17)
3133
seed[0] ^= <UINT32_t>(seed[0] << 5)
3234

33-
# Note: we must be careful with the final line cast to np.uint32 so that
34-
# the function behaves consistently across platforms.
35-
#
36-
# The following cast might yield different results on different platforms:
37-
# wrong_cast = <UINT32_t> RAND_R_MAX + 1
38-
#
39-
# We can use:
40-
# good_cast = <UINT32_t>(RAND_R_MAX + 1)
41-
# or:
42-
# cdef np.uint32_t another_good_cast = <UINT32_t>RAND_R_MAX + 1
43-
return seed[0] % <UINT32_t>(RAND_R_MAX + 1)
35+
# Use the modulo to make sure that we don't return a values greater than the
36+
# maximum representable value for signed 32bit integers (i.e. 2^31 - 1).
37+
# Note that the parenthesis are needed to avoid overflow: here
38+
# RAND_R_MAX is cast to UINT32_t before 1 is added.
39+
return seed[0] % ((<UINT32_t>RAND_R_MAX) + 1)

0 commit comments

Comments
 (0)