File Coverage

blib/lib/PDL/VectorValued/Utils.pm
Criterion Covered Total %
statement 94 94 100.0
branch 43 78 55.1
condition 3 9 33.3
subroutine 12 12 100.0
pod 0 8 0.0
total 152 201 75.6


line stmt bran cond sub pod time code
1              
2             #
3             # GENERATED WITH PDL::PP! Don't modify!
4             #
5             package PDL::VectorValued::Utils;
6              
7             @EXPORT_OK = qw( PDL::PP rlevec PDL::PP rldvec PDL::PP enumvec PDL::PP enumvecg PDL::PP rleseq PDL::PP rldseq PDL::PP vsearchvec PDL::PP cmpvec PDL::PP vv_qsortvec PDL::PP vv_qsortveci PDL::PP vv_union PDL::PP vv_intersect PDL::PP vv_setdiff PDL::PP v_union PDL::PP v_intersect PDL::PP v_setdiff PDL::PP vv_vcos );
8             %EXPORT_TAGS = (Func=>[@EXPORT_OK]);
9              
10 6     6   37 use PDL::Core;
  6         13  
  6         31  
11 6     6   1159 use PDL::Exporter;
  6         14  
  6         27  
12 6     6   126 use DynaLoader;
  6         13  
  6         287  
13              
14              
15              
16             $PDL::VectorValued::Utils::VERSION = 1.0.7;
17             @ISA = ( 'PDL::Exporter','DynaLoader' );
18             push @PDL::Core::PP, __PACKAGE__;
19             bootstrap PDL::VectorValued::Utils $VERSION;
20              
21              
22              
23              
24              
25 6     6   27 use strict;
  6         13  
  6         6937  
26              
27             =pod
28              
29             =head1 NAME
30              
31             PDL::VectorValued::Utils - Low-level utilities for vector-valued PDLs
32              
33             =head1 SYNOPSIS
34              
35             use PDL;
36             use PDL::VectorValued::Utils;
37              
38             ##---------------------------------------------------------------------
39             ## ... stuff happens
40              
41             =cut
42              
43              
44              
45              
46              
47              
48              
49             =head1 FUNCTIONS
50              
51              
52              
53             =cut
54              
55              
56              
57              
58              
59             =pod
60              
61             =head1 Vector-Based Run-Length Encoding and Decoding
62              
63             =cut
64              
65              
66              
67              
68              
69             =head2 rlevec
70              
71             =for sig
72              
73             Signature: (c(M,N); indx [o]a(N); [o]b(M,N))
74              
75             Run-length encode a set of vectors.
76              
77             Higher-order rle(), for use with qsortvec().
78              
79             Given set of vectors $c, generate a vector $a with the number of occurrences of each element
80             (where an "element" is a vector of length $M ocurring in $c),
81             and a set of vectors $b containing the unique values.
82             As for rle(), only the elements up to the first instance of 0 in $a should be considered.
83              
84             Can be used together with clump() to run-length encode "values" of arbitrary dimensions.
85             Can be used together with rotate(), cat(), append(), and qsortvec() to count N-grams
86             over a 1d PDL.
87              
88             See also: PDL::Slices::rle, PDL::Ufunc::qsortvec, PDL::Primitive::uniqvec
89              
90              
91              
92             =for bad
93              
94             rlevec does not process bad values.
95             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
96              
97              
98             =cut
99              
100              
101              
102              
103              
104              
105             *rlevec = \&PDL::rlevec;
106              
107              
108              
109              
110              
111             =head2 rldvec
112              
113             =for sig
114              
115             Signature: (int a(N); b(M,N); [o]c(M,N))
116              
117             Run-length decode a set of vectors, akin to a higher-order rld().
118              
119             Given a vector $a() of the number of occurrences of each row, and a set $c()
120             of row-vectors each of length $M, run-length decode to $c().
121              
122             Can be used together with clump() to run-length decode "values" of arbitrary dimensions.
123              
124             See also: PDL::Slices::rld.
125              
126              
127              
128             =for bad
129              
130             rldvec does not process bad values.
131             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
132              
133              
134             =cut
135              
136              
137              
138              
139             sub PDL::rldvec {
140 3     3 0 2208 my ($a,$b,$c) = @_;
141 3 100       10 if (!defined($c)) {
142             # XXX Need to improve emulation of threading in auto-generating c
143 1         14 my ($rowlen) = $b->dim(0);
144 1         30 my ($size) = $a->sumover->max;
145 1         66 my (@dims) = $a->dims;
146 1         22 shift(@dims);
147 1         7 $c = $b->zeroes($b->type,$rowlen,$size,@dims);
148             }
149 3         166 &PDL::_rldvec_int($a,$b,$c);
150 3         12 return $c;
151             }
152              
153              
154             *rldvec = \&PDL::rldvec;
155              
156              
157              
158              
159              
160             =head2 enumvec
161              
162             =for sig
163              
164             Signature: (v(M,N); int [o]k(N))
165              
166             Enumerate a list of vectors with locally unique keys.
167              
168             Given a sorted list of vectors $v, generate a vector $k containing locally unique keys for the elements of $v
169             (where an "element" is a vector of length $M ocurring in $v).
170              
171             Note that the keys returned in $k are only unique over a run of a single vector in $v,
172             so that each unique vector in $v has at least one 0 (zero) index in $k associated with it.
173             If you need global keys, see enumvecg().
174              
175              
176              
177             =for bad
178              
179             enumvec does not process bad values.
180             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
181              
182              
183             =cut
184              
185              
186              
187              
188              
189              
190             *enumvec = \&PDL::enumvec;
191              
192              
193              
194              
195              
196             =head2 enumvecg
197              
198             =for sig
199              
200             Signature: (v(M,N); int [o]k(N))
201              
202             Enumerate a list of vectors with globally unique keys.
203              
204             Given a sorted list of vectors $v, generate a vector $k containing globally unique keys for the elements of $v
205             (where an "element" is a vector of length $M ocurring in $v).
206             Basically does the same thing as:
207              
208             $k = $v->vsearchvec($v->uniqvec);
209              
210             ... but somewhat more efficiently.
211              
212              
213              
214             =for bad
215              
216             enumvecg does not process bad values.
217             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
218              
219              
220             =cut
221              
222              
223              
224              
225              
226              
227             *enumvecg = \&PDL::enumvecg;
228              
229              
230              
231              
232              
233             =head2 rleseq
234              
235             =for sig
236              
237             Signature: (c(N); indx [o]a(N); [o]b(N))
238              
239             Run-length encode a vector of subsequences.
240              
241             Given a vector of $c() of concatenated variable-length, variable-offset subsequences,
242             generate a vector $a containing the length of each subsequence
243             and a vector $b containg the subsequence offsets.
244             As for rle(), only the elements up to the first instance of 0 in $a should be considered.
245              
246             See also PDL::Slices::rle.
247              
248              
249              
250             =for bad
251              
252             rleseq does not process bad values.
253             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
254              
255              
256             =cut
257              
258              
259              
260              
261              
262              
263             *rleseq = \&PDL::rleseq;
264              
265              
266              
267              
268              
269             =head2 rldseq
270              
271             =for sig
272              
273             Signature: (int a(N); b(N); [o]c(M))
274              
275             Run-length decode a subsequence vector.
276              
277             Given a vector $a() of sequence lengths
278             and a vector $b() of corresponding offsets,
279             decode concatenation of subsequences to $c(),
280             as for:
281              
282             $c = null;
283             $c = $c->append($b($_)+sequence($a->type,$a($_))) foreach (0..($N-1));
284              
285             See also: PDL::Slices::rld.
286              
287              
288              
289             =for bad
290              
291             rldseq does not process bad values.
292             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
293              
294              
295             =cut
296              
297              
298              
299              
300             sub PDL::rldseq {
301 1     1 0 2336 my ($a,$b,$c) = @_;
302 1 50       6 if (!defined($c)) {
303 1         9 my $size = $a->sumover->max;
304 1         41 my (@dims) = $a->dims;
305 1         21 shift(@dims);
306 1         5 $c = $b->zeroes($b->type,$size,@dims);
307             }
308 1         98 &PDL::_rldseq_int($a,$b,$c);
309 1         4 return $c;
310             }
311              
312              
313             *rldseq = \&PDL::rldseq;
314              
315              
316              
317              
318              
319             =head2 vsearchvec
320              
321             =for sig
322              
323             Signature: (find(M); which(M,N); int [o]found())
324              
325             =for ref
326              
327             Routine for searching N-dimensional values - akin to vsearch() for vectors.
328              
329             =for usage
330              
331             $found = ccs_vsearchvec($find, $which);
332             $nearest = $which->dice_axis(1,$found);
333              
334             Returns for each row-vector in C<$find> the index along dimension N
335             of the least row vector of C<$which>
336             greater or equal to it.
337             C<$which> should be sorted in increasing order.
338             If the value of C<$find> is larger
339             than any member of C<$which>, the index to the last element of C<$which> is
340             returned.
341              
342             See also: PDL::Primitive::vsearch().
343              
344              
345              
346             =for bad
347              
348             vsearchvec does not process bad values.
349             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
350              
351              
352             =cut
353              
354              
355              
356              
357              
358              
359             *vsearchvec = \&PDL::vsearchvec;
360              
361              
362              
363              
364             =pod
365              
366             =head1 Vector-Valued Sorting and Comparison
367              
368             The following functions are provided for lexicographic sorting of
369             vectors, rsp. axis indices. Note that vv_qsortvec() is functionally
370             identical to the builtin PDL function qsortvec(), but also that
371             the latter is broken in the stock PDL-2.4.3 distribution. The version
372             included here includes Chris Marshall's "uniqsortvec" patch, which
373             is available here:
374              
375             http://sourceforge.net/tracker/index.php?func=detail&aid=1548824&group_id=612&atid=300612
376              
377             =cut
378              
379              
380              
381              
382              
383             =head2 cmpvec
384              
385             =for sig
386              
387             Signature: (a(N); b(N); int [o]cmp())
388              
389             =for ref
390              
391             Lexicographically compare a pair of vectors.
392              
393              
394              
395             =for bad
396              
397             cmpvec does not process bad values.
398             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
399              
400              
401             =cut
402              
403              
404              
405              
406              
407              
408             *cmpvec = \&PDL::cmpvec;
409              
410              
411              
412              
413              
414             =head2 vv_qsortvec
415              
416             =for sig
417              
418             Signature: (a(n,m); [o]b(n,m))
419              
420              
421             =for ref
422              
423             Drop-in replacement for qsortvec(),
424             which is broken in the stock PDL-2.4.3 release.
425             See PDL::Ufunc::qsortvec.
426              
427              
428             =for bad
429              
430             Vectors with bad components should be moved to the end of the array.
431              
432              
433             =cut
434              
435              
436              
437              
438              
439              
440             *vv_qsortvec = \&PDL::vv_qsortvec;
441              
442              
443              
444              
445              
446             =head2 vv_qsortveci
447              
448             =for sig
449              
450             Signature: (a(n,m); indx [o]ix(m))
451              
452              
453             =for ref
454              
455             Get lexicographic sort order of a matrix $a() viewed as a list of vectors.
456              
457              
458             =for bad
459              
460             Vectors with bad components should be treated as last in the lexicographic order.
461              
462              
463             =cut
464              
465              
466              
467              
468              
469              
470             *vv_qsortveci = \&PDL::vv_qsortveci;
471              
472              
473              
474              
475             =pod
476              
477             =head1 Vector-Valued Set Operations
478              
479             The following functions are provided for set operations on
480             sorted vector-valued PDLs.
481              
482             =cut
483              
484              
485              
486              
487              
488             =head2 vv_union
489              
490             =for sig
491              
492             Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())
493              
494              
495             Union of two vector-valued PDLs. Input PDLs $a() and $b() B be
496             sorted in lexicographic order.
497             On return, $nc() holds the actual number of vector-values in the union.
498              
499             In scalar context, slices $c() to the actual number of elements in the union
500             and returns the sliced PDL.
501              
502              
503              
504              
505             =for bad
506              
507             vv_union does not process bad values.
508             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
509              
510              
511             =cut
512              
513              
514              
515              
516              
517             sub PDL::vv_union {
518 2     2 0 2073 my ($a,$b,$c,$nc) = @_;
519 2 50       28 barf("PDL::VectorValued::vv_union(): dimension mismatch") if ($a->dim(-2) != $b->dim(-2));
520 2         21 my @adims = $a->dims;
521 2 50       55 if (!defined($c)) {
522 2 50       8 my $ctype = $a->type > $b->type ? $a->type : $b->type;
523 2         154 $c = PDL->zeroes($ctype, @adims[0..($#adims-1)], $adims[$#adims] + $b->dim(-1));
524             }
525 2 50       209 $nc = PDL->zeroes(PDL::long(), (@adims > 2 ? @adims[0..($#adims-2)] : 1)) if (!defined($nc));
    50          
526 2         167 &PDL::_vv_union_int($a,$b,$c,$nc);
527 2 100       11 return ($c,$nc) if (wantarray);
528 1         9 return $c->mv(-1,0)->slice("0:".($nc->sclr-1))->mv(0,-1);
529             }
530              
531              
532             *vv_union = \&PDL::vv_union;
533              
534              
535              
536              
537              
538             =head2 vv_intersect
539              
540             =for sig
541              
542             Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())
543              
544              
545             Intersection of two vector-valued PDLs.
546             Input PDLs $a() and $b() B be sorted in lexicographic order.
547             On return, $nc() holds the actual number of vector-values in the intersection.
548              
549             In scalar context, slices $c() to the actual number of elements in the intersection
550             and returns the sliced PDL.
551              
552              
553              
554             =for bad
555              
556             vv_intersect does not process bad values.
557             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
558              
559              
560             =cut
561              
562              
563              
564              
565              
566             sub PDL::vv_intersect {
567 2     2 0 1987 my ($a,$b,$c,$nc) = @_;
568 2 50       14 barf("PDL::VectorValued::vv_intersect(): dimension mismatch") if ($a->dim(-2) != $b->dim(-2));
569 2         8 my @adims = $a->dims;
570 2         48 my $NA = $adims[$#adims];
571 2         7 my $NB = $b->dim(-1);
572 2 50       5 if (!defined($c)) {
573 2 50       7 my $ctype = $a->type > $b->type ? $a->type : $b->type;
574 2 50       127 $c = PDL->zeroes($ctype, @adims[0..($#adims-1)], $NA < $NB ? $NA : $NB);
575             }
576 2 50       147 $nc = PDL->zeroes(PDL::long(), (@adims > 2 ? @adims[0..($#adims-2)] : 1)) if (!defined($nc));
    50          
577 2         142 &PDL::_vv_intersect_int($a,$b,$c,$nc);
578 2 100       11 return ($c,$nc) if (wantarray);
579 1         24 return $c->mv(-1,0)->slice("0:".($nc->sclr-1))->mv(0,-1);
580             }
581              
582              
583             *vv_intersect = \&PDL::vv_intersect;
584              
585              
586              
587              
588              
589             =head2 vv_setdiff
590              
591             =for sig
592              
593             Signature: (a(M,NA); b(M,NB); [o]c(M,NC); int [o]nc())
594              
595              
596             Set-difference ($a() \ $b()) of two vector-valued PDLs.
597             Input PDLs $a() and $b() B be sorted in lexicographic order.
598             On return, $nc() holds the actual number of vector-values in the computed vector set.
599              
600             In scalar context, slices $c() to the actual number of elements in the output vector set
601             and returns the sliced PDL.
602              
603              
604              
605             =for bad
606              
607             vv_setdiff does not process bad values.
608             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
609              
610              
611             =cut
612              
613              
614              
615              
616              
617             sub PDL::vv_setdiff {
618 2     2 0 2008 my ($a,$b,$c,$nc) = @_;
619 2 50       13 barf("PDL::VectorValued::vv_setdiff(): dimension mismatch") if ($a->dim(-2) != $b->dim(-2));
620 2         8 my @adims = $a->dims;
621 2         48 my $NA = $adims[$#adims];
622 2         6 my $NB = $b->dim(-1);
623 2 50       7 if (!defined($c)) {
624 2 50       6 my $ctype = $a->type > $b->type ? $a->type : $b->type;
625 2         126 $c = PDL->zeroes($ctype, @adims[0..($#adims-1)], $NA);
626             }
627 2 50       183 $nc = PDL->zeroes(PDL::long(), (@adims > 2 ? @adims[0..($#adims-2)] : 1)) if (!defined($nc));
    50          
628 2         141 &PDL::_vv_setdiff_int($a,$b,$c,$nc);
629 2 100       10 return ($c,$nc) if (wantarray);
630 1         9 return $c->mv(-1,0)->slice("0:".($nc->sclr-1))->mv(0,-1);
631             }
632              
633              
634             *vv_setdiff = \&PDL::vv_setdiff;
635              
636              
637              
638              
639             =pod
640              
641             =head1 Sorted Vector Set Operations
642              
643             The following functions are provided for set operations on
644             flat sorted PDLs with unique values. They may be more efficient to compute
645             than the corresponding implenentations via PDL::Primitive::setops().
646              
647             =cut
648              
649              
650              
651              
652              
653             =head2 v_union
654              
655             =for sig
656              
657             Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
658              
659              
660             Union of two flat sorted unique-valued PDLs.
661             Input PDLs $a() and $b() B be sorted in lexicographic order and contain no duplicates.
662             On return, $nc() holds the actual number of values in the union.
663              
664             In scalar context, reshapes $c() to the actual number of elements in the union and returns it.
665              
666              
667              
668             =for bad
669              
670             v_union does not process bad values.
671             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
672              
673              
674             =cut
675              
676              
677              
678              
679              
680             sub PDL::v_union {
681 1     1 0 1022 my ($a,$b,$c,$nc) = @_;
682 1 50 33     15 barf("PDL::VectorValued::v_union(): only 1d vectors are supported") if ($a->ndims > 1 || $b->ndims > 1);
683 1 50       6 $nc = PDL->pdl(PDL::long(), $a->dim(0) + $b->dim(0)) if (!defined($nc));
684 1 50       120 if (!defined($c)) {
685 1 50       4 my $ctype = $a->type > $b->type ? $a->type : $b->type;
686 1 50       69 $c = PDL->zeroes($ctype, ref($nc) ? $nc->sclr : $nc);
687             }
688 1         90 &PDL::_v_union_int($a,$b,$c,$nc);
689 1 50       6 return ($c,$nc) if (wantarray);
690 1         5 return $c->reshape($nc->sclr);
691             }
692              
693              
694             *v_union = \&PDL::v_union;
695              
696              
697              
698              
699              
700             =head2 v_intersect
701              
702             =for sig
703              
704             Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
705              
706              
707             Intersection of two flat sorted unique-valued PDLs.
708             Input PDLs $a() and $b() B be sorted in lexicographic order and contain no duplicates.
709             On return, $nc() holds the actual number of values in the intersection.
710              
711             In scalar context, reshapes $c() to the actual number of elements in the intersection and returns it.
712              
713              
714              
715             =for bad
716              
717             v_intersect does not process bad values.
718             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
719              
720              
721             =cut
722              
723              
724              
725              
726              
727             sub PDL::v_intersect {
728 1     1 0 829 my ($a,$b,$c,$nc) = @_;
729 1 50 33     13 barf("PDL::VectorValued::v_intersect(): only 1d vectors are supported") if ($a->ndims > 1 || $b->ndims > 1);
730 1         4 my $NA = $a->dim(0);
731 1         3 my $NB = $b->dim(0);
732 1 50       5 $nc = PDL->pdl(PDL::long(), $NA < $NB ? $NA : $NB) if (!defined($nc));
    50          
733 1 50       59 if (!defined($c)) {
734 1 50       4 my $ctype = $a->type > $b->type ? $a->type : $b->type;
735 1 50       65 $c = PDL->zeroes($ctype, ref($nc) ? $nc->sclr : $nc);
736             }
737 1         84 &PDL::_v_intersect_int($a,$b,$c,$nc);
738 1 50       5 return ($c,$nc) if (wantarray);
739 1         4 return $c->reshape($nc->sclr);
740             }
741              
742              
743             *v_intersect = \&PDL::v_intersect;
744              
745              
746              
747              
748              
749             =head2 v_setdiff
750              
751             =for sig
752              
753             Signature: (a(NA); b(NB); [o]c(NC); int [o]nc())
754              
755              
756             Set-difference ($a() \ $b()) of two flat sorted unique-valued PDLs.
757             Input PDLs $a() and $b() B be sorted in lexicographic order and contain no duplicate values.
758             On return, $nc() holds the actual number of values in the computed vector set.
759              
760             In scalar context, reshapes $c() to the actual number of elements in the difference set and returns it.
761              
762              
763              
764             =for bad
765              
766             v_setdiff does not process bad values.
767             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
768              
769              
770             =cut
771              
772              
773              
774              
775              
776             sub PDL::v_setdiff {
777 1     1 0 774 my ($a,$b,$c,$nc) = @_;
778 1 50 33     12 barf("PDL::VectorValued::v_setdiff(): only 1d vectors are supported") if ($a->ndims > 1 || $b->ndims > 1);
779 1         4 my $NA = $a->dim(0);
780 1         3 my $NB = $b->dim(0);
781 1 50       5 $nc = PDL->pdl(PDL::long(), $NA) if (!defined($nc));
782 1 50       48 if (!defined($c)) {
783 1 50       4 my $ctype = $a->type > $b->type ? $a->type : $b->type;
784 1         63 $c = PDL->zeroes($ctype, $NA);
785             }
786 1         75 &PDL::_v_setdiff_int($a,$b,$c,$nc);
787 1 50       4 return ($c,$nc) if (wantarray);
788 1         5 return $c->reshape($nc->sclr);
789             }
790              
791              
792             *v_setdiff = \&PDL::v_setdiff;
793              
794              
795              
796              
797             =pod
798              
799             =head1 Miscellaneous Vector-Valued Operations
800              
801             =cut
802              
803              
804              
805              
806              
807             =head2 vv_vcos
808              
809             =for sig
810              
811             Signature: (a(M,N);b(M);float+ [o]vcos(N))
812              
813              
814             Computes the vector cosine similarity of a dense vector $b() with respect to each row $a(*,i)
815             of a dense PDL $a(). This is basically the same thing as:
816              
817             ($a * $b)->sumover / ($a->pow(2)->sumover->sqrt * $b->pow(2)->sumover->sqrt)
818              
819             ... but should be must faster to compute, and avoids allocating potentially large temporaries for
820             the vector magnitudes. Output values in $vcos() are cosine similarities in the range [-1,1],
821             except for zero-magnitude vectors which will result in NaN values in $vcos().
822              
823             You can use PDL threading to batch-compute distances for multiple $b() vectors simultaneously:
824              
825             $bx = random($M, $NB); ##-- get $NB random vectors of size $N
826             $vcos = vv_vcos($a,$bx); ##-- $vcos(i,j) ~ sim($a(,i),$b(,j))
827              
828              
829              
830             =for bad
831              
832             vv_vcos() will set the bad status flag on the output piddle $vcos() if it is set on either of the input
833             piddles $a() or $b(), but BAD values will otherwise be ignored for computing the cosine similary.
834              
835              
836             =cut
837              
838              
839              
840              
841              
842              
843             *vv_vcos = \&PDL::vv_vcos;
844              
845              
846              
847              
848             ##---------------------------------------------------------------------
849             =pod
850              
851             =head1 ACKNOWLEDGEMENTS
852              
853             =over 4
854              
855             =item *
856              
857             Perl by Larry Wall
858              
859             =item *
860              
861             PDL by Karl Glazebrook, Tuomas J. Lukka, Christian Soeller, and others.
862              
863             =item *
864              
865             Code for rlevec() and rldvec() derived from the PDL builtin functions
866             rle() and rld() in $PDL_SRC_ROOT/Basic/Slices/slices.pd
867              
868             =item *
869              
870             Code for vv_qsortvec() copied nearly verbatim from the builtin PDL functions
871             in $PDL_SRC_ROOT/Basic/Ufunc/ufunc.pd, with Chris Marshall's "uniqsortvec" patch.
872             Code for vv_qsortveci() based on the same.
873              
874             =back
875              
876             =cut
877              
878             ##----------------------------------------------------------------------
879             =pod
880              
881             =head1 KNOWN BUGS
882              
883             Probably many.
884              
885             =cut
886              
887              
888             ##---------------------------------------------------------------------
889             =pod
890              
891             =head1 AUTHOR
892              
893             Bryan Jurish Emoocow@cpan.orgE
894              
895              
896             =head1 COPYRIGHT
897              
898             =over 4
899              
900             =item *
901              
902             Code for qsortvec() copyright (C) Tuomas J. Lukka 1997.
903             Contributions by Christian Soeller (c.soeller@auckland.ac.nz)
904             and Karl Glazebrook (kgb@aaoepp.aao.gov.au). All rights
905             reserved. There is no warranty. You are allowed to redistribute this
906             software / documentation under certain conditions. For details, see
907             the file COPYING in the PDL distribution. If this file is separated
908             from the PDL distribution, the copyright notice should be included in
909             the file.
910              
911              
912             =item *
913              
914             All other parts copyright (c) 2007-2015, Bryan Jurish. All rights reserved.
915              
916             This package is free software, and entirely without warranty.
917             You may redistribute it and/or modify it under the same terms
918             as Perl itself.
919              
920             =back
921              
922              
923             =head1 SEE ALSO
924              
925             perl(1), PDL(3perl)
926              
927             =cut
928              
929              
930              
931             ;
932              
933              
934              
935             # Exit with OK status
936              
937             1;
938              
939