File Coverage

blib/lib/PDL/PP/Signature.pm
Criterion Covered Total %
statement 193 200 96.5
branch 51 66 77.2
condition 45 63 71.4
subroutine 38 39 97.4
pod 0 32 0.0
total 327 400 81.7


line stmt bran cond sub pod time code
1             package # hide from PAUSE/MetaCPAN
2             PDL::PP::Signature;
3              
4 4     4   24 use strict; use warnings;
  4     4   8  
  4         158  
  4         16  
  4         6  
  4         219  
5 4     4   415 use PDL::PP::PdlParObj;
  4         9  
  4         135  
6 4     4   6683 use PDL::PP::Dims;
  4         15  
  4         149  
7 4     4   25 use Carp;
  4         6  
  4         30915  
8              
9             =head1 NAME
10              
11             PDL::PP::Signature - Internal module to handle signatures
12              
13             =head1 DESCRIPTION
14              
15             Internal module to handle signatures
16              
17             =head1 SYNOPSIS
18              
19             use PDL::PP::Signature;
20              
21             =cut
22              
23             # Eliminate whitespace entries
24 255     255 0 4279 sub nospacesplit {grep /\S/, split $_[0],$_[1]}
25              
26             sub new {
27 128     128 0 6447 my ($type,$pars,$opname,$otherpars,$otherparsdefaults,$argorder) = @_;
28 128 50 66     353 confess "$opname ArgOrder given defined but false value" if defined $argorder and !$argorder;
29 128         282 my @objects = map PDL::PP::PdlParObj->new($_, $opname), nospacesplit ';',$pars;
30 127   100     906 my $this = bless {
31             Names=>[map $_->name, @objects], Objects=>{map +($_->name => $_), @objects},
32             OtherParsDefaults=>$otherparsdefaults||{},
33             ArgOrder=>$argorder,
34             }, $type;
35 127         451 my @objects_sorted = ((grep !$_->{FlagW}, @objects), (grep $_->{FlagW}, @objects));
36 127         521 $objects_sorted[$_]{Number} = $_ for 0..$#objects_sorted;
37 127         341 $this->{NamesSorted} = [ map $_->name, @objects_sorted ];
38 127         447 $this->{DimsObj} = my $dimsobj = PDL::PP::PdlDimsObj->new;
39 127         368 $_->add_inds($dimsobj) for @objects;
40 127   100     549 @$this{qw(OtherNames OtherObjs OtherAnyOut OtherFlags)} = $this->_otherPars_nft($otherpars||'', $opname);
41 126         361 $this->_validate($opname);
42 122         157 my $i=0; $dimsobj->ind_obj($_)->set_index($i++) for sort $dimsobj->ind_names;
  122         322  
43 122         559 $this;
44             }
45              
46             sub _validate {
47 126     126   221 my ($sig, $name) = @_;
48 126         280 my ($argorder, $otherdefaults) = @$sig{qw(ArgOrder OtherParsDefaults)};
49 126 100 100     371 if (!$argorder and
50 115         431 keys(%$otherdefaults) != (my @other_args = @{ $sig->{OtherNames} })
51             ) {
52 11         21 my $default_seen = '';
53 11         21 for (@other_args) {
54 14 100       29 $default_seen = $_ if exists $otherdefaults->{$_};
55             confess "$name got default-less arg '$_' after default-ful arg '$default_seen'"
56 14 100 100     380 if $default_seen and !exists $otherdefaults->{$_};
57             }
58             }
59 125 100 100     340 if ($argorder and ref $argorder) {
60 6         10 my @names = @{ $sig->allnames(1, 1) };
  6         17  
61 6         31 my %namehash = map +($_=>1), @names;
62 6         40 delete @namehash{@$argorder};
63 6 100       261 confess "$name ArgOrder missed params: ".join(' ', keys %namehash) if keys %namehash;
64 5         19 my %orderhash = map +($_=>1), @$argorder;
65 5         10 delete @orderhash{@names};
66 5 100       201 confess "$name ArgOrder too many params: ".join(' ', keys %orderhash) if keys %orderhash;
67 4         16 my %optionals = map +($_=>1), keys(%$otherdefaults), $sig->names_out, $sig->other_out;
68 4         9 my $optional = '';
69 4         8 for (@$argorder) {
70 17 100       32 $optional = $_, next if exists $optionals{$_};
71             confess "$name got mandatory argument '$_' after optional argument '$optional'"
72 12 100 66     278 if $optional and !exists $optionals{$_};
73             }
74             }
75             }
76              
77             sub _otherPars_nft {
78 127     127   298 my ($sig,$otherpars,$opname) = @_;
79 127   33     418 my $dimobjs = $sig && $sig->dims_obj;
80 127         247 my (@names,%types,$type,$any_out,%allflags);
81 127         235 for (nospacesplit(';',$otherpars)) {
82 37         98 my (%flags);
83 37 100       322 if (s/^\s*$PDL::PP::PdlParObj::sqbr_re\s*//) {
84 2         17 %flags = my %lflags = map +($_=>1), split /\s*,\s*/, my $opts = $1;
85 2 50 33     13 croak "pp_def($opname): Can't have both [io] and [o]" if $lflags{o} && $lflags{io};
86 2   33     6 my $this_out = delete($lflags{o}) || delete($lflags{io});
87 2 50       6 croak "pp_def($opname): Invalid options '$opts' in '$_'" if keys %lflags;
88 2   33     8 $any_out ||= $this_out;
89             }
90 37 100       103 if (/^\s*([^=]+?)\s*=>\s*(\S+)\s*$/) {
91             # support 'int ndim => n;' syntax
92 2         7 my ($ctype,$dim) = ($1,$2);
93 2 50       5 print "OtherPars: setting dim '$dim' from '$ctype'\n" if $::PP_VERBOSE;
94 2         32 $type = PDL::PP::CType->new($ctype);
95 2         5 $dimobjs->get_indobj_make($dim)->set_from($type);
96             } else {
97 35         104 $type = PDL::PP::CType->new($_);
98             }
99 37         82 my $name = $type->protoname;
100             croak "pp_def($opname): Invalid OtherPars name: $name"
101 37 100       296 if $PDL::PP::PdlParObj::INVALID_PAR{$name};
102 36         61 push @names,$name;
103 36         68 $types{$name} = $type;
104 36 50       81 $types{"${name}_count"} = PDL::PP::CType->new("PDL_Indx ${name}_count") if $type->is_array;
105 36         86 $allflags{$name} = \%flags;
106             }
107 126         771 (\@names,\%types,$any_out,\%allflags);
108             }
109              
110             =head1 AUTHOR
111              
112             Copyright (C) Tuomas J. Lukka 1997 (lukka@husc.harvard.edu) and by Christian
113             Soeller (c.soeller@auckland.ac.nz).
114             All rights reserved. There is no warranty. You are allowed
115             to redistribute this software / documentation under certain
116             conditions. For details, see the file COPYING in the PDL
117             distribution. If this file is separated from the PDL distribution,
118             the copyright notice should be included in the file.
119              
120             =cut
121              
122 6     6 0 17 sub names { $_[0]{Names} }
123 17     17 0 60 sub names_sorted { $_[0]{NamesSorted} }
124             sub names_sorted_tuples {
125 26     26 0 52 my ($count, @names) = (0, @{$_[0]{NamesSorted}});
  26         117  
126 26         362 map [$count++, $_[0]{Objects}{$_}{FlagTemp}, $_], @names;
127             }
128              
129 366     366 0 723 sub objs { $_[0]{Objects} }
130 84   66 84 0 195 sub names_in { my $o=$_[0]->objs; grep !$o->{$_}{FlagOut} && !$o->{$_}{FlagTemp}, @{$_[0]{Names}} }
  84         140  
  84         854  
131 82     82 0 228 sub names_out { my $o=$_[0]->objs; grep $o->{$_}{FlagOut}, @{$_[0]{Names}} }
  82         110  
  82         450  
132 95     95 0 193 sub names_oca { my $o=$_[0]->objs; grep $o->{$_}{FlagCreateAlways}, @{$_[0]{Names}} }
  95         156  
  95         386  
133 53   66 53 0 137 sub names_out_nca { my $o=$_[0]->objs; grep $o->{$_}{FlagOut} && !$o->{$_}{FlagCreateAlways}, @{$_[0]{Names}} }
  53         101  
  53         435  
134 0     0 0 0 sub names_tmp { my $o=$_[0]->objs; grep $o->{$_}{FlagTemp}, @{$_[0]{Names}} }
  0         0  
  0         0  
135              
136 145     145 0 449 sub dims_obj { $_[0]->{DimsObj} }
137             sub dims_init {
138 23     23 0 66 my ($self) = @_;
139             join "\n",
140             (sort map $_->get_initdim, $self->{DimsObj}->ind_fromcomp),
141 23         127 (sort map $_->get_initdim, $self->{DimsObj}->ind_notfromcomp);
142             }
143              
144             sub othernames {
145 737     737 0 1262 my ($self, $omit_count, $with_xs, $except) = @_;
146 737   100     2462 $except ||= {};
147 737 100 66     3361 return $self->{OtherNames} if $omit_count && $omit_count > 0 && !keys %$except && $with_xs;
      100        
      66        
148 508 50 66     1016 return [] if $omit_count && $omit_count < 0;
149 508         907 my $objs = $self->otherobjs;
150 508         657 my @raw_names = grep !$except->{$_}, @{$self->{OtherNames}};
  508         993  
151 508 50       1104 @raw_names = map $objs->{$_}->is_array ? ($_, "${_}_count") : $_, @raw_names if !$omit_count;
    100          
152 508 100       1036 @raw_names = grep !$objs->{$_}{WasDollar}, @raw_names if !$with_xs;
153 508         2268 \@raw_names;
154             }
155 1094     1094 0 2154 sub otherobjs { $_[0]{OtherObjs} }
156 7     7 0 41 sub other_any_out { $_[0]{OtherAnyOut} }
157             sub other_is_flag {
158 360     360 0 416 my $flag = $_[2];
159 360         485 my $has_count = (my $without_count = $_[1]) =~ s/_count$//;
160 360 50 100     1561 return $_[0]{OtherFlags}{$_[1]} && $_[0]{OtherFlags}{$_[1]}{$flag} if !$has_count;
161 0 0       0 $_[0]{OtherFlags}{$without_count} && $_[0]{OtherFlags}{$without_count}{$flag};
162             }
163 140 50   140 0 223 sub other_is_output { &other_is_out || &other_is_io }
164 199     199 0 346 sub other_is_out { $_[0]->other_is_flag($_[1], 'o') }
165 139     139 0 167 sub other_out { grep $_[0]->other_is_out($_), @{$_[0]{OtherNames}} }
  139         370  
166 161     161 0 251 sub other_is_io { $_[0]->other_is_flag($_[1], 'io') }
167 78     78 0 93 sub other_io { grep $_[0]->other_is_io($_), @{$_[0]{OtherNames}} }
  78         260  
168              
169 199     199 0 387 sub allnames { my ($self, $omit_count, $with_xs, $except) = @_; [
170 0         0 ($omit_count && $omit_count < 0) ? (grep $self->{Objects}{$_}{FlagCreateAlways}, @{$self->{Names}}) :
171 199         1406 (grep +(!$except || !$except->{$_}) && !$self->{Objects}{$_}{FlagTemp}, @{$self->{Names}}),
172 199 50 66     590 @{$self->othernames(@_[1..3])},
  199   33     564  
173             ] }
174             sub allobjs {
175 52     52 0 251 my $pdltype = PDL::PP::CType->new("pdl *__foo__");
176 52         112 +{ ( map +($_,$pdltype), @{$_[0]{Names}} ), %{$_[0]->otherobjs} };
  52         208  
  52         114  
177             }
178             sub alldecls {
179 52     52 0 115 my ($self, $omit_count, $indirect, $with_xs, $except) = @_;
180 52         108 my $objs = $self->allobjs;
181 52         81 my @names = @{$self->allnames($omit_count, $with_xs, $except)};
  52         133  
182 52 100       210 $indirect = $indirect ? { map +($_=>$self->other_is_output($_)), @names } : {};
183 52         289 map $objs->{$_}->get_decl($_, {VarArrays2Ptrs=>1,AddIndirect=>$indirect->{$_}}), @names;
184             }
185             sub getcomp {
186 36     36 0 108 my ($self) = @_;
187 36         116 my $objs = $self->otherobjs;
188 36         64 my @names = @{$self->othernames(0)};
  36         109  
189 36         145 my $indirect = { map +($_=>$self->other_is_output($_)), @names };
190 36         219 join "\n", map " $_;", grep $_, map $objs->{$_}->get_decl($_, {VarArrays2Ptrs=>1,AddIndirect=>$indirect->{$_}}), @names;
191             }
192             sub getfree {
193 46     46 0 152 my ($self,$symbol) = @_;
194 46         125 my $objs = $self->otherobjs;
195             join '', map $objs->{$_}->get_free("\$$symbol($_)",
196 46         76 { VarArrays2Ptrs => 1 }), @{$self->othernames(0)};
  46         101  
197             }
198             sub getcopy {
199 26     26 0 62 my ($self, $to_pat) = @_;
200 26         74 my $objs = $self->otherobjs;
201 26         58 PDL::PP::indent(2, join '', map $objs->{$_}->get_copy($_,sprintf $to_pat,$_)."\n", @{$self->othernames(0)});
  26         63  
202             }
203              
204             sub args_callorder {
205 71     71 0 124 my ($self) = @_;
206 71         144 my $argorder = $self->{ArgOrder};
207 71 100       235 return $self->allnames(1, 1) if !$argorder;
208 8 100       26 return $argorder if ref $argorder;
209 4         8 my $otherdefaults = $self->{OtherParsDefaults};
210 4         12 my %optionals = map +($_=>1), keys(%$otherdefaults);
211             my @other_mand = grep !$optionals{$_} && !$self->other_is_out($_),
212 4   100     7 my @other = @{$self->othernames(1, 1)};
  4         8  
213 4         10 my @other_opt = grep $optionals{$_}, @other;
214 4         9 [$self->names_in, @other_mand, @other_opt, $self->names_out, $self->other_out];
215             }
216              
217             sub realdims {
218 10     10 0 22 my $this = shift;
219 10         24 [ map scalar @{$this->{Objects}{$_}{RawInds}}, @{$this->{Names}} ];
  27         94  
  10         150  
220             }
221              
222             sub creating {
223 10     10 0 18 my $this = shift;
224             confess "you must perform a checkdims before calling creating"
225 10 50       72 unless defined $this->{Create};
226 10         431 return $this->{Create};
227             }
228              
229             sub checkdims {
230 12     12 0 26 my $this = shift;
231             # we have to recreate to keep defaults currently
232 12         54 $this->{Dims} = PDL::PP::PdlDimsObj->new;
233 12         23 $this->{Objects}{$_}->add_inds($this->{Dims}) for @{$this->{Names}};
  12         91  
234 12         21 my $n = @{$this->{Names}};
  12         26  
235 12 50       38 confess "not enough pdls to match signature" unless $#_ >= $n-1;
236 12         38 my @pdls = @_[0..$n-1];
237 12 50       35 if ($PDL::debug) { print "args: ".
238 0         0 join(' ,',map { "[".join(',',$_->dims)."]," } @pdls)
  0         0  
239             . "\n"}
240 12         18 my $i = 0;
241             my @creating = map $this->{Objects}{$_}->perldimcheck($pdls[$i++]),
242 12         20 @{$this->{Names}};
  12         56  
243 10         22 $i = 0;
244 10         18 for (@{$this->{Names}}) {
  10         28  
245 27 100       122 push @creating, $this->{Objects}{$_}->getcreatedims
246             if $creating[$i++];
247             }
248 10         32 $this->{Create} = \@creating;
249 10         17 $i = 0;
250 10         22 my $corr = 0;
251 10         13 for (@{$this->{Names}}) {
  10         27  
252 27         88 $corr = $this->{Objects}{$_}->finalcheck($pdls[$i++]);
253 27 100       93 next unless $#$corr>-1;
254 1         4 my ($j,$str) = (0,"");
255 1         3 for (@$corr) {$str.= ":,"x($_->[0]-$j)."(0),*$_->[1],";
  1         6  
256 1         4 $j=$_->[0]+1 }
257 1         2 chop $str;
258 1         27 $_[$i-1] = $pdls[$i-1]->slice($str);
259             }
260             }
261              
262             1;