File Coverage

blib/lib/POSIX/bsearch.pm
Criterion Covered Total %
statement 93 96 96.8
branch 32 38 84.2
condition n/a
subroutine 5 5 100.0
pod 0 1 0.0
total 130 140 92.8


line stmt bran cond sub pod time code
1             package POSIX::bsearch;
2              
3 1     1   13112 use 5.000;
  1         4  
  1         41  
4 1     1   6 use strict;
  1         2  
  1         45  
5              
6             require Exporter;
7 1         158 use vars qw($VERSION @ISA @EXPORT
8 1     1   5 $a $b $index $count);
  1         18  
9             @ISA = qw(Exporter);
10             @EXPORT = qw( bsearch );
11              
12             $VERSION = '0.02';
13              
14              
15             sub bsearch(&$\@){
16             # warn "in bsearch with args [@_]";
17 8     8 0 1004 my $comparator = shift;
18 8         14 my ($ca,$cb);
19             {
20 1     1   5 no strict 'refs';
  1         1  
  1         618  
  8         11  
21 8         14 my $callerpackage = caller();
22 8         11 $ca = \*{"$callerpackage\::a"};
  8         23  
23 8         11 $cb = \*{"$callerpackage\::b"};
  8         23  
24             };
25 8         16 local *$ca = \$a;
26 8         13 local *$cb = \$b;
27 8         15 $a = shift;
28 8         13 my $table = shift;
29 8         11 undef($count);
30 8         19 my ($lowerbound,$first,$last,$upperbound) = (-1,-1,-1,0+@$table);
31 8 100       23 $upperbound or return (); # empty list
32            
33 7         9 my ($guess,$compres);
34              
35             # find index
36 7         9 our $icount = 0;
37 7         10 do {{
38             # warn join ', ',$lowerbound,$first,$last,$upperbound;
39 26 50       32 $icount++ > 40 and die "STUCK";
  26         56  
40 26         50 $guess = int (($upperbound + $lowerbound)/2);
41 26 100       54 if ($guess == $lowerbound){
42 1         2 $index = $lowerbound;
43 1         6 return ();
44             };
45 25         40 $b = $table->[$guess];
46 25         61 $compres = &$comparator;
47             # warn "got $compres";
48 25 100       117 if ($compres < 0){
49 10 100       20 unless ($guess){
50             # guess is zero! we are off the low end
51 1         3 $index = -1;
52 1         6 return ();
53             };
54 9         14 $upperbound = $guess;
55 9         24 next;
56             };
57 15 100       40 if ($compres > 0){
58 11 100       29 if ($guess == $#$table){
59             # we are off the high end
60 1         2 $index = @$table;
61 1         6 return ();
62             };
63 10         12 $lowerbound = $guess;
64 10         31 next;
65             };
66             }} while ($compres);
67              
68             # Found something. POSIX semantics actually stops here.
69 4 100       14 wantarray or return $table->[$guess];
70              
71             # call in array context for the special sauce.
72 3         6 ($index,$count) =(-1,0);
73 3         5 my $GoodGuess = $guess;
74 3 50       9 if ($guess == 1+$lowerbound){
75 0         0 $first = $guess;
76             }else{
77             # search for the first
78 3         6 my $upperboun = $guess;
79 3         4 $icount = 0;
80 3         4 for(;;){
81 12 50       27 $icount++ > 40 and die "STUCK";
82             # warn join ', ',SearchingForFirst =>$lowerbound,$first,$last,$upperboun;
83 12         16 $guess = int (( $upperboun + $lowerbound ) /2);
84 12 100       25 if ($guess == $lowerbound){
85            
86 1         2 $first = $upperboun;
87 1         3 last;
88             };
89 11         19 $b = $table->[$guess];
90 11         34 $compres = &$comparator;
91             # warn "got $compres";
92 11 50       49 if ($compres < 0){
93 0         0 die "TABLE NOT SORTED\n";
94             };
95 11 100       22 if ($compres > 0){
96 8         13 $lowerbound = $guess;
97 8         12 next;
98             };
99 3 100       9 if ($guess == 1+ $lowerbound){
100 2         3 $first = $guess;
101 2         4 last;
102             };
103 1         2 $upperboun = $guess;
104             };
105             };
106              
107              
108 3         4 $guess = $GoodGuess;
109 3 50       28 if ($guess == -1+$upperbound){
110 0         0 $last = $guess;
111             }else{
112             # search for the last
113 3         6 my $lowerboun = $guess;
114 3         4 $icount = 0;
115 3         5 for(;;){
116 10 50       24 $icount++ > 40 and die "STUCK";
117             # warn join ', ',SearchingForLast =>$lowerboun,$first,$last,$upperbound;
118 10         18 $guess = int (( $upperbound + $lowerboun ) /2);
119 10         19 $b = $table->[$guess];
120 10         21 $compres = &$comparator;
121             # warn "got $compres";
122 10 100       46 if ($compres > 0){
123 1         11 die "TABLE NOT SORTED\n";
124             };
125 9 100       28 if ($compres < 0){
126 3         5 $upperbound = $guess;
127 3         13 next;
128             };
129 6 100       15 if ($guess == -1+ $upperbound){
130 2         3 $last = $guess;
131 2         4 last;
132             };
133 4         6 $lowerboun = $guess;
134             };
135             };
136             # warn "finished, should have $lowerbound < $first <= $last < $upperbound";
137            
138              
139 2         3 $index = $first;
140 2         5 $count = 1 + $last - $first;
141              
142              
143             # return result
144 2         16 @$table[ $first .. $last ];
145             }
146              
147             1;
148             __END__