edsger 0.1.1__pp39-pypy39_pp73-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ """ Priority queue based on a minimum binary heap. Header file.
2
+ """
3
+
4
+ cimport numpy as cnp
5
+
6
+ from edsger.commons cimport DTYPE_t, ElementState
7
+
8
+
9
+ cdef struct Element:
10
+ DTYPE_t key
11
+ ElementState state
12
+ size_t node_idx
13
+
14
+ cdef struct PriorityQueue:
15
+ size_t length # number of elements in the array
16
+ size_t size # number of elements in the heap
17
+ size_t* A # array storing the binary tree
18
+ Element* Elements # array storing the elements
19
+
20
+ cdef void init_pqueue(PriorityQueue*, size_t, size_t) nogil
21
+ cdef void free_pqueue(PriorityQueue*) nogil
22
+ cdef void insert(PriorityQueue*, size_t, DTYPE_t) nogil
23
+ cdef DTYPE_t peek(PriorityQueue*) nogil
24
+ cdef size_t extract_min(PriorityQueue*) nogil
25
+ cdef bint is_empty(PriorityQueue*) nogil
26
+ cdef void decrease_key(PriorityQueue*, size_t, DTYPE_t) nogil
27
+ cdef cnp.ndarray copy_keys_to_numpy(PriorityQueue*, size_t)
28
+
29
+
30
+ # author : Francois Pacull
31
+ # copyright : Architecture & Performance
32
+ # email: francois.pacull@architecture-performance.fr
33
+ # license : MIT
@@ -0,0 +1,692 @@
1
+ """
2
+ Priority queue based on a minimum 4-ary heap.
3
+
4
+ - dec: priority queue with decrease-key operation.
5
+ - 0b: indices are zero-based
6
+
7
+ cdef functions:
8
+
9
+ - init_pqueue
10
+ Initialize the priority queue.
11
+ - _initialize_element
12
+ Initialize a single element.
13
+ - free_pqueue
14
+ Free the priority queue.
15
+ - insert
16
+ Insert an element into the heap and reorder the heap.
17
+ - decrease_key
18
+ Decrease the key of a element in the heap, given its element index.
19
+ - peek
20
+ Find heap min key.
21
+ - is_empty
22
+ Check if the heap is empty.
23
+ - extract_min
24
+ Extract element with min keay from the heap,
25
+ and return its element index.
26
+ - copy_keys_to_numpy
27
+ Copy the keys into a numpy array.
28
+ - _exchange_nodes
29
+ Exchange two nodes in the heap.
30
+ - _min_heapify
31
+ Re-order sub-tree under a given node (given its node index)
32
+ until it satisfies the heap property.
33
+ - _decrease_key_from_node_index
34
+ Decrease the key of an element in the heap, given its tree index.
35
+
36
+ """
37
+
38
+ cimport numpy as cnp
39
+ from libc.stdlib cimport free, malloc
40
+
41
+ from edsger.commons import DTYPE_PY
42
+ from edsger.commons cimport (
43
+ DTYPE_INF, LABELED, UNLABELED, SCANNED, DTYPE_t
44
+ )
45
+
46
+
47
+ cdef void init_pqueue(
48
+ PriorityQueue* pqueue,
49
+ size_t heap_length,
50
+ size_t element_count) nogil noexcept:
51
+ """
52
+ Initialize the priority queue.
53
+
54
+ input
55
+ =====
56
+ * PriorityQueue* pqueue : priority queue
57
+ * size_t length : length (maximum size) of the heap
58
+ * size_t element_count : element count
59
+
60
+ assumptions
61
+ ===========
62
+ * heap_length <= element_count
63
+ """
64
+ cdef size_t i
65
+
66
+ pqueue.length = heap_length
67
+ pqueue.size = 0
68
+ pqueue.A = <size_t*> malloc(heap_length * sizeof(size_t))
69
+ pqueue.Elements = <Element*> malloc(element_count * sizeof(Element))
70
+
71
+ for i in range(heap_length):
72
+ pqueue.A[i] = heap_length
73
+ _initialize_element(pqueue, i)
74
+ for i in range(heap_length, element_count):
75
+ _initialize_element(pqueue, i)
76
+
77
+
78
+ cdef void _initialize_element(
79
+ PriorityQueue* pqueue,
80
+ size_t element_idx) nogil noexcept:
81
+ """
82
+ Initialize a single element.
83
+
84
+ input
85
+ =====
86
+ * PriorityQueue* pqueue : priority queue
87
+ * size_t element_idx : index of the element in the element array
88
+ """
89
+ pqueue.Elements[element_idx].key = DTYPE_INF
90
+ pqueue.Elements[element_idx].state = UNLABELED
91
+ pqueue.Elements[element_idx].node_idx = pqueue.length
92
+
93
+
94
+ cdef void free_pqueue(
95
+ PriorityQueue* pqueue) nogil noexcept:
96
+ """
97
+ Free the priority queue.
98
+
99
+ input
100
+ =====
101
+ * PriorityQueue* pqueue : priority queue
102
+ """
103
+ free(pqueue.A)
104
+ free(pqueue.Elements)
105
+
106
+
107
+ cdef void insert(
108
+ PriorityQueue* pqueue,
109
+ size_t element_idx,
110
+ DTYPE_t key) nogil noexcept:
111
+ """
112
+ Insert an element into the heap and reorder the heap.
113
+
114
+ input
115
+ =====
116
+ * PriorityQueue* pqueue : priority queue
117
+ * size_t element_idx : index of the element in the element array
118
+ * DTYPE_t key : key value of the element
119
+
120
+ assumptions
121
+ ===========
122
+ * the element pqueue.Elements[element_idx] is not in the heap
123
+ * its new key is smaller than DTYPE_INF
124
+ """
125
+ cdef size_t node_idx = pqueue.size
126
+
127
+ pqueue.size += 1
128
+ pqueue.Elements[element_idx].state = LABELED
129
+ pqueue.Elements[element_idx].node_idx = node_idx
130
+ pqueue.A[node_idx] = element_idx
131
+ _decrease_key_from_node_index(pqueue, node_idx, key)
132
+
133
+
134
+ cdef void decrease_key(
135
+ PriorityQueue* pqueue,
136
+ size_t element_idx,
137
+ DTYPE_t key_new) nogil noexcept:
138
+ """
139
+ Decrease the key of a element in the heap, given its element index.
140
+
141
+ input
142
+ =====
143
+ * PriorityQueue* pqueue : priority queue
144
+ * size_t element_idx : index of the element in the element array
145
+ * DTYPE_t key_new : new value of the element key
146
+
147
+ assumption
148
+ ==========
149
+ * pqueue.Elements[idx] is in the heap
150
+ """
151
+ _decrease_key_from_node_index(
152
+ pqueue,
153
+ pqueue.Elements[element_idx].node_idx,
154
+ key_new)
155
+
156
+
157
+ cdef DTYPE_t peek(PriorityQueue* pqueue) nogil noexcept:
158
+ """
159
+ Find heap min key.
160
+
161
+ input
162
+ =====
163
+ * PriorityQueue* pqueue : priority queue
164
+
165
+ output
166
+ ======
167
+ * DTYPE_t : key value of the min element
168
+
169
+ assumption
170
+ ==========
171
+ * pqueue.size > 0
172
+ * heap is heapified
173
+ """
174
+ return pqueue.Elements[pqueue.A[0]].key
175
+
176
+
177
+ cdef bint is_empty(PriorityQueue* pqueue) nogil noexcept:
178
+ """
179
+ Check if the heap is empty.
180
+
181
+ input
182
+ =====
183
+ * PriorityQueue* pqueue : priority queue
184
+ """
185
+ cdef bint isempty = 0
186
+
187
+ if pqueue.size == 0:
188
+ isempty = 1
189
+
190
+ return isempty
191
+
192
+
193
+ cdef size_t extract_min(PriorityQueue* pqueue) nogil noexcept:
194
+ """
195
+ Extract element with min keay from the heap,
196
+ and return its element index.
197
+
198
+ input
199
+ =====
200
+ * PriorityQueue* pqueue : priority queue
201
+
202
+ output
203
+ ======
204
+ * size_t : element index with min key
205
+
206
+ assumption
207
+ ==========
208
+ * pqueue.size > 0
209
+ """
210
+ cdef:
211
+ size_t element_idx = pqueue.A[0] # min element index
212
+ size_t node_idx = pqueue.size - 1 # last leaf node index
213
+
214
+ # exchange the root node with the last leaf node
215
+ _exchange_nodes(pqueue, 0, node_idx)
216
+
217
+ # remove this element from the heap
218
+ pqueue.Elements[element_idx].state = SCANNED
219
+ pqueue.Elements[element_idx].node_idx = pqueue.length
220
+ pqueue.A[node_idx] = pqueue.length
221
+ pqueue.size -= 1
222
+
223
+ # reorder the tree Elements from the root node
224
+ _min_heapify(pqueue, 0)
225
+
226
+ return element_idx
227
+
228
+
229
+ cdef cnp.ndarray copy_keys_to_numpy(
230
+ PriorityQueue* pqueue,
231
+ size_t vertex_count
232
+ ) noexcept:
233
+ """
234
+ Copy the keys into a numpy array.
235
+
236
+ input
237
+ =====
238
+ * PriorityQueue* pqueue : priority queue
239
+ * int vertex_count : vertex count
240
+ * int num_threads : number of threads for the parallel job
241
+
242
+ output
243
+ ======
244
+ * cnp.ndarray : NumPy array with all the keys
245
+ """
246
+
247
+ path_lengths = cnp.ndarray(vertex_count, dtype=DTYPE_PY)
248
+
249
+ cdef:
250
+ size_t i # loop counter
251
+ DTYPE_t[::1] path_lengths_view = path_lengths
252
+
253
+ with nogil:
254
+
255
+ for i in range(vertex_count):
256
+ path_lengths_view[i] = pqueue.Elements[i].key
257
+
258
+ return path_lengths
259
+
260
+
261
+ cdef void _exchange_nodes(
262
+ PriorityQueue* pqueue,
263
+ size_t node_i,
264
+ size_t node_j) nogil noexcept:
265
+ """
266
+ Exchange two nodes in the heap.
267
+
268
+ input
269
+ =====
270
+ * PriorityQueue* pqueue : priority queue
271
+ * size_t node_i: first node index
272
+ * size_t node_j: second node index
273
+ """
274
+ cdef:
275
+ size_t element_i = pqueue.A[node_i]
276
+ size_t element_j = pqueue.A[node_j]
277
+
278
+ # exchange element indices in the heap array
279
+ pqueue.A[node_i] = element_j
280
+ pqueue.A[node_j] = element_i
281
+
282
+ # exchange node indices in the element array
283
+ pqueue.Elements[element_j].node_idx = node_i
284
+ pqueue.Elements[element_i].node_idx = node_j
285
+
286
+
287
+ cdef void _min_heapify(
288
+ PriorityQueue* pqueue,
289
+ size_t node_idx) nogil noexcept:
290
+ """
291
+ Re-order sub-tree under a given node (given its node index)
292
+ until it satisfies the heap property.
293
+
294
+ input
295
+ =====
296
+ * PriorityQueue* pqueue : priority queue
297
+ * size_t node_idx : node index
298
+ """
299
+ cdef:
300
+ size_t c1, c2, c3, c4, i = node_idx, s
301
+ DTYPE_t val_tmp, val_min
302
+
303
+ while True:
304
+
305
+ c1 = 4 * i + 1
306
+ c2 = c1 + 1
307
+ c3 = c2 + 1
308
+ c4 = c3 + 1
309
+
310
+ s = i
311
+ val_min = pqueue.Elements[pqueue.A[s]].key
312
+ if (c4 < pqueue.size):
313
+ val_tmp = pqueue.Elements[pqueue.A[c4]].key
314
+ if val_tmp < val_min:
315
+ s = c4
316
+ val_min = val_tmp
317
+ val_tmp = pqueue.Elements[pqueue.A[c3]].key
318
+ if val_tmp < val_min:
319
+ s = c3
320
+ val_min = val_tmp
321
+ val_tmp = pqueue.Elements[pqueue.A[c2]].key
322
+ if val_tmp < val_min:
323
+ s = c2
324
+ val_min = val_tmp
325
+ val_tmp = pqueue.Elements[pqueue.A[c1]].key
326
+ if val_tmp < val_min:
327
+ s = c1
328
+ else:
329
+ if (c3 < pqueue.size):
330
+ val_tmp = pqueue.Elements[pqueue.A[c3]].key
331
+ if val_tmp < val_min:
332
+ s = c3
333
+ val_min = val_tmp
334
+ val_tmp = pqueue.Elements[pqueue.A[c2]].key
335
+ if val_tmp < val_min:
336
+ s = c2
337
+ val_min = val_tmp
338
+ val_tmp = pqueue.Elements[pqueue.A[c1]].key
339
+ if val_tmp < val_min:
340
+ s = c1
341
+ else:
342
+ if (c2 < pqueue.size):
343
+ val_tmp = pqueue.Elements[pqueue.A[c2]].key
344
+ if val_tmp < val_min:
345
+ s = c2
346
+ val_min = val_tmp
347
+ val_tmp = pqueue.Elements[pqueue.A[c1]].key
348
+ if val_tmp < val_min:
349
+ s = c1
350
+ else:
351
+ if (c1 < pqueue.size):
352
+ val_tmp = pqueue.Elements[pqueue.A[c1]].key
353
+ if val_tmp < val_min:
354
+ s = c1
355
+
356
+ if s != i:
357
+ _exchange_nodes(pqueue, i, s)
358
+ i = s
359
+ else:
360
+ break
361
+
362
+
363
+ cdef void _decrease_key_from_node_index(
364
+ PriorityQueue* pqueue,
365
+ size_t node_idx,
366
+ DTYPE_t key_new) nogil noexcept:
367
+ """
368
+ Decrease the key of an element in the heap, given its tree index.
369
+
370
+ input
371
+ =====
372
+ * PriorityQueue* pqueue : priority queue
373
+ * size_t node_idx : node index
374
+ * DTYPE_t key_new : new key value
375
+
376
+ assumptions
377
+ ===========
378
+ * pqueue.Elements[pqueue.A[node_idx]] is in the heap (node_idx < pqueue.size)
379
+ * key_new < pqueue.Elements[pqueue.A[node_idx]].key
380
+ """
381
+ cdef:
382
+ size_t i = node_idx, j
383
+ DTYPE_t key_j
384
+
385
+ pqueue.Elements[pqueue.A[i]].key = key_new
386
+ while i > 0:
387
+ j = (i - 1) // 4
388
+ key_j = pqueue.Elements[pqueue.A[j]].key
389
+ if key_j > key_new:
390
+ _exchange_nodes(pqueue, i, j)
391
+ i = j
392
+ else:
393
+ break
394
+
395
+
396
+ # ============================================================================ #
397
+ # tests #
398
+ # ============================================================================ #
399
+
400
+ import numpy as np
401
+
402
+
403
+ cpdef init_01(int length=4):
404
+ """
405
+ Initialize an empty priority queue.
406
+ """
407
+
408
+ cdef:
409
+ PriorityQueue pqueue
410
+ size_t length_val = <size_t>length
411
+
412
+ init_pqueue(&pqueue, length_val, length_val)
413
+
414
+ assert pqueue.length == length_val
415
+ assert pqueue.size == 0
416
+ for i in range(length_val):
417
+ assert pqueue.A[i] == pqueue.length
418
+ assert pqueue.Elements[i].key == DTYPE_INF
419
+ assert pqueue.Elements[i].state == UNLABELED
420
+ assert pqueue.Elements[i].node_idx == pqueue.length
421
+
422
+ free_pqueue(&pqueue)
423
+
424
+
425
+ cpdef insert_01():
426
+ """
427
+ Insert an element into an empty priority queue of length 1.
428
+ """
429
+
430
+ cdef:
431
+ PriorityQueue pqueue
432
+ DTYPE_t key
433
+
434
+ init_pqueue(&pqueue, 1, 1)
435
+ assert pqueue.length == 1
436
+ key = 1.0
437
+ insert(&pqueue, 0, key)
438
+ assert pqueue.size == 1
439
+ assert pqueue.A[0] == 0
440
+ assert pqueue.Elements[0].key == key
441
+ assert pqueue.Elements[0].state == LABELED
442
+ assert pqueue.Elements[0].node_idx == 0
443
+
444
+ free_pqueue(&pqueue)
445
+
446
+
447
+ cpdef insert_02():
448
+ """
449
+ Insert 4 elements into an empty priority queue of length 4.
450
+ """
451
+
452
+ cdef:
453
+ PriorityQueue pqueue
454
+ DTYPE_t key
455
+
456
+ init_pqueue(&pqueue, 4, 4)
457
+
458
+ elem_idx = 1
459
+ key = 3.0
460
+ insert(&pqueue, elem_idx, key)
461
+ A_ref = [1, 4, 4, 4]
462
+ for i in range(4):
463
+ assert pqueue.A[i] == A_ref[i]
464
+ assert pqueue.Elements[elem_idx].key == key
465
+ assert pqueue.Elements[elem_idx].state == LABELED
466
+ assert pqueue.Elements[1].node_idx == 0
467
+ assert pqueue.size == 1
468
+
469
+ elem_idx = 0
470
+ key = 2.0
471
+ insert(&pqueue, elem_idx, key)
472
+ A_ref = [0, 1, 4, 4]
473
+ for i in range(4):
474
+ assert pqueue.A[i] == A_ref[i]
475
+ assert pqueue.Elements[elem_idx].key == key
476
+ assert pqueue.Elements[elem_idx].state == LABELED
477
+ assert pqueue.Elements[0].node_idx == 0
478
+ assert pqueue.Elements[1].node_idx == 1
479
+ assert pqueue.size == 2
480
+
481
+ elem_idx = 3
482
+ key = 4.0
483
+ insert(&pqueue, elem_idx, key)
484
+ A_ref = [0, 1, 3, 4]
485
+ for i in range(4):
486
+ assert pqueue.A[i] == A_ref[i]
487
+ assert pqueue.Elements[elem_idx].key == key
488
+ assert pqueue.Elements[elem_idx].state == LABELED
489
+ assert pqueue.Elements[0].node_idx == 0
490
+ assert pqueue.Elements[1].node_idx == 1
491
+ assert pqueue.Elements[3].node_idx == 2
492
+ assert pqueue.size == 3
493
+
494
+ elem_idx = 2
495
+ key = 1.0
496
+ insert(&pqueue, elem_idx, key)
497
+ A_ref = [2, 1, 3, 0]
498
+ for i in range(4):
499
+ assert pqueue.A[i] == A_ref[i]
500
+ assert pqueue.Elements[2].key == key
501
+ assert pqueue.Elements[2].state == LABELED
502
+ assert pqueue.Elements[0].node_idx == 3
503
+ assert pqueue.Elements[1].node_idx == 1
504
+ assert pqueue.Elements[2].node_idx == 0
505
+ assert pqueue.Elements[3].node_idx == 2
506
+ assert pqueue.size == 4
507
+
508
+ free_pqueue(&pqueue)
509
+
510
+
511
+ cpdef insert_03(int length=4):
512
+ """
513
+ Insert elements with equal key values.
514
+ """
515
+
516
+ cdef:
517
+ PriorityQueue pqueue
518
+ size_t i, length_val = <size_t>length
519
+ DTYPE_t key = 1.0
520
+
521
+ init_pqueue(&pqueue, length_val, length_val)
522
+ for i in range(length_val):
523
+ insert(&pqueue, i, key)
524
+ for i in range(length_val):
525
+ assert pqueue.A[i] == i
526
+
527
+ free_pqueue(&pqueue)
528
+
529
+
530
+ cpdef peek_01():
531
+ """
532
+ Successively insert elements into a priority queue and
533
+ check the min element of the priority without extracting it.
534
+ """
535
+
536
+ cdef PriorityQueue pqueue
537
+
538
+ init_pqueue(&pqueue, 4, 4)
539
+
540
+ insert(&pqueue, 0, 9.0)
541
+ assert peek(&pqueue) == 9.0
542
+ insert(&pqueue, 1, 9.0)
543
+ assert peek(&pqueue) == 9.0
544
+ insert(&pqueue, 2, 5.0)
545
+ assert peek(&pqueue) == 5.0
546
+ insert(&pqueue, 3, 3.0)
547
+ assert peek(&pqueue) == 3.0
548
+
549
+ free_pqueue(&pqueue)
550
+
551
+
552
+ cpdef extract_min_01():
553
+ """
554
+ Insert 4 elements into a priority queue and
555
+ extract them all.
556
+ """
557
+
558
+ cdef PriorityQueue pqueue
559
+
560
+ init_pqueue(&pqueue, 4, 4)
561
+ insert(&pqueue, 1, 3.0)
562
+ insert(&pqueue, 0, 2.0)
563
+ insert(&pqueue, 3, 4.0)
564
+ insert(&pqueue, 2, 1.0)
565
+ idx = extract_min(&pqueue)
566
+ assert idx == 2
567
+ assert pqueue.size == 3
568
+ assert pqueue.Elements[idx].state == SCANNED
569
+ idx = extract_min(&pqueue)
570
+ assert idx == 0
571
+ assert pqueue.size == 2
572
+ assert pqueue.Elements[idx].state == SCANNED
573
+ idx = extract_min(&pqueue)
574
+ assert idx == 1
575
+ assert pqueue.size == 1
576
+ assert pqueue.Elements[idx].state == SCANNED
577
+ idx = extract_min(&pqueue)
578
+ assert idx == 3
579
+ assert pqueue.size == 0
580
+ assert pqueue.Elements[idx].state == SCANNED
581
+
582
+ free_pqueue(&pqueue)
583
+
584
+
585
+ cpdef is_empty_01():
586
+ """
587
+ Insert an element and extract it.
588
+ """
589
+
590
+ cdef PriorityQueue pqueue
591
+
592
+ init_pqueue(&pqueue, 2, 2)
593
+
594
+ assert is_empty(&pqueue) == 1
595
+ insert(&pqueue, 1, 3.0)
596
+ assert is_empty(&pqueue) == 0
597
+ idx = extract_min(&pqueue)
598
+ assert is_empty(&pqueue) == 1
599
+
600
+ free_pqueue(&pqueue)
601
+
602
+
603
+ cpdef decrease_key_01():
604
+ """
605
+ Insert elements into a priority queue and decrease the largest
606
+ key value to become the smallest.
607
+ """
608
+
609
+ cdef PriorityQueue pqueue
610
+
611
+ init_pqueue(&pqueue, 4, 4)
612
+
613
+ insert(&pqueue, 1, 3.0)
614
+ insert(&pqueue, 0, 2.0)
615
+ insert(&pqueue, 3, 4.0)
616
+ insert(&pqueue, 2, 1.0)
617
+
618
+ assert pqueue.size == 4
619
+ A_ref = [2, 1, 3, 0]
620
+ n_ref = [3, 1, 0, 2]
621
+ key_ref = [2.0, 3.0, 1.0, 4.0]
622
+ for i in range(4):
623
+ assert pqueue.A[i] == A_ref[i]
624
+ assert pqueue.Elements[i].node_idx == n_ref[i]
625
+ assert pqueue.Elements[i].state == LABELED
626
+ assert pqueue.Elements[i].key == key_ref[i]
627
+
628
+ decrease_key(&pqueue, 3, 0.0)
629
+
630
+ assert pqueue.size == 4
631
+ A_ref = [3, 1, 2, 0]
632
+ n_ref = [3, 1, 2, 0]
633
+ key_ref = [2.0, 3.0, 1.0, 0.0]
634
+ for i in range(4):
635
+ assert pqueue.A[i] == A_ref[i]
636
+ assert pqueue.Elements[i].node_idx == n_ref[i]
637
+ assert pqueue.Elements[i].state == LABELED
638
+ assert pqueue.Elements[i].key == key_ref[i]
639
+
640
+ decrease_key(&pqueue, 1, -1.0)
641
+
642
+ assert pqueue.size == 4
643
+ A_ref = [1, 3, 2, 0]
644
+ n_ref = [3, 0, 2, 1]
645
+ key_ref = [2.0, -1.0, 1.0, 0.0]
646
+ for i in range(4):
647
+ assert pqueue.A[i] == A_ref[i]
648
+ assert pqueue.Elements[i].node_idx == n_ref[i]
649
+ assert pqueue.Elements[i].state == LABELED
650
+ assert pqueue.Elements[i].key == key_ref[i]
651
+
652
+ free_pqueue(&pqueue)
653
+
654
+
655
+ cdef void heapsort(DTYPE_t[::1] values_in, DTYPE_t[::1] values_out) nogil:
656
+ """
657
+ Heap sort by inerting all the values into the priority queue,
658
+ and extracting them.
659
+ """
660
+
661
+ cdef:
662
+ size_t i, length_val = <size_t>values_in.shape[0]
663
+ PriorityQueue pqueue
664
+
665
+ init_pqueue(&pqueue, length_val, length_val)
666
+ for i in range(length_val):
667
+ insert(&pqueue, i, values_in[i])
668
+ for i in range(length_val):
669
+ values_out[i] = pqueue.Elements[extract_min(&pqueue)].key
670
+ free_pqueue(&pqueue)
671
+
672
+
673
+ cpdef sort_01(int n, random_seed=124):
674
+ """
675
+ Create an array of random number, sort it with the heapsort function
676
+ and with the numpy default sort function, compare the results.
677
+ """
678
+
679
+ cdef PriorityQueue pqueue
680
+
681
+ rng = np.random.default_rng(random_seed)
682
+ values_in = rng.random(size=n)
683
+ values_out = np.empty_like(values_in, dtype=DTYPE_PY)
684
+ heapsort(values_in, values_out)
685
+ values_in_sorted = np.sort(values_in)
686
+ np.testing.assert_array_equal(values_in_sorted, values_out)
687
+
688
+
689
+ # author : Francois Pacull
690
+ # copyright : Architecture & Performance
691
+ # email: francois.pacull@architecture-performance.fr
692
+ # license : MIT