File Coverage

lib/Algorithm/MedianSelect/XS.xs
Criterion Covered Total %
statement 35 40 87.5
branch 30 42 71.4
condition n/a
subroutine n/a
pod n/a
total 65 82 79.2


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);