File Coverage

inc/List/MoreUtils/PP.pm
Criterion Covered Total %
statement 23 438 5.2
branch 0 178 0.0
condition 0 56 0.0
subroutine 8 72 11.1
pod 0 60 0.0
total 31 804 3.8


line stmt bran cond sub pod time code
1             #line 1
2             package List::MoreUtils::PP;
3 6     6   99  
  6         20  
4 6     6   34 use 5.008_001;
  6         10  
  6         122  
5 6     6   28 use strict;
  6         12  
  6         3473  
6             use warnings;
7              
8             our $VERSION = '0.428';
9              
10             #line 20
11              
12             sub any (&@)
13             {
14             my $f = shift;
15             foreach (@_)
16             {
17             return 1 if $f->();
18             }
19             return 0;
20             }
21              
22             sub all (&@)
23 0     0 0   {
24 0           my $f = shift;
25             foreach (@_)
26 0 0         {
27             return 0 unless $f->();
28 0           }
29             return 1;
30             }
31              
32             sub none (&@)
33 0     0 0   {
34 0           my $f = shift;
35             foreach (@_)
36 0 0         {
37             return 0 if $f->();
38 0           }
39             return 1;
40             }
41              
42             sub notall (&@)
43 0     0 0   {
44 0           my $f = shift;
45             foreach (@_)
46 0 0         {
47             return 1 unless $f->();
48 0           }
49             return 0;
50             }
51              
52             sub one (&@)
53 0     0 0   {
54 0           my $f = shift;
55             my $found = 0;
56 0 0         foreach (@_)
57             {
58 0           $f->() and $found++ and return 0;
59             }
60             $found;
61             }
62              
63 0     0 0   sub any_u (&@)
64 0           {
65 0           my $f = shift;
66             return if !@_;
67 0 0 0       $f->() and return 1 foreach (@_);
68             return 0;
69 0           }
70              
71             sub all_u (&@)
72             {
73             my $f = shift;
74 0     0 0   return if !@_;
75 0 0         $f->() or return 0 foreach (@_);
76 0   0       return 1;
77 0           }
78              
79             sub none_u (&@)
80             {
81             my $f = shift;
82 0     0 0   return if !@_;
83 0 0         $f->() and return 0 foreach (@_);
84 0   0       return 1;
85 0           }
86              
87             sub notall_u (&@)
88             {
89             my $f = shift;
90 0     0 0   return if !@_;
91 0 0         $f->() or return 1 foreach (@_);
92 0   0       return 0;
93 0           }
94              
95             sub one_u (&@)
96             {
97             my $f = shift;
98 0     0 0   return if !@_;
99 0 0         my $found = 0;
100 0   0       foreach (@_)
101 0           {
102             $f->() and $found++ and return 0;
103             }
104             $found;
105             }
106 0     0 0    
107 0 0         sub reduce_u(&@)
108 0           {
109 0           my $code = shift;
110              
111 0 0 0       # Localise $a, $b
112             my ($caller_a, $caller_b) = do
113 0           {
114             my $pkg = caller();
115             no strict 'refs';
116             \*{$pkg . '::a'}, \*{$pkg . '::b'};
117             };
118 0     0 0    
119             local (*$caller_a, *$caller_b);
120             *$caller_a = \();
121             for (0 .. $#_)
122 0           {
123 0           *$caller_b = \$_[$_];
124 6     6   47 *$caller_a = \($code->());
  6         20  
  6         1022  
125 0           }
  0            
  0            
126              
127             ${*$caller_a};
128 0           }
129 0            
130 0           sub reduce_0(&@)
131             {
132 0           my $code = shift;
133 0            
134             # Localise $a, $b
135             my ($caller_a, $caller_b) = do
136 0           {
  0            
137             my $pkg = caller();
138             no strict 'refs';
139             \*{$pkg . '::a'}, \*{$pkg . '::b'};
140             };
141 0     0 0    
142             local (*$caller_a, *$caller_b);
143             *$caller_a = \0;
144             for (0 .. $#_)
145 0           {
146 0           *$caller_b = \$_[$_];
147 6     6   50 *$caller_a = \($code->());
  6         13  
  6         924  
148 0           }
  0            
  0            
149              
150             ${*$caller_a};
151 0           }
152 0            
153 0           sub reduce_1(&@)
154             {
155 0           my $code = shift;
156 0            
157             # Localise $a, $b
158             my ($caller_a, $caller_b) = do
159 0           {
  0            
160             my $pkg = caller();
161             no strict 'refs';
162             \*{$pkg . '::a'}, \*{$pkg . '::b'};
163             };
164 0     0 0    
165             local (*$caller_a, *$caller_b);
166             *$caller_a = \1;
167             for (0 .. $#_)
168 0           {
169 0           *$caller_b = \$_[$_];
170 6     6   42 *$caller_a = \($code->());
  6         11  
  6         8234  
171 0           }
  0            
  0            
172              
173             ${*$caller_a};
174 0           }
175 0            
176 0           sub true (&@)
177             {
178 0           my $f = shift;
179 0           my $count = 0;
180             $f->() and ++$count foreach (@_);
181             return $count;
182 0           }
  0            
183              
184             sub false (&@)
185             {
186             my $f = shift;
187 0     0 0   my $count = 0;
188 0           $f->() or ++$count foreach (@_);
189 0   0       return $count;
190 0           }
191              
192             sub firstidx (&@)
193             {
194             my $f = shift;
195 0     0 0   foreach my $i (0 .. $#_)
196 0           {
197 0   0       local *_ = \$_[$i];
198 0           return $i if $f->();
199             }
200             return -1;
201             }
202              
203 0     0 0   sub firstval (&@)
204 0           {
205             my $test = shift;
206 0           foreach (@_)
207 0 0         {
208             return $_ if $test->();
209 0           }
210             return undef;
211             }
212              
213             sub firstres (&@)
214 0     0 0   {
215 0           my $test = shift;
216             foreach (@_)
217 0 0         {
218             my $testval = $test->();
219 0           $testval and return $testval;
220             }
221             return undef;
222             }
223              
224 0     0 0   sub onlyidx (&@)
225 0           {
226             my $f = shift;
227 0           my $found;
228 0 0         foreach my $i (0 .. $#_)
229             {
230 0           local *_ = \$_[$i];
231             $f->() or next;
232             defined $found and return -1;
233             $found = $i;
234             }
235 0     0 0   return defined $found ? $found : -1;
236 0           }
237 0            
238             sub onlyval (&@)
239 0           {
240 0 0         my $test = shift;
241 0 0         my $result = undef;
242 0           my $found = 0;
243             foreach (@_)
244 0 0         {
245             $test->() or next;
246             $result = $_;
247             $found++ and return undef;
248             }
249 0     0 0   return $result;
250 0           }
251 0            
252 0           sub onlyres (&@)
253             {
254 0 0         my $test = shift;
255 0           my $result = undef;
256 0 0         my $found = 0;
257             foreach (@_)
258 0           {
259             my $rv = $test->() or next;
260             $result = $rv;
261             $found++ and return undef;
262             }
263 0     0 0   return $found ? $result : undef;
264 0           }
265 0            
266 0           sub lastidx (&@)
267             {
268 0 0         my $f = shift;
269 0           foreach my $i (reverse 0 .. $#_)
270 0 0         {
271             local *_ = \$_[$i];
272 0 0         return $i if $f->();
273             }
274             return -1;
275             }
276              
277 0     0 0   sub lastval (&@)
278 0           {
279             my $test = shift;
280 0           my $ix;
281 0 0         for ($ix = $#_; $ix >= 0; $ix--)
282             {
283 0           local *_ = \$_[$ix];
284             my $testval = $test->();
285              
286             # Simulate $_ as alias
287             $_[$ix] = $_;
288 0     0 0   return $_ if $testval;
289 0           }
290 0           return undef;
291             }
292 0            
293 0           sub lastres (&@)
294             {
295             my $test = shift;
296 0           my $ix;
297 0 0         for ($ix = $#_; $ix >= 0; $ix--)
298             {
299 0           local *_ = \$_[$ix];
300             my $testval = $test->();
301              
302             # Simulate $_ as alias
303             $_[$ix] = $_;
304 0     0 0   return $testval if $testval;
305 0           }
306 0           return undef;
307             }
308 0            
309 0           sub insert_after (&$\@)
310             {
311             my ($f, $val, $list) = @_;
312 0           my $c = &firstidx($f, @$list);
313 0 0         @$list = (@{$list}[0 .. $c], $val, @{$list}[$c + 1 .. $#$list],) and return 1 if $c != -1;
314             return 0;
315 0           }
316              
317             sub insert_after_string ($$\@)
318             {
319             my ($string, $val, $list) = @_;
320 0     0 0   my $c = firstidx { defined $_ and $string eq $_ } @$list;
321 0           @$list = (@{$list}[0 .. $c], $val, @{$list}[$c + 1 .. $#$list],) and return 1 if $c != -1;
322 0 0 0       return 0;
  0            
  0            
323 0           }
324              
325             sub apply (&@)
326             {
327             my $action = shift;
328 0     0 0   &$action foreach my @values = @_;
329 0 0   0     wantarray ? @values : $values[-1];
  0            
330 0 0 0       }
  0            
  0            
331 0            
332             sub after (&@)
333             {
334             my $test = shift;
335             my $started;
336 0     0 0   my $lag;
337 0           grep $started ||= do
338 0 0         {
339             my $x = $lag;
340             $lag = $test->();
341             $x;
342             }, @_;
343 0     0 0   }
344 0            
345             sub after_incl (&@)
346             {
347 0   0       my $test = shift;
348 0           my $started;
349 0           grep $started ||= $test->(), @_;
350 0           }
351              
352             sub before (&@)
353             {
354             my $test = shift;
355             my $more = 1;
356 0     0 0   grep $more &&= !$test->(), @_;
357 0           }
358 0   0        
359             sub before_incl (&@)
360             {
361             my $test = shift;
362             my $more = 1;
363 0     0 0   my $lag = 1;
364 0           grep $more &&= do
365 0   0       {
366             my $x = $lag;
367             $lag = !$test->();
368             $x;
369             }, @_;
370 0     0 0   }
371 0            
372 0           sub indexes (&@)
373             {
374 0   0       my $test = shift;
375 0           grep {
376 0           local *_ = \$_[$_];
377 0           $test->()
378             } 0 .. $#_;
379             }
380              
381             sub pairwise (&\@\@)
382             {
383 0     0 0   my $op = shift;
384              
385 0           # Symbols for caller's input arrays
  0            
386 0           use vars qw{ @A @B };
387             local (*A, *B) = @_;
388              
389             # Localise $a, $b
390             my ($caller_a, $caller_b) = do
391             {
392 0     0 0   my $pkg = caller();
393             no strict 'refs';
394             \*{$pkg . '::a'}, \*{$pkg . '::b'};
395 6     6   53 };
  6         19  
  6         518  
396 0            
397             # Loop iteration limit
398             my $limit = $#A > $#B ? $#A : $#B;
399              
400 0           # This map expression is also the return value
401 0           local (*$caller_a, *$caller_b);
402 6     6   43 map {
  6         12  
  6         16628  
403 0           # Assign to $a, $b as refs to caller's array elements
  0            
  0            
404             (*$caller_a, *$caller_b) = \($#A < $_ ? undef : $A[$_], $#B < $_ ? undef : $B[$_]);
405              
406             # Perform the transformation
407 0 0         $op->();
408             } 0 .. $limit;
409             }
410 0            
411             sub each_array (\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
412             {
413 0 0         return each_arrayref(@_);
  0 0          
414             }
415              
416 0           sub each_arrayref
417             {
418             my @list = @_; # The list of references to the arrays
419             my $index = 0; # Which one the caller will get next
420             my $max = 0; # Number of elements in longest array
421              
422 0     0 0   # Get the length of the longest input array
423             foreach (@list)
424             {
425             unless (ref $_ eq 'ARRAY')
426             {
427 0     0 0   require Carp;
428 0           Carp::croak("each_arrayref: argument is not an array reference\n");
429 0           }
430             $max = @$_ if @$_ > $max;
431             }
432 0            
433             # Return the iterator as a closure wrt the above variables.
434 0 0         return sub {
435             if (@_)
436 0           {
437 0           my $method = shift;
438             unless ($method eq 'index')
439 0 0         {
440             require Carp;
441             Carp::croak("each_array: unknown argument '$method' passed to iterator.");
442             }
443              
444 0 0   0     # Return current (last fetched) index
445             return undef if $index == 0 || $index > $max;
446 0           return $index - 1;
447 0 0         }
448              
449 0           # No more elements to return
450 0           return if $index >= $max;
451             my $i = $index++;
452              
453             # Return ith elements
454 0 0 0       return map $_->[$i], @list;
455 0           }
456             }
457              
458             sub natatime ($@)
459 0 0         {
460 0           my $n = shift;
461             my @list = @_;
462             return sub {
463 0           return splice @list, 0, $n;
464             }
465 0           }
466              
467             # "leaks" when lexically hidden in arrayify
468             my $flatten;
469 0     0 0   $flatten = sub {
470 0           map { (ref $_ and ("ARRAY" eq ref $_ or overload::Method($_, '@{}'))) ? ($flatten->(@{$_})) : ($_) } @_;
471             };
472 0     0      
473             sub arrayify
474 0           {
475             map { $flatten->($_) } @_;
476             }
477              
478             sub mesh (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
479             {
480             my $max = -1;
481             $max < $#$_ && ($max = $#$_) foreach @_;
482             map {
483             my $ix = $_;
484 0     0 0   map $_->[$ix], @_;
  0            
485             } 0 .. $max;
486             }
487              
488             sub zip6 (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
489 0     0 0   {
490 0   0       my $max = -1;
491             $max < $#$_ && ($max = $#$_) foreach @_;
492 0           map {
  0            
493 0           my $ix = $_;
494             [map $_->[$ix], @_];
495             } 0 .. $max;
496             }
497              
498             sub listcmp (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@)
499 0     0 0   {
500 0   0       my %ret;
501             for (my $i = 0; $i < scalar @_; ++$i)
502 0           {
  0            
503 0           my %seen;
504             my $k;
505             foreach my $w (grep { defined $_ and not $seen{$k = $_}++ } @{$_[$i]})
506             {
507             $ret{$w} ||= [];
508             push @{$ret{$w}}, $i;
509 0     0 0   }
510 0           }
511             %ret;
512 0           }
513              
514 0 0         sub uniq (@)
  0            
  0            
515             {
516 0   0       my %seen = ();
517 0           my $k;
  0            
518             my $seen_undef;
519             grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
520 0           }
521              
522             sub singleton (@)
523             {
524             my %seen = ();
525 0     0 0   my $k;
526 0           my $seen_undef;
527             grep { 1 == (defined $_ ? $seen{$k = $_} : $seen_undef) }
528 0 0         grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  0            
529             }
530              
531             sub duplicates (@)
532             {
533 0     0 0   my %seen = ();
534 0           my $k;
535             my $seen_undef;
536 0 0         grep { 1 < (defined $_ ? $seen{$k = $_} : $seen_undef) }
537 0 0         grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  0            
538             }
539              
540             sub frequency (@)
541             {
542 0     0 0   my %seen = ();
543 0           my $k;
544             my $seen_undef;
545 0 0         my %h = map { defined $_ ? ($_ => $seen{$k = $_}) : () }
546 0 0         grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_;
  0            
547             wantarray or return (scalar keys %h) + ($seen_undef ? 1 : 0);
548             undef $k;
549             (%h, $seen_undef ? (\$k => $seen_undef) : ());
550             }
551 0     0 0    
552 0           sub occurrences (@)
553             {
554 0 0         my %seen = ();
555 0 0         my $k;
  0            
556 0 0         my $seen_undef;
    0          
557 0           my @ret;
558 0 0         foreach my $l (map { $_ } grep { defined $_ ? not $seen{$k = $_}++ : not $seen_undef++ } @_)
559             {
560             my $n = defined $l ? $seen{$l} : $seen_undef;
561             defined $ret[$n] or $ret[$n] = [];
562             push @{$ret[$n]}, $l;
563 0     0 0   }
564 0           @ret;
565             }
566 0            
567 0 0         sub mode (@)
  0            
  0            
568             {
569 0 0         my %seen = ();
570 0 0         my ($max, $k, $seen_undef) = (1);
571 0            
  0            
572             foreach (@_) { defined $_ ? ($max < ++$seen{$k = $_} and ++$max) : ($max < ++$seen_undef and ++$max) }
573 0           wantarray or return $max;
574              
575             my @ret = ($max);
576             foreach my $l (grep { $seen{$_} == $max } keys %seen)
577             {
578 0     0 0   push @ret, $l;
579 0           }
580             $seen_undef and $seen_undef == $max and push @ret, undef;
581 0 0 0       @ret;
  0   0        
582 0 0         }
583              
584 0           sub samples ($@)
585 0           {
  0            
586             my $n = shift;
587 0           if ($n > @_)
588             {
589 0 0 0       require Carp;
590 0           Carp::croak(sprintf("Cannot get %d samples from %d elements", $n, scalar @_));
591             }
592              
593             for (my $i = @_; @_ - $i > $n;)
594             {
595 0     0 0   my $idx = @_ - $i;
596 0 0         my $swp = $idx + int(rand(--$i));
597             my $xchg = $_[$swp];
598 0           $_[$swp] = $_[$idx];
599 0           $_[$idx] = $xchg;
600             }
601              
602 0           return splice @_, 0, $n;
603             }
604 0            
605 0           sub minmax (@)
606 0           {
607 0           return unless @_;
608 0           my $min = my $max = $_[0];
609              
610             for (my $i = 1; $i < @_; $i += 2)
611 0           {
612             if ($_[$i - 1] <= $_[$i])
613             {
614             $min = $_[$i - 1] if $min > $_[$i - 1];
615             $max = $_[$i] if $max < $_[$i];
616 0 0   0 0   }
617 0           else
618             {
619 0           $min = $_[$i] if $min > $_[$i];
620             $max = $_[$i - 1] if $max < $_[$i - 1];
621 0 0         }
622             }
623 0 0          
624 0 0         if (@_ & 1)
625             {
626             my $i = $#_;
627             if ($_[$i - 1] <= $_[$i])
628 0 0         {
629 0 0         $min = $_[$i - 1] if $min > $_[$i - 1];
630             $max = $_[$i] if $max < $_[$i];
631             }
632             else
633 0 0         {
634             $min = $_[$i] if $min > $_[$i];
635 0           $max = $_[$i - 1] if $max < $_[$i - 1];
636 0 0         }
637             }
638 0 0          
639 0 0         return ($min, $max);
640             }
641              
642             sub minmaxstr (@)
643 0 0         {
644 0 0         return unless @_;
645             my $min = my $max = $_[0];
646              
647             for (my $i = 1; $i < @_; $i += 2)
648 0           {
649             if ($_[$i - 1] le $_[$i])
650             {
651             $min = $_[$i - 1] if $min gt $_[$i - 1];
652             $max = $_[$i] if $max lt $_[$i];
653 0 0   0 0   }
654 0           else
655             {
656 0           $min = $_[$i] if $min gt $_[$i];
657             $max = $_[$i - 1] if $max lt $_[$i - 1];
658 0 0         }
659             }
660 0 0          
661 0 0         if (@_ & 1)
662             {
663             my $i = $#_;
664             if ($_[$i - 1] le $_[$i])
665 0 0         {
666 0 0         $min = $_[$i - 1] if $min gt $_[$i - 1];
667             $max = $_[$i] if $max lt $_[$i];
668             }
669             else
670 0 0         {
671             $min = $_[$i] if $min gt $_[$i];
672 0           $max = $_[$i - 1] if $max lt $_[$i - 1];
673 0 0         }
674             }
675 0 0          
676 0 0         return ($min, $max);
677             }
678              
679             sub part (&@)
680 0 0         {
681 0 0         my ($code, @list) = @_;
682             my @parts;
683             push @{$parts[$code->($_)]}, $_ foreach @list;
684             return @parts;
685 0           }
686              
687             sub bsearch(&@)
688             {
689             my $code = shift;
690 0     0 0    
691 0           my $rc;
692 0           my $i = 0;
  0            
693 0           my $j = @_;
694             do
695             {
696             my $k = int(($i + $j) / 2);
697              
698 0     0 0   $k >= @_ and return;
699              
700 0           local *_ = \$_[$k];
701 0           $rc = $code->();
702 0            
703             $rc == 0
704 0           and return wantarray ? $_ : 1;
705 0            
706             if ($rc < 0)
707 0 0         {
708             $i = $k + 1;
709 0           }
710 0           else
711             {
712 0 0         $j = $k - 1;
    0          
713             }
714             } until $i > $j;
715 0 0          
716             return;
717 0           }
718              
719             sub bsearchidx(&@)
720             {
721 0           my $code = shift;
722              
723             my $rc;
724             my $i = 0;
725 0           my $j = @_;
726             do
727             {
728             my $k = int(($i + $j) / 2);
729              
730 0     0 0   $k >= @_ and return -1;
731              
732 0           local *_ = \$_[$k];
733 0           $rc = $code->();
734 0            
735             $rc == 0 and return $k;
736 0            
737 0           if ($rc < 0)
738             {
739 0 0         $i = $k + 1;
740             }
741 0           else
742 0           {
743             $j = $k - 1;
744 0 0         }
745             } until $i > $j;
746 0 0          
747             return -1;
748 0           }
749              
750             sub lower_bound(&@)
751             {
752 0           my $code = shift;
753             my $count = @_;
754             my $first = 0;
755             while ($count > 0)
756 0           {
757             my $step = $count >> 1;
758             my $it = $first + $step;
759             local *_ = \$_[$it];
760             if ($code->() < 0)
761 0     0 0   {
762 0           $first = ++$it;
763 0           $count -= $step + 1;
764 0           }
765             else
766 0           {
767 0           $count = $step;
768 0           }
769 0 0         }
770              
771 0           $first;
772 0           }
773              
774             sub upper_bound(&@)
775             {
776 0           my $code = shift;
777             my $count = @_;
778             my $first = 0;
779             while ($count > 0)
780 0           {
781             my $step = $count >> 1;
782             my $it = $first + $step;
783             local *_ = \$_[$it];
784             if ($code->() <= 0)
785 0     0 0   {
786 0           $first = ++$it;
787 0           $count -= $step + 1;
788 0           }
789             else
790 0           {
791 0           $count = $step;
792 0           }
793 0 0         }
794              
795 0           $first;
796 0           }
797              
798             sub equal_range(&@)
799             {
800 0           my $lb = &lower_bound(@_);
801             my $ub = &upper_bound(@_);
802             ($lb, $ub);
803             }
804 0            
805             sub binsert (&$\@)
806             {
807             my $lb = &lower_bound($_[0], @{$_[2]});
808             splice @{$_[2]}, $lb, 0, $_[1];
809 0     0 0   $lb;
810 0           }
811 0            
812             sub bremove (&\@)
813             {
814             my $lb = &lower_bound($_[0], @{$_[1]});
815             splice @{$_[1]}, $lb, 1;
816 0     0 0   }
  0            
817 0            
  0            
818 0           sub qsort(&\@)
819             {
820             require Carp;
821             Carp::croak("It's insane to use a pure-perl qsort");
822             }
823 0     0 0    
  0            
824 0           sub sort_by(&@)
  0            
825             {
826             my ($code, @list) = @_;
827             return map { $_->[0] }
828             sort { $a->[1] cmp $b->[1] }
829 0     0 0   map { [$_, scalar($code->())] } @list;
830 0           }
831              
832             sub nsort_by(&@)
833             {
834             my ($code, @list) = @_;
835 0     0 0   return map { $_->[0] }
836 0           sort { $a->[1] <=> $b->[1] }
837 0           map { [$_, scalar($code->())] } @list;
838 0           }
  0            
839              
840             sub _XScompiled { 0 }
841              
842             #line 888
843 0     0 0    
844 0           1;