@@ -16,6 +16,7 @@ ctypedef fused rank_t:
16
16
float64_t
17
17
float32_t
18
18
int64_t
19
+ uint64_t
19
20
object
20
21
21
22
@@ -34,6 +35,7 @@ def group_last(rank_t[:, :] out,
34
35
rank_t val
35
36
ndarray[rank_t, ndim=2] resx
36
37
ndarray[int64_t, ndim=2] nobs
38
+ bint runtime_error = False
37
39
38
40
assert min_count == -1, "'min_count' only used in add and prod"
39
41
@@ -106,11 +108,20 @@ def group_last(rank_t[:, :] out,
106
108
if nobs[i, j] == 0:
107
109
if rank_t is int64_t:
108
110
out[i, j] = NPY_NAT
111
+ elif rank_t is uint64_t:
112
+ runtime_error = True
113
+ break
109
114
else:
110
115
out[i, j] = NAN
111
116
else:
112
117
out[i, j] = resx[i, j]
113
118
119
+ if runtime_error:
120
+ # We cannot raise directly above because that is within a nogil
121
+ # block.
122
+ raise RuntimeError("empty group with uint64_t")
123
+
124
+
114
125
group_last_float64 = group_last["float64_t"]
115
126
group_last_float32 = group_last["float32_t"]
116
127
group_last_int64 = group_last["int64_t"]
@@ -132,6 +143,7 @@ def group_nth(rank_t[:, :] out,
132
143
rank_t val
133
144
ndarray[rank_t, ndim=2] resx
134
145
ndarray[int64_t, ndim=2] nobs
146
+ bint runtime_error = False
135
147
136
148
assert min_count == -1, "'min_count' only used in add and prod"
137
149
@@ -199,11 +211,19 @@ def group_nth(rank_t[:, :] out,
199
211
if nobs[i, j] == 0:
200
212
if rank_t is int64_t:
201
213
out[i, j] = NPY_NAT
214
+ elif rank_t is uint64_t:
215
+ runtime_error = True
216
+ break
202
217
else:
203
218
out[i, j] = NAN
204
219
else:
205
220
out[i, j] = resx[i, j]
206
221
222
+ if runtime_error:
223
+ # We cannot raise directly above because that is within a nogil
224
+ # block.
225
+ raise RuntimeError("empty group with uint64_t")
226
+
207
227
208
228
group_nth_float64 = group_nth["float64_t"]
209
229
group_nth_float32 = group_nth["float32_t"]
@@ -282,12 +302,16 @@ def group_rank(float64_t[:, :] out,
282
302
if ascending ^ (na_option == 'top'):
283
303
if rank_t is int64_t:
284
304
nan_fill_val = np.iinfo(np.int64).max
305
+ elif rank_t is uint64_t:
306
+ nan_fill_val = np.iinfo(np.uint64).max
285
307
else:
286
308
nan_fill_val = np.inf
287
309
order = (masked_vals, mask, labels)
288
310
else:
289
311
if rank_t is int64_t:
290
312
nan_fill_val = np.iinfo(np.int64).min
313
+ elif rank_t is uint64_t:
314
+ nan_fill_val = 0
291
315
else:
292
316
nan_fill_val = -np.inf
293
317
@@ -397,6 +421,7 @@ def group_rank(float64_t[:, :] out,
397
421
group_rank_float64 = group_rank["float64_t"]
398
422
group_rank_float32 = group_rank["float32_t"]
399
423
group_rank_int64 = group_rank["int64_t"]
424
+ group_rank_uint64 = group_rank["uint64_t"]
400
425
# Note: we do not have a group_rank_object because that would require a
401
426
# not-nogil implementation, see GH#19560
402
427
@@ -410,6 +435,7 @@ ctypedef fused groupby_t:
410
435
float64_t
411
436
float32_t
412
437
int64_t
438
+ uint64_t
413
439
414
440
415
441
@cython.wraparound(False)
@@ -426,6 +452,7 @@ def group_max(groupby_t[:, :] out,
426
452
Py_ssize_t i, j, N, K, lab, ncounts = len(counts)
427
453
groupby_t val, count, nan_val
428
454
ndarray[groupby_t, ndim=2] maxx, nobs
455
+ bint runtime_error = False
429
456
430
457
assert min_count == -1, "'min_count' only used in add and prod"
431
458
@@ -439,6 +466,11 @@ def group_max(groupby_t[:, :] out,
439
466
# Note: evaluated at compile-time
440
467
maxx[:] = -_int64_max
441
468
nan_val = NPY_NAT
469
+ elif groupby_t is uint64_t:
470
+ # NB: We do not define nan_val because there is no such thing
471
+ # for uint64_t. We carefully avoid having to reference it in this
472
+ # case.
473
+ maxx[:] = 0
442
474
else:
443
475
maxx[:] = -np.inf
444
476
nan_val = NAN
@@ -462,18 +494,26 @@ def group_max(groupby_t[:, :] out,
462
494
if val > maxx[lab, j]:
463
495
maxx[lab, j] = val
464
496
else:
465
- if val == val and val != nan_val :
497
+ if val == val:
466
498
nobs[lab, j] += 1
467
499
if val > maxx[lab, j]:
468
500
maxx[lab, j] = val
469
501
470
502
for i in range(ncounts):
471
503
for j in range(K):
472
504
if nobs[i, j] == 0:
505
+ if groupby_t is uint64_t:
506
+ runtime_error = True
507
+ break
473
508
out[i, j] = nan_val
474
509
else:
475
510
out[i, j] = maxx[i, j]
476
511
512
+ if runtime_error:
513
+ # We cannot raise directly above because that is within a nogil
514
+ # block.
515
+ raise RuntimeError("empty group with uint64_t")
516
+
477
517
478
518
@cython.wraparound(False)
479
519
@cython.boundscheck(False)
@@ -489,6 +529,7 @@ def group_min(groupby_t[:, :] out,
489
529
Py_ssize_t i, j, N, K, lab, ncounts = len(counts)
490
530
groupby_t val, count, nan_val
491
531
ndarray[groupby_t, ndim=2] minx, nobs
532
+ bint runtime_error = False
492
533
493
534
assert min_count == -1, "'min_count' only used in add and prod"
494
535
@@ -501,6 +542,11 @@ def group_min(groupby_t[:, :] out,
501
542
if groupby_t is int64_t:
502
543
minx[:] = _int64_max
503
544
nan_val = NPY_NAT
545
+ elif groupby_t is uint64_t:
546
+ # NB: We do not define nan_val because there is no such thing
547
+ # for uint64_t. We carefully avoid having to reference it in this
548
+ # case.
549
+ minx[:] = np.iinfo(np.uint64).max
504
550
else:
505
551
minx[:] = np.inf
506
552
nan_val = NAN
@@ -524,18 +570,26 @@ def group_min(groupby_t[:, :] out,
524
570
if val < minx[lab, j]:
525
571
minx[lab, j] = val
526
572
else:
527
- if val == val and val != nan_val :
573
+ if val == val:
528
574
nobs[lab, j] += 1
529
575
if val < minx[lab, j]:
530
576
minx[lab, j] = val
531
577
532
578
for i in range(ncounts):
533
579
for j in range(K):
534
580
if nobs[i, j] == 0:
581
+ if groupby_t is uint64_t:
582
+ runtime_error = True
583
+ break
535
584
out[i, j] = nan_val
536
585
else:
537
586
out[i, j] = minx[i, j]
538
587
588
+ if runtime_error:
589
+ # We cannot raise directly above because that is within a nogil
590
+ # block.
591
+ raise RuntimeError("empty group with uint64_t")
592
+
539
593
540
594
@cython.boundscheck(False)
541
595
@cython.wraparound(False)
@@ -575,6 +629,8 @@ def group_cummin(groupby_t[:, :] out,
575
629
accum = np.empty((ngroups, K), dtype=np.asarray(values).dtype)
576
630
if groupby_t is int64_t:
577
631
accum[:] = _int64_max
632
+ elif groupby_t is uint64_t:
633
+ accum[:] = np.iinfo(np.uint64).max
578
634
else:
579
635
accum[:] = np.inf
580
636
@@ -642,6 +698,8 @@ def group_cummax(groupby_t[:, :] out,
642
698
accum = np.empty((ngroups, K), dtype=np.asarray(values).dtype)
643
699
if groupby_t is int64_t:
644
700
accum[:] = -_int64_max
701
+ elif groupby_t is uint64_t:
702
+ accum[:] = 0
645
703
else:
646
704
accum[:] = -np.inf
647
705
0 commit comments