File Coverage

blib/lib/List/MoreUtils/PP.pm
Criterion Covered Total %
statement 416 438 94.9
branch 152 174 87.3
condition 42 56 75.0
subroutine 69 72 95.8
pod 0 60 0.0
total 679 800 84.8


line stmt bran cond sub pod time code
1             package List::MoreUtils::PP;
2              
3 118     118   1677 use 5.008_001;
  118         365  
4 118     118   537 use strict;
  118         207  
  118         2252  
5 118     118   597 use warnings;
  118         223  
  118         53072  
6              
7             our $VERSION = '0.426';
8              
9             =pod
10              
11             =head1 NAME
12              
13             List::MoreUtils::PP - Provide List::MoreUtils pure Perl implementation
14              
15             =head1 SYNOPSIS
16              
17             BEGIN { $ENV{LIST_MOREUTILS_PP} = 1; }
18             use List::MoreUtils qw(:all);
19              
20             =cut
21              
22             sub any (&@)
23             {
24 13     13 0 2074 my $f = shift;
25 13         32 foreach (@_)
26             {
27 40005 100       107810 return 1 if $f->();
28             }
29 2         21 return 0;
30             }
31              
32             sub all (&@)
33             {
34 9     9 0 1407 my $f = shift;
35 9         15 foreach (@_)
36             {
37 25005 100       67363 return 0 unless $f->();
38             }
39 3         25 return 1;
40             }
41              
42             sub none (&@)
43             {
44 9     9 0 1639 my $f = shift;
45 9         26 foreach (@_)
46             {
47 40002 100       109797 return 0 if $f->();
48             }
49 3         35 return 1;
50             }
51              
52             sub notall (&@)
53             {
54 9     9 0 1438 my $f = shift;
55 9         20 foreach (@_)
56             {
57 20006 100       53585 return 1 unless $f->();
58             }
59 2         18 return 0;
60             }
61              
62             sub one (&@)
63             {
64 15     15 0 12041 my $f = shift;
65 15         1382 my $found = 0;
66 15         1360 foreach (@_)
67             {
68 2667 100 100     432975 $f->() and $found++ and return 0;
69             }
70 4         23 $found;
71             }
72              
73             sub any_u (&@)
74             {
75 13     13 0 25751 my $f = shift;
76 13 100       38 return if !@_;
77 12   100     42 $f->() and return 1 foreach (@_);
78 1         15953 return 0;
79             }
80              
81             sub all_u (&@)
82             {
83 9     9 0 1410 my $f = shift;
84 9 100       27 return if !@_;
85 8   100     28 $f->() or return 0 foreach (@_);
86 2         31030 return 1;
87             }
88              
89             sub none_u (&@)
90             {
91 9     9 0 25119 my $f = shift;
92 9 100       28 return if !@_;
93 8   100     32 $f->() and return 0 foreach (@_);
94 2         31733 return 1;
95             }
96              
97             sub notall_u (&@)
98             {
99 9     9 0 1513 my $f = shift;
100 9 100       31 return if !@_;
101 8   100     28 $f->() or return 1 foreach (@_);
102 1         17820 return 0;
103             }
104              
105             sub one_u (&@)
106             {
107 16     16 0 12021 my $f = shift;
108 16 100       1397 return if !@_;
109 15         1365 my $found = 0;
110 15         1381 foreach (@_)
111             {
112 2667 100 100     413837 $f->() and $found++ and return 0;
113             }
114 4         21 $found;
115             }
116              
117             sub reduce_u(&@)
118             {
119 8     8 0 3483 my $code = shift;
120              
121             # Localise $a, $b
122             my ($caller_a, $caller_b) = do
123 8         11 {
124 8         15 my $pkg = caller();
125 118     118   760 no strict 'refs';
  118         227  
  118         15179  
126 8         9 \*{$pkg . '::a'}, \*{$pkg . '::b'};
  8         20  
  8         20  
127             };
128              
129 8         22 local (*$caller_a, *$caller_b);
130 8         13 *$caller_a = \();
131 8         21 for (0 .. $#_)
132             {
133 224         530 *$caller_b = \$_[$_];
134 224         289 *$caller_a = \($code->());
135             }
136              
137 5         18 ${*$caller_a};
  5         22  
138             }
139              
140             sub reduce_0(&@)
141             {
142 9     9 0 3702 my $code = shift;
143              
144             # Localise $a, $b
145             my ($caller_a, $caller_b) = do
146 9         13 {
147 9         18 my $pkg = caller();
148 118     118   730 no strict 'refs';
  118         276  
  118         14120  
149 9         13 \*{$pkg . '::a'}, \*{$pkg . '::b'};
  9         28  
  9         23  
150             };
151              
152 9         25 local (*$caller_a, *$caller_b);
153 9         14 *$caller_a = \0;
154 9         25 for (0 .. $#_)
155             {
156 231         514 *$caller_b = \$_[$_];
157 231         290 *$caller_a = \($code->());
158             }
159              
160 6         31 ${*$caller_a};
  6         27  
161             }
162              
163             sub reduce_1(&@)
164             {
165 1     1 0 113 my $code = shift;
166              
167             # Localise $a, $b
168             my ($caller_a, $caller_b) = do
169 1         3 {
170 1         4 my $pkg = caller();
171 118     118   695 no strict 'refs';
  118         219  
  118         124299  
172 1         3 \*{$pkg . '::a'}, \*{$pkg . '::b'};
  1         7  
  1         7  
173             };
174              
175 1         7 local (*$caller_a, *$caller_b);
176 1         3 *$caller_a = \1;
177 1         6 for (0 .. $#_)
178             {
179 750         2150 *$caller_b = \$_[$_];
180 750         1021 *$caller_a = \($code->());
181             }
182              
183 1         4 ${*$caller_a};
  1         7  
184             }
185              
186             sub true (&@)
187             {
188 10     10 0 3630 my $f = shift;
189 10         21 my $count = 0;
190 10   66     56 $f->() and ++$count foreach (@_);
191 9         157134 return $count;
192             }
193              
194             sub false (&@)
195             {
196 10     10 0 3017 my $f = shift;
197 10         21 my $count = 0;
198 10   66     48 $f->() or ++$count foreach (@_);
199 9         118051 return $count;
200             }
201              
202             sub firstidx (&@)
203             {
204 33     33 0 4778 my $f = shift;
205 33         1441 foreach my $i (0 .. $#_)
206             {
207 50066         161719 local *_ = \$_[$i];
208 50066 100       76234 return $i if $f->();
209             }
210 5         39 return -1;
211             }
212              
213             sub firstval (&@)
214             {
215 8     8 0 2425 my $test = shift;
216 8         17 foreach (@_)
217             {
218 21 100       68 return $_ if $test->();
219             }
220 3         11 return undef;
221             }
222              
223             sub firstres (&@)
224             {
225 7     7 0 3292 my $test = shift;
226 7         15 foreach (@_)
227             {
228 21         36 my $testval = $test->();
229 20 100       77 $testval and return $testval;
230             }
231 2         4 return undef;
232             }
233              
234             sub onlyidx (&@)
235             {
236 17     17 0 404 my $f = shift;
237 17         19 my $found;
238 17         39 foreach my $i (0 .. $#_)
239             {
240 3521         10067 local *_ = \$_[$i];
241 3521 100       4573 $f->() or next;
242 22 100       92 defined $found and return -1;
243 14         22 $found = $i;
244             }
245 8 100       46 return defined $found ? $found : -1;
246             }
247              
248             sub onlyval (&@)
249             {
250 17     17 0 426 my $test = shift;
251 17         21 my $result = undef;
252 17         22 my $found = 0;
253 17         31 foreach (@_)
254             {
255 3521 100       9208 $test->() or next;
256 22         65 $result = $_;
257 22 100       48 $found++ and return undef;
258             }
259 8         39 return $result;
260             }
261              
262             sub onlyres (&@)
263             {
264 15     15 0 438 my $test = shift;
265 15         18 my $result = undef;
266 15         19 my $found = 0;
267 15         28 foreach (@_)
268             {
269 2921 100       8001 my $rv = $test->() or next;
270 20         59 $result = $rv;
271 20 100       47 $found++ and return undef;
272             }
273 6 100       34 return $found ? $result : undef;
274             }
275              
276             sub lastidx (&@)
277             {
278 13     13 0 1874 my $f = shift;
279 13         1166 foreach my $i (reverse 0 .. $#_)
280             {
281 20009         58719 local *_ = \$_[$i];
282 20009 100       26850 return $i if $f->();
283             }
284 4         323 return -1;
285             }
286              
287             sub lastval (&@)
288             {
289 8     8 0 2479 my $test = shift;
290 8         8 my $ix;
291 8         26 for ($ix = $#_; $ix >= 0; $ix--)
292             {
293 13         22 local *_ = \$_[$ix];
294 13         29 my $testval = $test->();
295              
296             # Simulate $_ as alias
297 12         32 $_[$ix] = $_;
298 12 100       31 return $_ if $testval;
299             }
300 3         8 return undef;
301             }
302              
303             sub lastres (&@)
304             {
305 7     7 0 2344 my $test = shift;
306 7         12 my $ix;
307 7         20 for ($ix = $#_; $ix >= 0; $ix--)
308             {
309 13         22 local *_ = \$_[$ix];
310 13         26 my $testval = $test->();
311              
312             # Simulate $_ as alias
313 12         35 $_[$ix] = $_;
314 12 100       29 return $testval if $testval;
315             }
316 2         5 return undef;
317             }
318              
319             sub insert_after (&$\@)
320             {
321 11     11 0 5380 my ($f, $val, $list) = @_;
322 11         38 my $c = &firstidx($f, @$list);
323 6 100 50     29 @$list = (@{$list}[0 .. $c], $val, @{$list}[$c + 1 .. $#$list],) and return 1 if $c != -1;
  5         11  
  5         19  
324 1         2 return 0;
325             }
326              
327             sub insert_after_string ($$\@)
328             {
329 12     12 0 28979 my ($string, $val, $list) = @_;
330 12 100   34   1425 my $c = firstidx { defined $_ and $string eq $_ } @$list;
  34         9647  
331 7 50 50     741 @$list = (@{$list}[0 .. $c], $val, @{$list}[$c + 1 .. $#$list],) and return 1 if $c != -1;
  7         1348  
  7         3407  
332 0         0 return 0;
333             }
334              
335             sub apply (&@)
336             {
337 11     11 0 6350 my $action = shift;
338 11         40 &$action foreach my @values = @_;
339 8 100       139 wantarray ? @values : $values[-1];
340             }
341              
342             sub after (&@)
343             {
344 9     9 0 14517 my $test = shift;
345 9         726 my $started;
346             my $lag;
347             grep $started ||= do
348 9   100     685 {
349 25         2071 my $x = $lag;
350 25         2135 $lag = $test->();
351 24         10125 $x;
352             }, @_;
353             }
354              
355             sub after_incl (&@)
356             {
357 8     8 0 17195 my $test = shift;
358 8         657 my $started;
359 8   100     674 grep $started ||= $test->(), @_;
360             }
361              
362             sub before (&@)
363             {
364 8     8 0 19504 my $test = shift;
365 8         649 my $more = 1;
366 8   100     675 grep $more &&= !$test->(), @_;
367             }
368              
369             sub before_incl (&@)
370             {
371 8     8 0 12717 my $test = shift;
372 8         655 my $more = 1;
373 8         668 my $lag = 1;
374             grep $more &&= do
375 8   100     699 {
376 24         1962 my $x = $lag;
377 24         2006 $lag = !$test->();
378 23         9862 $x;
379             }, @_;
380             }
381              
382             sub indexes (&@)
383             {
384 24     24 0 10570 my $test = shift;
385             grep {
386 24         43 local *_ = \$_[$_];
  144         520  
387 144         190 $test->()
388             } 0 .. $#_;
389             }
390              
391             sub pairwise (&\@\@)
392             {
393 13     13 0 13484 my $op = shift;
394              
395             # Symbols for caller's input arrays
396 118     118   874 use vars qw{ @A @B };
  118         260  
  118         9661  
397 13         37 local (*A, *B) = @_;
398              
399             # Localise $a, $b
400             my ($caller_a, $caller_b) = do
401 13         19 {
402 13         27 my $pkg = caller();
403 118     118   735 no strict 'refs';
  118         300  
  118         270691  
404 13         18 \*{$pkg . '::a'}, \*{$pkg . '::b'};
  13         35  
  13         37  
405             };
406              
407             # Loop iteration limit
408 13 50       39 my $limit = $#A > $#B ? $#A : $#B;
409              
410             # This map expression is also the return value
411 13         33 local (*$caller_a, *$caller_b);
412             map {
413             # Assign to $a, $b as refs to caller's array elements
414 13         41 (*$caller_a, *$caller_b) = \($A[$_], $B[$_]);
  338         2471  
415              
416             # Perform the transformation
417 338         516 $op->();
418             } 0 .. $limit;
419             }
420              
421             sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
422             {
423 8     8 0 4377 return each_arrayref(@_);
424             }
425              
426             sub each_arrayref
427             {
428 14     14 0 5540 my @list = @_; # The list of references to the arrays
429 14         22 my $index = 0; # Which one the caller will get next
430 14         19 my $max = 0; # Number of elements in longest array
431              
432             # Get the length of the longest input array
433 14         26 foreach (@list)
434             {
435 22 100       41 unless (ref $_ eq 'ARRAY')
436             {
437 2         13 require Carp;
438 2         440 Carp::croak("each_arrayref: argument is not an array reference\n");
439             }
440 20 100       42 $max = @$_ if @$_ > $max;
441             }
442              
443             # Return the iterator as a closure wrt the above variables.
444             return sub {
445 100 100   100   370 if (@_)
446             {
447 10         13 my $method = shift;
448 10 50       16 unless ($method eq 'index')
449             {
450 0         0 require Carp;
451 0         0 Carp::croak("each_array: unknown argument '$method' passed to iterator.");
452             }
453              
454             # Return current (last fetched) index
455 10 50 33     28 return undef if $index == 0 || $index > $max;
456 10         26 return $index - 1;
457             }
458              
459             # No more elements to return
460 90 100       125 return if $index >= $max;
461 78         82 my $i = $index++;
462              
463             # Return ith elements
464 78         172 return map $_->[$i], @list;
465             }
466 12         57 }
467              
468             sub natatime ($@)
469             {
470 4     4 0 10107 my $n = shift;
471 4         40 my @list = @_;
472             return sub {
473 1009     1009   2375 return splice @list, 0, $n;
474             }
475 4         22 }
476              
477             # "leaks" when lexically hidden in arrayify
478             my $flatten;
479             $flatten = sub {
480             map { (ref $_ and ("ARRAY" eq ref $_ or overload::Method($_, '@{}'))) ? ($flatten->(@{$_})) : ($_) } @_;
481             };
482              
483             sub arrayify
484             {
485 23     23 0 99423 map { $flatten->($_) } @_;
  191         70759  
486             }
487              
488             sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
489             {
490 26     26 0 17108 my $max = -1;
491 26   66     164 $max < $#$_ && ($max = $#$_) foreach @_;
492             map {
493 25         83 my $ix = $_;
  1834         1906  
494 1834         3273 map $_->[$ix], @_;
495             } 0 .. $max;
496             }
497              
498             sub zip6 (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
499             {
500 6     6 0 6182 my $max = -1;
501 6   66     39 $max < $#$_ && ($max = $#$_) foreach @_;
502             map {
503 5         12 my $ix = $_;
  27         30  
504 27         69 [map $_->[$ix], @_];
505             } 0 .. $max;
506             }
507              
508             sub listcmp (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
509             {
510 14     14 0 50159 my %ret;
511 14         2127 for (my $i = 0; $i < scalar @_; ++$i)
512             {
513 29         4167 my %seen;
514             my $k;
515 29 100       4176 foreach my $w (grep { defined $_ and not $seen{$k = $_}++ } @{$_[$i]})
  198         49117  
  29         8284  
516             {
517 146   100     17665 $ret{$w} ||= [];
518 146         17410 push @{$ret{$w}}, $i;
  146         40230  
519             }
520             }
521 6         2823 %ret;
522             }
523              
524             sub uniq (@)
525             {
526 20     20 0 11000 my %seen = ();
527 20         31 my $k;
528             my $seen_undef;
529 20 100       39 grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  4713         8989  
530             }
531              
532             sub singleton (@)
533             {
534 19     19 0 62049 my %seen = ();
535 19         39 my $k;
536             my $seen_undef;
537 25535 100       43069 grep { 1 == (defined $_ ? $seen{$k = $_} : $seen_undef) }
538 19 100       91 grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  42305         80882  
539             }
540              
541             sub duplicates (@)
542             {
543 19     19 0 74112 my %seen = ();
544 19         34 my $k;
545             my $seen_undef;
546 24659 100       42694 grep { 1 < (defined $_ ? $seen{$k = $_} : $seen_undef) }
547 19 100       87 grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  41446         89786  
548             }
549              
550             sub frequency (@)
551             {
552 17     17 0 100407 my %seen = ();
553 17         32 my $k;
554             my $seen_undef;
555 25525 100       44262 my %h = map { defined $_ ? ($_ => $seen{$k = $_}) : () }
556 17 100       80 grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  42308         91609  
557 13 50       2940 wantarray or return (scalar keys %h) + ($seen_undef ? 1 : 0);
    100          
558 7         15 undef $k;
559 7 100       4660 (%h, $seen_undef ? (\$k => $seen_undef) : ());
560             }
561              
562             sub occurrences (@)
563             {
564 12     12 0 9047 my %seen = ();
565 12         31 my $k;
566             my $seen_undef;
567 12         0 my @ret;
568 12 100       23 foreach my $l (map { $_ } grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_)
  119         145  
  419         885  
569             {
570 119 100       177 my $n = defined $l ? $seen{$l} : $seen_undef;
571 119 100       174 defined $ret[$n] or $ret[$n] = [];
572 119         125 push @{$ret[$n]}, $l;
  119         189  
573             }
574 8         41 @ret;
575             }
576              
577             sub mode (@)
578             {
579 32     32 0 17276 my %seen = ();
580 32         62 my ($max, $k, $seen_undef) = (1);
581              
582 32 50 66     67 foreach (@_) { defined $_ ? ($max < ++$seen{$k = $_} and ++$max) : ($max < ++$seen_undef and ++$max) }
  1180   0     2512  
583 20 100       81 wantarray or return $max;
584              
585 10         17 my @ret = ($max);
586 10         36 foreach my $l (grep { $seen{$_} == $max } keys %seen)
  168         259  
587             {
588 18         32 push @ret, $l;
589             }
590 10 50 33     33 $seen_undef and $seen_undef == $max and push @ret, undef;
591 10         57 @ret;
592             }
593              
594             sub samples ($@)
595             {
596 4     4 0 1553 my $n = shift;
597 4 100       14 if ($n > @_)
598             {
599 1         8 require Carp;
600 1         165 Carp::croak(sprintf("Cannot get %d samples from %d elements", $n, scalar @_));
601             }
602              
603 3         11 for (my $i = @_; @_ - $i > $n;)
604             {
605 0         0 my $idx = @_ - $i;
606 0         0 my $swp = $idx + int(rand(--$i));
607 0         0 my $xchg = $_[$swp];
608 0         0 $_[$swp] = $_[$idx];
609 0         0 $_[$idx] = $xchg;
610             }
611              
612 3         12 return splice @_, 0, $n;
613             }
614              
615             sub minmax (@)
616             {
617 31 50   31 0 69983 return unless @_;
618 31         89 my $min = my $max = $_[0];
619              
620 31         120 for (my $i = 1; $i < @_; $i += 2)
621             {
622 10047 100       24593 if ($_[$i - 1] <= $_[$i])
623             {
624 28 100       86 $min = $_[$i - 1] if $min > $_[$i - 1];
625 28 100       94 $max = $_[$i] if $max < $_[$i];
626             }
627             else
628             {
629 10019 100       24496 $min = $_[$i] if $min > $_[$i];
630 10019 100       31766 $max = $_[$i - 1] if $max < $_[$i - 1];
631             }
632             }
633              
634 31 100       107 if (@_ & 1)
635             {
636 25         56 my $i = $#_;
637 25 100       115 if ($_[$i - 1] <= $_[$i])
638             {
639 22 50       82 $min = $_[$i - 1] if $min > $_[$i - 1];
640 22 100       75 $max = $_[$i] if $max < $_[$i];
641             }
642             else
643             {
644 3 50       14 $min = $_[$i] if $min > $_[$i];
645 3 50       13 $max = $_[$i - 1] if $max < $_[$i - 1];
646             }
647             }
648              
649 31         165 return ($min, $max);
650             }
651              
652             sub minmaxstr (@)
653             {
654 25 50   25 0 9829 return unless @_;
655 25         50 my $min = my $max = $_[0];
656              
657 25         67 for (my $i = 1; $i < @_; $i += 2)
658             {
659 1352 50       3154 if ($_[$i - 1] le $_[$i])
660             {
661 0 0       0 $min = $_[$i - 1] if $min gt $_[$i - 1];
662 0 0       0 $max = $_[$i] if $max lt $_[$i];
663             }
664             else
665             {
666 1352 50       3252 $min = $_[$i] if $min gt $_[$i];
667 1352 50       3949 $max = $_[$i - 1] if $max lt $_[$i - 1];
668             }
669             }
670              
671 25 100       64 if (@_ & 1)
672             {
673 24         50 my $i = $#_;
674 24 100       67 if ($_[$i - 1] le $_[$i])
675             {
676 22 50       54 $min = $_[$i - 1] if $min gt $_[$i - 1];
677 22 100       52 $max = $_[$i] if $max lt $_[$i];
678             }
679             else
680             {
681 2 50       9 $min = $_[$i] if $min gt $_[$i];
682 2 50       10 $max = $_[$i - 1] if $max lt $_[$i - 1];
683             }
684             }
685              
686 25         88 return ($min, $max);
687             }
688              
689             sub part (&@)
690             {
691 13     13 0 7344722 my ($code, @list) = @_;
692 13         21 my @parts;
693 13         26 push @{$parts[$code->($_)]}, $_ foreach @list;
  99         413  
694 12         568 return @parts;
695             }
696              
697             sub bsearch(&@)
698             {
699 2029     2029 0 448277 my $code = shift;
700              
701 2029         2713 my $rc;
702 2029         2519 my $i = 0;
703 2029         2687 my $j = @_;
704             do
705 2029         2421 {
706 18241         25579 my $k = int(($i + $j) / 2);
707              
708 18241 100       26931 $k >= @_ and return;
709              
710 18230         23290 local *_ = \$_[$k];
711 18230         25902 $rc = $code->();
712              
713 18227 100       47197 $rc == 0
    100          
714             and return wantarray ? $_ : 1;
715              
716 16223 100       21697 if ($rc < 0)
717             {
718 8212         13193 $i = $k + 1;
719             }
720             else
721             {
722 8011         12757 $j = $k - 1;
723             }
724             } until $i > $j;
725              
726 11         20 return;
727             }
728              
729             sub bsearchidx(&@)
730             {
731 1029     1029 0 430832 my $code = shift;
732              
733 1029         1314 my $rc;
734 1029         1203 my $i = 0;
735 1029         1336 my $j = @_;
736             do
737 1029         1193 {
738 9257         13019 my $k = int(($i + $j) / 2);
739              
740 9257 100       13536 $k >= @_ and return -1;
741              
742 9246         11708 local *_ = \$_[$k];
743 9246         13019 $rc = $code->();
744              
745 9243 100       24791 $rc == 0 and return $k;
746              
747 8239 100       10871 if ($rc < 0)
748             {
749 4169         7141 $i = $k + 1;
750             }
751             else
752             {
753 4070         6897 $j = $k - 1;
754             }
755             } until $i > $j;
756              
757 11         19 return -1;
758             }
759              
760             sub lower_bound(&@)
761             {
762 2475     2475 0 55244 my $code = shift;
763 2475         2838 my $count = @_;
764 2475         2970 my $first = 0;
765 2475         4055 while ($count > 0)
766             {
767 17852         19952 my $step = $count >> 1;
768 17852         19378 my $it = $first + $step;
769 17852         21850 local *_ = \$_[$it];
770 17852 100       24063 if ($code->() < 0)
771             {
772 8833         26745 $first = ++$it;
773 8833         14901 $count -= $step + 1;
774             }
775             else
776             {
777 9007         31406 $count = $step;
778             }
779             }
780              
781 2463         3619 $first;
782             }
783              
784             sub upper_bound(&@)
785             {
786 243     243 0 78669 my $code = shift;
787 243         414 my $count = @_;
788 243         347 my $first = 0;
789 243         588 while ($count > 0)
790             {
791 1607         2066 my $step = $count >> 1;
792 1607         2072 my $it = $first + $step;
793 1607         2353 local *_ = \$_[$it];
794 1607 100       2550 if ($code->() <= 0)
795             {
796 766         2234 $first = ++$it;
797 766         1536 $count -= $step + 1;
798             }
799             else
800             {
801 839         2977 $count = $step;
802             }
803             }
804              
805 241         916 $first;
806             }
807              
808             sub equal_range(&@)
809             {
810 12     12 0 820 my $lb = &lower_bound(@_);
811 9         20 my $ub = &upper_bound(@_);
812 9         28 ($lb, $ub);
813             }
814              
815             sub binsert (&$\@)
816             {
817 1811     1811 0 26713 my $lb = &lower_bound($_[0], @{$_[2]});
  1811         3583  
818 1808         1942 splice @{$_[2]}, $lb, 0, $_[1];
  1808         2776  
819 1808         3876 $lb;
820             }
821              
822             sub bremove (&\@)
823             {
824 420     420 0 214261 my $lb = &lower_bound($_[0], @{$_[1]});
  420         1245  
825 413         486 splice @{$_[1]}, $lb, 1;
  413         1454  
826             }
827              
828             sub qsort(&\@)
829             {
830 0     0 0 0 require Carp;
831 0         0 Carp::croak("It's insane to use a pure-perl qsort");
832             }
833              
834             sub sort_by(&@)
835             {
836 0     0 0 0 my ($code, @list) = @_;
837 0         0 return map { $_->[0] }
838 0         0 sort { $a->[1] cmp $b->[1] }
839 0         0 map { [$_, scalar($code->())] } @list;
  0         0  
840             }
841              
842             sub nsort_by(&@)
843             {
844 0     0 0 0 my ($code, @list) = @_;
845 0         0 return map { $_->[0] }
846 0         0 sort { $a->[1] <=> $b->[1] }
847 0         0 map { [$_, scalar($code->())] } @list;
  0         0  
848             }
849              
850 1     1   81 sub _XScompiled { 0 }
851              
852             =head1 SEE ALSO
853              
854             L
855              
856             =head1 AUTHOR
857              
858             Jens Rehsack Erehsack AT cpan.orgE
859              
860             Adam Kennedy Eadamk@cpan.orgE
861              
862             Tassilo von Parseval Etassilo.von.parseval@rwth-aachen.deE
863              
864             =head1 COPYRIGHT AND LICENSE
865              
866             Some parts copyright 2011 Aaron Crane.
867              
868             Copyright 2004 - 2010 by Tassilo von Parseval
869              
870             Copyright 2013 - 2017 by Jens Rehsack
871              
872             All code added with 0.417 or later is licensed under the Apache License,
873             Version 2.0 (the "License"); you may not use this file except in compliance
874             with the License. You may obtain a copy of the License at
875              
876             http://www.apache.org/licenses/LICENSE-2.0
877              
878             Unless required by applicable law or agreed to in writing, software
879             distributed under the License is distributed on an "AS IS" BASIS,
880             WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
881             See the License for the specific language governing permissions and
882             limitations under the License.
883              
884             All code until 0.416 is licensed under the same terms as Perl itself,
885             either Perl version 5.8.4 or, at your option, any later version of
886             Perl 5 you may have available.
887              
888             =cut
889              
890             1;