File Coverage

blib/lib/PDL/Basic.pm
Criterion Covered Total %
statement 169 177 95.4
branch 49 64 76.5
condition 20 31 64.5
subroutine 37 39 94.8
pod 0 25 0.0
total 275 336 81.8


line stmt bran cond sub pod time code
1             =encoding utf8
2              
3             =head1 NAME
4              
5             PDL::Basic -- Basic utility functions for PDL
6              
7             =head1 DESCRIPTION
8              
9             This module contains basic utility functions for
10             creating and manipulating ndarrays. Most of these functions
11             are simplified interfaces to the more flexible functions in
12             the modules
13             L
14             and
15             L.
16              
17             =head1 SYNOPSIS
18              
19             use PDL::Basic;
20              
21             =head1 FUNCTIONS
22              
23             =cut
24              
25             package PDL::Basic;
26 70     70   485 use strict;
  70         138  
  70         2907  
27 70     70   357 use warnings;
  70         732  
  70         4301  
28 70     70   408 use PDL::Core '';
  70         141  
  70         473  
29 70     70   449 use PDL::Types;
  70         167  
  70         14118  
30 70     70   465 use PDL::Exporter;
  70         137  
  70         422  
31 70     70   38903 use PDL::Options;
  70         219  
  70         10071  
32              
33             our @ISA=qw/PDL::Exporter/;
34             our @EXPORT_OK = qw(
35             sec ins hist whist similar_assign transpose
36             allaxisvals ndcoords sequence rvals
37             axisvals xvals yvals zvals
38             allaxislinvals axislinvals xlinvals ylinvals zlinvals
39             allaxislogvals axislogvals xlogvals ylogvals zlogvals
40             );
41             our %EXPORT_TAGS = (Func=>[@EXPORT_OK]);
42              
43             # Exportable functions
44             for (@EXPORT_OK) {
45 70     70   523 no strict 'refs';
  70         132  
  70         226470  
46             *$_ = \&{ $PDL::{$_} };
47             }
48              
49             =head2 axisvals, xvals, yvals, zvals
50              
51             =for ref
52              
53             Fills an ndarray with index values on X, Y, Z, or Nth dimension
54              
55             Uses similar specifications to L and
56             L.
57             B: If you use the single argument ndarray form (top row
58             in the usage table) the output will have the same type as the input,
59             except that between 2.064 and 2.100, the returned ndarray will
60             default to at least type C; as of 2.101 this upgrade is
61             relaxed to C.
62             As of 2.085, this will respect a given type as in the second
63             or third form below.
64              
65             =for usage
66              
67             $x = xvals($somearray); # at least type float
68             $x = xvals([OPTIONAL TYPE],$nx,$ny,$nz...);
69             $x = xvals([OPTIONAL TYPE], $somarray->dims);
70             $y = yvals($somearray); yvals(inplace($somearray));
71             $y = yvals([OPTIONAL TYPE],$nx,$ny,$nz...);
72             $z = zvals($somearray); zvals(inplace($somearray));
73             $z = zvals([OPTIONAL TYPE],$nx,$ny,$nz...);
74             $axisv = axisvals ($ndarray, $nth);
75             $axisv = $ndarray->axisvals($nth);
76             $axisv = axisvals ([type,] $nth, $dim0, $dim1, ...); # new in PDL 2.101
77             $axisv = axisvals ($nth, [type,] $dim0, $dim1, ...); # new in PDL 2.101
78              
79             See also L, which generates all axis values
80             simultaneously in a form useful for L, L,
81             L, etc.
82              
83             =for example
84              
85             pdl> print xvals zeroes(5,2)
86             [
87             [0 1 2 3 4]
88             [0 1 2 3 4]
89             ]
90             pdl> print yvals zeroes(5,2)
91             [
92             [0 0 0 0 0]
93             [1 1 1 1 1]
94             ]
95             pdl> print zvals zeroes(3,2,2)
96             [
97             [
98             [0 0 0]
99             [0 0 0]
100             ]
101             [
102             [1 1 1]
103             [1 1 1]
104             ]
105             ]
106              
107             =cut
108              
109             sub PDL::axisvals {
110 236   100 236 0 2450 my $type_given = grep +(ref($_[$_])||'') eq 'PDL::Type', 0..2;
111 236         1002 my ($first_non_ref) = grep !ref $_[$_], 0..$#_;
112 236         713 my ($nth) = splice @_, $first_non_ref, 1;
113 236         883 axisvals2(&PDL::Core::_construct,$nth,$type_given);
114             }
115              
116             # We need this version for xvals etc to work in place
117             sub axisvals2 {
118 690     690 0 1953 my($dummy,$nth,$keep_type) = @_;
119 690 100 100     3848 $dummy = PDL::Core::float($dummy)
120             if !$keep_type && $dummy->get_datatype < PDL::Core::float()->enum;
121 690 100       3598 return $dummy .= 0 if $dummy->getndims <= $nth; # 'kind of' consistency
122 686 100       27635 (0==$nth ? $dummy : $dummy->xchg(0,$nth))->inplace->axisvalues;
123 686         6860 $dummy;
124             }
125              
126             # Conveniently named interfaces to axisvals()
127 132     132 0 452166 sub PDL::xvals { unshift @_, 0; goto &axisvals; }
  132         567  
128 36     36 0 184 sub PDL::yvals { unshift @_, 1; goto &axisvals; }
  36         179  
129 3     3 0 17 sub PDL::zvals { unshift @_, 2; goto &axisvals; }
  3         13  
130              
131             =head2 axislinvals, xlinvals, ylinvals, zlinvals
132              
133             =for ref
134              
135             Axis values linearly spaced between endpoints (see L).
136              
137             =for usage
138              
139             $w = zeroes(100,100);
140             $x = $w->xlinvals(0.5,1.5); # can give ndarrays as start and endpoints
141             $y = $w->ylinvals(-2,-1);
142             $z = f($x,$y); # calculate Z for X from 0.5 to 1.5, Y from -2 to -1
143             # alternatively (new in PDL 2.101):
144             $x = xlinvals(0.5,1.5,100); # can give ndarrays as start and endpoints
145             $y = xlinvals(-2,-1,100); # x = along 0-th dim
146             $z = f(meshgrid($x,$y)); # should go faster as meshgrid makes better locality
147             $pdl = xlinvals(float,0.5,1.5,100); # can specify type
148             $x = $w->axislinvals(0,0.5,1.5); # same as xlinvals
149             $x = axislinvals(0,0.5,1.5,100,100); # same as xlinvals
150             $x = axislinvals(float,0,0.5,1.5,100,100); # same as xlinvals
151             $x = axislinvals(0,float,0.5,1.5,100,100); # same as xlinvals
152              
153             C, C and C return an ndarray with the same shape
154             as their first argument if an ndarray, and linearly scaled values between the two other
155             arguments along the given axis.
156             Works with dim-length of one as of 2.093, giving the starting point.
157             As of 2.101, instead of giving an ndarray you can give an optional
158             type at the start, and dimensions after the two mandatory arguments.
159              
160             =cut
161              
162             sub _dimcheck {
163 50     50   132 my ($pdl, $whichdim, $name) = @_;
164 50 50       208 barf "Given non-PDL '$pdl'" if !UNIVERSAL::isa($pdl, 'PDL');
165 50         167 my $dimlength = $pdl->getdim($whichdim);
166 50 100       144 barf "Must have at least one element in dimension for $name" if $dimlength < 1;
167 48         99 $dimlength;
168             }
169             sub _extract_endpoints {
170 61     61   128 my ($v1, $v2);
171 61         292 my @pdl_inds = grep UNIVERSAL::isa($_[$_], 'PDL'), 2..$#_; # not the invocant
172 61 100       168 if (@pdl_inds < 2) {
173 53         256 my @nonref_inds = grep !ref $_[$_], 0..$#_;
174 53         168 $v2 = splice @_, $nonref_inds[2], 1;
175 53         279 $v1 = splice @_, $nonref_inds[1], 1;
176             } else {
177 8         21 $v2 = splice @_, $pdl_inds[1], 1;
178 8         19 $v1 = splice @_, $pdl_inds[0], 1;
179             }
180 61         197 ($v1, $v2);
181             }
182             sub _linvals {
183 31     31   99 my ($name) = splice @_, 0, 1;
184 31         156 my ($first_non_ref) = grep !ref $_[$_], 0..$#_;
185 31         70 my $whichdim = $_[$first_non_ref];
186 31         70 my ($v1, $v2) = &_extract_endpoints;
187 31         90 my $pdl = &axisvals;
188 31         94 my $dimlength = _dimcheck($pdl, $whichdim, $name);
189 30 100       201 $pdl *= (($v2 - $v1) / ($dimlength > 1 ? ($dimlength-1) : 1));
190 30         156 $pdl += $v1;
191             }
192 20     20 0 69 sub PDL::axislinvals { unshift @_, 'axislinvals'; goto &_linvals; }
  20         70  
193 6     6 0 1707 sub PDL::xlinvals { unshift @_, 'xlinvals', 0; goto &_linvals; }
  6         27  
194 4     4 0 25 sub PDL::ylinvals { unshift @_, 'ylinvals', 1; goto &_linvals; }
  4         20  
195 1     1 0 10 sub PDL::zlinvals { unshift @_, 'zlinvals', 2; goto &_linvals; }
  1         2  
196              
197             =head2 axislogvals, xlogvals, ylogvals, zlogvals
198              
199             =for ref
200              
201             Axis values logarithmically spaced between endpoints (see L).
202              
203             =for usage
204              
205             $w = zeroes(100,100);
206             $x = $w->xlogvals(1e-6,1e-3);
207             $y = $w->ylogvals(1e-4,1e3);
208             $z = f($x,$y); # calculate Z for X from 1e-6 to 1e-3, Y from 1e-4 to 1e3
209             # alternatively (new in PDL 2.101):
210             $x = xlogvals(1e-6,1e-3,100);
211             $y = xlogvals(1e-4,1e3,100); # x = along 0-th dim
212             $z = f(meshgrid($x,$y)); # should go faster as meshgrid makes better locality
213             $pdl = xlogvals(float,1e-6,1e-3,100); # can specify type
214             $x = $w->axislogvals(0,0.5,1.5); # same as xlogvals
215             $x = axislogvals(0,0.5,1.5,100,100); # same as xlogvals
216             $x = axislogvals(float,0,0.5,1.5,100,100); # same as xlogvals
217             $x = axislogvals(0,float,0.5,1.5,100,100); # same as xlogvals
218              
219             C, C and C return an ndarray with the same shape
220             as their first argument and logarithmically scaled values between the two other
221             arguments along the given axis.
222             Works with dim-length of one as of 2.093, giving the starting point.
223             As of 2.101, instead of giving an ndarray you can give an optional
224             type at the start, and dimensions after the two mandatory arguments.
225              
226             =cut
227              
228             sub _logvals {
229 19     19   66 my ($name) = splice @_, 0, 1;
230 19         105 my ($first_non_ref) = grep !ref $_[$_], 0..$#_;
231 19         522 my $whichdim = $_[$first_non_ref];
232 19         55 my ($min, $max) = &_extract_endpoints;
233 19 50 33     114 barf "min and max must be positive" if $min <= 0 || $max <= 0;
234 19         100 my ($lmin,$lmax) = map log($_), $min, $max;
235 19         52 my $pdl = &axisvals;
236 19         61 my $dimlength = _dimcheck($pdl, $whichdim, $name);
237 18 100       125 $pdl .= exp($pdl * (($lmax - $lmin) / ($dimlength > 1 ? ($dimlength-1) : 1)) + $lmin);
238             }
239 10     10 0 38 sub PDL::axislogvals { unshift @_, 'axislogvals'; goto &_logvals; }
  10         40  
240 6     6 0 32 sub PDL::xlogvals { unshift @_, 'xlogvals', 0; goto &_logvals; }
  6         24  
241 2     2 0 23 sub PDL::ylogvals { unshift @_, 'ylogvals', 1; goto &_logvals; }
  2         12  
242 1     1 0 15 sub PDL::zlogvals { unshift @_, 'zlogvals', 2; goto &_logvals; }
  1         5  
243              
244             =head2 ndcoords, allaxisvals, allaxislinvals, allaxislogvals
245              
246             =for ref
247              
248             Enumerate pixel coordinates for an N-D ndarray
249              
250             C and C return an enumerated list of coordinates
251             suitable for use in
252             L, L, or
253             L: you feed
254             in a dimension list and get out an ndarray whose 0th dimension runs over
255             dimension index and whose 1st through Nth dimensions are the
256             dimensions given in the input. If you feed in an ndarray instead of a
257             perl list, then its dimension list is used, as in L etc.
258              
259             Unlike L etc., if you supply an ndarray input, you get
260             out an ndarray of the default ndarray type: double. This causes less
261             surprises than the previous default of keeping the data type of
262             the input ndarray since that rarely made sense in most usages.
263              
264             C and C enumerate a list of linear-
265             or logarithm-spaced values respectively, like their non-C counterparts.
266              
267             =for usage
268              
269             $indices = ndcoords($pdl); # double
270             $indices = ndcoords(@dimlist); # double
271             $indices = ndcoords($type,$pdl); # $type
272             $indices = $pdl->ndcoords($type); # $type
273             $indices = ndcoords($type,@dimlist); # $type
274             $indices = allaxisvals($pdl);
275             $indices = allaxisvals(@dimlist);
276             $indices = allaxisvals($type,$pdl);
277             $indices = allaxisvals($type,@dimlist);
278             $linvals = allaxislinvals($pdl,$start,$end); # start and end can be ndarrays
279             $linvals = allaxislinvals($type,$pdl,$start,$end); # also here
280             $linvals = allaxislinvals($type,$start,$end,@dimlist); # also here
281             $linvals = allaxislinvals($start,$end,@dimlist); # not here
282             $linvals = allaxislogvals($pdl,$start,$end);
283             $linvals = allaxislogvals($type,$pdl,$start,$end);
284             $linvals = allaxislogvals($start,$end,@dimlist);
285             $linvals = allaxislogvals($type,$start,$end,@dimlist);
286              
287             =for example
288              
289             pdl> print ndcoords(2,3)
290             [
291             [
292             [0 0]
293             [1 0]
294             ]
295             [
296             [0 1]
297             [1 1]
298             ]
299             [
300             [0 2]
301             [1 2]
302             ]
303             ]
304             pdl> $w = zeroes(byte,2,3); # $w is a 2x3 byte ndarray
305             pdl> $y = ndcoords($w); # $y is double to avoid problems
306             pdl> $c = ndcoords(long,$w->dims); # $c is a long ndarray, same dims as $y
307             pdl> $d = ndcoords(long,$w); # $d overrides the default double
308             pdl> help $y;
309             This variable is Double D [2,2,3] P 0.09KB
310             pdl> help $c;
311             This variable is Long D [2,2,3] P 0.05KB
312              
313             =cut
314              
315             sub _allvals_construct {
316 73     73   149 my $type;
317 73 100       446 if (my ($type_ind) = grep ref $_[$_] eq 'PDL::Type', 0..$#_) {
318 8         23 $type = splice @_, $type_ind, 1;
319             }
320 73 100       291 my @dims = ref($_[0]) ? shift->dims : @_;
321 73 100       2825 PDL->zeroes(defined($type) ? $type : (), scalar(@dims), @dims);
322             }
323             sub PDL::ndcoords {
324 62     62 0 169 my $out = &_allvals_construct;
325 62         772 axisvals2($out->slice("($_)"), $_, 1) for 0..$out->ndims-2;
326 62         437 $out;
327             }
328             *PDL::allaxisvals = \&PDL::ndcoords;
329             sub _nonref_vals2 {
330 0     0   0 my ($first_non_ref) = grep !ref $_[$_], 0..$#_;
331 0         0 splice @_, $first_non_ref, 2;
332             }
333             sub PDL::allaxislinvals {
334 8     8 0 31 unshift @_, 1; # dummy for _extract_endpoints "whichdim"
335 8         26 my ($v1, $v2) = &_extract_endpoints;
336 8         15 shift @_; # drop dummy
337 8         27 my $out = &_allvals_construct;
338 8         93 $out->slice("($_)")->inplace->axislinvals($_,$v1,$v2) for 0..$out->ndims-2;
339 8         52 $out;
340             }
341             sub PDL::allaxislogvals {
342 3     3 0 15 unshift @_, 1; # dummy for _extract_endpoints "whichdim"
343 3         10 my ($v1, $v2) = &_extract_endpoints;
344 3         7 shift @_; # drop dummy
345 3         11 my $out = &_allvals_construct;
346 3         37 $out->slice("($_)")->inplace->axislogvals($_,$v1,$v2) for 0..$out->ndims-2;
347 3         23 $out;
348             }
349              
350             =head2 hist, whist
351              
352             =for ref
353              
354             Create histogram, or weighted histogram, of an ndarray
355              
356             =for usage
357              
358             $hist = hist($data);
359             ($xvals,$hist) = hist($data);
360             # or:
361             $hist = hist($data,$min,$max,$step);
362             ($xvals,$hist) = hist($data,[$min,$max,$step]);
363             # weighted:
364             $whist = whist($data, $wt, [$min,$max,$step]);
365             ($xvals,$whist) = whist($data, $wt, [$min,$max,$step]);
366              
367             If requested, C<$xvals> gives the computed bin centres
368             as type double values. C<$data> and C<$wt> should have
369             the same dimensionality and extents.
370              
371             A nice idiom (with L) is
372              
373             bins hist($data), {yrange=>[0,$data->dim(0)]}; # Plot histogram
374             bin whist $data, $wt; # weighted histogram
375             bins whist($data, $wt), {yrange=>[0,$data->dim(0)]}; # weighted histogram
376              
377             =for example
378              
379             pdl> p $y
380             [13 10 13 10 9 13 9 12 11 10 10 13 7 6 8 10 11 7 12 9 11 11 12 6 12 7]
381             pdl> $h = hist $y,0,20,1; # hist with step 1, min 0 and 20 bins
382             pdl> p $h
383             [0 0 0 0 0 0 2 3 1 3 5 4 4 4 0 0 0 0 0 0]
384             # or, weighted:
385             pdl> $wt = grandom($y->nelem)
386             pdl> $h = whist $y, $wt, 0, 20, 1 # hist with step 1, min 0 and 20 bins
387             pdl> p $h
388             [0 0 0 0 0 0 -0.49552342 1.7987439 0.39450696 4.0073722 -2.6255299 -2.5084501 2.6458365 4.1671676 0 0 0 0 0 0]
389              
390             =cut
391              
392             sub PDL::hist {
393 4 50   4 0 1027 barf(<<'EOF') if !@_;
394             Usage: $hist = hist($data)
395             $hist = hist($data,$min,$max,$step)
396             ($xvals,$hist) = hist($data)
397             ($xvals,$hist) = hist($data,$min,$max,$step)
398             EOF
399 4         12 my ($pdl,$min,$max,$step) = @_;
400 4         22 ($step, $min, my $bins, my $xvals) =
401             _hist_bin_calc($pdl, $min, $max, $step, wantarray);
402 4         21 my $hist = PDL::Primitive::histogram($pdl->flat, $step,$min,$bins);
403 3 100       30 wantarray ? ($xvals,$hist) : $hist;
404             }
405              
406             sub PDL::whist {
407 1 50   1 0 10 barf('Usage: ([$xvals],$hist) = whist($data,$wt,[$min,$max,$step])')
408             if @_ < 2;
409 1         4 my ($pdl,$wt,$min,$max,$step) = @_;
410 1         5 ($step, $min, my $bins, my $xvals) =
411             _hist_bin_calc($pdl, $min, $max, $step, wantarray);
412 1         8 my $hist = PDL::Primitive::whistogram($pdl->flat,$wt->flat, $step, $min, $bins);
413 1 50       12 wantarray ? ($xvals,$hist) : $hist;
414             }
415              
416             sub _hist_bin_calc {
417 5     5   17 my ($pdl,$min,$max,$step,$wantarray) = @_;
418 5         32 my $nelem = $pdl->nelem;
419 5 50       17 barf "empty ndarray, no values to work with" if $nelem == 0;
420 5   33     19 $min //= $pdl->min;
421 5   33     16 $max //= $pdl->max;
422 5 0 33     18 $step //= ($max-$min)/(($nelem>10_000) ? 100 : sqrt($nelem));
423 5 50       29 barf "step is zero (or all data equal to one value)" if $step == 0;
424 5         61 my $bins = int(($max-$min)/$step+0.5);
425 5 50       22 print "hist with step $step, min $min and $bins bins\n"
426             if $PDL::debug;
427 5 100       29 return ( $step, $min, $bins ) if !$wantarray;
428             # Need to use double for $xvals here
429 2         13 my $xvals = $min + $step/2 + sequence(PDL::Core::double,$bins)*$step;
430 2         22 ( $step, $min, $bins, $xvals );
431             }
432              
433             =head2 sequence
434              
435             =for ref
436              
437             Create array filled with a sequence of values
438              
439             =for usage
440              
441             $w = sequence($y); $w = sequence [OPTIONAL TYPE], @dims;
442              
443             etc. see L.
444              
445             =for example
446              
447             pdl> p sequence(10)
448             [0 1 2 3 4 5 6 7 8 9]
449             pdl> p sequence(3,4)
450             [
451             [ 0 1 2]
452             [ 3 4 5]
453             [ 6 7 8]
454             [ 9 10 11]
455             ]
456              
457             =cut
458              
459             sub PDL::sequence {
460 282   100 282 0 12552000 my $type_given = grep +(ref($_[$_])||'') eq 'PDL::Type', 0..1;
461 282   66     1735 $type_given ||= ref($_[0]) && UNIVERSAL::isa($_[0], 'PDL'); # instance method
      100        
462 282         1100 my $pdl = &PDL::Core::_construct;
463 282         1205 axisvals2($pdl->flat->inplace,0,$type_given);
464 282         2801 return $pdl;
465             }
466              
467             =head2 rvals
468              
469             =for ref
470              
471             Fills an ndarray with radial distance values from some centre.
472              
473             =for usage
474              
475             $r = rvals $ndarray,{OPTIONS};
476             $r = rvals [OPTIONAL TYPE],$nx,$ny,...{OPTIONS};
477              
478             =for options
479              
480             Options:
481              
482             Centre => [$x,$y,$z...] # Specify centre
483             Center => [$x,$y.$z...] # synonym.
484             Center => $c # as 1d array
485             Squared => 1 # return distance squared (i.e., don't take the square root)
486              
487             =for example
488              
489             pdl> print rvals long,7,7,{Centre=>[2,2]}
490             [
491             [2 2 2 2 2 3 4]
492             [2 1 1 1 2 3 4]
493             [2 1 0 1 2 3 4]
494             [2 1 1 1 2 3 4]
495             [2 2 2 2 2 3 4]
496             [3 3 3 3 3 4 5]
497             [4 4 4 4 4 5 5]
498             ]
499              
500             If C
is not specified, the midpoint for a given dimension of
501             size C is given by C< int(N/2) > so that the midpoint always falls
502             on an exact pixel point in the data. For dimensions of even size,
503             that means the midpoint is shifted by 1/2 pixel from the true center
504             of that dimension.
505              
506             If C
has less components than the number of dimensions of the
507             array, its remaining components are computed as above. If it has more,
508             a warning is issued.
509              
510             Also note that the calculation for C for integer values
511             does not promote the datatype so you will have wraparound when
512             the value calculated for C< r**2 > is greater than the datatype
513             can hold. If you need exact values, be sure to use large integer
514             or floating point datatypes.
515              
516             For a more general metric, one can define, e.g.,
517              
518             sub distance {
519             my ($w,$centre,$f) = @_;
520             my ($r) = $w->allaxisvals-$centre;
521             $f->($r);
522             }
523             sub l1 { sumover(abs($_[0])); }
524             sub euclid { use PDL::Math 'pow'; pow(sumover(pow($_[0],2)),0.5); }
525             sub linfty { maximum(abs($_[0])); }
526              
527             so now
528              
529             distance($w, $centre, \&euclid);
530              
531             will emulate rvals, while C<\&l1> and C<\&linfty> will generate other
532             well-known norms.
533              
534             =cut
535              
536             sub PDL::rvals { # Return radial distance from given point and offset
537 19 100   19 0 2748 my $opt = ref($_[-1]) eq "HASH" ? pop @_ : undef;
538 19 100       107 my %opt = defined $opt ?
539             iparse( {
540             CENTRE => undef, # needed, otherwise centre/center handling painful
541             Squared => 0,
542             }, $opt ) : ();
543 19         102 my $r = &PDL::Core::_construct;
544 19         39 my @pos;
545 19 100       66 if (defined $opt{CENTRE}) {
546 8         51 my $pos = PDL->topdl($opt{CENTRE});
547 8 50       41 barf "Center should be a 1D vector" unless $pos->getndims==1;
548 8 50       37 barf "Center has more coordinates than dimensions of ndarray" if $pos->dim(0) > $r->getndims;
549 8         35 @pos = $pos->list;
550             }
551 19         33 my $offset;
552 19         197 $r .= 0.0;
553 19         77 my $tmp = $r->copy;
554 19         39 my $i;
555 19         114 for ($i=0; $i<$r->getndims; $i++) {
556 38   66     238 $offset = $pos[$i] // int($r->getdim($i)/2);
557             # Note careful coding for speed and min memory footprint
558 38         112 axisvals2($tmp, $i, 1);
559 38         129 $tmp -= $offset; $tmp *= $tmp;
  38         102  
560 38         116 $r += $tmp;
561             }
562 19 100       894 return $opt{Squared} ? $r : $r->inplace->sqrt;
563             }
564              
565             =head2 sec
566              
567             =for ref
568              
569             Take a subsection of an ndarray with given coordinates.
570              
571             =for usage
572              
573             $new = sec($input, $x1, $x2, $y1, $y2, $z1, $z2, ... ) # Take subsection
574              
575             =cut
576              
577             sub PDL::sec {
578 1     1 0 4 my ($this,@coords) = @_;
579 1         8 @coords = map int, @coords;
580 1         3 my @maps;
581 1         11 push @maps, shift(@coords).":".shift(@coords) while @coords;
582 1         9 $this->slice(join ',',@maps)->sever;
583             }
584              
585             =head2 ins
586              
587             =for ref
588              
589             Insert one ndarray into another at given coordinates.
590              
591             =for usage
592              
593             $newimage = ins($bigimage,$smallimage,$x,$y,$z...) # Insert at x,y,z
594              
595             =cut
596              
597             sub PDL::ins {
598 2     2 0 8 my ($this,$what,@coords) = @_;
599 2         11 my $w = PDL->topdl($what);
600 2         11 $this = $this->new_or_inplace;
601 2         70 my @thisdims = $this->dims;
602 2         14 my @wdims_m1 = map $_-1, $w->dims;
603 2         10 @coords = map int, @coords;
604 2 50       39 $this->slice(
605             join ',',map $coords[$_].":".
606             (($coords[$_]+$wdims_m1[$_])<$thisdims[$_] ?
607             ($coords[$_]+$wdims_m1[$_]):$thisdims[$_]),
608             0..$#coords)
609             .= $w;
610 2         26 $this;
611             }
612              
613             sub PDL::similar_assign {
614 0     0 0 0 my ($from,$to) = @_;
615 0 0       0 if ((my $fd = join ',',@{$from->dims}) ne (my $td = join ',',@{$to->dims})) {
  0         0  
  0         0  
616 0         0 barf "Similar_assign: dimensions [$fd] and [$td] do not match!\n";
617             }
618 0         0 $to .= $from;
619             }
620              
621             =head2 transpose
622              
623             =for ref
624              
625             transpose rows and columns.
626              
627             =for usage
628              
629             $y = transpose($w);
630              
631             =for example
632              
633             pdl> $w = sequence(3,2)
634             pdl> p $w
635             [
636             [0 1 2]
637             [3 4 5]
638             ]
639             pdl> p transpose( $w )
640             [
641             [0 3]
642             [1 4]
643             [2 5]
644             ]
645              
646             =cut
647              
648             sub PDL::transpose {
649 198     198 0 1381 my ($this) = @_;
650 198         748 my $ndims = $this->dims;
651 198 100       2891 $ndims > 1 ? $this->xchg(0,1) :
    100          
652             $ndims > 0 ? $this->dummy(0) :
653             $this->dummy(0)->dummy(0);
654             }
655              
656             =head2 t
657              
658             =for usage
659              
660             $pdl = $pdl->t(SCALAR(conj))
661             conj : Conjugate Transpose = 1 | Transpose = 0, default = 0;
662              
663             =for ref
664              
665             Convenient function for transposing real or complex 2D array(s).
666             For complex data, if conj is true returns conjugate transposed array(s).
667             Supports broadcasting. Not exported.
668              
669             Originally by GrĂ©gory Vanuxem.
670              
671             =cut
672              
673             sub PDL::t {
674 77     77 0 299 my ($m, $conj) = @_;
675 77         146 my $r = $m->transpose;
676 77 100 66     741 ($conj && !$r->type->real) ? $r->conj : $r;
677             }
678              
679             1;