| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #include "EXTERN.h" | 
| 2 |  |  |  |  |  |  | #include "perl.h" | 
| 3 |  |  |  |  |  |  | #include "XSUB.h" | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | #include "ppport.h" | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | #define croak_msg(msg) \ | 
| 8 |  |  |  |  |  |  | croak ("median(): %s", msg) | 
| 9 |  |  |  |  |  |  | #define croak_msg_internal(msg) \ | 
| 10 |  |  |  |  |  |  | croak ("median(): internal error: %s", msg) | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | enum { LESS_THAN = -1, EQUAL_TO, GREATER_THAN }; | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | static int | 
| 15 | 108 |  |  |  |  |  | quick_sort (const void *arg1, const void *arg2) | 
| 16 |  |  |  |  |  |  | { | 
| 17 | 108 |  |  |  |  |  | const long num1 = *(long *)arg1, num2 = *(long *)arg2; | 
| 18 | 108 | 100 |  |  |  |  | if (num1 < num2) | 
| 19 |  |  |  |  |  |  | return LESS_THAN; | 
| 20 | 60 | 50 |  |  |  |  | else if (num1 == num2) | 
| 21 |  |  |  |  |  |  | return EQUAL_TO; | 
| 22 | 60 | 50 |  |  |  |  | else if (num1 > num2) | 
| 23 |  |  |  |  |  |  | return GREATER_THAN; | 
| 24 |  |  |  |  |  |  | else | 
| 25 | 0 |  |  |  |  |  | croak_msg_internal ("quick sort did not return a long integer"); | 
| 26 |  |  |  |  |  |  | } | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | #define SWAP(num_curr, num_next) \ | 
| 29 |  |  |  |  |  |  | const long tmp = num_curr;   \ | 
| 30 |  |  |  |  |  |  | num_curr = num_next;         \ | 
| 31 |  |  |  |  |  |  | num_next = tmp; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | static void | 
| 34 | 4 |  |  |  |  |  | bubble_sort (long *numbers, unsigned int realitems) | 
| 35 |  |  |  |  |  |  | { | 
| 36 |  |  |  |  |  |  | bool sort; | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | do | 
| 39 |  |  |  |  |  |  | { | 
| 40 |  |  |  |  |  |  | unsigned int i; | 
| 41 |  |  |  |  |  |  | sort = FALSE; | 
| 42 | 176 | 100 |  |  |  |  | for (i = 0; i < (realitems - 1); i++) | 
| 43 |  |  |  |  |  |  | { | 
| 44 | 160 | 100 |  |  |  |  | if (i >= 1 | 
| 45 | 144 | 50 |  |  |  |  | && (numbers[i - 1] <= numbers[i]) && (numbers[i] <= numbers[i + 1])) | 
|  |  | 100 |  |  |  |  |  | 
| 46 | 98 |  |  |  |  |  | continue; /* optimization */ | 
| 47 | 62 | 100 |  |  |  |  | else if (numbers[i] > numbers[i + 1]) | 
| 48 |  |  |  |  |  |  | { | 
| 49 | 52 |  |  |  |  |  | SWAP (numbers[i], numbers[i + 1]); | 
| 50 |  |  |  |  |  |  | sort = TRUE; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  | } | 
| 54 | 16 | 100 |  |  |  |  | while (sort); | 
| 55 | 2 |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | MODULE = Algorithm::MedianSelect::XS        PACKAGE = Algorithm::MedianSelect::XS | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | void | 
| 60 |  |  |  |  |  |  | xs_median (...) | 
| 61 |  |  |  |  |  |  | PROTOTYPE: @\@ | 
| 62 |  |  |  |  |  |  | INIT: | 
| 63 |  |  |  |  |  |  | long *numbers = NULL; | 
| 64 |  |  |  |  |  |  | unsigned int median, realitems; | 
| 65 |  |  |  |  |  |  | enum { BUBBLE_SORT = 1, QUICK_SORT }; | 
| 66 |  |  |  |  |  |  | PPCODE: | 
| 67 | 6 | 100 |  |  |  |  | if (items == 1) | 
| 68 |  |  |  |  |  |  | { | 
| 69 | 3 | 50 |  |  |  |  | if (SvROK (ST(0))) | 
| 70 |  |  |  |  |  |  | { | 
| 71 | 3 | 50 |  |  |  |  | if (SvTYPE (SvRV(ST(0))) == SVt_PVAV) | 
| 72 |  |  |  |  |  |  | { | 
| 73 |  |  |  |  |  |  | AV *aref = (AV *)SvRV (ST(0)); | 
| 74 |  |  |  |  |  |  | unsigned int i; | 
| 75 | 3 |  |  |  |  |  | realitems = av_len (aref) + 1; | 
| 76 | 3 | 50 |  |  |  |  | Newx (numbers, realitems, long); | 
| 77 | 36 | 100 |  |  |  |  | for (i = 0; i < realitems; i++) | 
| 78 | 33 | 50 |  |  |  |  | numbers[i] = (long)SvIV (*av_fetch(aref, i, 0)); | 
| 79 |  |  |  |  |  |  | } | 
| 80 |  |  |  |  |  |  | else | 
| 81 | 0 |  |  |  |  |  | croak_msg ("reference is not an array reference"); | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  | else | 
| 84 | 0 |  |  |  |  |  | croak_msg ("requires either list or reference to an array"); | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  | else | 
| 87 |  |  |  |  |  |  | { | 
| 88 |  |  |  |  |  |  | unsigned int i; | 
| 89 | 3 |  |  |  |  |  | realitems = items; | 
| 90 | 3 | 50 |  |  |  |  | Newx (numbers, realitems, long); | 
| 91 | 36 | 100 |  |  |  |  | for (i = 0; i < realitems; i++) | 
| 92 | 33 | 50 |  |  |  |  | numbers[i] = (long)SvIV (ST(i)); | 
| 93 |  |  |  |  |  |  | } | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 6 | 50 |  |  |  |  | switch (SvIV (get_sv("Algorithm::MedianSelect::XS::ALGORITHM", FALSE))) | 
| 96 |  |  |  |  |  |  | { | 
| 97 |  |  |  |  |  |  | case BUBBLE_SORT: | 
| 98 | 2 |  |  |  |  |  | bubble_sort (numbers, realitems); | 
| 99 | 2 |  |  |  |  |  | break; | 
| 100 |  |  |  |  |  |  | case QUICK_SORT: | 
| 101 | 4 |  |  |  |  |  | qsort (numbers, realitems, sizeof (long), quick_sort); | 
| 102 | 4 |  |  |  |  |  | break; | 
| 103 |  |  |  |  |  |  | default: | 
| 104 | 0 |  |  |  |  |  | croak_msg_internal ("no mode available"); | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  |  | 
| 107 | 6 | 50 |  |  |  |  | if (realitems % 2 == 0) | 
| 108 | 0 |  |  |  |  |  | median = realitems / 2; | 
| 109 |  |  |  |  |  |  | else | 
| 110 | 6 |  |  |  |  |  | median = (realitems - 1) / 2; | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 6 | 50 |  |  |  |  | EXTEND (SP, 1); | 
| 113 | 6 |  |  |  |  |  | PUSHs (sv_2mortal(newSViv(numbers[median]))); | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 6 |  |  |  |  |  | Safefree (numbers); |