File Coverage

blib/lib/PDL/Primitive.pm
Criterion Covered Total %
statement 314 390 80.5
branch 125 210 59.5
condition 38 82 46.3
subroutine 37 38 97.3
pod 8 30 26.6
total 522 750 69.6


line stmt bran cond sub pod time code
1              
2             #
3             # GENERATED WITH PDL::PP! Don't modify!
4             #
5             package PDL::Primitive;
6              
7             @EXPORT_OK = qw( PDL::PP inner PDL::PP outer matmult PDL::PP matmult PDL::PP innerwt PDL::PP inner2 PDL::PP inner2d PDL::PP inner2t PDL::PP crossp PDL::PP norm PDL::PP indadd PDL::PP conv1d PDL::PP in uniq uniqind uniqvec PDL::PP hclip PDL::PP lclip clip PDL::PP clip PDL::PP wtstat PDL::PP statsover stats PDL::PP histogram PDL::PP whistogram PDL::PP histogram2d PDL::PP whistogram2d PDL::PP fibonacci PDL::PP append PDL::PP axisvalues PDL::PP random PDL::PP randsym grandom vsearch PDL::PP vsearch_sample PDL::PP vsearch_insert_leftmost PDL::PP vsearch_insert_rightmost PDL::PP vsearch_match PDL::PP vsearch_bin_inclusive PDL::PP vsearch_bin_exclusive PDL::PP interpolate interpol interpND one2nd PDL::PP which PDL::PP which_both where whereND whichND setops intersect );
8             %EXPORT_TAGS = (Func=>[@EXPORT_OK]);
9              
10 123     123   938 use PDL::Core;
  123         260  
  123         855  
11 123     123   859 use PDL::Exporter;
  123         259  
  123         678  
12 123     123   691 use DynaLoader;
  123         244  
  123         9029  
13              
14              
15              
16            
17             @ISA = ( 'PDL::Exporter','DynaLoader' );
18             push @PDL::Core::PP, __PACKAGE__;
19             bootstrap PDL::Primitive ;
20              
21              
22              
23              
24              
25 123     123   77551 use PDL::Slices;
  123         361  
  123         968  
26 123     123   995 use Carp;
  123         268  
  123         75205  
27              
28             =head1 NAME
29              
30             PDL::Primitive - primitive operations for pdl
31              
32             =head1 DESCRIPTION
33              
34             This module provides some primitive and useful functions defined
35             using PDL::PP and able to use the new indexing tricks.
36              
37             See L for how to use indices creatively.
38             For explanation of the signature format, see L.
39              
40             =head1 SYNOPSIS
41              
42             # Pulls in PDL::Primitive, among other modules.
43             use PDL;
44              
45             # Only pull in PDL::Primitive:
46             use PDL::Primitive;
47              
48             =cut
49              
50              
51              
52              
53              
54              
55              
56             =head1 FUNCTIONS
57              
58              
59              
60             =cut
61              
62              
63              
64              
65              
66              
67             =head2 inner
68              
69             =for sig
70              
71             Signature: (a(n); b(n); [o]c())
72              
73              
74              
75             =for ref
76              
77             Inner product over one dimension
78              
79             c = sum_i a_i * b_i
80              
81              
82              
83             =for bad
84              
85             =for bad
86              
87             If C contains only bad data,
88             C is set bad. Otherwise C will have its bad flag cleared,
89             as it will not contain any bad values.
90              
91              
92              
93             =cut
94              
95              
96              
97              
98              
99              
100             *inner = \&PDL::inner;
101              
102              
103              
104              
105              
106             =head2 outer
107              
108             =for sig
109              
110             Signature: (a(n); b(m); [o]c(n,m))
111              
112              
113              
114             =for ref
115              
116             outer product over one dimension
117              
118             Naturally, it is possible to achieve the effects of outer
119             product simply by threading over the "C<*>"
120             operator but this function is provided for convenience.
121              
122              
123              
124             =for bad
125              
126             outer processes bad values.
127             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
128              
129              
130             =cut
131              
132              
133              
134              
135              
136              
137             *outer = \&PDL::outer;
138              
139              
140              
141              
142             =head2 x
143              
144             =for sig
145              
146             Signature: (a(i,z), b(x,i),[o]c(x,z))
147              
148             =for ref
149              
150             Matrix multiplication
151              
152             PDL overloads the C operator (normally the repeat operator) for
153             matrix multiplication. The number of columns (size of the 0
154             dimension) in the left-hand argument must normally equal the number of
155             rows (size of the 1 dimension) in the right-hand argument.
156              
157             Row vectors are represented as (N x 1) two-dimensional PDLs, or you
158             may be sloppy and use a one-dimensional PDL. Column vectors are
159             represented as (1 x N) two-dimensional PDLs.
160              
161             Threading occurs in the usual way, but as both the 0 and 1 dimension
162             (if present) are included in the operation, you must be sure that
163             you don't try to thread over either of those dims.
164              
165             EXAMPLES
166              
167             Here are some simple ways to define vectors and matrices:
168              
169             pdl> $r = pdl(1,2); # A row vector
170             pdl> $c = pdl([[3],[4]]); # A column vector
171             pdl> $c = pdl(3,4)->(*1); # A column vector, using NiceSlice
172             pdl> $m = pdl([[1,2],[3,4]]); # A 2x2 matrix
173              
174             Now that we have a few objects prepared, here is how to
175             matrix-multiply them:
176              
177             pdl> print $r x $m # row x matrix = row
178             [
179             [ 7 10]
180             ]
181              
182             pdl> print $m x $r # matrix x row = ERROR
183             PDL: Dim mismatch in matmult of [2x2] x [2x1]: 2 != 1
184              
185             pdl> print $m x $c # matrix x column = column
186             [
187             [ 5]
188             [11]
189             ]
190              
191             pdl> print $m x 2 # Trivial case: scalar mult.
192             [
193             [2 4]
194             [6 8]
195             ]
196              
197             pdl> print $r x $c # row x column = scalar
198             [
199             [11]
200             ]
201              
202             pdl> print $c x $r # column x row = matrix
203             [
204             [3 6]
205             [4 8]
206             ]
207              
208              
209             INTERNALS
210              
211             The mechanics of the multiplication are carried out by the
212             L method.
213              
214             =cut
215              
216              
217              
218              
219              
220             =head2 matmult
221              
222             =for sig
223              
224             Signature: (a(t,h); b(w,t); [o]c(w,h))
225              
226             =for ref
227              
228             Matrix multiplication
229              
230             Notionally, matrix multiplication $x x $y is equivalent to the
231             threading expression
232              
233             $x->dummy(1)->inner($y->xchg(0,1)->dummy(2),$c);
234              
235             but for large matrices that breaks CPU cache and is slow. Instead,
236             matmult calculates its result in 32x32x32 tiles, to keep the memory
237             footprint within cache as long as possible on most modern CPUs.
238              
239             For usage, see L, a description of the overloaded 'x' operator
240              
241              
242              
243             =for bad
244              
245             matmult ignores the bad-value flag of the input piddles.
246             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
247              
248              
249             =cut
250              
251              
252              
253              
254             sub PDL::matmult {
255 108     108 0 862 my ($x,$y,$c) = @_;
256              
257 108 100       244 $y = pdl($y) unless eval { $y->isa('PDL') };
  108         508  
258 108 100       217 $c = PDL->null unless eval { $c->isa('PDL') };
  108         436  
259              
260 108         524 while($x->getndims < 2) {$x = $x->dummy(-1)}
  25         75  
261 108         369 while($y->getndims < 2) {$y = $y->dummy(-1)}
  2         10  
262              
263 108 100 100     1012 return ($c .= $x * $y) if( ($x->dim(0)==1 && $x->dim(1)==1) ||
      100        
      100        
264             ($y->dim(0)==1 && $y->dim(1)==1) );
265 105 100       414 if($y->dim(1) != $x->dim(0)) {
266 1         14 barf(sprintf("Dim mismatch in matmult of [%dx%d] x [%dx%d]: %d != %d",$x->dim(0),$x->dim(1),$y->dim(0),$y->dim(1),$x->dim(0),$y->dim(1)));
267             }
268 104         260887 PDL::_matmult_int($x,$y,$c);
269 104         669 $c;
270             }
271              
272              
273             *matmult = \&PDL::matmult;
274              
275              
276              
277              
278              
279             =head2 innerwt
280              
281             =for sig
282              
283             Signature: (a(n); b(n); c(n); [o]d())
284              
285              
286              
287             =for ref
288              
289             Weighted (i.e. triple) inner product
290              
291             d = sum_i a(i) b(i) c(i)
292              
293              
294              
295             =for bad
296              
297             innerwt processes bad values.
298             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
299              
300              
301             =cut
302              
303              
304              
305              
306              
307              
308             *innerwt = \&PDL::innerwt;
309              
310              
311              
312              
313              
314             =head2 inner2
315              
316             =for sig
317              
318             Signature: (a(n); b(n,m); c(m); [o]d())
319              
320              
321              
322             =for ref
323              
324             Inner product of two vectors and a matrix
325              
326             d = sum_ij a(i) b(i,j) c(j)
327              
328             Note that you should probably not thread over C and C since that would be
329             very wasteful. Instead, you should use a temporary for C.
330              
331              
332              
333             =for bad
334              
335             inner2 processes bad values.
336             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
337              
338              
339             =cut
340              
341              
342              
343              
344              
345              
346             *inner2 = \&PDL::inner2;
347              
348              
349              
350              
351              
352             =head2 inner2d
353              
354             =for sig
355              
356             Signature: (a(n,m); b(n,m); [o]c())
357              
358              
359              
360             =for ref
361              
362             Inner product over 2 dimensions.
363              
364             Equivalent to
365              
366             $c = inner($x->clump(2), $y->clump(2))
367              
368              
369              
370             =for bad
371              
372             inner2d processes bad values.
373             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
374              
375              
376             =cut
377              
378              
379              
380              
381              
382              
383             *inner2d = \&PDL::inner2d;
384              
385              
386              
387              
388              
389             =head2 inner2t
390              
391             =for sig
392              
393             Signature: (a(j,n); b(n,m); c(m,k); [t]tmp(n,k); [o]d(j,k)))
394              
395              
396              
397             =for ref
398              
399             Efficient Triple matrix product C
400              
401             Efficiency comes from by using the temporary C. This operation only
402             scales as C whereas threading using L would scale
403             as C.
404              
405             The reason for having this routine is that you do not need to
406             have the same thread-dimensions for C as for the other arguments,
407             which in case of large numbers of matrices makes this much more
408             memory-efficient.
409              
410             It is hoped that things like this could be taken care of as a kind of
411             closures at some point.
412              
413              
414              
415             =for bad
416              
417             inner2t processes bad values.
418             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
419              
420              
421             =cut
422              
423              
424              
425              
426              
427              
428             *inner2t = \&PDL::inner2t;
429              
430              
431              
432              
433              
434             =head2 crossp
435              
436             =for sig
437              
438             Signature: (a(tri=3); b(tri); [o] c(tri))
439              
440              
441             =for ref
442              
443             Cross product of two 3D vectors
444              
445             After
446              
447             =for example
448              
449             $c = crossp $x, $y
450              
451             the inner product C<$c*$x> and C<$c*$y> will be zero, i.e. C<$c> is
452             orthogonal to C<$x> and C<$y>
453              
454              
455              
456             =for bad
457              
458             crossp does not process bad values.
459             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
460              
461              
462             =cut
463              
464              
465              
466              
467              
468              
469             *crossp = \&PDL::crossp;
470              
471              
472              
473              
474              
475             =head2 norm
476              
477             =for sig
478              
479             Signature: (vec(n); [o] norm(n))
480              
481             =for ref
482              
483             Normalises a vector to unit Euclidean length
484              
485             =for bad
486              
487             norm processes bad values.
488             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
489              
490              
491             =cut
492              
493              
494              
495              
496              
497              
498             *norm = \&PDL::norm;
499              
500              
501              
502              
503              
504             =head2 indadd
505              
506             =for sig
507              
508             Signature: (a(); indx ind(); [o] sum(m))
509              
510              
511              
512             =for ref
513              
514             Threaded Index Add: Add C to the C element of C, i.e:
515              
516             sum(ind) += a
517              
518             =for example
519              
520             Simple Example:
521              
522             $x = 2;
523             $ind = 3;
524             $sum = zeroes(10);
525             indadd($x,$ind, $sum);
526             print $sum
527             #Result: ( 2 added to element 3 of $sum)
528             # [0 0 0 2 0 0 0 0 0 0]
529              
530             Threaded Example:
531              
532             $x = pdl( 1,2,3);
533             $ind = pdl( 1,4,6);
534             $sum = zeroes(10);
535             indadd($x,$ind, $sum);
536             print $sum."\n";
537             #Result: ( 1, 2, and 3 added to elements 1,4,6 $sum)
538             # [0 1 0 0 2 0 3 0 0 0]
539              
540              
541              
542             =for bad
543              
544             =for bad
545              
546             The routine barfs if any of the indices are bad.
547              
548              
549              
550             =cut
551              
552              
553              
554              
555              
556              
557             *indadd = \&PDL::indadd;
558              
559              
560              
561              
562              
563             =head2 conv1d
564              
565             =for sig
566              
567             Signature: (a(m); kern(p); [o]b(m); int reflect)
568              
569              
570             =for ref
571              
572             1D convolution along first dimension
573              
574             The m-th element of the discrete convolution of an input piddle
575             C<$a> of size C<$M>, and a kernel piddle C<$kern> of size C<$P>, is
576             calculated as
577              
578             n = ($P-1)/2
579             ====
580             \
581             ($a conv1d $kern)[m] = > $a_ext[m - n] * $kern[n]
582             /
583             ====
584             n = -($P-1)/2
585              
586             where C<$a_ext> is either the periodic (or reflected) extension of
587             C<$a> so it is equal to C<$a> on C< 0..$M-1 > and equal to the
588             corresponding periodic/reflected image of C<$a> outside that range.
589              
590              
591             =for example
592              
593             $con = conv1d sequence(10), pdl(-1,0,1);
594              
595             $con = conv1d sequence(10), pdl(-1,0,1), {Boundary => 'reflect'};
596              
597             By default, periodic boundary conditions are assumed (i.e. wrap around).
598             Alternatively, you can request reflective boundary conditions using
599             the C option:
600              
601             {Boundary => 'reflect'} # case in 'reflect' doesn't matter
602              
603             The convolution is performed along the first dimension. To apply it across
604             another dimension use the slicing routines, e.g.
605              
606             $y = $x->mv(2,0)->conv1d($kernel)->mv(0,2); # along third dim
607              
608             This function is useful for threaded filtering of 1D signals.
609              
610             Compare also L, L,
611             L, L,
612             L
613              
614             =for bad
615              
616             WARNING: C processes bad values in its inputs as
617             the numeric value of C<< $pdl->badvalue >> so it is not
618             recommended for processing pdls with bad values in them
619             unless special care is taken.
620              
621              
622              
623             =for bad
624              
625             conv1d ignores the bad-value flag of the input piddles.
626             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
627              
628              
629             =cut
630              
631              
632              
633              
634              
635              
636             sub PDL::conv1d {
637 0 0   0 0 0 my $opt = pop @_ if ref($_[$#_]) eq 'HASH';
638 0 0 0     0 die 'Usage: conv1d( a(m), kern(p), [o]b(m), {Options} )'
639             if $#_<1 || $#_>2;
640 0         0 my($x,$kern) = @_;
641 0 0       0 my $c = $#_ == 2 ? $_[2] : PDL->null;
642             &PDL::_conv1d_int($x,$kern,$c,
643             !(defined $opt && exists $$opt{Boundary}) ? 0 :
644 0 0 0     0 lc $$opt{Boundary} eq "reflect");
645 0         0 return $c;
646             }
647              
648              
649              
650             *conv1d = \&PDL::conv1d;
651              
652              
653              
654              
655              
656             =head2 in
657              
658             =for sig
659              
660             Signature: (a(); b(n); [o] c())
661              
662              
663             =for ref
664              
665             test if a is in the set of values b
666              
667             =for example
668              
669             $goodmsk = $labels->in($goodlabels);
670             print pdl(3,1,4,6,2)->in(pdl(2,3,3));
671             [1 0 0 0 1]
672              
673             C is akin to the I of set theory. In principle,
674             PDL threading could be used to achieve its functionality by using a
675             construct like
676              
677             $msk = ($labels->dummy(0) == $goodlabels)->orover;
678              
679             However, C doesn't create a (potentially large) intermediate
680             and is generally faster.
681              
682              
683              
684             =for bad
685              
686             in does not process bad values.
687             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
688              
689              
690             =cut
691              
692              
693              
694              
695              
696              
697             *in = \&PDL::in;
698              
699              
700              
701              
702             =head2 uniq
703              
704             =for ref
705              
706             return all unique elements of a piddle
707              
708             The unique elements are returned in ascending order.
709              
710             =for example
711              
712             PDL> p pdl(2,2,2,4,0,-1,6,6)->uniq
713             [-1 0 2 4 6] # 0 is returned 2nd (sorted order)
714              
715             PDL> p pdl(2,2,2,4,nan,-1,6,6)->uniq
716             [-1 2 4 6 nan] # NaN value is returned at end
717              
718             Note: The returned pdl is 1D; any structure of the input
719             piddle is lost. C values are never compare equal to
720             any other values, even themselves. As a result, they are
721             always unique. C returns the NaN values at the end
722             of the result piddle. This follows the Matlab usage.
723              
724             See L if you need the indices of the unique
725             elements rather than the values.
726              
727             =cut
728              
729              
730              
731              
732             =for bad
733              
734             Bad values are not considered unique by uniq and are ignored.
735              
736             $x=sequence(10);
737             $x=$x->setbadif($x%3);
738             print $x->uniq;
739             [0 3 6 9]
740              
741             =cut
742              
743              
744              
745              
746             *uniq = \&PDL::uniq;
747             # return unique elements of array
748             # find as jumps in the sorted array
749             # flattens in the process
750             sub PDL::uniq {
751 123     123   1059 use PDL::Core 'barf';
  123         291  
  123         642  
752 11     11 0 24 my ($arr) = @_;
753 11 50       36 return $arr if($arr->nelem == 0); # The null list is unique (CED)
754 11         33 my $srt = $arr->clump(-1)->where($arr==$arr)->qsort; # no NaNs or BADs for qsort
755 11         110 my $nans = $arr->clump(-1)->where($arr!=$arr);
756 11 50       285 my $uniq = ($srt->nelem > 0) ? $srt->where($srt != $srt->rotate(-1)) : $srt;
757             # make sure we return something if there is only one value
758 11         83 my $answ = $nans; # NaN values always uniq
759 11 50       74 if ( $uniq->nelem > 0 ) {
760 11         169 $answ = $uniq->append($answ);
761             } else {
762 0 0       0 $answ = ( ($srt->nelem == 0) ? $srt : PDL::pdl( ref($srt), [$srt->index(0)] ) )->append($answ);
763             }
764 11         109 return $answ;
765             }
766              
767              
768              
769              
770             =head2 uniqind
771              
772             =for ref
773              
774             Return the indices of all unique elements of a piddle
775             The order is in the order of the values to be consistent
776             with uniq. C values never compare equal with any
777             other value and so are always unique. This follows the
778             Matlab usage.
779              
780             =for example
781              
782             PDL> p pdl(2,2,2,4,0,-1,6,6)->uniqind
783             [5 4 1 3 6] # the 0 at index 4 is returned 2nd, but...
784              
785             PDL> p pdl(2,2,2,4,nan,-1,6,6)->uniqind
786             [5 1 3 6 4] # ...the NaN at index 4 is returned at end
787              
788              
789             Note: The returned pdl is 1D; any structure of the input
790             piddle is lost.
791              
792             See L if you want the unique values instead of the
793             indices.
794              
795             =cut
796              
797              
798              
799              
800             =for bad
801              
802             Bad values are not considered unique by uniqind and are ignored.
803              
804             =cut
805              
806              
807              
808              
809             *uniqind = \&PDL::uniqind;
810             # return unique elements of array
811             # find as jumps in the sorted array
812             # flattens in the process
813             sub PDL::uniqind {
814 123     123   1055 use PDL::Core 'barf';
  123         308  
  123         556  
815 2     2 0 12 my ($arr) = @_;
816 2 50       12 return $arr if($arr->nelem == 0); # The null list is unique (CED)
817             # Different from uniq we sort and store the result in an intermediary
818 2         7 my $aflat = $arr->flat;
819 2         32 my $nanind = which($aflat!=$aflat); # NaN indexes
820 2         17 my $good = $aflat->sequence->long->where($aflat==$aflat); # good indexes
821 2         32 my $i_srt = $aflat->where($aflat==$aflat)->qsorti; # no BAD or NaN values for qsorti
822 2         38 my $srt = $aflat->where($aflat==$aflat)->index($i_srt);
823 2         10 my $uniqind;
824 2 50       18 if ($srt->nelem > 0) {
825 2         72 $uniqind = which($srt != $srt->rotate(-1));
826 2 100       22 $uniqind = $i_srt->slice('0') if $uniqind->isempty;
827             } else {
828 0         0 $uniqind = which($srt);
829             }
830             # Now map back to the original space
831 2         5 my $ansind = $nanind;
832 2 50       10 if ( $uniqind->nelem > 0 ) {
833 2         85 $ansind = ($good->index($i_srt->index($uniqind)))->append($ansind);
834             } else {
835 0         0 $ansind = $uniqind->append($ansind);
836             }
837 2         45 return $ansind;
838             }
839              
840              
841              
842              
843             =head2 uniqvec
844              
845             =for ref
846              
847             Return all unique vectors out of a collection
848              
849             NOTE: If any vectors in the input piddle have NaN values
850             they are returned at the end of the non-NaN ones. This is
851             because, by definition, NaN values never compare equal with
852             any other value.
853              
854             NOTE: The current implementation does not sort the vectors
855             containing NaN values.
856              
857             The unique vectors are returned in lexicographically sorted
858             ascending order. The 0th dimension of the input PDL is treated
859             as a dimensional index within each vector, and the 1st and any
860             higher dimensions are taken to run across vectors. The return
861             value is always 2D; any structure of the input PDL (beyond using
862             the 0th dimension for vector index) is lost.
863              
864             See also L for a unique list of scalars; and
865             L for sorting a list of vectors
866             lexicographcally.
867              
868             =cut
869              
870              
871              
872              
873             =for bad
874              
875             If a vector contains all bad values, it is ignored as in L.
876             If some of the values are good, it is treated as a normal vector. For
877             example, [1 2 BAD] and [BAD 2 3] could be returned, but [BAD BAD BAD]
878             could not. Vectors containing BAD values will be returned after any
879             non-NaN and non-BAD containing vectors, followed by the NaN vectors.
880              
881              
882             =cut
883              
884              
885              
886              
887             sub PDL::uniqvec {
888              
889 9     9 0 1853 my($pdl) = shift;
890              
891 9 50 33     92 return $pdl if ( $pdl->nelem == 0 || $pdl->ndims < 2 );
892 9 100       38 return $pdl if ( $pdl->slice("(0)")->nelem < 2 ); # slice isn't cheap but uniqvec isn't either
893              
894 8         56 my $pdl2d = null;
895 8         68 $pdl2d = $pdl->mv(0,-1)->clump($pdl->ndims-1)->mv(-1,0); # clump all but dim(0)
896              
897 8         39 my $ngood = null;
898 8         33 $ngood = $pdl2d->ones->sumover;
899 8 50 33     145 $ngood = $pdl2d->ngoodover if ($PDL::Bad::Status && $pdl->badflag); # number of good values each vector
900 8         33 my $ngood2 = null;
901 8         40 $ngood2 = $ngood->where($ngood); # number of good values with no all-BADs
902              
903 8         65 $pdl2d = $pdl2d->mv(0,-1)->dice($ngood->which)->mv(-1,0); # remove all-BAD vectors
904              
905              
906 8         41 my $numnan = null;
907 8         12808 $numnan = ($pdl2d!=$pdl2d)->sumover; # works since no all-BADs to confuse
908              
909 8         56 my $presrt = null;
910 8         294 $presrt = $pdl2d->mv(0,-1)->dice($numnan->not->which)->mv(0,-1); # remove vectors with any NaN values
911 8         54 my $nanvec = null;
912 8         52 $nanvec = $pdl2d->mv(0,-1)->dice($numnan->which)->mv(0,-1); # the vectors with any NaN values
913              
914             # use dice instead of nslice since qsortvec might be packing
915             # the badvals to the front of the array instead of the end like
916             # the docs say. If that is the case and it gets fixed, it won't
917             # bust uniqvec. DAL 14-March 2006
918              
919 8         44 my $srt = null;
920 8         50964 $srt = $presrt->qsortvec->mv(0,-1); # BADs are sorted by qsortvec
921 8         46 my $srtdice = $srt;
922 8         27 my $somebad = null;
923 8 50 33     113 if ($PDL::Bad::Status && $srt->badflag) {
924 0         0 $srtdice = $srt->dice($srt->mv(0,-1)->nbadover->not->which);
925 0         0 $somebad = $srt->dice($srt->mv(0,-1)->nbadover->which);
926             }
927              
928 8         36 my $uniq = null;
929 8 50       58 if ($srtdice->nelem > 0) {
930 8         19403 $uniq = ($srtdice != $srtdice->rotate(-1))->mv(0,-1)->orover->which;
931             } else {
932 0         0 $uniq = $srtdice->orover->which;
933             }
934              
935 8         674 my $ans = null;
936 8 100       41 if ( $uniq->nelem > 0 ) {
937 1         5 $ans = $srtdice->dice($uniq);
938             } else {
939 7 50       50 $ans = ($srtdice->nelem > 0) ? $srtdice->slice("0,:") : $srtdice;
940             }
941 8         1342 return $ans->append($somebad)->append($nanvec->mv(0,-1))->mv(0,-1);
942             }
943              
944              
945              
946              
947              
948             =head2 hclip
949              
950             =for sig
951              
952             Signature: (a(); b(); [o] c())
953              
954             =for ref
955              
956             clip (threshold) C<$a> by C<$b> (C<$b> is upper bound)
957              
958             =for bad
959              
960             hclip processes bad values.
961             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
962              
963              
964             =cut
965              
966              
967              
968              
969             sub PDL::hclip {
970 2     2 0 7 my ($x,$y) = @_;
971 2         4 my $c;
972 2 50       21 if ($x->is_inplace) {
    50          
973 0         0 $x->set_inplace(0); $c = $x;
  0         0  
974 0         0 } elsif ($#_ > 1) {$c=$_[2]} else {$c=PDL->nullcreate($x)}
  2         8  
975 2         136 &PDL::_hclip_int($x,$y,$c);
976 2         25 return $c;
977             }
978              
979              
980             *hclip = \&PDL::hclip;
981              
982              
983              
984              
985              
986             =head2 lclip
987              
988             =for sig
989              
990             Signature: (a(); b(); [o] c())
991              
992             =for ref
993              
994             clip (threshold) C<$a> by C<$b> (C<$b> is lower bound)
995              
996             =for bad
997              
998             lclip processes bad values.
999             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1000              
1001              
1002             =cut
1003              
1004              
1005              
1006              
1007             sub PDL::lclip {
1008 2     2 0 320 my ($x,$y) = @_;
1009 2         5 my $c;
1010 2 50       14 if ($x->is_inplace) {
    50          
1011 0         0 $x->set_inplace(0); $c = $x;
  0         0  
1012 0         0 } elsif ($#_ > 1) {$c=$_[2]} else {$c=PDL->nullcreate($x)}
  2         9  
1013 2         105 &PDL::_lclip_int($x,$y,$c);
1014 2         24 return $c;
1015             }
1016              
1017              
1018             *lclip = \&PDL::lclip;
1019              
1020              
1021              
1022              
1023             =head2 clip
1024              
1025             =for ref
1026              
1027             Clip (threshold) a piddle by (optional) upper or lower bounds.
1028              
1029             =for usage
1030              
1031             $y = $x->clip(0,3);
1032             $c = $x->clip(undef, $x);
1033              
1034             =cut
1035              
1036              
1037              
1038              
1039             =for bad
1040              
1041             clip handles bad values since it is just a
1042             wrapper around L and
1043             L.
1044              
1045             =cut
1046              
1047              
1048              
1049              
1050              
1051             =head2 clip
1052              
1053             =for sig
1054              
1055             Signature: (a(); l(); h(); [o] c())
1056              
1057              
1058             =for ref
1059              
1060             info not available
1061              
1062              
1063             =for bad
1064              
1065             clip processes bad values.
1066             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1067              
1068              
1069             =cut
1070              
1071              
1072              
1073              
1074             *clip = \&PDL::clip;
1075             sub PDL::clip {
1076 11     11 0 843 my($x, $l, $h) = @_;
1077 11         22 my $d;
1078 11 50 33     36 unless(defined($l) || defined($h)) {
1079             # Deal with pathological case
1080 0 0       0 if($x->is_inplace) {
1081 0         0 $x->set_inplace(0);
1082 0         0 return $x;
1083             } else {
1084 0         0 return $x->copy;
1085             }
1086             }
1087              
1088 11 50       183 if($x->is_inplace) {
    50          
1089 0         0 $x->set_inplace(0); $d = $x
  0         0  
1090             } elsif ($#_ > 2) {
1091 0         0 $d=$_[3]
1092             } else {
1093 11         40 $d = PDL->nullcreate($x);
1094             }
1095 11 100 66     104 if(defined($l) && defined($h)) {
    50          
    0          
1096 10         402 &PDL::_clip_int($x,$l,$h,$d);
1097             } elsif( defined($l) ) {
1098 1         49 &PDL::_lclip_int($x,$l,$d);
1099             } elsif( defined($h) ) {
1100 0         0 &PDL::_hclip_int($x,$h,$d);
1101             } else {
1102 0         0 die "This can't happen (clip contingency) - file a bug";
1103             }
1104              
1105 11         123 return $d;
1106             }
1107              
1108              
1109             *clip = \&PDL::clip;
1110              
1111              
1112              
1113              
1114              
1115             =head2 wtstat
1116              
1117             =for sig
1118              
1119             Signature: (a(n); wt(n); avg(); [o]b(); int deg)
1120              
1121              
1122              
1123             =for ref
1124              
1125             Weighted statistical moment of given degree
1126              
1127             This calculates a weighted statistic over the vector C.
1128             The formula is
1129              
1130             b() = (sum_i wt_i * (a_i ** degree - avg)) / (sum_i wt_i)
1131              
1132              
1133              
1134             =for bad
1135              
1136             =for bad
1137              
1138             Bad values are ignored in any calculation; C<$b> will only
1139             have its bad flag set if the output contains any bad data.
1140              
1141              
1142              
1143             =cut
1144              
1145              
1146              
1147              
1148              
1149              
1150             *wtstat = \&PDL::wtstat;
1151              
1152              
1153              
1154              
1155              
1156             =head2 statsover
1157              
1158             =for sig
1159              
1160             Signature: (a(n); w(n); float+ [o]avg(); float+ [o]prms(); int+ [o]median(); int+ [o]min(); int+ [o]max(); float+ [o]adev(); float+ [o]rms())
1161              
1162              
1163              
1164             =for ref
1165              
1166             Calculate useful statistics over a dimension of a piddle
1167              
1168             =for usage
1169              
1170             ($mean,$prms,$median,$min,$max,$adev,$rms) = statsover($piddle, $weights);
1171              
1172             This utility function calculates various useful
1173             quantities of a piddle. These are:
1174              
1175             =over 3
1176              
1177             =item * the mean:
1178              
1179             MEAN = sum (x)/ N
1180              
1181             with C being the number of elements in x
1182              
1183             =item * the population RMS deviation from the mean:
1184              
1185             PRMS = sqrt( sum( (x-mean(x))^2 )/(N-1)
1186              
1187             The population deviation is the best-estimate of the deviation
1188             of the population from which a sample is drawn.
1189              
1190             =item * the median
1191              
1192             The median is the 50th percentile data value. Median is found by
1193             L, so WEIGHTING IS IGNORED FOR THE MEDIAN CALCULATION.
1194              
1195             =item * the minimum
1196              
1197             =item * the maximum
1198              
1199             =item * the average absolute deviation:
1200              
1201             AADEV = sum( abs(x-mean(x)) )/N
1202              
1203             =item * RMS deviation from the mean:
1204              
1205             RMS = sqrt(sum( (x-mean(x))^2 )/N)
1206              
1207             (also known as the root-mean-square deviation, or the square root of the
1208             variance)
1209              
1210             =back
1211              
1212             This operator is a projection operator so the calculation
1213             will take place over the final dimension. Thus if the input
1214             is N-dimensional each returned value will be N-1 dimensional,
1215             to calculate the statistics for the entire piddle either
1216             use C directly on the piddle or call C.
1217              
1218              
1219              
1220             =for bad
1221              
1222             =for bad
1223              
1224             Bad values are simply ignored in the calculation, effectively reducing
1225             the sample size. If all data are bad then the output data are marked bad.
1226              
1227              
1228              
1229             =cut
1230              
1231              
1232              
1233              
1234              
1235              
1236             sub PDL::statsover {
1237 19 50   19 0 78 barf('Usage: ($mean,[$prms, $median, $min, $max, $adev, $rms]) = statsover($data,[$weights])') if $#_>1;
1238 19         166 my ($data, $weights) = @_;
1239 19 100       191 $weights = $data->ones() if !defined($weights);
1240              
1241 19         763 my $median = $data->medover();
1242 19         171 my $mean = PDL->nullcreate($data);
1243 19         67 my $rms = PDL->nullcreate($data);
1244 19         65 my $min = PDL->nullcreate($data);
1245 19         59 my $max = PDL->nullcreate($data);
1246 19         57 my $adev = PDL->nullcreate($data);
1247 19         68 my $prms = PDL->nullcreate($data);
1248 19         1006 &PDL::_statsover_int($data, $weights, $mean, $prms, $median, $min, $max, $adev, $rms);
1249              
1250 19 100       144 return $mean unless wantarray;
1251 15         226 return ($mean, $prms, $median, $min, $max, $adev, $rms);
1252             }
1253              
1254              
1255              
1256             *statsover = \&PDL::statsover;
1257              
1258              
1259              
1260              
1261             =head2 stats
1262              
1263             =for ref
1264              
1265             Calculates useful statistics on a piddle
1266              
1267             =for usage
1268              
1269             ($mean,$prms,$median,$min,$max,$adev,$rms) = stats($piddle,[$weights]);
1270              
1271             This utility calculates all the most useful quantities in one call.
1272             It works the same way as L, except that the quantities are
1273             calculated considering the entire input PDL as a single sample, rather
1274             than as a collection of rows. See L for definitions of the
1275             returned quantities.
1276              
1277             =cut
1278              
1279              
1280              
1281              
1282             =for bad
1283              
1284             Bad values are handled; if all input values are bad, then all of the output
1285             values are flagged bad.
1286              
1287             =cut
1288              
1289              
1290              
1291             *stats = \&PDL::stats;
1292             sub PDL::stats {
1293 17 50   17 0 327 barf('Usage: ($mean,[$rms]) = stats($data,[$weights])') if $#_>1;
1294 17         79 my ($data,$weights) = @_;
1295              
1296             # Ensure that $weights is properly threaded over; this could be
1297             # done rather more efficiently...
1298 17 100       62 if(defined $weights) {
1299 1 50       8 $weights = pdl($weights) unless UNIVERSAL::isa($weights,'PDL');
1300 1 50 33     13 if( ($weights->ndims != $data->ndims) or
1301             (pdl($weights->dims) != pdl($data->dims))->or
1302             ) {
1303 0         0 $weights = $weights + zeroes($data)
1304             }
1305 1         9 $weights = $weights->flat;
1306             }
1307              
1308 17         66 return PDL::statsover($data->flat,$weights);
1309             }
1310              
1311              
1312              
1313              
1314             =head2 histogram
1315              
1316             =for sig
1317              
1318             Signature: (in(n); int+[o] hist(m); double step; double min; int msize => m)
1319              
1320              
1321             =for ref
1322              
1323             Calculates a histogram for given stepsize and minimum.
1324              
1325             =for usage
1326              
1327             $h = histogram($data, $step, $min, $numbins);
1328             $hist = zeroes $numbins; # Put histogram in existing piddle.
1329             histogram($data, $hist, $step, $min, $numbins);
1330              
1331             The histogram will contain C<$numbins> bins starting from C<$min>, each
1332             C<$step> wide. The value in each bin is the number of
1333             values in C<$data> that lie within the bin limits.
1334              
1335              
1336             Data below the lower limit is put in the first bin, and data above the
1337             upper limit is put in the last bin.
1338              
1339             The output is reset in a different threadloop so that you
1340             can take a histogram of C<$a(10,12)> into C<$b(15)> and get the result
1341             you want.
1342              
1343             For a higher-level interface, see L.
1344              
1345             =for example
1346              
1347             pdl> p histogram(pdl(1,1,2),1,0,3)
1348             [0 2 1]
1349              
1350              
1351              
1352             =for bad
1353              
1354             histogram processes bad values.
1355             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1356              
1357              
1358             =cut
1359              
1360              
1361              
1362              
1363              
1364              
1365             *histogram = \&PDL::histogram;
1366              
1367              
1368              
1369              
1370              
1371             =head2 whistogram
1372              
1373             =for sig
1374              
1375             Signature: (in(n); float+ wt(n);float+[o] hist(m); double step; double min; int msize => m)
1376              
1377              
1378             =for ref
1379              
1380             Calculates a histogram from weighted data for given stepsize and minimum.
1381              
1382             =for usage
1383              
1384             $h = whistogram($data, $weights, $step, $min, $numbins);
1385             $hist = zeroes $numbins; # Put histogram in existing piddle.
1386             whistogram($data, $weights, $hist, $step, $min, $numbins);
1387              
1388             The histogram will contain C<$numbins> bins starting from C<$min>, each
1389             C<$step> wide. The value in each bin is the sum of the values in C<$weights>
1390             that correspond to values in C<$data> that lie within the bin limits.
1391              
1392             Data below the lower limit is put in the first bin, and data above the
1393             upper limit is put in the last bin.
1394              
1395             The output is reset in a different threadloop so that you
1396             can take a histogram of C<$a(10,12)> into C<$b(15)> and get the result
1397             you want.
1398              
1399             =for example
1400              
1401             pdl> p whistogram(pdl(1,1,2), pdl(0.1,0.1,0.5), 1, 0, 4)
1402             [0 0.2 0.5 0]
1403              
1404              
1405              
1406             =for bad
1407              
1408             whistogram processes bad values.
1409             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1410              
1411              
1412             =cut
1413              
1414              
1415              
1416              
1417              
1418              
1419             *whistogram = \&PDL::whistogram;
1420              
1421              
1422              
1423              
1424              
1425             =head2 histogram2d
1426              
1427             =for sig
1428              
1429             Signature: (ina(n); inb(n); int+[o] hist(ma,mb); double stepa; double mina; int masize => ma;
1430             double stepb; double minb; int mbsize => mb;)
1431              
1432              
1433             =for ref
1434              
1435             Calculates a 2d histogram.
1436              
1437             =for usage
1438              
1439             $h = histogram2d($datax, $datay, $stepx, $minx,
1440             $nbinx, $stepy, $miny, $nbiny);
1441             $hist = zeroes $nbinx, $nbiny; # Put histogram in existing piddle.
1442             histogram2d($datax, $datay, $hist, $stepx, $minx,
1443             $nbinx, $stepy, $miny, $nbiny);
1444              
1445             The histogram will contain C<$nbinx> x C<$nbiny> bins, with the lower
1446             limits of the first one at C<($minx, $miny)>, and with bin size
1447             C<($stepx, $stepy)>.
1448             The value in each bin is the number of
1449             values in C<$datax> and C<$datay> that lie within the bin limits.
1450              
1451             Data below the lower limit is put in the first bin, and data above the
1452             upper limit is put in the last bin.
1453              
1454             =for example
1455              
1456             pdl> p histogram2d(pdl(1,1,1,2,2),pdl(2,1,1,1,1),1,0,3,1,0,3)
1457             [
1458             [0 0 0]
1459             [0 2 2]
1460             [0 1 0]
1461             ]
1462              
1463              
1464              
1465             =for bad
1466              
1467             histogram2d processes bad values.
1468             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1469              
1470              
1471             =cut
1472              
1473              
1474              
1475              
1476              
1477              
1478             *histogram2d = \&PDL::histogram2d;
1479              
1480              
1481              
1482              
1483              
1484             =head2 whistogram2d
1485              
1486             =for sig
1487              
1488             Signature: (ina(n); inb(n); float+ wt(n);float+[o] hist(ma,mb); double stepa; double mina; int masize => ma;
1489             double stepb; double minb; int mbsize => mb;)
1490              
1491              
1492             =for ref
1493              
1494             Calculates a 2d histogram from weighted data.
1495              
1496             =for usage
1497              
1498             $h = whistogram2d($datax, $datay, $weights,
1499             $stepx, $minx, $nbinx, $stepy, $miny, $nbiny);
1500             $hist = zeroes $nbinx, $nbiny; # Put histogram in existing piddle.
1501             whistogram2d($datax, $datay, $weights, $hist,
1502             $stepx, $minx, $nbinx, $stepy, $miny, $nbiny);
1503              
1504             The histogram will contain C<$nbinx> x C<$nbiny> bins, with the lower
1505             limits of the first one at C<($minx, $miny)>, and with bin size
1506             C<($stepx, $stepy)>.
1507             The value in each bin is the sum of the values in
1508             C<$weights> that correspond to values in C<$datax> and C<$datay> that lie within the bin limits.
1509              
1510             Data below the lower limit is put in the first bin, and data above the
1511             upper limit is put in the last bin.
1512              
1513             =for example
1514              
1515             pdl> p whistogram2d(pdl(1,1,1,2,2),pdl(2,1,1,1,1),pdl(0.1,0.2,0.3,0.4,0.5),1,0,3,1,0,3)
1516             [
1517             [ 0 0 0]
1518             [ 0 0.5 0.9]
1519             [ 0 0.1 0]
1520             ]
1521              
1522              
1523              
1524              
1525             =for bad
1526              
1527             whistogram2d processes bad values.
1528             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1529              
1530              
1531             =cut
1532              
1533              
1534              
1535              
1536              
1537              
1538             *whistogram2d = \&PDL::whistogram2d;
1539              
1540              
1541              
1542              
1543              
1544             =head2 fibonacci
1545              
1546             =for sig
1547              
1548             Signature: ([o]x(n))
1549              
1550             =for ref
1551              
1552             Constructor - a vector with Fibonacci's sequence
1553              
1554             =for bad
1555              
1556             fibonacci does not process bad values.
1557             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1558              
1559              
1560             =cut
1561              
1562              
1563              
1564              
1565 1 50 33 1 1 321 sub fibonacci { ref($_[0]) && ref($_[0]) ne 'PDL::Type' ? $_[0]->fibonacci : PDL->fibonacci(@_) }
1566             sub PDL::fibonacci{
1567 1     1 0 4 my $class = shift;
1568 1 50       6 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1569 1         4 &PDL::_fibonacci_int($x->clump(-1));
1570 1         7 return $x;
1571             }
1572              
1573              
1574              
1575              
1576              
1577              
1578              
1579             =head2 append
1580              
1581             =for sig
1582              
1583             Signature: (a(n); b(m); [o] c(mn))
1584              
1585              
1586              
1587             =for ref
1588              
1589             append two piddles by concatenating along their first dimensions
1590              
1591             =for example
1592              
1593             $x = ones(2,4,7);
1594             $y = sequence 5;
1595             $c = $x->append($y); # size of $c is now (7,4,7) (a jumbo-piddle ;)
1596              
1597             C appends two piddles along their first dimensions. The rest of the
1598             dimensions must be compatible in the threading sense. The resulting
1599             size of the first dimension is the sum of the sizes of the first dimensions
1600             of the two argument piddles - i.e. C.
1601              
1602             Similar functions include L (below), which can append more
1603             than two piddles along an arbitrary dimension, and
1604             L, which can append more than two piddles that all
1605             have the same sized dimensions.
1606              
1607              
1608              
1609             =for bad
1610              
1611             append does not process bad values.
1612             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1613              
1614              
1615             =cut
1616              
1617              
1618              
1619              
1620              
1621              
1622             *append = \&PDL::append;
1623              
1624              
1625              
1626              
1627             =head2 glue
1628              
1629             =for usage
1630              
1631             $c = $x->glue(,$y,...)
1632              
1633             =for ref
1634              
1635             Glue two or more PDLs together along an arbitrary dimension
1636             (N-D L).
1637              
1638             Sticks $x, $y, and all following arguments together along the
1639             specified dimension. All other dimensions must be compatible in the
1640             threading sense.
1641              
1642             Glue is permissive, in the sense that every PDL is treated as having an
1643             infinite number of trivial dimensions of order 1 -- so C<< $x->glue(3,$y) >>
1644             works, even if $x and $y are only one dimensional.
1645              
1646             If one of the PDLs has no elements, it is ignored. Likewise, if one
1647             of them is actually the undefined value, it is treated as if it had no
1648             elements.
1649              
1650             If the first parameter is a defined perl scalar rather than a pdl,
1651             then it is taken as a dimension along which to glue everything else,
1652             so you can say C<$cube = PDL::glue(3,@image_list);> if you like.
1653              
1654             C is implemented in pdl, using a combination of L and
1655             L. It should probably be updated (one day) to a pure PP
1656             function.
1657              
1658             Similar functions include L (above), which appends
1659             only two piddles along their first dimension, and
1660             L, which can append more than two piddles that all
1661             have the same sized dimensions.
1662              
1663             =cut
1664              
1665             sub PDL::glue{
1666 6     6 0 92 my($x) = shift;
1667 6         11 my($dim) = shift;
1668              
1669 6 50 33     29 if(defined $x && !(ref $x)) {
1670 0         0 my $y = $dim;
1671 0         0 $dim = $x;
1672 0         0 $x = $y;
1673             }
1674              
1675 6 50 33     40 if(!defined $x || $x->nelem==0) {
1676 0 0       0 return $x unless(@_);
1677 0 0       0 return shift() if(@_<=1);
1678 0         0 $x=shift;
1679 0         0 return PDL::glue($x,$dim,@_);
1680             }
1681              
1682 6 50       28 if($dim - $x->dim(0) > 100) {
1683 0         0 print STDERR "warning:: PDL::glue allocating >100 dimensions!\n";
1684             }
1685 6         33 while($dim >= $x->ndims) {
1686 0         0 $x = $x->dummy(-1,1);
1687             }
1688 6         42 $x = $x->xchg(0,$dim);
1689              
1690 6         17 while(scalar(@_)){
1691 8         25 my $y = shift;
1692 8 50 33     43 next unless(defined $y && $y->nelem);
1693              
1694 8         26 while($dim >= $y->ndims) {
1695 0         0 $y = $y->dummy(-1,1);
1696             }
1697 8         37 $y = $y->xchg(0,$dim);
1698 8         218 $x = $x->append($y);
1699             }
1700 6         61 $x->xchg(0,$dim);
1701             }
1702              
1703              
1704              
1705              
1706              
1707              
1708              
1709              
1710             =head2 axisvalues
1711              
1712             =for sig
1713              
1714             Signature: ([o,nc]a(n))
1715              
1716              
1717              
1718             =for ref
1719              
1720             Internal routine
1721              
1722             C is the internal primitive that implements
1723             L
1724             and alters its argument.
1725              
1726              
1727              
1728             =for bad
1729              
1730             axisvalues does not process bad values.
1731             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
1732              
1733              
1734             =cut
1735              
1736              
1737              
1738              
1739              
1740              
1741             *axisvalues = \&PDL::axisvalues;
1742              
1743              
1744              
1745              
1746             =head2 random
1747              
1748             =for ref
1749              
1750             Constructor which returns piddle of random numbers
1751              
1752             =for usage
1753              
1754             $x = random([type], $nx, $ny, $nz,...);
1755             $x = random $y;
1756              
1757             etc (see L).
1758              
1759             This is the uniform distribution between 0 and 1 (assumedly
1760             excluding 1 itself). The arguments are the same as C
1761             (q.v.) - i.e. one can specify dimensions, types or give
1762             a template.
1763              
1764             You can use the perl function L to seed the random
1765             generator. For further details consult Perl's L
1766             documentation.
1767              
1768             =head2 randsym
1769              
1770             =for ref
1771              
1772             Constructor which returns piddle of random numbers
1773              
1774             =for usage
1775              
1776             $x = randsym([type], $nx, $ny, $nz,...);
1777             $x = randsym $y;
1778              
1779             etc (see L).
1780              
1781             This is the uniform distribution between 0 and 1 (excluding both 0 and
1782             1, cf L). The arguments are the same as C (q.v.) -
1783             i.e. one can specify dimensions, types or give a template.
1784              
1785             You can use the perl function L to seed the random
1786             generator. For further details consult Perl's L
1787             documentation.
1788              
1789             =cut
1790              
1791              
1792              
1793 10 100 66 10 1 2798 sub random { ref($_[0]) && ref($_[0]) ne 'PDL::Type' ? $_[0]->random : PDL->random(@_) }
1794             sub PDL::random {
1795 10     10 0 21 my $class = shift;
1796 10 100       48 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1797 10         197 &PDL::_random_int($x);
1798 10         179 return $x;
1799             }
1800              
1801              
1802              
1803              
1804              
1805 2 50 33 2 1 26 sub randsym { ref($_[0]) && ref($_[0]) ne 'PDL::Type' ? $_[0]->randsym : PDL->randsym(@_) }
1806             sub PDL::randsym {
1807 2     2 0 3 my $class = shift;
1808 2 50       9 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1809 2         21 &PDL::_randsym_int($x);
1810 2         100 return $x;
1811             }
1812              
1813              
1814              
1815              
1816              
1817              
1818             =head2 grandom
1819              
1820             =for ref
1821              
1822             Constructor which returns piddle of Gaussian random numbers
1823              
1824             =for usage
1825              
1826             $x = grandom([type], $nx, $ny, $nz,...);
1827             $x = grandom $y;
1828              
1829             etc (see L).
1830              
1831             This is generated using the math library routine C.
1832              
1833             Mean = 0, Stddev = 1
1834              
1835              
1836             You can use the perl function L to seed the random
1837             generator. For further details consult Perl's L
1838             documentation.
1839              
1840             =cut
1841              
1842 2 50 33 2 1 426 sub grandom { ref($_[0]) && ref($_[0]) ne 'PDL::Type' ? $_[0]->grandom : PDL->grandom(@_) }
1843             sub PDL::grandom {
1844 2     2 0 5 my $class = shift;
1845 2 50       12 my $x = scalar(@_)? $class->new_from_specification(@_) : $class->new_or_inplace;
1846 123     123   74081 use PDL::Math 'ndtri';
  123         432  
  123         1013  
1847 2         7 $x .= ndtri(randsym($x));
1848 2         15 return $x;
1849             }
1850              
1851              
1852              
1853              
1854             =head2 vsearch
1855              
1856             =for sig
1857              
1858             Signature: ( vals(); xs(n); [o] indx(); [\%options] )
1859              
1860             =for ref
1861              
1862             Efficiently search for values in a sorted piddle, returning indices.
1863              
1864             =for usage
1865              
1866             $idx = vsearch( $vals, $x, [\%options] );
1867             vsearch( $vals, $x, $idx, [\%options ] );
1868              
1869             B performs a binary search in the ordered piddle C<$x>,
1870             for the values from C<$vals> piddle, returning indices into C<$x>.
1871             What is a "match", and the meaning of the returned indices, are determined
1872             by the options.
1873              
1874             The C option indicates which method of searching to use, and may
1875             be one of:
1876              
1877             =over
1878              
1879             =item C
1880              
1881             invoke L|/vsearch_sample>, returning indices appropriate for sampling
1882             within a distribution.
1883              
1884             =item C
1885              
1886             invoke L|/vsearch_insert_leftmost>, returning the left-most possible
1887             insertion point which still leaves the piddle sorted.
1888              
1889             =item C
1890              
1891             invoke L|/vsearch_insert_rightmost>, returning the right-most possible
1892             insertion point which still leaves the piddle sorted.
1893              
1894             =item C
1895              
1896             invoke L|/vsearch_match>, returning the index of a matching element,
1897             else -(insertion point + 1)
1898              
1899             =item C
1900              
1901             invoke L|/vsearch_bin_inclusive>, returning an index appropriate for binning
1902             on a grid where the left bin edges are I of the bin. See
1903             below for further explanation of the bin.
1904              
1905             =item C
1906              
1907             invoke L|/vsearch_bin_exclusive>, returning an index appropriate for binning
1908             on a grid where the left bin edges are I of the bin. See
1909             below for further explanation of the bin.
1910              
1911             =back
1912              
1913             The default value of C is C.
1914              
1915             =for example
1916              
1917             use PDL;
1918            
1919             my @modes = qw( sample insert_leftmost insert_rightmost match
1920             bin_inclusive bin_exclusive );
1921            
1922             # Generate a sequence of 3 zeros, 3 ones, ..., 3 fours.
1923             my $x = zeroes(3,5)->yvals->flat;
1924            
1925             for my $mode ( @modes ) {
1926             # if the value is in $x
1927             my $contained = 2;
1928             my $idx_contained = vsearch( $contained, $x, { mode => $mode } );
1929             my $x_contained = $x->copy;
1930             $x_contained->slice( $idx_contained ) .= 9;
1931            
1932             # if the value is not in $x
1933             my $not_contained = 1.5;
1934             my $idx_not_contained = vsearch( $not_contained, $x, { mode => $mode } );
1935             my $x_not_contained = $x->copy;
1936             $x_not_contained->slice( $idx_not_contained ) .= 9;
1937            
1938             print sprintf("%-23s%30s\n", '$x', $x);
1939             print sprintf("%-23s%30s\n", "$mode ($contained)", $x_contained);
1940             print sprintf("%-23s%30s\n\n", "$mode ($not_contained)", $x_not_contained);
1941             }
1942            
1943             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1944             # sample (2) [0 0 0 1 1 1 9 2 2 3 3 3 4 4 4]
1945             # sample (1.5) [0 0 0 1 1 1 9 2 2 3 3 3 4 4 4]
1946             #
1947             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1948             # insert_leftmost (2) [0 0 0 1 1 1 9 2 2 3 3 3 4 4 4]
1949             # insert_leftmost (1.5) [0 0 0 1 1 1 9 2 2 3 3 3 4 4 4]
1950             #
1951             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1952             # insert_rightmost (2) [0 0 0 1 1 1 2 2 2 9 3 3 4 4 4]
1953             # insert_rightmost (1.5) [0 0 0 1 1 1 9 2 2 3 3 3 4 4 4]
1954             #
1955             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1956             # match (2) [0 0 0 1 1 1 2 9 2 3 3 3 4 4 4]
1957             # match (1.5) [0 0 0 1 1 1 2 2 9 3 3 3 4 4 4]
1958             #
1959             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1960             # bin_inclusive (2) [0 0 0 1 1 1 2 2 9 3 3 3 4 4 4]
1961             # bin_inclusive (1.5) [0 0 0 1 1 9 2 2 2 3 3 3 4 4 4]
1962             #
1963             # $x [0 0 0 1 1 1 2 2 2 3 3 3 4 4 4]
1964             # bin_exclusive (2) [0 0 0 1 1 9 2 2 2 3 3 3 4 4 4]
1965             # bin_exclusive (1.5) [0 0 0 1 1 9 2 2 2 3 3 3 4 4 4]
1966              
1967              
1968             Also see
1969             L|/vsearch_sample>,
1970             L|/vsearch_insert_leftmost>,
1971             L|/vsearch_insert_rightmost>,
1972             L|/vsearch_match>,
1973             L|/vsearch_bin_inclusive>, and
1974             L|/vsearch_bin_exclusive>
1975              
1976             =cut
1977              
1978             sub vsearch {
1979 149 100   149 1 38616 my $opt = 'HASH' eq ref $_[-1]
1980             ? pop
1981             : { mode => 'sample' };
1982              
1983             croak( "unknown options to vsearch\n" )
1984 149 50 33     732 if ( ! defined $opt->{mode} && keys %$opt )
      33        
1985             || keys %$opt > 1;
1986              
1987 149         207 my $mode = $opt->{mode};
1988             goto
1989 149 50       7568 $mode eq 'sample' ? \&vsearch_sample
    100          
    100          
    100          
    100          
    100          
1990             : $mode eq 'insert_leftmost' ? \&vsearch_insert_leftmost
1991             : $mode eq 'insert_rightmost' ? \&vsearch_insert_rightmost
1992             : $mode eq 'match' ? \&vsearch_match
1993             : $mode eq 'bin_inclusive' ? \&vsearch_bin_inclusive
1994             : $mode eq 'bin_exclusive' ? \&vsearch_bin_exclusive
1995             : croak( "unknown vsearch mode: $mode\n" );
1996             }
1997              
1998             *PDL::vsearch = \&vsearch;
1999              
2000              
2001              
2002              
2003              
2004             =head2 vsearch_sample
2005              
2006             =for sig
2007              
2008             Signature: (vals(); x(n); indx [o]idx())
2009              
2010              
2011             =for ref
2012              
2013             Search for values in a sorted array, return index appropriate for sampling from a distribution
2014              
2015             =for usage
2016              
2017             $idx = vsearch_sample($vals, $x);
2018              
2019             C<$x> must be sorted, but may be in decreasing or increasing
2020             order.
2021              
2022              
2023              
2024             B returns an index I for each value I of C<$vals> appropriate
2025             for sampling C<$vals>
2026              
2027              
2028              
2029            
2030              
2031             I has the following properties:
2032              
2033             =over
2034              
2035             =item *
2036              
2037             if C<$x> is sorted in increasing order
2038              
2039              
2040             V <= x[0] : I = 0
2041             x[0] < V <= x[-1] : I s.t. x[I-1] < V <= x[I]
2042             x[-1] < V : I = $x->nelem -1
2043              
2044              
2045              
2046             =item *
2047              
2048             if C<$x> is sorted in decreasing order
2049              
2050              
2051             V > x[0] : I = 0
2052             x[0] >= V > x[-1] : I s.t. x[I] >= V > x[I+1]
2053             x[-1] >= V : I = $x->nelem - 1
2054              
2055              
2056              
2057             =back
2058              
2059              
2060              
2061              
2062             If all elements of C<$x> are equal, I<< I = $x->nelem - 1 >>.
2063              
2064             If C<$x> contains duplicated elements, I is the index of the
2065             leftmost (by position in array) duplicate if I matches.
2066              
2067             =for example
2068              
2069             This function is useful e.g. when you have a list of probabilities
2070             for events and want to generate indices to events:
2071              
2072             $x = pdl(.01,.86,.93,1); # Barnsley IFS probabilities cumulatively
2073             $y = random 20;
2074             $c = vsearch_sample($y, $x); # Now, $c will have the appropriate distr.
2075              
2076             It is possible to use the L
2077             function to obtain cumulative probabilities from absolute probabilities.
2078              
2079              
2080              
2081              
2082              
2083              
2084              
2085             =for bad
2086              
2087             needs major (?) work to handles bad values
2088              
2089             =cut
2090              
2091              
2092              
2093              
2094              
2095              
2096             *vsearch_sample = \&PDL::vsearch_sample;
2097              
2098              
2099              
2100              
2101              
2102             =head2 vsearch_insert_leftmost
2103              
2104             =for sig
2105              
2106             Signature: (vals(); x(n); indx [o]idx())
2107              
2108              
2109             =for ref
2110              
2111             Determine the insertion point for values in a sorted array, inserting before duplicates.
2112              
2113             =for usage
2114              
2115             $idx = vsearch_insert_leftmost($vals, $x);
2116              
2117             C<$x> must be sorted, but may be in decreasing or increasing
2118             order.
2119              
2120              
2121              
2122             B returns an index I for each value I of
2123             C<$vals> equal to the leftmost position (by index in array) within
2124             C<$x> that I may be inserted and still maintain the order in
2125             C<$x>.
2126              
2127             Insertion at index I involves shifting elements I and higher of
2128             C<$x> to the right by one and setting the now empty element at index
2129             I to I.
2130              
2131              
2132              
2133            
2134              
2135             I has the following properties:
2136              
2137             =over
2138              
2139             =item *
2140              
2141             if C<$x> is sorted in increasing order
2142              
2143              
2144             V <= x[0] : I = 0
2145             x[0] < V <= x[-1] : I s.t. x[I-1] < V <= x[I]
2146             x[-1] < V : I = $x->nelem
2147              
2148              
2149              
2150             =item *
2151              
2152             if C<$x> is sorted in decreasing order
2153              
2154              
2155             V > x[0] : I = -1
2156             x[0] >= V >= x[-1] : I s.t. x[I] >= V > x[I+1]
2157             x[-1] >= V : I = $x->nelem -1
2158              
2159              
2160              
2161             =back
2162              
2163              
2164              
2165              
2166             If all elements of C<$x> are equal,
2167              
2168             i = 0
2169              
2170             If C<$x> contains duplicated elements, I is the index of the
2171             leftmost (by index in array) duplicate if I matches.
2172              
2173              
2174              
2175              
2176              
2177              
2178              
2179             =for bad
2180              
2181             needs major (?) work to handles bad values
2182              
2183             =cut
2184              
2185              
2186              
2187              
2188              
2189              
2190             *vsearch_insert_leftmost = \&PDL::vsearch_insert_leftmost;
2191              
2192              
2193              
2194              
2195              
2196             =head2 vsearch_insert_rightmost
2197              
2198             =for sig
2199              
2200             Signature: (vals(); x(n); indx [o]idx())
2201              
2202              
2203             =for ref
2204              
2205             Determine the insertion point for values in a sorted array, inserting after duplicates.
2206              
2207             =for usage
2208              
2209             $idx = vsearch_insert_rightmost($vals, $x);
2210              
2211             C<$x> must be sorted, but may be in decreasing or increasing
2212             order.
2213              
2214              
2215              
2216             B returns an index I for each value I of
2217             C<$vals> equal to the rightmost position (by index in array) within
2218             C<$x> that I may be inserted and still maintain the order in
2219             C<$x>.
2220              
2221             Insertion at index I involves shifting elements I and higher of
2222             C<$x> to the right by one and setting the now empty element at index
2223             I to I.
2224              
2225              
2226              
2227            
2228              
2229             I has the following properties:
2230              
2231             =over
2232              
2233             =item *
2234              
2235             if C<$x> is sorted in increasing order
2236              
2237              
2238             V < x[0] : I = 0
2239             x[0] <= V < x[-1] : I s.t. x[I-1] <= V < x[I]
2240             x[-1] <= V : I = $x->nelem
2241              
2242              
2243              
2244             =item *
2245              
2246             if C<$x> is sorted in decreasing order
2247              
2248              
2249             V >= x[0] : I = -1
2250             x[0] > V >= x[-1] : I s.t. x[I] >= V > x[I+1]
2251             x[-1] > V : I = $x->nelem -1
2252              
2253              
2254              
2255             =back
2256              
2257              
2258              
2259              
2260             If all elements of C<$x> are equal,
2261              
2262             i = $x->nelem - 1
2263              
2264             If C<$x> contains duplicated elements, I is the index of the
2265             leftmost (by index in array) duplicate if I matches.
2266              
2267              
2268              
2269              
2270              
2271              
2272              
2273             =for bad
2274              
2275             needs major (?) work to handles bad values
2276              
2277             =cut
2278              
2279              
2280              
2281              
2282              
2283              
2284             *vsearch_insert_rightmost = \&PDL::vsearch_insert_rightmost;
2285              
2286              
2287              
2288              
2289              
2290             =head2 vsearch_match
2291              
2292             =for sig
2293              
2294             Signature: (vals(); x(n); indx [o]idx())
2295              
2296              
2297             =for ref
2298              
2299             Match values against a sorted array.
2300              
2301             =for usage
2302              
2303             $idx = vsearch_match($vals, $x);
2304              
2305             C<$x> must be sorted, but may be in decreasing or increasing
2306             order.
2307              
2308              
2309              
2310             B returns an index I for each value I of
2311             C<$vals>. If I matches an element in C<$x>, I is the
2312             index of that element, otherwise it is I<-( insertion_point + 1 )>,
2313             where I is an index in C<$x> where I may be
2314             inserted while maintaining the order in C<$x>. If C<$x> has
2315             duplicated values, I may refer to any of them.
2316              
2317              
2318              
2319            
2320              
2321              
2322              
2323              
2324              
2325             =for bad
2326              
2327             needs major (?) work to handles bad values
2328              
2329             =cut
2330              
2331              
2332              
2333              
2334              
2335              
2336             *vsearch_match = \&PDL::vsearch_match;
2337              
2338              
2339              
2340              
2341              
2342             =head2 vsearch_bin_inclusive
2343              
2344             =for sig
2345              
2346             Signature: (vals(); x(n); indx [o]idx())
2347              
2348              
2349             =for ref
2350              
2351             Determine the index for values in a sorted array of bins, lower bound inclusive.
2352              
2353             =for usage
2354              
2355             $idx = vsearch_bin_inclusive($vals, $x);
2356              
2357             C<$x> must be sorted, but may be in decreasing or increasing
2358             order.
2359              
2360              
2361              
2362             C<$x> represents the edges of contiguous bins, with the first and
2363             last elements representing the outer edges of the outer bins, and the
2364             inner elements the shared bin edges.
2365              
2366             The lower bound of a bin is inclusive to the bin, its outer bound is exclusive to it.
2367             B returns an index I for each value I of C<$vals>
2368              
2369              
2370              
2371            
2372              
2373             I has the following properties:
2374              
2375             =over
2376              
2377             =item *
2378              
2379             if C<$x> is sorted in increasing order
2380              
2381              
2382             V < x[0] : I = -1
2383             x[0] <= V < x[-1] : I s.t. x[I] <= V < x[I+1]
2384             x[-1] <= V : I = $x->nelem - 1
2385              
2386              
2387              
2388             =item *
2389              
2390             if C<$x> is sorted in decreasing order
2391              
2392              
2393             V >= x[0] : I = 0
2394             x[0] > V >= x[-1] : I s.t. x[I+1] > V >= x[I]
2395             x[-1] > V : I = $x->nelem
2396              
2397              
2398              
2399             =back
2400              
2401              
2402              
2403              
2404             If all elements of C<$x> are equal,
2405              
2406             i = $x->nelem - 1
2407              
2408             If C<$x> contains duplicated elements, I is the index of the
2409             righmost (by index in array) duplicate if I matches.
2410              
2411              
2412              
2413              
2414              
2415              
2416              
2417             =for bad
2418              
2419             needs major (?) work to handles bad values
2420              
2421             =cut
2422              
2423              
2424              
2425              
2426              
2427              
2428             *vsearch_bin_inclusive = \&PDL::vsearch_bin_inclusive;
2429              
2430              
2431              
2432              
2433              
2434             =head2 vsearch_bin_exclusive
2435              
2436             =for sig
2437              
2438             Signature: (vals(); x(n); indx [o]idx())
2439              
2440              
2441             =for ref
2442              
2443             Determine the index for values in a sorted array of bins, lower bound exclusive.
2444              
2445             =for usage
2446              
2447             $idx = vsearch_bin_exclusive($vals, $x);
2448              
2449             C<$x> must be sorted, but may be in decreasing or increasing
2450             order.
2451              
2452              
2453              
2454             C<$x> represents the edges of contiguous bins, with the first and
2455             last elements representing the outer edges of the outer bins, and the
2456             inner elements the shared bin edges.
2457              
2458             The lower bound of a bin is exclusive to the bin, its upper bound is inclusive to it.
2459             B returns an index I for each value I of C<$vals>.
2460              
2461              
2462              
2463            
2464              
2465             I has the following properties:
2466              
2467             =over
2468              
2469             =item *
2470              
2471             if C<$x> is sorted in increasing order
2472              
2473              
2474             V <= x[0] : I = -1
2475             x[0] < V <= x[-1] : I s.t. x[I] < V <= x[I+1]
2476             x[-1] < V : I = $x->nelem - 1
2477              
2478              
2479              
2480             =item *
2481              
2482             if C<$x> is sorted in decreasing order
2483              
2484              
2485             V > x[0] : I = 0
2486             x[0] >= V > x[-1] : I s.t. x[I-1] >= V > x[I]
2487             x[-1] >= V : I = $x->nelem
2488              
2489              
2490              
2491             =back
2492              
2493              
2494              
2495              
2496             If all elements of C<$x> are equal,
2497              
2498             i = $x->nelem - 1
2499              
2500             If C<$x> contains duplicated elements, I is the index of the
2501             righmost (by index in array) duplicate if I matches.
2502              
2503              
2504              
2505              
2506              
2507              
2508              
2509             =for bad
2510              
2511             needs major (?) work to handles bad values
2512              
2513             =cut
2514              
2515              
2516              
2517              
2518              
2519              
2520             *vsearch_bin_exclusive = \&PDL::vsearch_bin_exclusive;
2521              
2522              
2523              
2524              
2525              
2526             =head2 interpolate
2527              
2528             =for sig
2529              
2530             Signature: (xi(); x(n); y(n); [o] yi(); int [o] err())
2531              
2532              
2533             =for ref
2534              
2535             routine for 1D linear interpolation
2536              
2537             =for usage
2538              
2539             ( $yi, $err ) = interpolate($xi, $x, $y)
2540              
2541             Given a set of points C<($x,$y)>, use linear interpolation
2542             to find the values C<$yi> at a set of points C<$xi>.
2543              
2544             C uses a binary search to find the suspects, er...,
2545             interpolation indices and therefore abscissas (ie C<$x>)
2546             have to be I ordered (increasing or decreasing).
2547             For interpolation at lots of
2548             closely spaced abscissas an approach that uses the last index found as
2549             a start for the next search can be faster (compare Numerical Recipes
2550             C routine). Feel free to implement that on top of the binary
2551             search if you like. For out of bounds values it just does a linear
2552             extrapolation and sets the corresponding element of C<$err> to 1,
2553             which is otherwise 0.
2554              
2555             See also L, which uses the same routine,
2556             differing only in the handling of extrapolation - an error message
2557             is printed rather than returning an error piddle.
2558              
2559              
2560              
2561             =for bad
2562              
2563             needs major (?) work to handles bad values
2564              
2565             =cut
2566              
2567              
2568              
2569              
2570              
2571              
2572             *interpolate = \&PDL::interpolate;
2573              
2574              
2575              
2576              
2577             =head2 interpol
2578              
2579             =for sig
2580              
2581             Signature: (xi(); x(n); y(n); [o] yi())
2582              
2583             =for ref
2584              
2585             routine for 1D linear interpolation
2586              
2587             =for usage
2588              
2589             $yi = interpol($xi, $x, $y)
2590              
2591             C uses the same search method as L,
2592             hence C<$x> must be I ordered (either increasing or decreasing).
2593             The difference occurs in the handling of out-of-bounds values; here
2594             an error message is printed.
2595              
2596             =cut
2597              
2598             # kept in for backwards compatability
2599             sub interpol ($$$;$) {
2600 1     1 1 8 my $xi = shift;
2601 1         2 my $x = shift;
2602 1         3 my $y = shift;
2603              
2604 1         2 my $yi;
2605 1 50       4 if ( $#_ == 0 ) { $yi = $_[0]; }
  0         0  
2606 1         5 else { $yi = PDL->null; }
2607              
2608 1         5 interpolate( $xi, $x, $y, $yi, my $err = PDL->null );
2609 1 50       9 print "some values had to be extrapolated\n"
2610             if any $err;
2611              
2612 1 50       10 return $yi if $#_ == -1;
2613              
2614             } # sub: interpol()
2615             *PDL::interpol = \&interpol;
2616              
2617              
2618              
2619              
2620             =head2 interpND
2621              
2622             =for ref
2623              
2624             Interpolate values from an N-D piddle, with switchable method
2625              
2626             =for example
2627              
2628             $source = 10*xvals(10,10) + yvals(10,10);
2629             $index = pdl([[2.2,3.5],[4.1,5.0]],[[6.0,7.4],[8,9]]);
2630             print $source->interpND( $index );
2631              
2632             InterpND acts like L,
2633             collapsing C<$index> by lookup
2634             into C<$source>; but it does interpolation rather than direct sampling.
2635             The interpolation method and boundary condition are switchable via
2636             an options hash.
2637              
2638             By default, linear or sample interpolation is used, with constant
2639             value outside the boundaries of the source pdl. No dataflow occurs,
2640             because in general the output is computed rather than indexed.
2641              
2642             All the interpolation methods treat the pixels as value-centered, so
2643             the C method will return C<< $a->(0) >> for coordinate values on
2644             the set [-0.5,0.5), and all methods will return C<< $a->(1) >> for
2645             a coordinate value of exactly 1.
2646              
2647              
2648             Recognized options:
2649              
2650             =over 3
2651              
2652             =item method
2653              
2654             Values can be:
2655              
2656             =over 3
2657              
2658             =item * 0, s, sample, Sample (default for integer source types)
2659              
2660             The nearest value is taken. Pixels are regarded as centered on their
2661             respective integer coordinates (no offset from the linear case).
2662              
2663             =item * 1, l, linear, Linear (default for floating point source types)
2664              
2665             The values are N-linearly interpolated from an N-dimensional cube of size 2.
2666              
2667             =item * 3, c, cube, cubic, Cubic
2668              
2669             The values are interpolated using a local cubic fit to the data. The
2670             fit is constrained to match the original data and its derivative at the
2671             data points. The second derivative of the fit is not continuous at the
2672             data points. Multidimensional datasets are interpolated by the
2673             successive-collapse method.
2674              
2675             (Note that the constraint on the first derivative causes a small amount
2676             of ringing around sudden features such as step functions).
2677              
2678             =item * f, fft, fourier, Fourier
2679              
2680             The source is Fourier transformed, and the interpolated values are
2681             explicitly calculated from the coefficients. The boundary condition
2682             option is ignored -- periodic boundaries are imposed.
2683              
2684             If you pass in the option "fft", and it is a list (ARRAY) ref, then it
2685             is a stash for the magnitude and phase of the source FFT. If the list
2686             has two elements then they are taken as already computed; otherwise
2687             they are calculated and put in the stash.
2688              
2689             =back
2690              
2691             =item b, bound, boundary, Boundary
2692              
2693             This option is passed unmodified into L,
2694             which is used as the indexing engine for the interpolation.
2695             Some current allowed values are 'extend', 'periodic', 'truncate', and 'mirror'
2696             (default is 'truncate').
2697              
2698             =item bad
2699              
2700             contains the fill value used for 'truncate' boundary. (default 0)
2701              
2702             =item fft
2703              
2704             An array ref whose associated list is used to stash the FFT of the source
2705             data, for the FFT method.
2706              
2707             =back
2708              
2709             =cut
2710              
2711             *interpND = *PDL::interpND;
2712             sub PDL::interpND {
2713 16     16 0 127 my $source = shift;
2714 16         27 my $index = shift;
2715 16         27 my $options = shift;
2716              
2717 16 50 66     103 barf 'Usage: interp_nd($source,$index,[{%options}])\n'
2718             if(defined $options and ref $options ne 'HASH');
2719              
2720 16 100       115 my($opt) = (defined $options) ? $options : {};
2721              
2722 16   66     172 my($method) = $opt->{m} || $opt->{meth} || $opt->{method} || $opt->{Method};
2723 16 100       68 if(!defined $method) {
2724 5 50       39 $method = ($source->type <= zeroes(long,1)->type) ?
2725             'sample' :
2726             'linear';
2727             }
2728              
2729 16   50     211 my($boundary) = $opt->{b} || $opt->{boundary} || $opt->{Boundary} || $opt->{bound} || $opt->{Bound} || 'extend';
2730 16   50     95 my($bad) = $opt->{bad} || $opt->{Bad} || 0.0;
2731              
2732 16 100 66     157 if($method =~ m/^s(am(p(le)?)?)?/i) {
    100 33        
    50          
    0          
2733 6         10538 return $source->range(PDL::Math::floor($index+0.5),0,$boundary);
2734             }
2735              
2736             elsif (($method eq 1) || $method =~ m/^l(in(ear)?)?/i) {
2737             ## key: (ith = index thread; cth = cube thread; sth = source thread)
2738 9         45 my $d = $index->dim(0);
2739 9         34 my $di = $index->ndims - 1;
2740              
2741             # Grab a 2-on-a-side n-cube around each desired pixel
2742 9         4742 my $samp = $source->range($index->floor,2,$boundary); # (ith, cth, sth)
2743              
2744             # Reorder to put the cube dimensions in front and convert to a list
2745 9         134 $samp = $samp->reorder( $di .. $di+$d-1,
2746             0 .. $di-1,
2747             $di+$d .. $samp->ndims-1) # (cth, ith, sth)
2748             ->clump($d); # (clst, ith, sth)
2749              
2750             # Enumerate the corners of an n-cube and convert to a list
2751             # (the 'x' is the normal perl repeat operator)
2752 9         75 my $crnr = PDL::Basic::ndcoords( (2) x $index->dim(0) ) # (index,cth)
2753             ->mv(0,-1)->clump($index->dim(0))->mv(-1,0); # (index, clst)
2754              
2755             # a & b are the weighting coefficients.
2756 9         46 my($x,$y);
2757 9         0 my($indexwhere);
2758 9         1969 ($indexwhere = $index->where( 0 * $index )) .= -10; # Change NaN to invalid
2759             {
2760 9         59 my $bb = PDL::Math::floor($index);
  9         3085  
2761 9         4098 $x = ($index - $bb) -> dummy(1,$crnr->dim(1)); # index, clst, ith
2762 9         8208 $y = ($bb + 1 - $index) -> dummy(1,$crnr->dim(1)); # index, clst, ith
2763             }
2764              
2765             # Use 1/0 corners to select which multiplier happens, multiply
2766             # 'em all together to get sample weights, and sum to get the answer.
2767 9         102732 my $out0 = ( ($x * ($crnr==1) + $y * ($crnr==0)) #index, clst, ith
2768             -> prodover #clst, ith
2769             );
2770              
2771 9         75269 my $out = ($out0 * $samp)->sumover; # ith, sth
2772              
2773             # Work around BAD-not-being-contagious bug in PDL <= 2.6 bad handling code --CED 3-April-2013
2774 9 100 66     141 if($PDL::Bad::Status and $source->badflag) {
2775 1         109 my $baddies = $samp->isbad->orover;
2776 1         67 $out = $out->setbadif($baddies);
2777             }
2778              
2779 9         3345 return $out;
2780              
2781             } elsif(($method eq 3) || $method =~ m/^c(u(b(e|ic)?)?)?/i) {
2782              
2783 1         8 my ($d,@di) = $index->dims;
2784 1         6 my $di = $index->ndims - 1;
2785              
2786             # Grab a 4-on-a-side n-cube around each desired pixel
2787 1         8692 my $samp = $source->range($index->floor - 1,4,$boundary) #ith, cth, sth
2788             ->reorder( $di .. $di+$d-1, 0..$di-1, $di+$d .. $source->ndims-1 );
2789             # (cth, ith, sth)
2790              
2791             # Make a cube of the subpixel offsets, and expand its dims to
2792             # a 4-on-a-side N-1 cube, to match the slices of $samp (used below).
2793 1         4333 my $y = $index - $index->floor;
2794 1         22 for my $i(1..$d-1) {
2795 1         10 $y = $y->dummy($i,4);
2796             }
2797              
2798             # Collapse by interpolation, one dimension at a time...
2799 1         5 for my $i(0..$d-1) {
2800 2         9 my $a0 = $samp->slice("(1)"); # Just-under-sample
2801 2         8 my $a1 = $samp->slice("(2)"); # Just-over-sample
2802 2         124102 my $a1a0 = $a1 - $a0;
2803              
2804 2         31 my $gradient = 0.5 * ($samp->slice("2:3")-$samp->slice("0:1"));
2805 2         86 my $s0 = $gradient->slice("(0)"); # Just-under-gradient
2806 2         9 my $s1 = $gradient->slice("(1)"); # Just-over-gradient
2807              
2808 2         13 $bb = $y->slice("($i)");
2809              
2810             # Collapse the sample...
2811 2         149516 $samp = ( $a0 +
2812             $bb * (
2813             $s0 +
2814             $bb * ( (3 * $a1a0 - 2*$s0 - $s1) +
2815             $bb * ( $s1 + $s0 - 2*$a1a0 )
2816             )
2817             )
2818             );
2819              
2820             # "Collapse" the subpixel offset...
2821 2         125 $y = $y->slice(":,($i)");
2822             }
2823              
2824 1         28 return $samp;
2825              
2826             } elsif($method =~ m/^f(ft|ourier)?/i) {
2827              
2828 0         0 eval "use PDL::FFT;";
2829 0         0 my $fftref = $opt->{fft};
2830 0 0       0 $fftref = [] unless(ref $fftref eq 'ARRAY');
2831 0 0       0 if(@$fftref != 2) {
2832 0         0 my $x = $source->copy;
2833 0         0 my $y = zeroes($source);
2834 0         0 fftnd($x,$y);
2835 0         0 $fftref->[0] = sqrt($x*$x+$y*$y) / $x->nelem;
2836 0         0 $fftref->[1] = - atan2($y,$x);
2837             }
2838              
2839 0         0 my $i;
2840 0         0 my $c = PDL::Basic::ndcoords($source); # (dim, source-dims)
2841 0         0 for $i(1..$index->ndims-1) {
2842 0         0 $c = $c->dummy($i,$index->dim($i))
2843             }
2844 0         0 my $id = $index->ndims-1;
2845 0         0 my $phase = (($c * $index * 3.14159 * 2 / pdl($source->dims))
2846             ->sumover) # (index-dims, source-dims)
2847             ->reorder($id..$id+$source->ndims-1,0..$id-1); # (src, index)
2848              
2849 0         0 my $phref = $fftref->[1]->copy; # (source-dims)
2850 0         0 my $mag = $fftref->[0]->copy; # (source-dims)
2851              
2852 0         0 for $i(1..$index->ndims-1) {
2853 0         0 $phref = $phref->dummy(-1,$index->dim($i));
2854 0         0 $mag = $mag->dummy(-1,$index->dim($i));
2855             }
2856 0         0 my $out = cos($phase + $phref ) * $mag;
2857 0         0 $out = $out->clump($source->ndims)->sumover;
2858              
2859 0         0 return $out;
2860             } else {
2861 0         0 barf("interpND: unknown method '$method'; valid ones are 'linear' and 'sample'.\n");
2862             }
2863             }
2864              
2865              
2866              
2867              
2868             =head2 one2nd
2869              
2870             =for ref
2871              
2872             Converts a one dimensional index piddle to a set of ND coordinates
2873              
2874             =for usage
2875              
2876             @coords=one2nd($x, $indices)
2877              
2878             returns an array of piddles containing the ND indexes corresponding to
2879             the one dimensional list indices. The indices are assumed to
2880             correspond to array C<$x> clumped using C. This routine is
2881             used in the old vector form of L, but is useful on
2882             its own occasionally.
2883              
2884             Returned piddles have the L datatype. C<$indices> can have
2885             values larger than C<< $x->nelem >> but negative values in C<$indices>
2886             will not give the answer you expect.
2887              
2888             =for example
2889              
2890             pdl> $x=pdl [[[1,2],[-1,1]], [[0,-3],[3,2]]]; $c=$x->clump(-1)
2891             pdl> $maxind=maximum_ind($c); p $maxind;
2892             6
2893             pdl> print one2nd($x, maximum_ind($c))
2894             0 1 1
2895             pdl> p $x->at(0,1,1)
2896             3
2897              
2898             =cut
2899              
2900             *one2nd = \&PDL::one2nd;
2901             sub PDL::one2nd {
2902 1 50   1 0 11 barf "Usage: one2nd \$array \$indices\n" if $#_ != 1;
2903 1         4 my ($x, $ind)=@_;
2904 1         4 my @dimension=$x->dims;
2905 1         6 $ind = indx($ind);
2906 1         3 my(@index);
2907 1         3 my $count=0;
2908 1         3 foreach (@dimension) {
2909 3         46 $index[$count++]=$ind % $_;
2910 3         20 $ind /= $_;
2911             }
2912 1         10 return @index;
2913             }
2914              
2915              
2916              
2917              
2918              
2919             =head2 which
2920              
2921             =for sig
2922              
2923             Signature: (mask(n); indx [o] inds(m))
2924              
2925              
2926             =for ref
2927              
2928             Returns indices of non-zero values from a 1-D PDL
2929              
2930             =for usage
2931              
2932             $i = which($mask);
2933              
2934             returns a pdl with indices for all those elements that are nonzero in
2935             the mask. Note that the returned indices will be 1D. If you feed in a
2936             multidimensional mask, it will be flattened before the indices are
2937             calculated. See also L for multidimensional masks.
2938              
2939             If you want to index into the original mask or a similar piddle
2940             with output from C, remember to flatten it before calling index:
2941              
2942             $data = random 5, 5;
2943             $idx = which $data > 0.5; # $idx is now 1D
2944             $bigsum = $data->flat->index($idx)->sum; # flatten before indexing
2945              
2946             Compare also L for similar functionality.
2947              
2948             SEE ALSO:
2949              
2950             L returns separately the indices of both
2951             zero and nonzero values in the mask.
2952              
2953             L returns associated values from a data PDL, rather than
2954             indices into the mask PDL.
2955              
2956             L returns N-D indices into a multidimensional PDL.
2957              
2958             =for example
2959              
2960             pdl> $x = sequence(10); p $x
2961             [0 1 2 3 4 5 6 7 8 9]
2962             pdl> $indx = which($x>6); p $indx
2963             [7 8 9]
2964              
2965              
2966              
2967             =for bad
2968              
2969             which processes bad values.
2970             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
2971              
2972              
2973             =cut
2974              
2975              
2976              
2977              
2978 279     279 1 1159 sub which { my ($this,$out) = @_;
2979 279         782 $this = $this->flat;
2980 279 50       1115 $out = $this->nullcreate unless defined $out;
2981 279         40065 PDL::_which_int($this,$out);
2982 279         3367 return $out;
2983             }
2984             *PDL::which = \&which;
2985              
2986              
2987             *which = \&PDL::which;
2988              
2989              
2990              
2991              
2992              
2993             =head2 which_both
2994              
2995             =for sig
2996              
2997             Signature: (mask(n); indx [o] inds(m); indx [o]notinds(q))
2998              
2999              
3000             =for ref
3001              
3002             Returns indices of zero and nonzero values in a mask PDL
3003              
3004             =for usage
3005              
3006             ($i, $c_i) = which_both($mask);
3007              
3008             This works just as L, but the complement of C<$i> will be in
3009             C<$c_i>.
3010              
3011             =for example
3012              
3013             pdl> $x = sequence(10); p $x
3014             [0 1 2 3 4 5 6 7 8 9]
3015             pdl> ($small, $big) = which_both ($x >= 5); p "$small\n $big"
3016             [5 6 7 8 9]
3017             [0 1 2 3 4]
3018              
3019              
3020              
3021             =for bad
3022              
3023             which_both processes bad values.
3024             It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.
3025              
3026              
3027             =cut
3028              
3029              
3030              
3031              
3032 1     1 1 7 sub which_both { my ($this,$outi,$outni) = @_;
3033 1         5 $this = $this->flat;
3034 1 50       5 $outi = $this->nullcreate unless defined $outi;
3035 1 50       6 $outni = $this->nullcreate unless defined $outni;
3036 1         65 PDL::_which_both_int($this,$outi,$outni);
3037 1 50       10 return wantarray ? ($outi,$outni) : $outi;
3038             }
3039             *PDL::which_both = \&which_both;
3040              
3041              
3042             *which_both = \&PDL::which_both;
3043              
3044              
3045              
3046              
3047             =head2 where
3048              
3049             =for ref
3050              
3051             Use a mask to select values from one or more data PDLs
3052              
3053             C accepts one or more data piddles and a mask piddle. It
3054             returns a list of output piddles, corresponding to the input data
3055             piddles. Each output piddle is a 1-dimensional list of values in its
3056             corresponding data piddle. The values are drawn from locations where
3057             the mask is nonzero.
3058              
3059             The output PDLs are still connected to the original data PDLs, for the
3060             purpose of dataflow.
3061              
3062             C combines the functionality of L and L
3063             into a single operation.
3064              
3065             BUGS:
3066              
3067             While C works OK for most N-dimensional cases, it does not
3068             thread properly over (for example) the (N+1)th dimension in data
3069             that is compared to an N-dimensional mask. Use C for that.
3070              
3071             =for usage
3072              
3073             $i = $x->where($x+5 > 0); # $i contains those elements of $x
3074             # where mask ($x+5 > 0) is 1
3075             $i .= -5; # Set those elements (of $x) to -5. Together, these
3076             # commands clamp $x to a maximum of -5.
3077              
3078             It is also possible to use the same mask for several piddles with
3079             the same call:
3080              
3081             ($i,$j,$k) = where($x,$y,$z, $x+5>0);
3082              
3083             Note: C<$i> is always 1-D, even if C<$x> is E1-D.
3084              
3085             WARNING: The first argument
3086             (the values) and the second argument (the mask) currently have to have
3087             the exact same dimensions (or horrible things happen). You *cannot*
3088             thread over a smaller mask, for example.
3089              
3090              
3091             =cut
3092              
3093             sub PDL::where {
3094 189 50   189 0 1762 barf "Usage: where( \$pdl1, ..., \$pdlN, \$mask )\n" if $#_ == 0;
3095              
3096 189 100       539 if($#_ == 1) {
3097 188         386 my($data,$mask) = @_;
3098 188 100       772 $data = $_[0]->clump(-1) if $_[0]->getndims>1;
3099 188 100       579 $mask = $_[1]->clump(-1) if $_[0]->getndims>1;
3100 188         497 return $data->index($mask->which());
3101             } else {
3102 1 50       19 if($_[-1]->getndims > 1) {
3103 0         0 my $mask = $_[-1]->clump(-1)->which;
3104 0         0 return map {$_->clump(-1)->index($mask)} @_[0..$#_-1];
  0         0  
3105             } else {
3106 1         5 my $mask = $_[-1]->which;
3107 1         5 return map {$_->index($mask)} @_[0..$#_-1];
  2         33  
3108             }
3109             }
3110             }
3111             *where = \&PDL::where;
3112              
3113              
3114              
3115              
3116             =head2 whereND
3117              
3118             =for ref
3119              
3120             C with support for ND masks and threading
3121              
3122             C accepts one or more data piddles and a
3123             mask piddle. It returns a list of output piddles,
3124             corresponding to the input data piddles. The values
3125             are drawn from locations where the mask is nonzero.
3126              
3127             C differs from C in that the mask
3128             dimensionality is preserved which allows for
3129             proper threading of the selection operation over
3130             higher dimensions.
3131              
3132             As with C the output PDLs are still connected
3133             to the original data PDLs, for the purpose of dataflow.
3134              
3135             =for usage
3136              
3137             $sdata = whereND $data, $mask
3138             ($s1, $s2, ..., $sn) = whereND $d1, $d2, ..., $dn, $mask
3139              
3140             where
3141              
3142             $data is M dimensional
3143             $mask is N < M dimensional
3144             dims($data) 1..N == dims($mask) 1..N
3145             with threading over N+1 to M dimensions
3146              
3147             =for example
3148              
3149             $data = sequence(4,3,2); # example data array
3150             $mask4 = (random(4)>0.5); # example 1-D mask array, has $n4 true values
3151             $mask43 = (random(4,3)>0.5); # example 2-D mask array, has $n43 true values
3152             $sdat4 = whereND $data, $mask4; # $sdat4 is a [$n4,3,2] pdl
3153             $sdat43 = whereND $data, $mask43; # $sdat43 is a [$n43,2] pdl
3154              
3155             Just as with C, you can use the returned value in an
3156             assignment. That means that both of these examples are valid:
3157              
3158             # Used to create a new slice stored in $sdat4:
3159             $sdat4 = $data->whereND($mask4);
3160             $sdat4 .= 0;
3161             # Used in lvalue context:
3162             $data->whereND($mask4) .= 0;
3163              
3164             =cut
3165              
3166             sub PDL::whereND :lvalue {
3167 5 50   5 0 108 barf "Usage: whereND( \$pdl1, ..., \$pdlN, \$mask )\n" if $#_ == 0;
3168              
3169 5         10 my $mask = pop @_; # $mask has 0==false, 1==true
3170 5         9 my @to_return;
3171              
3172 5         19 my $n = PDL::sum($mask);
3173              
3174 5         12 foreach my $arr (@_) {
3175              
3176 5         18 my $sub_i = $mask * ones($arr);
3177 5         29 my $where_sub_i = PDL::where($arr, $sub_i);
3178              
3179             # count the number of dims in $mask and $arr
3180             # $mask = a b c d e f.....
3181 5         28 my @idims = dims($arr);
3182              
3183             # ...and pop off the number of dims in $mask
3184 5         16 foreach ( dims($mask) ) { shift(@idims) };
  8         21  
3185              
3186 5         7 my $ndim = 0;
3187 5         15 foreach my $id ($n, @idims[0..($#idims-1)]) {
3188 7 100       52 $where_sub_i = $where_sub_i->splitdim($ndim++,$id) if $n>0;
3189             }
3190              
3191 5         24 push @to_return, $where_sub_i;
3192             }
3193              
3194 5 50       25 return (@to_return == 1) ? $to_return[0] : @to_return;
3195             }
3196             *whereND = \&PDL::whereND;
3197              
3198              
3199              
3200              
3201             =head2 whichND
3202              
3203             =for ref
3204              
3205             Return the coordinates of non-zero values in a mask.
3206              
3207             =for usage
3208              
3209             WhichND returns the N-dimensional coordinates of each nonzero value in
3210             a mask PDL with any number of dimensions. The returned values arrive
3211             as an array-of-vectors suitable for use in
3212             L or L.
3213              
3214             $coords = whichND($mask);
3215              
3216             returns a PDL containing the coordinates of the elements that are non-zero
3217             in C<$mask>, suitable for use in indexND. The 0th dimension contains the
3218             full coordinate listing of each point; the 1st dimension lists all the points.
3219             For example, if $mask has rank 4 and 100 matching elements, then $coords has
3220             dimension 4x100.
3221              
3222             If no such elements exist, then whichND returns a structured empty PDL:
3223             an Nx0 PDL that contains no values (but matches, threading-wise, with
3224             the vectors that would be produced if such elements existed).
3225              
3226             DEPRECATED BEHAVIOR IN LIST CONTEXT:
3227              
3228             whichND once delivered different values in list context than in scalar
3229             context, for historical reasons. In list context, it returned the
3230             coordinates transposed, as a collection of 1-PDLs (one per dimension)
3231             in a list. This usage is deprecated in PDL 2.4.10, and will cause a
3232             warning to be issued every time it is encountered. To avoid the
3233             warning, you can set the global variable "$PDL::whichND" to 's' to
3234             get scalar behavior in all contexts, or to 'l' to get list behavior in
3235             list context.
3236              
3237             In later versions of PDL, the deprecated behavior will disappear. Deprecated
3238             list context whichND expressions can be replaced with:
3239              
3240             @list = $x->whichND->mv(0,-1)->dog;
3241              
3242              
3243             SEE ALSO:
3244              
3245             L finds coordinates of nonzero values in a 1-D mask.
3246              
3247             L extracts values from a data PDL that are associated
3248             with nonzero values in a mask PDL.
3249              
3250             =for example
3251              
3252             pdl> $s=sequence(10,10,3,4)
3253             pdl> ($x, $y, $z, $w)=whichND($s == 203); p $x, $y, $z, $w
3254             [3] [0] [2] [0]
3255             pdl> print $s->at(list(cat($x,$y,$z,$w)))
3256             203
3257              
3258             =cut
3259              
3260             *whichND = \&PDL::whichND;
3261             sub PDL::whichND {
3262 33     33 0 535 my $mask = shift;
3263 33 50       182 $mask = PDL::pdl('PDL',$mask) unless(UNIVERSAL::isa($mask,'PDL'));
3264              
3265             # List context: generate a perl list by dimension
3266 33 50       113 if(wantarray) {
3267 0 0       0 if(!defined($PDL::whichND)) {
    0          
3268 0         0 printf STDERR "whichND: WARNING - list context deprecated. Set \$PDL::whichND. Details in pod.";
3269             } elsif($PDL::whichND =~ m/l/i) {
3270             # old list context enabled by setting $PDL::whichND to 'l'
3271 0         0 my $ind=($mask->clump(-1))->which;
3272 0         0 return $mask->one2nd($ind);
3273             }
3274             # if $PDL::whichND does not contain 'l' or 'L', fall through to scalar context
3275             }
3276              
3277             # Scalar context: generate an N-D index piddle
3278              
3279 33 100       229 unless($mask->nelem) {
3280 2         8 return PDL::new_from_specification('PDL',indx,$mask->ndims,0);
3281             }
3282              
3283 31 100       175 unless($mask->getndims) {
3284 2 100       8 return $mask ? pdl(indx,0) : PDL::new_from_specification('PDL',indx,0);
3285             }
3286              
3287 29         198 $ind = $mask->flat->which->dummy(0,$mask->getndims)->make_physical;
3288 29 100       457 if($ind->nelem==0) {
3289             # In the empty case, explicitly return the correct type of structured empty
3290 9         47 return PDL::new_from_specification('PDL',indx,$mask->ndims, 0);
3291             }
3292              
3293 20         133 my $mult = ones($mask->getndims)->long;
3294 20         152 my @mdims = $mask->dims;
3295 20         228 my $i;
3296              
3297 20         69 for $i(0..$#mdims-1) {
3298             # use $tmp for 5.005_03 compatibility
3299 24         1412 (my $tmp = $mult->index($i+1)) .= $mult->index($i)*$mdims[$i];
3300             }
3301              
3302 20         84 for $i(0..$#mdims) {
3303 44         384 my($s) = $ind->index($i);
3304 44         512 $s /= $mult->index($i);
3305 44         329 $s %= $mdims[$i];
3306             }
3307              
3308 20         844 return $ind;
3309             }
3310              
3311              
3312              
3313              
3314             =head2 setops
3315              
3316             =for ref
3317              
3318             Implements simple set operations like union and intersection
3319              
3320             =for usage
3321              
3322             Usage: $set = setops($x, , $y);
3323              
3324             The operator can be C, C or C. This is then applied
3325             to C<$x> viewed as a set and C<$y> viewed as a set. Set theory says
3326             that a set may not have two or more identical elements, but setops
3327             takes care of this for you, so C<$x=pdl(1,1,2)> is OK. The functioning
3328             is as follows:
3329              
3330             =over
3331              
3332             =item C
3333              
3334             The resulting vector will contain the elements that are either in C<$x>
3335             I in C<$y> or both. This is the union in set operation terms
3336              
3337             =item C
3338              
3339             The resulting vector will contain the elements that are either in C<$x>
3340             or C<$y>, but not in both. This is
3341              
3342             Union($x, $y) - Intersection($x, $y)
3343              
3344             in set operation terms.
3345              
3346             =item C
3347              
3348             The resulting vector will contain the intersection of C<$x> and C<$y>, so
3349             the elements that are in both C<$x> and C<$y>. Note that for convenience
3350             this operation is also aliased to L.
3351              
3352             =back
3353              
3354             It should be emphasized that these routines are used when one or both of
3355             the sets C<$x>, C<$y> are hard to calculate or that you get from a separate
3356             subroutine.
3357              
3358             Finally IDL users might be familiar with Craig Markwardt's C
3359             routine which has inspired this routine although it was written independently
3360             However the present routine has a few less options (but see the examples)
3361              
3362             =for example
3363              
3364             You will very often use these functions on an index vector, so that is
3365             what we will show here. We will in fact something slightly silly. First
3366             we will find all squares that are also cubes below 10000.
3367              
3368             Create a sequence vector:
3369              
3370             pdl> $x = sequence(10000)
3371              
3372             Find all odd and even elements:
3373              
3374             pdl> ($even, $odd) = which_both( ($x % 2) == 0)
3375              
3376             Find all squares
3377              
3378             pdl> $squares= which(ceil(sqrt($x)) == floor(sqrt($x)))
3379              
3380             Find all cubes (being careful with roundoff error!)
3381              
3382             pdl> $cubes= which(ceil($x**(1.0/3.0)) == floor($x**(1.0/3.0)+1e-6))
3383              
3384             Then find all squares that are cubes:
3385              
3386             pdl> $both = setops($squares, 'AND', $cubes)
3387              
3388             And print these (assumes that C is loaded!)
3389              
3390             pdl> p $x($both)
3391             [0 1 64 729 4096]
3392              
3393             Then find all numbers that are either cubes or squares, but not both:
3394              
3395             pdl> $cube_xor_square = setops($squares, 'XOR', $cubes)
3396              
3397             pdl> p $cube_xor_square->nelem()
3398             112
3399              
3400             So there are a total of 112 of these!
3401              
3402             Finally find all odd squares:
3403              
3404             pdl> $odd_squares = setops($squares, 'AND', $odd)
3405              
3406              
3407             Another common occurrence is to want to get all objects that are
3408             in C<$x> and in the complement of C<$y>. But it is almost always best
3409             to create the complement explicitly since the universe that both are
3410             taken from is not known. Thus use L if possible
3411             to keep track of complements.
3412              
3413             If this is impossible the best approach is to make a temporary:
3414              
3415             This creates an index vector the size of the universe of the sets and
3416             set all elements in C<$y> to 0
3417              
3418             pdl> $tmp = ones($n_universe); $tmp($y) .= 0;
3419              
3420             This then finds the complement of C<$y>
3421              
3422             pdl> $C_b = which($tmp == 1);
3423              
3424             and this does the final selection:
3425              
3426             pdl> $set = setops($x, 'AND', $C_b)
3427              
3428             =cut
3429              
3430             *setops = \&PDL::setops;
3431              
3432             sub PDL::setops {
3433              
3434 5     5 0 659 my ($x, $op, $y)=@_;
3435              
3436             # Check that $x and $y are 1D.
3437 5 50 33     38 if ($x->ndims() > 1 || $y->ndims() > 1) {
3438 0         0 warn 'setops: $x and $y must be 1D - flattening them!'."\n";
3439 0         0 $x = $x->flat;
3440 0         0 $y = $y->flat;
3441             }
3442              
3443             #Make sure there are no duplicate elements.
3444 5         22 $x=$x->uniq;
3445 5         15 $y=$y->uniq;
3446              
3447 5         11 my $result;
3448              
3449 5 100       19 if ($op eq 'OR') {
    100          
    50          
3450             # Easy...
3451 1         12 $result = uniq(append($x, $y));
3452             } elsif ($op eq 'XOR') {
3453             # Make ordered list of set union.
3454 1         19 my $union = append($x, $y)->qsort;
3455             # Index lists.
3456 1         8 my $s1=zeroes(byte, $union->nelem());
3457 1         5 my $s2=zeroes(byte, $union->nelem());
3458              
3459             # Find indices which are duplicated - these are to be excluded
3460             #
3461             # We do this by comparing x with x shifted each way.
3462 1         24 my $i1 = which($union != rotate($union, 1));
3463 1         28 my $i2 = which($union != rotate($union, -1));
3464             #
3465             # We then mark/mask these in the s1 and s2 arrays to indicate which ones
3466             # are not equal to their neighbours.
3467             #
3468 1         9 my $ts;
3469 1 50       15 ($ts = $s1->index($i1)) .= 1 if $i1->nelem() > 0;
3470 1 50       17 ($ts = $s2->index($i2)) .= 1 if $i2->nelem() > 0;
3471              
3472 1         17 my $inds=which($s1 == $s2);
3473              
3474 1 50       9 if ($inds->nelem() > 0) {
3475 1         18 return $union->index($inds);
3476             } else {
3477 0         0 return $inds;
3478             }
3479              
3480             } elsif ($op eq 'AND') {
3481             # The intersection of the arrays.
3482              
3483             # Make ordered list of set union.
3484 3         56 my $union = append($x, $y)->qsort;
3485              
3486 3         74 return $union->where($union == rotate($union, -1));
3487             } else {
3488 0         0 print "The operation $op is not known!";
3489 0         0 return -1;
3490             }
3491              
3492             }
3493              
3494              
3495              
3496             =head2 intersect
3497              
3498             =for ref
3499              
3500             Calculate the intersection of two piddles
3501              
3502             =for usage
3503              
3504             Usage: $set = intersect($x, $y);
3505              
3506             This routine is merely a simple interface to L. See
3507             that for more information
3508              
3509             =for example
3510              
3511             Find all numbers less that 100 that are of the form 2*y and 3*x
3512              
3513             pdl> $x=sequence(100)
3514             pdl> $factor2 = which( ($x % 2) == 0)
3515             pdl> $factor3 = which( ($x % 3) == 0)
3516             pdl> $ii=intersect($factor2, $factor3)
3517             pdl> p $x($ii)
3518             [0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96]
3519              
3520             =cut
3521              
3522             *intersect = \&PDL::intersect;
3523              
3524             sub PDL::intersect {
3525              
3526 2     2 0 337 return setops($_[0], 'AND', $_[1]);
3527              
3528             }
3529              
3530              
3531              
3532             ;
3533              
3534              
3535             =head1 AUTHOR
3536              
3537             Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu). Contributions
3538             by Christian Soeller (c.soeller@auckland.ac.nz), Karl Glazebrook
3539             (kgb@aaoepp.aao.gov.au), Craig DeForest (deforest@boulder.swri.edu)
3540             and Jarle Brinchmann (jarle@astro.up.pt)
3541             All rights reserved. There is no warranty. You are allowed
3542             to redistribute this software / documentation under certain
3543             conditions. For details, see the file COPYING in the PDL
3544             distribution. If this file is separated from the PDL distribution,
3545             the copyright notice should be included in the file.
3546              
3547             Updated for CPAN viewing compatibility by David Mertens.
3548              
3549             =cut
3550              
3551              
3552              
3553              
3554              
3555             # Exit with OK status
3556              
3557             1;
3558              
3559