@@ -19,8 +19,17 @@ from . import check_random_state
19
19
cdef UINT32_t DEFAULT_SEED = 1
20
20
21
21
22
- cpdef _sample_without_replacement_check_input(cnp.int_t n_population,
23
- cnp.int_t n_samples):
22
+ # Compatibility type to always accept the default int type used by NumPy, both
23
+ # before and after NumPy 2. On Windows, `long` does not always match `cnp.inp_t`.
24
+ # See the comments in the `sample_without_replacement` Python function for more
25
+ # details.
26
+ ctypedef fused default_int:
27
+ cnp.intp_t
28
+ long
29
+
30
+
31
+ cpdef _sample_without_replacement_check_input(default_int n_population,
32
+ default_int n_samples):
24
33
""" Check that input are consistent for sample_without_replacement"""
25
34
if n_population < 0 :
26
35
raise ValueError (' n_population should be greater than 0, got %s .'
@@ -33,8 +42,8 @@ cpdef _sample_without_replacement_check_input(cnp.int_t n_population,
33
42
34
43
35
44
cpdef _sample_without_replacement_with_tracking_selection(
36
- cnp.int_t n_population,
37
- cnp.int_t n_samples,
45
+ default_int n_population,
46
+ default_int n_samples,
38
47
random_state = None ):
39
48
r """ Sample integers without replacement.
40
49
@@ -76,9 +85,9 @@ cpdef _sample_without_replacement_with_tracking_selection(
76
85
"""
77
86
_sample_without_replacement_check_input(n_population, n_samples)
78
87
79
- cdef cnp.int_t i
80
- cdef cnp.int_t j
81
- cdef cnp.int_t [::1 ] out = np. empty(( n_samples, ) , dtype=int)
88
+ cdef default_int i
89
+ cdef default_int j
90
+ cdef default_int [::1 ] out = np. empty(( n_samples, ) , dtype=int)
82
91
83
92
rng = check_random_state( random_state)
84
93
rng_randint = rng. randint
@@ -97,8 +106,8 @@ cpdef _sample_without_replacement_with_tracking_selection(
97
106
return np. asarray( out)
98
107
99
108
100
- cpdef _sample_without_replacement_with_pool( cnp . int_t n_population,
101
- cnp . int_t n_samples,
109
+ cpdef _sample_without_replacement_with_pool( default_int n_population,
110
+ default_int n_samples,
102
111
random_state=None) :
103
112
""" Sample integers without replacement.
104
113
@@ -131,10 +140,10 @@ cpdef _sample_without_replacement_with_pool(cnp.int_t n_population,
131
140
"""
132
141
_sample_without_replacement_check_input(n_population, n_samples)
133
142
134
- cdef cnp.int_t i
135
- cdef cnp.int_t j
136
- cdef cnp.int_t [::1] out = np.empty((n_samples,), dtype=int)
137
- cdef cnp.int_t [::1] pool = np.empty((n_population,), dtype=int)
143
+ cdef default_int i
144
+ cdef default_int j
145
+ cdef default_int [::1] out = np.empty((n_samples,), dtype=int)
146
+ cdef default_int [::1] pool = np.empty((n_population,), dtype=int)
138
147
139
148
rng = check_random_state(random_state)
140
149
rng_randint = rng.randint
@@ -154,8 +163,8 @@ cpdef _sample_without_replacement_with_pool(cnp.int_t n_population,
154
163
155
164
156
165
cpdef _sample_without_replacement_with_reservoir_sampling(
157
- cnp.int_t n_population,
158
- cnp.int_t n_samples,
166
+ default_int n_population,
167
+ default_int n_samples,
159
168
random_state=None
160
169
):
161
170
""" Sample integers without replacement.
@@ -191,9 +200,9 @@ cpdef _sample_without_replacement_with_reservoir_sampling(
191
200
"""
192
201
_sample_without_replacement_check_input(n_population, n_samples)
193
202
194
- cdef cnp.int_t i
195
- cdef cnp.int_t j
196
- cdef cnp.int_t [::1] out = np.empty((n_samples, ), dtype=int)
203
+ cdef default_int i
204
+ cdef default_int j
205
+ cdef default_int [::1] out = np.empty((n_samples, ), dtype=int)
197
206
198
207
rng = check_random_state(random_state)
199
208
rng_randint = rng.randint
@@ -213,8 +222,8 @@ cpdef _sample_without_replacement_with_reservoir_sampling(
213
222
return np.asarray(out)
214
223
215
224
216
- cpdef sample_without_replacement(cnp.int_t n_population,
217
- cnp.int_t n_samples,
225
+ cdef _sample_without_replacement(default_int n_population,
226
+ default_int n_samples,
218
227
method="auto",
219
228
random_state=None):
220
229
""" Sample integers without replacement.
@@ -303,6 +312,32 @@ cpdef sample_without_replacement(cnp.int_t n_population,
303
312
% (all_methods, method))
304
313
305
314
315
+ def sample_without_replacement(
316
+ object n_population, object n_samples, method="auto", random_state=None):
317
+ cdef:
318
+ cnp.intp_t n_pop_intp, n_samples_intp
319
+ long n_pop_long, n_samples_long
320
+
321
+ # On most platforms `np.int_ is np.intp`. However, before NumPy 2 the
322
+ # default integer `np.int_` was a long which is 32bit on 64bit windows
323
+ # while `intp` is 64bit on 64bit platforms and 32bit on 32bit ones.
324
+ if np.int_ is np.intp:
325
+ # Branch always taken on NumPy >=2 (or when not on 64bit windows).
326
+ # Cython has different rules for conversion of values to integers.
327
+ # For NumPy <1.26.2 AND Cython 3, this first branch requires `int()`
328
+ # called explicitly to allow e.g. floats.
329
+ n_pop_intp = int(n_population)
330
+ n_samples_intp = int(n_samples)
331
+ return _sample_without_replacement(
332
+ n_pop_intp, n_samples_intp, method, random_state)
333
+ else:
334
+ # Branch taken on 64bit windows with Numpy<2.0 where `long` is 32bit
335
+ n_pop_long = n_population
336
+ n_samples_long = n_samples
337
+ return _sample_without_replacement(
338
+ n_pop_long, n_samples_long, method, random_state)
339
+
340
+
306
341
def _our_rand_r_py(seed):
307
342
""" Python utils to test the our_rand_r function"""
308
343
cdef UINT32_t my_seed = seed
0 commit comments