@@ -98,10 +98,9 @@ cdef class IntIndex(SparseIndex):
98
98
99
99
cpdef IntIndex intersect(self , SparseIndex y_):
100
100
cdef:
101
- Py_ssize_t out_length, xi, yi = 0
101
+ Py_ssize_t out_length, xi, yi = 0 , result_indexer = 0
102
102
int32_t xind
103
- ndarray[int32_t, ndim= 1 ] xindices, yindices
104
- list new_list = []
103
+ ndarray[int32_t, ndim= 1 ] xindices, yindices, new_indices
105
104
IntIndex y
106
105
107
106
# if is one already, returns self
@@ -112,6 +111,7 @@ cdef class IntIndex(SparseIndex):
112
111
113
112
xindices = self .indices
114
113
yindices = y.indices
114
+ new_indices = np.empty(min (len (xindices), len (yindices)), dtype = np.int32)
115
115
116
116
for xi from 0 <= xi < self .npoints:
117
117
xind = xindices[xi]
@@ -124,9 +124,11 @@ cdef class IntIndex(SparseIndex):
124
124
125
125
# TODO: would a two-pass algorithm be faster?
126
126
if yindices[yi] == xind:
127
- new_list.append(xind)
127
+ new_indices[result_indexer] = xind
128
+ result_indexer += 1
128
129
129
- return IntIndex(self .length, new_list)
130
+ new_indices = new_indices[:result_indexer]
131
+ return IntIndex(self .length, new_indices)
130
132
131
133
cpdef IntIndex make_union(self , SparseIndex y_):
132
134
@@ -238,34 +240,42 @@ cdef class IntIndex(SparseIndex):
238
240
239
241
cpdef get_blocks(ndarray[int32_t, ndim= 1 ] indices):
240
242
cdef:
241
- Py_ssize_t i, npoints
243
+ Py_ssize_t init_len, i, npoints, result_indexer = 0
242
244
int32_t block, length = 1 , cur, prev
243
- list locs = [] , lens = []
245
+ ndarray[int32_t, ndim = 1 ] locs , lens
244
246
245
247
npoints = len (indices)
246
248
247
249
# just handle the special empty case separately
248
250
if npoints == 0 :
249
- return [], []
251
+ return np.array([], dtype = np.int32), np.array([], dtype = np.int32)
252
+
253
+ # block size can't be longer than npoints
254
+ locs = np.empty(npoints, dtype = np.int32)
255
+ lens = np.empty(npoints, dtype = np.int32)
250
256
251
257
# TODO: two-pass algorithm faster?
252
258
prev = block = indices[0 ]
253
259
for i from 1 <= i < npoints:
254
260
cur = indices[i]
255
261
if cur - prev > 1 :
256
262
# new block
257
- locs.append( block)
258
- lens.append( length)
263
+ locs[result_indexer] = block
264
+ lens[result_indexer] = length
259
265
block = cur
260
266
length = 1
267
+ result_indexer += 1
261
268
else :
262
269
# same block, increment length
263
270
length += 1
264
271
265
272
prev = cur
266
273
267
- locs.append(block)
268
- lens.append(length)
274
+ locs[result_indexer] = block
275
+ lens[result_indexer] = length
276
+ result_indexer += 1
277
+ locs = locs[:result_indexer]
278
+ lens = lens[:result_indexer]
269
279
return locs, lens
270
280
271
281
# -------------------------------------------------------------------------------
@@ -398,12 +408,8 @@ cdef class BlockIndex(SparseIndex):
398
408
"""
399
409
cdef:
400
410
BlockIndex y
401
- ndarray[int32_t, ndim= 1 ] xloc, xlen, yloc, ylen
402
-
403
- list out_blocs = []
404
- list out_blengths = []
405
-
406
- Py_ssize_t xi = 0 , yi = 0
411
+ ndarray[int32_t, ndim= 1 ] xloc, xlen, yloc, ylen, out_bloc, out_blen
412
+ Py_ssize_t xi = 0 , yi = 0 , max_len, result_indexer = 0
407
413
int32_t cur_loc, cur_length, diff
408
414
409
415
y = other.to_block_index()
@@ -416,6 +422,11 @@ cdef class BlockIndex(SparseIndex):
416
422
yloc = y.blocs
417
423
ylen = y.blengths
418
424
425
+ # block may be split, but can't exceed original len / 2 + 1
426
+ max_len = int (min (self .length, y.length) / 2 ) + 1
427
+ out_bloc = np.empty(max_len, dtype = np.int32)
428
+ out_blen = np.empty(max_len, dtype = np.int32)
429
+
419
430
while True :
420
431
# we are done (or possibly never began)
421
432
if xi >= self .nblocks or yi >= y.nblocks:
@@ -458,10 +469,14 @@ cdef class BlockIndex(SparseIndex):
458
469
cur_length = ylen[yi]
459
470
yi += 1
460
471
461
- out_blocs.append(cur_loc)
462
- out_blengths.append(cur_length)
472
+ out_bloc[result_indexer] = cur_loc
473
+ out_blen[result_indexer] = cur_length
474
+ result_indexer += 1
463
475
464
- return BlockIndex(self .length, out_blocs, out_blengths)
476
+ out_bloc = out_bloc[:result_indexer]
477
+ out_blen = out_blen[:result_indexer]
478
+
479
+ return BlockIndex(self .length, out_bloc, out_blen)
465
480
466
481
cpdef BlockIndex make_union(self , SparseIndex y):
467
482
"""
@@ -626,15 +641,19 @@ cdef class BlockUnion(BlockMerge):
626
641
627
642
cdef _make_merged_blocks(self ):
628
643
cdef:
629
- ndarray[int32_t, ndim= 1 ] xstart, xend, ystart, yend
644
+ ndarray[int32_t, ndim= 1 ] xstart, xend, ystart, yend, out_bloc, out_blen
630
645
int32_t nstart, nend, diff
631
- list out_blocs = [], out_blengths = []
646
+ Py_ssize_t max_len, result_indexer = 0
632
647
633
648
xstart = self .xstart
634
649
xend = self .xend
635
650
ystart = self .ystart
636
651
yend = self .yend
637
652
653
+ max_len = int (min (self .x.length, self .y.length) / 2 ) + 1
654
+ out_bloc = np.empty(max_len, dtype = np.int32)
655
+ out_blen = np.empty(max_len, dtype = np.int32)
656
+
638
657
while True :
639
658
# we are done (or possibly never began)
640
659
if self .xi >= self .x.nblocks and self .yi >= self .y.nblocks:
@@ -658,10 +677,14 @@ cdef class BlockUnion(BlockMerge):
658
677
nstart = ystart[self .yi]
659
678
nend = self ._find_next_block_end(1 )
660
679
661
- out_blocs.append(nstart)
662
- out_blengths.append(nend - nstart)
680
+ out_bloc[result_indexer] = nstart
681
+ out_blen[result_indexer] = nend - nstart
682
+ result_indexer += 1
683
+
684
+ out_bloc = out_bloc[:result_indexer]
685
+ out_blen = out_blen[:result_indexer]
663
686
664
- return BlockIndex(self .x.length, out_blocs, out_blengths )
687
+ return BlockIndex(self .x.length, out_bloc, out_blen )
665
688
666
689
cdef int32_t _find_next_block_end(self , bint mode) except - 1 :
667
690
"""
0 commit comments