| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# This file provides a class that parses the Code -member |
|
2
|
|
|
|
|
|
|
# of the PDLA::PP code. |
|
3
|
|
|
|
|
|
|
# |
|
4
|
|
|
|
|
|
|
# This is what makes the nice loops go around etc. |
|
5
|
|
|
|
|
|
|
# |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
package PDLA::PP::Code; |
|
8
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
|
2
|
|
|
|
|
7
|
|
|
|
2
|
|
|
|
|
114
|
|
|
9
|
|
|
|
|
|
|
our @CARP_NOT; |
|
10
|
|
|
|
|
|
|
|
|
11
|
2
|
|
|
2
|
|
8
|
use strict; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
50
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# check for bad value support |
|
14
|
|
|
|
|
|
|
# |
|
15
|
2
|
|
|
2
|
|
13
|
use PDLA::Config; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
3783
|
|
|
16
|
|
|
|
|
|
|
#use vars qw ( $bvalflag $usenan ); |
|
17
|
|
|
|
|
|
|
my $bvalflag = $PDLA::Config{WITH_BADVAL} || 0; |
|
18
|
|
|
|
|
|
|
my $usenan = $PDLA::Config{BADVAL_USENAN} || 0; |
|
19
|
|
|
|
|
|
|
|
|
20
|
4
|
|
|
4
|
|
5
|
sub get_pdls {my($this) = @_; return ($this->{ParNames},$this->{ParObjs});} |
|
|
4
|
|
|
|
|
9
|
|
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# we define the method separate_code() at the end of this |
|
23
|
|
|
|
|
|
|
# file, so that it can call the constructors from the classes |
|
24
|
|
|
|
|
|
|
# defined in this file. ugly... |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# Do the appropriate substitutions in the code. |
|
27
|
|
|
|
|
|
|
sub new { |
|
28
|
3
|
|
|
3
|
|
8
|
my($type,$code,$badcode,$parnames,$parobjs,$indobjs,$generictypes, |
|
29
|
|
|
|
|
|
|
$extrageneric,$havethreading,$name, |
|
30
|
|
|
|
|
|
|
$dont_add_thrloop, $nogeneric_loop, $backcode ) = @_; |
|
31
|
|
|
|
|
|
|
|
|
32
|
3
|
50
|
|
|
|
10
|
die "Error: missing name argument to PDLA::PP::Code->new call!\n" |
|
33
|
|
|
|
|
|
|
unless defined $name; |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
# simple way of handling bad code check |
|
36
|
3
|
50
|
|
|
|
15
|
$badcode = undef unless $bvalflag; |
|
37
|
3
|
|
|
|
|
5
|
my $handlebad = defined($badcode); |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# last three arguments may not be supplied |
|
40
|
|
|
|
|
|
|
# (in fact, the nogeneric_loop argument may never be supplied now?) |
|
41
|
|
|
|
|
|
|
# |
|
42
|
|
|
|
|
|
|
# "backcode" is a flag to the PDLA::PP::Threadloop class indicating thre threadloop |
|
43
|
|
|
|
|
|
|
# is for writeback code (typically used for writeback of data from child to parent PDLA |
|
44
|
|
|
|
|
|
|
|
|
45
|
3
|
100
|
|
|
|
9
|
$dont_add_thrloop = 0 unless defined $dont_add_thrloop; |
|
46
|
3
|
50
|
|
|
|
9
|
$nogeneric_loop = 0 unless defined $nogeneric_loop; |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# C++ style comments |
|
50
|
|
|
|
|
|
|
# |
|
51
|
|
|
|
|
|
|
# This regexp isn't perfect because it doesn't cope with |
|
52
|
|
|
|
|
|
|
# literal string constants. |
|
53
|
|
|
|
|
|
|
# |
|
54
|
3
|
|
|
|
|
7
|
$code =~ s,//.*?\n,,g; |
|
55
|
|
|
|
|
|
|
|
|
56
|
3
|
50
|
|
|
|
8
|
if ($::PP_VERBOSE) { |
|
57
|
0
|
|
|
|
|
0
|
print "Processing code for $name\n"; |
|
58
|
0
|
0
|
|
|
|
0
|
print "DONT_ADD_THRLOOP!\n" if $dont_add_thrloop; |
|
59
|
|
|
|
|
|
|
print "EXTRAGEN: {" . |
|
60
|
|
|
|
|
|
|
join(" ", |
|
61
|
0
|
|
|
|
|
0
|
map { "$_=>" . $$extrageneric{$_}} keys %$extrageneric) |
|
|
0
|
|
|
|
|
0
|
|
|
62
|
|
|
|
|
|
|
. "}\n"; |
|
63
|
0
|
|
|
|
|
0
|
print "ParNAMES: ",(join ',',@$parnames),"\n"; |
|
64
|
0
|
|
|
|
|
0
|
print "GENTYPES: ", @$generictypes, "\n"; |
|
65
|
0
|
|
|
|
|
0
|
print "HandleBad: $handlebad\n"; |
|
66
|
|
|
|
|
|
|
} |
|
67
|
3
|
|
|
|
|
30
|
my $this = bless { |
|
68
|
|
|
|
|
|
|
IndObjs => $indobjs, |
|
69
|
|
|
|
|
|
|
ParNames => $parnames, |
|
70
|
|
|
|
|
|
|
ParObjs => $parobjs, |
|
71
|
|
|
|
|
|
|
Gencurtype => [], # stack to hold GenType in generic loops |
|
72
|
|
|
|
|
|
|
types => 0, # hack for PDLA::PP::Types/GenericLoop |
|
73
|
|
|
|
|
|
|
pars => {}, # hack for PDLA::PP::NaNSupport/GenericLoop |
|
74
|
|
|
|
|
|
|
Generictypes => $generictypes, # so that MacroAccess can check it |
|
75
|
|
|
|
|
|
|
Name => $name, |
|
76
|
|
|
|
|
|
|
}, $type; |
|
77
|
|
|
|
|
|
|
|
|
78
|
3
|
|
|
|
|
9
|
my $inccode = join '',map {$_->get_incregisters();} (values %{$this->{ParObjs}}); |
|
|
3
|
|
|
|
|
14
|
|
|
|
3
|
|
|
|
|
18
|
|
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# First, separate the code into an array of C fragments (strings), |
|
81
|
|
|
|
|
|
|
# variable references (strings starting with $) and |
|
82
|
|
|
|
|
|
|
# loops (array references, 1. item = variable. |
|
83
|
|
|
|
|
|
|
# |
|
84
|
3
|
|
|
|
|
18
|
my ( $threadloops, $coderef, $sizeprivs ) = |
|
85
|
|
|
|
|
|
|
$this->separate_code( "{$inccode\n$code\n}" ); |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Now, if there is no explicit threadlooping in the code, |
|
88
|
|
|
|
|
|
|
# enclose everything into it. |
|
89
|
2
|
50
|
66
|
|
|
13
|
if(!$threadloops && !$dont_add_thrloop && $havethreading) { |
|
|
|
|
33
|
|
|
|
|
|
90
|
0
|
0
|
|
|
|
0
|
print "Adding threadloop...\n" if $::PP_VERBOSE; |
|
91
|
0
|
|
|
|
|
0
|
my $nc = $coderef; |
|
92
|
0
|
0
|
|
|
|
0
|
if( !$backcode ){ # Normal readbackdata threadloop |
|
93
|
0
|
|
|
|
|
0
|
$coderef = PDLA::PP::ThreadLoop->new(); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
else{ # writebackcode threadloop |
|
96
|
0
|
|
|
|
|
0
|
$coderef = PDLA::PP::BackCodeThreadLoop->new(); |
|
97
|
|
|
|
|
|
|
} |
|
98
|
0
|
|
|
|
|
0
|
push @{$coderef},$nc; |
|
|
0
|
|
|
|
|
0
|
|
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# repeat for the bad code, then stick good and bad into |
|
102
|
|
|
|
|
|
|
# a BadSwitch object which creates the necessary |
|
103
|
|
|
|
|
|
|
# 'if (bad) { badcode } else { goodcode }' code |
|
104
|
|
|
|
|
|
|
# |
|
105
|
|
|
|
|
|
|
# NOTE: amalgamate sizeprivs from good and bad code |
|
106
|
|
|
|
|
|
|
# |
|
107
|
2
|
50
|
|
|
|
5
|
if ( $handlebad ) { |
|
108
|
0
|
0
|
|
|
|
0
|
print "Processing 'bad' code...\n" if $::PP_VERBOSE; |
|
109
|
0
|
|
|
|
|
0
|
my ( $bad_threadloops, $bad_coderef, $bad_sizeprivs ) = |
|
110
|
|
|
|
|
|
|
$this->separate_code( "{$inccode\n$badcode\n}" ); |
|
111
|
|
|
|
|
|
|
|
|
112
|
0
|
0
|
0
|
|
|
0
|
if(!$bad_threadloops && !$dont_add_thrloop && $havethreading) { |
|
|
|
|
0
|
|
|
|
|
|
113
|
0
|
0
|
|
|
|
0
|
print "Adding 'bad' threadloop...\n" if $::PP_VERBOSE; |
|
114
|
0
|
|
|
|
|
0
|
my $nc = $bad_coderef; |
|
115
|
0
|
0
|
|
|
|
0
|
if( !$backcode ){ # Normal readbackdata threadloop |
|
116
|
0
|
|
|
|
|
0
|
$bad_coderef = PDLA::PP::ThreadLoop->new(); |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
else{ # writebackcode threadloop |
|
119
|
0
|
|
|
|
|
0
|
$bad_coderef = PDLA::PP::BackCodeThreadLoop->new(); |
|
120
|
|
|
|
|
|
|
} |
|
121
|
0
|
|
|
|
|
0
|
push @{$bad_coderef},$nc; |
|
|
0
|
|
|
|
|
0
|
|
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
0
|
|
|
|
|
0
|
my $good_coderef = $coderef; |
|
125
|
0
|
|
|
|
|
0
|
$coderef = PDLA::PP::BadSwitch->new( $good_coderef, $bad_coderef ); |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# amalgamate sizeprivs from Code/BadCode segments |
|
128
|
|
|
|
|
|
|
# (sizeprivs is a simple hash, with each element |
|
129
|
|
|
|
|
|
|
# containing a string - see PDLA::PP::Loop) |
|
130
|
0
|
|
|
|
|
0
|
while ( my ( $bad_key, $bad_str ) = each %$bad_sizeprivs ) { |
|
131
|
0
|
|
|
|
|
0
|
my $str = $$sizeprivs{$bad_key}; |
|
132
|
0
|
0
|
|
|
|
0
|
if ( defined $str ) { |
|
133
|
0
|
0
|
|
|
|
0
|
die "ERROR: sizeprivs problem in PP/PDLACode.pm (BadVal stuff)\n" |
|
134
|
|
|
|
|
|
|
unless $str eq $bad_str; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
0
|
|
|
|
|
0
|
$$sizeprivs{$bad_key} = $bad_str; # copy over |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
} # if: $handlebad |
|
140
|
|
|
|
|
|
|
|
|
141
|
2
|
50
|
|
|
|
5
|
print "SIZEPRIVSX: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Enclose it all in a genericloop. |
|
144
|
2
|
50
|
|
|
|
4
|
unless ($nogeneric_loop) { |
|
145
|
|
|
|
|
|
|
# XXX Make genericloop understand denied pointers;... |
|
146
|
2
|
|
|
|
|
3
|
my $nc = $coderef; |
|
147
|
|
|
|
|
|
|
$coderef = PDLA::PP::GenericLoop->new($generictypes,"", |
|
148
|
2
|
|
|
|
|
10
|
[grep {!$extrageneric->{$_}} @$parnames],'$PRIV(__datatype)'); |
|
|
2
|
|
|
|
|
16
|
|
|
149
|
2
|
|
|
|
|
3
|
push @{$coderef},$nc; |
|
|
2
|
|
|
|
|
7
|
|
|
150
|
|
|
|
|
|
|
} |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Do we have extra generic loops? |
|
153
|
|
|
|
|
|
|
# If we do, first reverse the hash: |
|
154
|
2
|
|
|
|
|
3
|
my %glh; |
|
155
|
2
|
|
|
|
|
6
|
for(keys %$extrageneric) { |
|
156
|
0
|
|
|
|
|
0
|
push @{$glh{$extrageneric->{$_}}},$_; |
|
|
0
|
|
|
|
|
0
|
|
|
157
|
|
|
|
|
|
|
} |
|
158
|
2
|
|
|
|
|
4
|
my $no = 0; |
|
159
|
2
|
|
|
|
|
4
|
for(keys %glh) { |
|
160
|
0
|
|
|
|
|
0
|
my $nc = $coderef; |
|
161
|
|
|
|
|
|
|
$coderef = PDLA::PP::GenericLoop->new($generictypes,$no++, |
|
162
|
0
|
|
|
|
|
0
|
$glh{$_},$_); |
|
163
|
0
|
|
|
|
|
0
|
push @$coderef,$nc; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# Then, in this form, put it together what we want the code to actually do. |
|
167
|
2
|
50
|
|
|
|
10
|
print "SIZEPRIVS: ",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
168
|
2
|
|
|
|
|
12
|
$this->{Code} = "{".(join '',values %$sizeprivs). |
|
169
|
|
|
|
|
|
|
$coderef->get_str($this,[]) |
|
170
|
|
|
|
|
|
|
."}"; |
|
171
|
2
|
|
|
|
|
46
|
$this->{Code}; |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
} # new() |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# This sub determines the index name for this index. |
|
176
|
|
|
|
|
|
|
# For example, a(x,y) and x0 becomes [x,x0] |
|
177
|
3
|
|
|
3
|
|
5
|
sub make_loopind { my($this,$ind) = @_; |
|
178
|
3
|
|
|
|
|
5
|
my $orig = $ind; |
|
179
|
3
|
|
|
|
|
11
|
while(!$this->{IndObjs}{$ind}) { |
|
180
|
0
|
0
|
|
|
|
0
|
if(!((chop $ind) =~ /[0-9]/)) { |
|
181
|
0
|
|
|
|
|
0
|
confess("Index not found for $_ ($ind)!\n"); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
} |
|
184
|
3
|
|
|
|
|
9
|
return [$ind,$orig]; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
##################################################################### |
|
189
|
|
|
|
|
|
|
# |
|
190
|
|
|
|
|
|
|
# Encapsulate the parsing code objects |
|
191
|
|
|
|
|
|
|
# |
|
192
|
|
|
|
|
|
|
# All objects have two methods: |
|
193
|
|
|
|
|
|
|
# new - constructor |
|
194
|
|
|
|
|
|
|
# get_str - get the string to be put into the xsub. |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
########################### |
|
197
|
|
|
|
|
|
|
# |
|
198
|
|
|
|
|
|
|
# Encapsulate a block |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
package PDLA::PP::Block; |
|
201
|
|
|
|
|
|
|
|
|
202
|
2
|
|
|
2
|
|
4
|
sub new { my($type) = @_; bless [],$type; } |
|
|
2
|
|
|
|
|
4
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
4
|
|
|
4
|
|
6
|
sub myoffs { return 0; } |
|
205
|
|
|
|
4
|
|
|
sub myprelude {} |
|
206
|
16
|
|
|
16
|
|
23
|
sub myitem {return "";} |
|
207
|
|
|
|
4
|
|
|
sub mypostlude {} |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub get_str { |
|
210
|
10
|
|
|
10
|
|
16
|
my ($this,$parent,$context) = @_; |
|
211
|
10
|
|
|
|
|
24
|
my $str = $this->myprelude($parent,$context); |
|
212
|
10
|
|
|
|
|
43
|
$str .= $this->get_str_int($parent,$context); |
|
213
|
10
|
|
|
|
|
24
|
$str .= $this->mypostlude($parent,$context); |
|
214
|
10
|
|
|
|
|
50
|
return $str; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub get_str_int { |
|
218
|
10
|
|
|
10
|
|
11
|
my ( $this, $parent, $context ) = @_; |
|
219
|
|
|
|
|
|
|
|
|
220
|
10
|
|
|
|
|
13
|
my $nth=0; |
|
221
|
10
|
|
|
|
|
11
|
my $str = ""; |
|
222
|
10
|
|
|
|
|
10
|
MYLOOP: while(1) { |
|
223
|
22
|
|
|
|
|
53
|
my $it = $this->myitem($parent,$nth); |
|
224
|
22
|
100
|
100
|
|
|
84
|
last MYLOOP if $nth and !$it; |
|
225
|
12
|
|
|
|
|
21
|
$str .= $it; |
|
226
|
28
|
100
|
|
|
|
96
|
$str .= (join '',map {ref $_ ? $_->get_str($parent,$context) : $_} |
|
227
|
12
|
|
|
|
|
31
|
@{$this}[$this->myoffs()..$#{$this}]); |
|
|
12
|
|
|
|
|
18
|
|
|
|
12
|
|
|
|
|
20
|
|
|
228
|
12
|
|
|
|
|
25
|
$nth++; |
|
229
|
|
|
|
|
|
|
} |
|
230
|
10
|
|
|
|
|
26
|
return $str; |
|
231
|
|
|
|
|
|
|
} # get_str_int() |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
########################### |
|
234
|
|
|
|
|
|
|
# |
|
235
|
|
|
|
|
|
|
# Deal with bad code |
|
236
|
|
|
|
|
|
|
# - ie create something like |
|
237
|
|
|
|
|
|
|
# if ( badflag ) { badcode } else { goodcode } |
|
238
|
|
|
|
|
|
|
# |
|
239
|
|
|
|
|
|
|
package PDLA::PP::BadSwitch; |
|
240
|
|
|
|
|
|
|
@PDLA::PP::BadSwitch::ISA = "PDLA::PP::Block"; |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub new { |
|
243
|
0
|
|
|
0
|
|
0
|
my($type,$good,$bad) = @_; |
|
244
|
0
|
|
|
|
|
0
|
return bless [$good,$bad], $type; |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub get_str { |
|
248
|
0
|
|
|
0
|
|
0
|
my ($this,$parent,$context) = @_; |
|
249
|
|
|
|
|
|
|
|
|
250
|
0
|
|
|
|
|
0
|
my $good = $this->[0]; |
|
251
|
0
|
|
|
|
|
0
|
my $bad = $this->[1]; |
|
252
|
|
|
|
|
|
|
|
|
253
|
0
|
|
|
|
|
0
|
my $str = "if ( \$PRIV(bvalflag) ) { PDLA_COMMENT(\"** do 'bad' Code **\")\n"; |
|
254
|
0
|
|
|
|
|
0
|
$str .= "\n#define PDLA_BAD_CODE\n"; |
|
255
|
0
|
|
|
|
|
0
|
$str .= $bad->get_str($parent,$context); |
|
256
|
0
|
|
|
|
|
0
|
$str .= "\n#undef PDLA_BAD_CODE\n"; |
|
257
|
0
|
|
|
|
|
0
|
$str .= "} else { PDLA_COMMENT(\"** else do 'good' Code **\")\n"; |
|
258
|
0
|
|
|
|
|
0
|
$str .= $good->get_str($parent,$context); |
|
259
|
0
|
|
|
|
|
0
|
$str .= "}\n"; |
|
260
|
|
|
|
|
|
|
|
|
261
|
0
|
|
|
|
|
0
|
return $str; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
########################### |
|
265
|
|
|
|
|
|
|
# |
|
266
|
|
|
|
|
|
|
# Encapsulate a loop |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
package PDLA::PP::Loop; |
|
269
|
|
|
|
|
|
|
@PDLA::PP::Loop::ISA = "PDLA::PP::Block"; |
|
270
|
|
|
|
|
|
|
|
|
271
|
1
|
|
|
1
|
|
3
|
sub new { my($type,$args,$sizeprivs,$parent) = @_; |
|
272
|
1
|
|
|
|
|
2
|
my $this = bless [$args],$type; |
|
273
|
1
|
|
|
|
|
2
|
for(@{$this->[0]}) { |
|
|
1
|
|
|
|
|
5
|
|
|
274
|
1
|
50
|
|
|
|
4
|
print "SIZP $sizeprivs, $_\n" if $::PP_VERBOSE; |
|
275
|
1
|
|
|
|
|
4
|
my $i = $parent->make_loopind($_); |
|
276
|
1
|
|
|
|
|
5
|
$sizeprivs->{$i->[0]} = |
|
277
|
|
|
|
|
|
|
"register PDLA_Indx __$i->[0]_size = \$PRIV(__$i->[0]_size);\n"; |
|
278
|
1
|
50
|
|
|
|
29
|
print "SP :",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
279
|
|
|
|
|
|
|
} |
|
280
|
1
|
|
|
|
|
3
|
return $this; |
|
281
|
|
|
|
|
|
|
} |
|
282
|
|
|
|
|
|
|
|
|
283
|
2
|
|
|
2
|
|
3
|
sub myoffs { return 1; } |
|
284
|
2
|
|
|
2
|
|
3
|
sub myprelude { my($this,$parent,$context) = @_; |
|
285
|
2
|
|
|
|
|
9
|
my $text = ""; my $i; |
|
|
2
|
|
|
|
|
3
|
|
|
286
|
|
|
|
|
|
|
push @$context, map { |
|
287
|
2
|
|
|
|
|
6
|
$i = $parent->make_loopind($_); |
|
288
|
|
|
|
|
|
|
# Used to be $PRIV(.._size) but now we have it in a register. |
|
289
|
2
|
|
|
|
|
10
|
$text .= "{PDLA_COMMENT(\"Open $_\") register PDLA_Indx $_; |
|
290
|
|
|
|
|
|
|
for($_=0; $_<(__$i->[0]_size); $_++) {"; |
|
291
|
2
|
|
|
|
|
6
|
$i; |
|
292
|
2
|
|
|
|
|
4
|
} @{$this->[0]}; |
|
|
2
|
|
|
|
|
5
|
|
|
293
|
2
|
|
|
|
|
5
|
return $text; |
|
294
|
|
|
|
|
|
|
} |
|
295
|
2
|
|
|
2
|
|
3
|
sub mypostlude { my($this,$parent,$context) = @_; |
|
296
|
2
|
|
|
|
|
4
|
splice @$context, - ($#{$this->[0]}+1); |
|
|
2
|
|
|
|
|
6
|
|
|
297
|
2
|
|
|
|
|
4
|
return join '',map {"}} PDLA_COMMENT(\"Close $_\")"} @{$this->[0]}; |
|
|
2
|
|
|
|
|
8
|
|
|
|
2
|
|
|
|
|
5
|
|
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
########################### |
|
301
|
|
|
|
|
|
|
# |
|
302
|
|
|
|
|
|
|
# Encapsulate a generic type loop |
|
303
|
|
|
|
|
|
|
# |
|
304
|
|
|
|
|
|
|
# we use the value of $parent->{types} [set by a PDLA::PP::Types object] |
|
305
|
|
|
|
|
|
|
# to determine whether to define/undefine the THISISxxx macros |
|
306
|
|
|
|
|
|
|
# (makes the xs code easier to read) |
|
307
|
|
|
|
|
|
|
# |
|
308
|
|
|
|
|
|
|
package PDLA::PP::GenericLoop; |
|
309
|
|
|
|
|
|
|
@PDLA::PP::GenericLoop::ISA = "PDLA::PP::Block"; |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
# Types: BSULFD |
|
312
|
2
|
|
|
2
|
|
16
|
use PDLA::Types ':All'; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
1648
|
|
|
313
|
|
|
|
|
|
|
sub new { |
|
314
|
2
|
|
|
2
|
|
3
|
my($type,$types,$name,$varnames,$whattype) = @_; |
|
315
|
2
|
|
|
|
|
6
|
bless [(PDLA::PP::get_generictyperecs($types)),$name,$varnames, |
|
316
|
|
|
|
|
|
|
$whattype],$type; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
4
|
|
|
4
|
|
6
|
sub myoffs {4} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub myprelude { |
|
322
|
2
|
|
|
2
|
|
3
|
my($this,$parent,$context) = @_; |
|
323
|
2
|
|
|
|
|
7
|
push @{$parent->{Gencurtype}},'PDLA_undef'; # so that $GENERIC can get at it |
|
|
2
|
|
|
|
|
6
|
|
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
# horrible hack for PDLA::PP::NaNSupport |
|
326
|
2
|
50
|
|
|
|
8
|
if ( $this->[1] ne "" ) { |
|
327
|
0
|
|
|
|
|
0
|
my ( @test ) = keys %{$parent->{pars}}; |
|
|
0
|
|
|
|
|
0
|
|
|
328
|
0
|
0
|
|
|
|
0
|
die "ERROR: need to rethink NaNSupport in GenericLoop\n" |
|
329
|
|
|
|
|
|
|
if $#test != -1; |
|
330
|
0
|
|
|
|
|
0
|
$parent->{pars} = {}; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
2
|
|
|
|
|
4
|
my $thisis_loop = ''; |
|
334
|
2
|
50
|
|
|
|
5
|
if ( $parent->{types} ) { |
|
335
|
|
|
|
|
|
|
$thisis_loop = join '', |
|
336
|
|
|
|
|
|
|
map { |
|
337
|
0
|
|
|
|
|
0
|
"#undef THISIS$this->[1]_$_\n#define THISIS$this->[1]_$_(a)\n" |
|
|
0
|
|
|
|
|
0
|
|
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
(ppdefs); |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
2
|
|
|
|
|
8
|
return <
|
|
343
|
|
|
|
|
|
|
PDLA_COMMENT("Start generic loop") |
|
344
|
|
|
|
|
|
|
$thisis_loop |
|
345
|
|
|
|
|
|
|
switch($this->[3]) { case -42: PDLA_COMMENT("Warning eater") {(void)1; |
|
346
|
|
|
|
|
|
|
WARNING_EATER |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
sub myitem { |
|
350
|
6
|
|
|
6
|
|
8
|
my($this,$parent,$nth) = @_; |
|
351
|
|
|
|
|
|
|
# print "GENERICITEM\n"; |
|
352
|
6
|
|
|
|
|
9
|
my $item = $this->[0]->[$nth]; |
|
353
|
6
|
100
|
|
|
|
43
|
if(!$item) {return "";} |
|
|
2
|
|
|
|
|
4
|
|
|
354
|
4
|
|
|
|
|
9
|
$parent->{Gencurtype}->[-1] = $item->[1]; |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
# horrible hack for PDLA::PP::NaNSupport |
|
357
|
4
|
50
|
|
|
|
10
|
if ( $this->[1] ne "" ) { |
|
358
|
0
|
|
|
|
|
0
|
foreach my $parname ( @{$this->[2]} ) { |
|
|
0
|
|
|
|
|
0
|
|
|
359
|
0
|
|
|
|
|
0
|
$parent->{pars}{$parname} = $item->[1]; |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
} |
|
362
|
|
|
|
|
|
|
|
|
363
|
4
|
|
|
|
|
5
|
my $thisis_loop = ''; |
|
364
|
4
|
50
|
|
|
|
9
|
if ( $parent->{types} ) { |
|
365
|
|
|
|
|
|
|
$thisis_loop = ( |
|
366
|
|
|
|
|
|
|
join '', |
|
367
|
|
|
|
|
|
|
map { |
|
368
|
0
|
|
|
|
|
0
|
"#undef THISIS$this->[1]_$_\n#define THISIS$this->[1]_$_(a)\n"; |
|
|
0
|
|
|
|
|
0
|
|
|
369
|
|
|
|
|
|
|
} |
|
370
|
|
|
|
|
|
|
(ppdefs) |
|
371
|
|
|
|
|
|
|
) . |
|
372
|
|
|
|
|
|
|
"#undef THISIS$this->[1]_$item->[3]\n" . |
|
373
|
|
|
|
|
|
|
"#define THISIS$this->[1]_$item->[3](a) a\n"; |
|
374
|
|
|
|
|
|
|
} |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
return "\t} break; case $item->[0]: {\n". |
|
377
|
|
|
|
|
|
|
$thisis_loop . |
|
378
|
|
|
|
|
|
|
(join '',map{ |
|
379
|
|
|
|
|
|
|
# print "DAPAT: '$_'\n"; |
|
380
|
4
|
|
|
|
|
15
|
$parent->{ParObjs}{$_}->get_xsdatapdecl($item->[1]); |
|
381
|
4
|
|
|
|
|
9
|
} (@{$this->[2]})) ; |
|
|
4
|
|
|
|
|
12
|
|
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub mypostlude { |
|
385
|
2
|
|
|
2
|
|
5
|
my($this,$parent,$context) = @_; |
|
386
|
2
|
|
|
|
|
3
|
pop @{$parent->{Gencurtype}}; # and clean up the Gentype stack |
|
|
2
|
|
|
|
|
5
|
|
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# horrible hack for PDLA::PP::NaNSupport |
|
389
|
2
|
50
|
|
|
|
7
|
if ( $this->[1] ne "" ) { $parent->{pars} = {}; } |
|
|
0
|
|
|
|
|
0
|
|
|
390
|
|
|
|
|
|
|
|
|
391
|
2
|
|
|
|
|
4
|
return "\tbreak;} |
|
392
|
|
|
|
|
|
|
default:barf(\"PP INTERNAL ERROR! PLEASE MAKE A BUG REPORT\\n\");}\n"; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
########################### |
|
397
|
|
|
|
|
|
|
# |
|
398
|
|
|
|
|
|
|
# Encapsulate a threadloop. |
|
399
|
|
|
|
|
|
|
# There are several different |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
package PDLA::PP::ThreadLoop; |
|
402
|
|
|
|
|
|
|
sub new { |
|
403
|
1
|
|
|
1
|
|
8
|
return PDLA::PP::ComplexThreadLoop->new(@_); |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
package PDLA::PP::SimpleThreadLoop; |
|
407
|
2
|
|
|
2
|
|
14
|
use Carp; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
592
|
|
|
408
|
|
|
|
|
|
|
@PDLA::PP::SimpleThreadLoop::ISA = "PDLA::PP::Block"; |
|
409
|
|
|
|
|
|
|
our @CARP_NOT; |
|
410
|
|
|
|
|
|
|
|
|
411
|
0
|
|
|
0
|
|
0
|
sub new { my($type) = @_; bless [],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
412
|
0
|
|
|
0
|
|
0
|
sub myoffs { return 0; } |
|
413
|
0
|
|
|
0
|
|
0
|
sub myprelude {my($this,$parent,$context) = @_; |
|
414
|
0
|
|
|
|
|
0
|
my $no; |
|
415
|
0
|
|
|
|
|
0
|
my ($ord,$pdls) = $parent->get_pdls(); |
|
416
|
|
|
|
|
|
|
' PDLA_COMMENT("THREADLOOPBEGIN") |
|
417
|
|
|
|
|
|
|
if(PDLA->startthreadloop(&($PRIV(__pdlthread)),$PRIV(vtable)->readdata, |
|
418
|
|
|
|
|
|
|
__privtrans))) return; |
|
419
|
|
|
|
|
|
|
do { |
|
420
|
0
|
|
|
|
|
0
|
'.(join '',map {"${_}_datap += \$PRIV(__pdlthread).offs[".(0+$no++)."];\n"} |
|
|
0
|
|
|
|
|
0
|
|
|
421
|
|
|
|
|
|
|
@$ord).' |
|
422
|
|
|
|
|
|
|
'; |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
0
|
|
|
0
|
|
0
|
sub mypostlude {my($this,$parent,$context) = @_; |
|
426
|
0
|
|
|
|
|
0
|
my $no; |
|
427
|
0
|
|
|
|
|
0
|
my ($ord,$pdls) = $parent->get_pdls(); |
|
428
|
|
|
|
|
|
|
' PDLA_COMMENT("THREADLOOPEND") |
|
429
|
0
|
|
|
|
|
0
|
'.(join '',map {"${_}_datap -= \$PRIV(__pdlthread).offs[".(0+$no++)."];\n"} |
|
|
0
|
|
|
|
|
0
|
|
|
430
|
|
|
|
|
|
|
@$ord).' |
|
431
|
|
|
|
|
|
|
} while(PDLA->iterthreadloop(&$PRIV(__pdlthread),0)); |
|
432
|
|
|
|
|
|
|
' |
|
433
|
|
|
|
|
|
|
} |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
#### |
|
436
|
|
|
|
|
|
|
# |
|
437
|
|
|
|
|
|
|
# This relies on PP.pm making sure that initthreadloop always sets |
|
438
|
|
|
|
|
|
|
# up the two first dimensions even when they are not necessary. |
|
439
|
|
|
|
|
|
|
# |
|
440
|
|
|
|
|
|
|
package PDLA::PP::ComplexThreadLoop; |
|
441
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
|
2
|
|
|
|
|
7
|
|
|
|
2
|
|
|
|
|
850
|
|
|
442
|
|
|
|
|
|
|
@PDLA::PP::ComplexThreadLoop::ISA = "PDLA::PP::Block"; |
|
443
|
|
|
|
|
|
|
our @CARP_NOT; |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub new { |
|
447
|
1
|
|
|
1
|
|
3
|
my $type = shift; |
|
448
|
1
|
|
|
|
|
3
|
bless [],$type; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
2
|
|
|
2
|
|
4
|
sub myoffs { return 0; } |
|
451
|
|
|
|
|
|
|
sub myprelude { |
|
452
|
2
|
|
|
2
|
|
3
|
my($this,$parent,$context, $backcode) = @_; |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Set appropriate function from the vtable to supply to threadthreadloop. |
|
455
|
|
|
|
|
|
|
# Function name from the vtable is readdata for normal code |
|
456
|
|
|
|
|
|
|
# function name for backcode is writebackdata |
|
457
|
2
|
|
|
|
|
3
|
my $funcName = "readdata"; |
|
458
|
2
|
50
|
|
|
|
5
|
$funcName = "writebackdata" if( $backcode ); |
|
459
|
|
|
|
|
|
|
|
|
460
|
2
|
|
|
|
|
8
|
my ($ord,$pdls) = $parent->get_pdls(); |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
join( "\n ", |
|
463
|
|
|
|
|
|
|
'', |
|
464
|
|
|
|
|
|
|
'PDLA_COMMENT("THREADLOOPBEGIN")', |
|
465
|
|
|
|
|
|
|
'if ( PDLA->startthreadloop(&($PRIV(__pdlthread)),$PRIV(vtable)->'.$funcName.', __tr) ) return; |
|
466
|
|
|
|
|
|
|
do { register PDLA_Indx __tind1=0,__tind2=0; |
|
467
|
|
|
|
|
|
|
register PDLA_Indx __tnpdls = $PRIV(__pdlthread).npdls; |
|
468
|
|
|
|
|
|
|
register PDLA_Indx __tdims1 = $PRIV(__pdlthread.dims[1]); |
|
469
|
|
|
|
|
|
|
register PDLA_Indx __tdims0 = $PRIV(__pdlthread.dims[0]); |
|
470
|
|
|
|
|
|
|
register PDLA_Indx *__offsp = PDLA->get_threadoffsp(&$PRIV(__pdlthread));', |
|
471
|
2
|
|
|
|
|
6
|
( map { "register PDLA_Indx __tinc0_${_} = \$PRIV(__pdlthread).incs[${_}];"} 0..$#{$ord}), |
|
|
2
|
|
|
|
|
5
|
|
|
472
|
2
|
|
|
|
|
6
|
( map { "register PDLA_Indx __tinc1_${_} = \$PRIV(__pdlthread).incs[__tnpdls+$_];"} 0.. $#{$ord}), |
|
|
2
|
|
|
|
|
5
|
|
|
473
|
2
|
|
|
|
|
8
|
( map { $ord->[$_] ."_datap += __offsp[$_];"} 0..$#{$ord} ), |
|
|
2
|
|
|
|
|
3
|
|
|
474
|
|
|
|
|
|
|
'for( __tind2 = 0 ; |
|
475
|
|
|
|
|
|
|
__tind2 < __tdims1 ; |
|
476
|
|
|
|
|
|
|
__tind2++', |
|
477
|
2
|
|
|
|
|
8
|
( map { "\t\t," . $ord->[$_] . "_datap += __tinc1_${_} - __tinc0_${_} * __tdims0"} 0..$#{$ord} ), |
|
|
2
|
|
|
|
|
3
|
|
|
478
|
|
|
|
|
|
|
')', |
|
479
|
|
|
|
|
|
|
'{ |
|
480
|
|
|
|
|
|
|
for( __tind1 = 0 ; |
|
481
|
|
|
|
|
|
|
__tind1 < __tdims0 ; |
|
482
|
|
|
|
|
|
|
__tind1++', |
|
483
|
2
|
|
|
|
|
6
|
( map { "\t\t," . $ord->[$_] . "_datap += __tinc0_${_}"} 0..$#{$ord}), |
|
|
2
|
|
|
|
|
12
|
|
|
|
2
|
|
|
|
|
3
|
|
|
484
|
|
|
|
|
|
|
')', |
|
485
|
|
|
|
|
|
|
'{ PDLA_COMMENT("This is the tightest threadloop. Make sure inside is optimal.")' |
|
486
|
|
|
|
|
|
|
); |
|
487
|
|
|
|
|
|
|
} |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
# Should possibly fold out thread.dims[0] and [1]. |
|
490
|
2
|
|
|
2
|
|
3
|
sub mypostlude {my($this,$parent,$context) = @_; |
|
491
|
|
|
|
|
|
|
|
|
492
|
2
|
|
|
|
|
6
|
my ($ord,$pdls) = $parent->get_pdls(); |
|
493
|
|
|
|
|
|
|
join( "\n ", |
|
494
|
|
|
|
|
|
|
'', |
|
495
|
|
|
|
|
|
|
'PDLA_COMMENT("THREADLOOPEND")', |
|
496
|
|
|
|
|
|
|
'}', |
|
497
|
|
|
|
|
|
|
'}', |
|
498
|
2
|
|
|
|
|
5
|
( map { $ord->[$_] . "_datap -= __tinc1_${_} * __tdims1 + __offsp[${_}];"} 0..$#{$ord} ), |
|
|
2
|
|
|
|
|
12
|
|
|
|
2
|
|
|
|
|
4
|
|
|
499
|
|
|
|
|
|
|
'} while(PDLA->iterthreadloop(&$PRIV(__pdlthread),2));' |
|
500
|
|
|
|
|
|
|
) |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
# Simple subclass of ComplexThreadLoop to implement writeback code |
|
504
|
|
|
|
|
|
|
# |
|
505
|
|
|
|
|
|
|
# |
|
506
|
|
|
|
|
|
|
package PDLA::PP::BackCodeThreadLoop; |
|
507
|
2
|
|
|
2
|
|
16
|
use Carp; |
|
|
2
|
|
|
|
|
73
|
|
|
|
2
|
|
|
|
|
233
|
|
|
508
|
|
|
|
|
|
|
@PDLA::PP::BackCodeThreadLoop::ISA = "PDLA::PP::ComplexThreadLoop"; |
|
509
|
|
|
|
|
|
|
our @CARP_NOT; |
|
510
|
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
sub myprelude { |
|
512
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context, $backcode) = @_; |
|
513
|
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
# Set backcode flag if not defined. This will make the parent |
|
515
|
|
|
|
|
|
|
# myprelude emit proper writeback code |
|
516
|
0
|
0
|
|
|
|
0
|
$backcode = 1 unless defined($backcode); |
|
517
|
|
|
|
|
|
|
|
|
518
|
0
|
|
|
|
|
0
|
$this->SUPER::myprelude($parent, $context, $backcode); |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
########################### |
|
523
|
|
|
|
|
|
|
# |
|
524
|
|
|
|
|
|
|
# Encapsulate a types() switch |
|
525
|
|
|
|
|
|
|
# |
|
526
|
|
|
|
|
|
|
# horrible hack: |
|
527
|
|
|
|
|
|
|
# set $parent->{types} if we create this object so that |
|
528
|
|
|
|
|
|
|
# PDLA::PP::GenericLoop knows to define the THISIS ... macros |
|
529
|
|
|
|
|
|
|
# |
|
530
|
|
|
|
|
|
|
package PDLA::PP::Types; |
|
531
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
102
|
|
|
532
|
2
|
|
|
2
|
|
8
|
use PDLA::Types ':All'; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
818
|
|
|
533
|
|
|
|
|
|
|
@PDLA::PP::Types::ISA = "PDLA::PP::Block"; |
|
534
|
|
|
|
|
|
|
our @CARP_NOT; |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
sub new { |
|
537
|
0
|
|
|
0
|
|
0
|
my($type,$ts,$parent) = @_; |
|
538
|
0
|
|
|
|
|
0
|
my $types = join '', ppdefs; # BSUL.... |
|
539
|
0
|
0
|
|
|
|
0
|
$ts =~ /[$types]+/ or confess "Invalid type access with '$ts'!"; |
|
540
|
0
|
|
|
|
|
0
|
$parent->{types} = 1; # hack for PDLA::PP::GenericLoop |
|
541
|
0
|
|
|
|
|
0
|
bless [$ts],$type; } |
|
542
|
0
|
|
|
0
|
|
0
|
sub myoffs { return 1; } |
|
543
|
|
|
|
|
|
|
sub myprelude { |
|
544
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context) = @_; |
|
545
|
0
|
|
|
|
|
0
|
return "\n#if ". (join '||',map {"(THISIS_$_(1)+0)"} split '',$this->[0])."\n"; |
|
|
0
|
|
|
|
|
0
|
|
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
|
|
548
|
0
|
|
|
0
|
|
0
|
sub mypostlude {my($this,$parent,$context) = @_; |
|
549
|
0
|
|
|
|
|
0
|
"\n#endif\n" |
|
550
|
|
|
|
|
|
|
} |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
########################### |
|
554
|
|
|
|
|
|
|
# |
|
555
|
|
|
|
|
|
|
# Encapsulate an access |
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
package PDLA::PP::Access; |
|
558
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
996
|
|
|
559
|
|
|
|
|
|
|
our @CARP_NOT; |
|
560
|
|
|
|
|
|
|
|
|
561
|
2
|
|
|
2
|
|
4
|
sub new { my($type,$str,$parent) = @_; |
|
562
|
2
|
50
|
|
|
|
16
|
$str =~ /^\$([a-zA-Z_]\w*)\s*\(([^)]*)\)/ or |
|
563
|
|
|
|
|
|
|
confess ("Access wrong: '$str'\n"); |
|
564
|
2
|
|
|
|
|
7
|
my($pdl,$inds) = ($1,$2); |
|
565
|
2
|
50
|
|
|
|
29
|
if($pdl =~ /^T/) {new PDLA::PP::MacroAccess($pdl,$inds, |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
566
|
0
|
|
|
|
|
0
|
$parent->{Generictypes},$parent->{Name});} |
|
567
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^P$/) {new PDLA::PP::PointerAccess($pdl,$inds);} |
|
568
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^PP$/) {new PDLA::PP::PhysPointerAccess($pdl,$inds);} |
|
569
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^SIZE$/) {new PDLA::PP::SizeAccess($pdl,$inds);} |
|
570
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^RESIZE$/) {new PDLA::PP::ReSizeAccess($pdl,$inds);} |
|
571
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^GENERIC$/) {new PDLA::PP::GentypeAccess($pdl,$inds);} |
|
572
|
0
|
|
|
|
|
0
|
elsif($pdl =~ /^PDLA$/) {new PDLA::PP::PdlAccess($pdl,$inds);} |
|
573
|
2
|
|
|
|
|
8
|
elsif(!defined $parent->{ParObjs}{$pdl}) {new PDLA::PP::OtherAccess($pdl,$inds);} |
|
574
|
|
|
|
|
|
|
else { |
|
575
|
0
|
|
|
|
|
0
|
bless [$pdl,$inds],$type; |
|
576
|
|
|
|
|
|
|
} |
|
577
|
|
|
|
|
|
|
} |
|
578
|
|
|
|
|
|
|
|
|
579
|
0
|
|
|
0
|
|
0
|
sub get_str { my($this,$parent,$context) = @_; |
|
580
|
|
|
|
|
|
|
# print "AC: $this->[0]\n"; |
|
581
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_access($this->[1],$context) |
|
582
|
0
|
0
|
|
|
|
0
|
if defined($parent->{ParObjs}{$this->[0]}); |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
########################### |
|
586
|
|
|
|
|
|
|
# |
|
587
|
|
|
|
|
|
|
# Just some other substituted thing. |
|
588
|
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
package PDLA::PP::OtherAccess; |
|
590
|
2
|
|
|
2
|
|
4
|
sub new { my($type,$pdl,$inds) = @_; bless [$pdl,$inds],$type; } |
|
|
2
|
|
|
|
|
10
|
|
|
591
|
4
|
|
|
4
|
|
7
|
sub get_str {my($this) = @_;return "\$$this->[0]($this->[1])"} |
|
|
4
|
|
|
|
|
13
|
|
|
592
|
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
########################### |
|
595
|
|
|
|
|
|
|
# |
|
596
|
|
|
|
|
|
|
# used by BadAccess code to know when to use NaN support |
|
597
|
|
|
|
|
|
|
# - the output depends on the value of the |
|
598
|
|
|
|
|
|
|
# BADVAL_USENAN option in perldl.conf |
|
599
|
|
|
|
|
|
|
# == 1 then we use NaN's |
|
600
|
|
|
|
|
|
|
# 0 PDLA.bvals.Float/Double |
|
601
|
|
|
|
|
|
|
# |
|
602
|
|
|
|
|
|
|
# note the *horrible hack* for piddles whose type have been |
|
603
|
|
|
|
|
|
|
# specified using the FType option - see GenericLoop. |
|
604
|
|
|
|
|
|
|
# There MUST be a better way than this... |
|
605
|
|
|
|
|
|
|
# |
|
606
|
|
|
|
|
|
|
package PDLA::PP::NaNSupport; |
|
607
|
2
|
|
|
2
|
|
9
|
use PDLA::Types ':All'; # typefld et al. |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
1278
|
|
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
# need to be lower-case because of FlagTyped stuff |
|
610
|
|
|
|
|
|
|
# |
|
611
|
|
|
|
|
|
|
# need to be able to handle signatures with fixed types |
|
612
|
|
|
|
|
|
|
# which means parameters like 'int mask()', |
|
613
|
|
|
|
|
|
|
# which means the hack to add 'int' to %use_nan |
|
614
|
|
|
|
|
|
|
# |
|
615
|
|
|
|
|
|
|
my %use_nan = |
|
616
|
|
|
|
|
|
|
map {(typefld($_,'convertfunc') => typefld($_,'usenan')*$usenan)} typesrtkeys; |
|
617
|
|
|
|
|
|
|
$use_nan{int} = 0; |
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
# original try |
|
620
|
|
|
|
|
|
|
##my %use_nan = |
|
621
|
|
|
|
|
|
|
## map {(typefld($_,'convertfunc') => typefld($_,'usenan')*$usenan)} typesrtkeys; |
|
622
|
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
# Was the following, before new Type "interface" |
|
624
|
|
|
|
|
|
|
# ( byte => 0, short => 0, ushort => 0, long => 0, |
|
625
|
|
|
|
|
|
|
# int => 0, longlong => 0, # necessary for fixed-type piddles (or something) |
|
626
|
|
|
|
|
|
|
# float => $usenan, |
|
627
|
|
|
|
|
|
|
# double => $usenan |
|
628
|
|
|
|
|
|
|
# ); |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
my %set_nan = |
|
631
|
|
|
|
|
|
|
( |
|
632
|
|
|
|
|
|
|
float => 'PDLA->bvals.Float', PDLA_Float => 'PDLA->bvals.Float', |
|
633
|
|
|
|
|
|
|
double => 'PDLA->bvals.Double', PDLA_Double => 'PDLA->bvals.Double', |
|
634
|
|
|
|
|
|
|
); |
|
635
|
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
sub use_nan ($) { |
|
637
|
0
|
|
|
0
|
|
0
|
my $type = shift; |
|
638
|
|
|
|
|
|
|
|
|
639
|
0
|
|
|
|
|
0
|
$type =~ s/^PDLA_//; |
|
640
|
0
|
|
|
|
|
0
|
$type = lc $type; |
|
641
|
|
|
|
|
|
|
die "ERROR: Unknown type [$type] used in a 'Bad' macro." |
|
642
|
0
|
0
|
|
|
|
0
|
unless exists $use_nan{$type}; |
|
643
|
0
|
|
|
|
|
0
|
return $use_nan{$type}; |
|
644
|
|
|
|
|
|
|
} |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
sub convert ($$$$$) { |
|
647
|
0
|
|
|
0
|
|
0
|
my ( $parent, $name, $lhs, $rhs, $opcode ) = @_; |
|
648
|
|
|
|
|
|
|
|
|
649
|
0
|
|
|
|
|
0
|
my $type = $parent->{Gencurtype}[-1]; |
|
650
|
0
|
0
|
|
|
|
0
|
die "ERROR: unable to find type info for $opcode access" |
|
651
|
|
|
|
|
|
|
unless defined $type; |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
# note: gentype may not be sensible because the |
|
654
|
|
|
|
|
|
|
# actual piddle could have a 'fixed' type |
|
655
|
|
|
|
|
|
|
die "ERROR: unable to find piddle $name in parent!" |
|
656
|
0
|
0
|
|
|
|
0
|
unless exists $parent->{ParObjs}{$name}; |
|
657
|
0
|
|
|
|
|
0
|
my $pobj = $parent->{ParObjs}{$name}; |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
# based on code from from PdlParObj::ctype() |
|
660
|
|
|
|
|
|
|
# - want to handle FlagTplus case |
|
661
|
|
|
|
|
|
|
# - may not be correct |
|
662
|
|
|
|
|
|
|
# - extended to include hack to GenericLoop |
|
663
|
|
|
|
|
|
|
# |
|
664
|
0
|
0
|
0
|
|
|
0
|
if ( exists $parent->{pars}{$name} ) { |
|
|
|
0
|
|
|
|
|
|
|
665
|
0
|
|
|
|
|
0
|
$type = $parent->{pars}{$name}; |
|
666
|
0
|
0
|
|
|
|
0
|
print "#DBG: hacked <$name> to type <$type>\n" if $::PP_VERBOSE; |
|
667
|
|
|
|
|
|
|
} elsif ( exists $pobj->{FlagTyped} and $pobj->{FlagTyped} ) { |
|
668
|
0
|
|
|
|
|
0
|
$type = $pobj->{Type}; |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
# this should use Dev.pm - fortunately only worried about double/float here |
|
671
|
|
|
|
|
|
|
# XXX - do I really know what I'm doing ? |
|
672
|
0
|
0
|
|
|
|
0
|
if ( $pobj->{FlagTplus} ) { |
|
673
|
0
|
|
|
|
|
0
|
my $gtype = $parent->{Gencurtype}[-1]; |
|
674
|
0
|
0
|
|
|
|
0
|
if ( $gtype eq "PDLA_Double" ) { |
|
|
|
0
|
|
|
|
|
|
|
675
|
0
|
0
|
|
|
|
0
|
$type = $gtype if $type ne "double"; |
|
676
|
|
|
|
|
|
|
} elsif ( $gtype eq "PDLA_Float" ) { |
|
677
|
0
|
0
|
|
|
|
0
|
$type = $gtype if $type !~ /^(float|double)$/; # note: ignore doubles |
|
678
|
|
|
|
|
|
|
} |
|
679
|
|
|
|
|
|
|
} |
|
680
|
|
|
|
|
|
|
} |
|
681
|
|
|
|
|
|
|
|
|
682
|
0
|
0
|
|
|
|
0
|
if ( use_nan($type) ) { |
|
683
|
0
|
0
|
|
|
|
0
|
if ( $opcode eq "SETBAD" ) { |
|
684
|
|
|
|
|
|
|
# $rhs = "(0.0/0.0)"; |
|
685
|
0
|
|
|
|
|
0
|
$rhs = $set_nan{$type}; |
|
686
|
|
|
|
|
|
|
} else { |
|
687
|
0
|
|
|
|
|
0
|
$rhs = "0"; |
|
688
|
0
|
|
|
|
|
0
|
$lhs = "finite($lhs)"; |
|
689
|
|
|
|
|
|
|
} |
|
690
|
|
|
|
|
|
|
} |
|
691
|
|
|
|
|
|
|
|
|
692
|
0
|
|
|
|
|
0
|
return ( $lhs, $rhs ); |
|
693
|
|
|
|
|
|
|
} |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
########################### |
|
696
|
|
|
|
|
|
|
# |
|
697
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad |
|
698
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
|
699
|
|
|
|
|
|
|
# |
|
700
|
|
|
|
|
|
|
# Integer types (BSUL) + floating point when no NaN (FD) |
|
701
|
|
|
|
|
|
|
# $ISBAD($a(n)) -> $a(n) == a_badval |
|
702
|
|
|
|
|
|
|
# $ISGOOD($a()) $a() != a_badval |
|
703
|
|
|
|
|
|
|
# $SETBAD($a()) $a() = a_badval |
|
704
|
|
|
|
|
|
|
# |
|
705
|
|
|
|
|
|
|
# floating point with NaN |
|
706
|
|
|
|
|
|
|
# $ISBAD($a(n)) -> finite($a(n)) == 0 |
|
707
|
|
|
|
|
|
|
# $ISGOOD($a()) finite($a()) != 0 |
|
708
|
|
|
|
|
|
|
# $SETBAD($a()) $a() = PDLA->bvals.Float (or .Double) |
|
709
|
|
|
|
|
|
|
# |
|
710
|
|
|
|
|
|
|
# I've also got it so that the $ on the pdl name is not |
|
711
|
|
|
|
|
|
|
# necessary - so $ISBAD(a(n)) is also accepted, so as to reduce the |
|
712
|
|
|
|
|
|
|
# amount of line noise. This is actually done by the regexp |
|
713
|
|
|
|
|
|
|
# in the separate_code() sub at the end of the file. |
|
714
|
|
|
|
|
|
|
# |
|
715
|
|
|
|
|
|
|
# note: |
|
716
|
|
|
|
|
|
|
# we also expand out $a(n) etc as well here |
|
717
|
|
|
|
|
|
|
# |
|
718
|
|
|
|
|
|
|
# To do: |
|
719
|
|
|
|
|
|
|
# need to allow use of F,D without NaN |
|
720
|
|
|
|
|
|
|
# |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
package PDLA::PP::BadAccess; |
|
723
|
2
|
|
|
2
|
|
11
|
use Carp; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
790
|
|
|
724
|
|
|
|
|
|
|
our @CARP_NOT; |
|
725
|
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
sub new { |
|
727
|
0
|
|
|
0
|
|
0
|
my ( $type, $opcode, $pdl_name, $inds, $parent ) = @_; |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
|
730
|
0
|
|
|
|
|
0
|
my $check = $parent->{ParObjs}; |
|
731
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$${opcode}() macro on an\n" . |
|
732
|
|
|
|
|
|
|
" unknown piddle <$pdl_name($inds)>\n" |
|
733
|
0
|
0
|
0
|
|
|
0
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
|
734
|
|
|
|
|
|
|
|
|
735
|
0
|
|
|
|
|
0
|
return bless [$opcode, $pdl_name, $inds], $type; |
|
736
|
|
|
|
|
|
|
} |
|
737
|
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
|
739
|
|
|
|
|
|
|
|
|
740
|
|
|
|
|
|
|
sub get_str { |
|
741
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context) = @_; |
|
742
|
|
|
|
|
|
|
|
|
743
|
0
|
|
|
|
|
0
|
my $opcode = $this->[0]; |
|
744
|
0
|
|
|
|
|
0
|
my $name = $this->[1]; |
|
745
|
0
|
|
|
|
|
0
|
my $inds = $this->[2]; |
|
746
|
|
|
|
|
|
|
|
|
747
|
0
|
0
|
|
|
|
0
|
print "PDLA::PP::BadAccess sent [$opcode] [$name] [$inds]\n" if $::PP_VERBOSE; |
|
748
|
|
|
|
|
|
|
|
|
749
|
0
|
|
|
|
|
0
|
my $op = $ops{$opcode}; |
|
750
|
0
|
0
|
|
|
|
0
|
die "ERROR: unknown check <$opcode> sent to PDLA::PP::BadAccess\n" |
|
751
|
|
|
|
|
|
|
unless defined $op; |
|
752
|
|
|
|
|
|
|
|
|
753
|
0
|
|
|
|
|
0
|
my $obj = $parent->{ParObjs}{$name}; |
|
754
|
0
|
0
|
|
|
|
0
|
die "ERROR: something screwy in PDLA::PP::BadAccess (PP/PDLACode.pm)\n" |
|
755
|
|
|
|
|
|
|
unless defined( $obj ); |
|
756
|
|
|
|
|
|
|
|
|
757
|
0
|
|
|
|
|
0
|
my $lhs = $obj->do_access($inds,$context); |
|
758
|
0
|
|
|
|
|
0
|
my $rhs = "${name}_badval"; |
|
759
|
|
|
|
|
|
|
|
|
760
|
0
|
|
|
|
|
0
|
( $lhs, $rhs ) = |
|
761
|
|
|
|
|
|
|
PDLA::PP::NaNSupport::convert( $parent, $name, $lhs, $rhs, $opcode ); |
|
762
|
|
|
|
|
|
|
|
|
763
|
0
|
0
|
|
|
|
0
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
|
764
|
0
|
|
|
|
|
0
|
return "$lhs $op $rhs"; |
|
765
|
|
|
|
|
|
|
} |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
########################### |
|
769
|
|
|
|
|
|
|
# |
|
770
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad |
|
771
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
|
772
|
|
|
|
|
|
|
# |
|
773
|
|
|
|
|
|
|
# Integer types (BSUL) + floating point when no NaN (FD) |
|
774
|
|
|
|
|
|
|
# $ISBADVAR(foo,a) -> foo == a_badval |
|
775
|
|
|
|
|
|
|
# $ISGOODVAR(foo,a) foo != a_badval |
|
776
|
|
|
|
|
|
|
# $SETBADVAR(foo,a) foo = a_badval |
|
777
|
|
|
|
|
|
|
# |
|
778
|
|
|
|
|
|
|
# floating point with NaN |
|
779
|
|
|
|
|
|
|
# $ISBADVAR(foo,a) -> finite(foo) == 0 |
|
780
|
|
|
|
|
|
|
# $ISGOODVAR(foo,a) finite(foo) != 0 |
|
781
|
|
|
|
|
|
|
# $SETBADVAR(foo,a) foo = PDLA->bvals.Float (or .Double) |
|
782
|
|
|
|
|
|
|
# |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
package PDLA::PP::BadVarAccess; |
|
785
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
809
|
|
|
786
|
|
|
|
|
|
|
our @CARP_NOT; |
|
787
|
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
sub new { |
|
789
|
0
|
|
|
0
|
|
0
|
my ( $type, $opcode, $var_name, $pdl_name, $parent ) = @_; |
|
790
|
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
|
792
|
0
|
|
|
|
|
0
|
my $check = $parent->{ParObjs}; |
|
793
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$${opcode}() macro on an\n" . |
|
794
|
|
|
|
|
|
|
" unknown piddle <$pdl_name>\n" |
|
795
|
0
|
0
|
0
|
|
|
0
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
|
796
|
|
|
|
|
|
|
|
|
797
|
0
|
|
|
|
|
0
|
bless [$opcode, $var_name, $pdl_name], $type; |
|
798
|
|
|
|
|
|
|
} |
|
799
|
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
sub get_str { |
|
803
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context) = @_; |
|
804
|
|
|
|
|
|
|
|
|
805
|
0
|
|
|
|
|
0
|
my $opcode = $this->[0]; |
|
806
|
0
|
|
|
|
|
0
|
my $var_name = $this->[1]; |
|
807
|
0
|
|
|
|
|
0
|
my $pdl_name = $this->[2]; |
|
808
|
|
|
|
|
|
|
|
|
809
|
0
|
0
|
|
|
|
0
|
print "PDLA::PP::BadVarAccess sent [$opcode] [$var_name] [$pdl_name]\n" if $::PP_VERBOSE; |
|
810
|
|
|
|
|
|
|
|
|
811
|
0
|
|
|
|
|
0
|
my $op = $ops{$opcode}; |
|
812
|
0
|
0
|
|
|
|
0
|
die "ERROR: unknown check <$opcode> sent to PDLA::PP::BadVarAccess\n" |
|
813
|
|
|
|
|
|
|
unless defined $op; |
|
814
|
|
|
|
|
|
|
|
|
815
|
0
|
|
|
|
|
0
|
my $obj = $parent->{ParObjs}{$pdl_name}; |
|
816
|
0
|
0
|
|
|
|
0
|
die "ERROR: something screwy in PDLA::PP::BadVarAccess (PP/PDLACode.pm)\n" |
|
817
|
|
|
|
|
|
|
unless defined( $obj ); |
|
818
|
|
|
|
|
|
|
|
|
819
|
0
|
|
|
|
|
0
|
my $lhs = $var_name; |
|
820
|
0
|
|
|
|
|
0
|
my $rhs = "${pdl_name}_badval"; |
|
821
|
|
|
|
|
|
|
|
|
822
|
0
|
|
|
|
|
0
|
( $lhs, $rhs ) = |
|
823
|
|
|
|
|
|
|
PDLA::PP::NaNSupport::convert( $parent, $pdl_name, $lhs, $rhs, $opcode ); |
|
824
|
|
|
|
|
|
|
|
|
825
|
0
|
0
|
|
|
|
0
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
|
826
|
0
|
|
|
|
|
0
|
return "$lhs $op $rhs"; |
|
827
|
|
|
|
|
|
|
} |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
########################### |
|
831
|
|
|
|
|
|
|
# |
|
832
|
|
|
|
|
|
|
# Encapsulate a check on whether a value is good or bad using PP |
|
833
|
|
|
|
|
|
|
# handles both checking (good/bad) and setting (bad) |
|
834
|
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
# this is only an initial attempt - it will, almost certainly, |
|
836
|
|
|
|
|
|
|
# need more work as more code is converted to handle bad values |
|
837
|
|
|
|
|
|
|
# |
|
838
|
|
|
|
|
|
|
# currently it can only handle cases like |
|
839
|
|
|
|
|
|
|
# $PPISBAD(PARENT,[i]) -> PARENT_physdatap[i] == PARENT_badval |
|
840
|
|
|
|
|
|
|
# etc |
|
841
|
|
|
|
|
|
|
# |
|
842
|
|
|
|
|
|
|
# if we use NaN's, then |
|
843
|
|
|
|
|
|
|
# $PPISBAD(PARENT,[i]) -> finite(PARENT_physdatap[i]) == 0 |
|
844
|
|
|
|
|
|
|
# $PPISGOOD(PARENT,[i]) -> finite(PARENT_physdatap[i]) != 0 |
|
845
|
|
|
|
|
|
|
# $PPSETBAD(PARENT,[i]) -> PARENT_physdatap[i] = PDLA->bvals.Float (or .Double) |
|
846
|
|
|
|
|
|
|
# |
|
847
|
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
package PDLA::PP::PPBadAccess; |
|
849
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
703
|
|
|
850
|
|
|
|
|
|
|
our @CARP_NOT; |
|
851
|
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
sub new { |
|
853
|
0
|
|
|
0
|
|
0
|
my ( $type, $opcode, $pdl_name, $inds, $parent ) = @_; |
|
854
|
|
|
|
|
|
|
|
|
855
|
0
|
|
|
|
|
0
|
$opcode =~ s/^PP//; |
|
856
|
0
|
|
|
|
|
0
|
bless [$opcode, $pdl_name, $inds], $type; |
|
857
|
|
|
|
|
|
|
} |
|
858
|
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
# PP is stripped in new() |
|
860
|
|
|
|
|
|
|
our %ops = ( ISBAD => '==', ISGOOD => '!=', SETBAD => '=' ); |
|
861
|
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
sub get_str { |
|
863
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context) = @_; |
|
864
|
|
|
|
|
|
|
|
|
865
|
0
|
|
|
|
|
0
|
my $opcode = $this->[0]; |
|
866
|
0
|
|
|
|
|
0
|
my $name = $this->[1]; |
|
867
|
0
|
|
|
|
|
0
|
my $inds = $this->[2]; |
|
868
|
|
|
|
|
|
|
|
|
869
|
0
|
0
|
|
|
|
0
|
print "PDLA::PP::PPBadAccess sent [$opcode] [$name] [$inds]\n" if $::PP_VERBOSE; |
|
870
|
|
|
|
|
|
|
|
|
871
|
0
|
|
|
|
|
0
|
my $op = $ops{$opcode}; |
|
872
|
0
|
0
|
|
|
|
0
|
die "\nERROR: unknown check <$opcode> sent to PDLA::PP::PPBadAccess\n" |
|
873
|
|
|
|
|
|
|
unless defined $op; |
|
874
|
|
|
|
|
|
|
|
|
875
|
0
|
|
|
|
|
0
|
my $obj = $parent->{ParObjs}{$name}; |
|
876
|
0
|
0
|
|
|
|
0
|
die "\nERROR: ParObjs does not seem to exist for <$name> = problem in PDLA::PP::PPBadAccess\n" |
|
877
|
|
|
|
|
|
|
unless defined $obj; |
|
878
|
|
|
|
|
|
|
|
|
879
|
0
|
|
|
|
|
0
|
my $lhs = $obj->do_physpointeraccess() . "$inds"; |
|
880
|
0
|
|
|
|
|
0
|
my $rhs = "${name}_badval"; |
|
881
|
|
|
|
|
|
|
|
|
882
|
0
|
|
|
|
|
0
|
( $lhs, $rhs ) = |
|
883
|
|
|
|
|
|
|
PDLA::PP::NaNSupport::convert( $parent, $name, $lhs, $rhs, $opcode ); |
|
884
|
|
|
|
|
|
|
|
|
885
|
0
|
0
|
|
|
|
0
|
print "DBG: [$lhs $op $rhs]\n" if $::PP_VERBOSE; |
|
886
|
0
|
|
|
|
|
0
|
return "$lhs $op $rhs"; |
|
887
|
|
|
|
|
|
|
} |
|
888
|
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
########################### |
|
891
|
|
|
|
|
|
|
# |
|
892
|
|
|
|
|
|
|
# Encapsulate a check on whether the state flag of a piddle |
|
893
|
|
|
|
|
|
|
# is set/change this state |
|
894
|
|
|
|
|
|
|
# |
|
895
|
|
|
|
|
|
|
# $PDLASTATEISBAD(a) -> ($PDLA(a)->state & PDLA_BADVAL) > 0 |
|
896
|
|
|
|
|
|
|
# $PDLASTATEISGOOD(a) -> ($PDLA(a)->state & PDLA_BADVAL) == 0 |
|
897
|
|
|
|
|
|
|
# |
|
898
|
|
|
|
|
|
|
# $PDLASTATESETBAD(a) -> ($PDLA(a)->state |= PDLA_BADVAL) |
|
899
|
|
|
|
|
|
|
# $PDLASTATESETGOOD(a) -> ($PDLA(a)->state &= ~PDLA_BADVAL) |
|
900
|
|
|
|
|
|
|
# |
|
901
|
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
package PDLA::PP::PDLAStateBadAccess; |
|
903
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
741
|
|
|
904
|
|
|
|
|
|
|
our @CARP_NOT; |
|
905
|
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub new { |
|
907
|
0
|
|
|
0
|
|
0
|
my ( $type, $op, $val, $pdl_name, $parent ) = @_; |
|
908
|
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
# $op is one of: IS SET |
|
910
|
|
|
|
|
|
|
# $val is one of: GOOD BAD |
|
911
|
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
# trying to avoid auto creation of hash elements |
|
913
|
0
|
|
|
|
|
0
|
my $check = $parent->{ParObjs}; |
|
914
|
|
|
|
|
|
|
die "\nIt looks like you have tried a \$PDLASTATE${op}${val}() macro on an\n" . |
|
915
|
|
|
|
|
|
|
" unknown piddle <$pdl_name>\n" |
|
916
|
0
|
0
|
0
|
|
|
0
|
unless exists($check->{$pdl_name}) and defined($check->{$pdl_name}); |
|
917
|
|
|
|
|
|
|
|
|
918
|
0
|
|
|
|
|
0
|
bless [$op, $val, $pdl_name], $type; |
|
919
|
|
|
|
|
|
|
} |
|
920
|
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
our %ops = ( |
|
922
|
|
|
|
|
|
|
IS => { GOOD => '== 0', BAD => '> 0' }, |
|
923
|
|
|
|
|
|
|
SET => { GOOD => '&= ~', BAD => '|= ' }, |
|
924
|
|
|
|
|
|
|
); |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
sub get_str { |
|
927
|
0
|
|
|
0
|
|
0
|
my($this,$parent,$context) = @_; |
|
928
|
|
|
|
|
|
|
|
|
929
|
0
|
|
|
|
|
0
|
my $op = $this->[0]; |
|
930
|
0
|
|
|
|
|
0
|
my $val = $this->[1]; |
|
931
|
0
|
|
|
|
|
0
|
my $name = $this->[2]; |
|
932
|
|
|
|
|
|
|
|
|
933
|
0
|
0
|
|
|
|
0
|
print "PDLA::PP::PDLAStateBadAccess sent [$op] [$val] [$name]\n" if $::PP_VERBOSE; |
|
934
|
|
|
|
|
|
|
|
|
935
|
0
|
|
|
|
|
0
|
my $opcode = $ops{$op}{$val}; |
|
936
|
0
|
|
|
|
|
0
|
my $type = $op . $val; |
|
937
|
0
|
0
|
|
|
|
0
|
die "ERROR: unknown check <$type> sent to PDLA::PP::PDLAStateBadAccess\n" |
|
938
|
|
|
|
|
|
|
unless defined $opcode; |
|
939
|
|
|
|
|
|
|
|
|
940
|
0
|
|
|
|
|
0
|
my $obj = $parent->{ParObjs}{$name}; |
|
941
|
0
|
0
|
|
|
|
0
|
die "\nERROR: ParObjs does not seem to exist for <$name> = problem in PDLA::PP::PDLAStateBadAccess\n" |
|
942
|
|
|
|
|
|
|
unless defined $obj; |
|
943
|
|
|
|
|
|
|
|
|
944
|
0
|
|
|
|
|
0
|
my $state = $obj->do_pdlaccess() . "->state"; |
|
945
|
|
|
|
|
|
|
|
|
946
|
0
|
|
|
|
|
0
|
my $str; |
|
947
|
0
|
0
|
|
|
|
0
|
if ( $op eq 'IS' ) { |
|
|
|
0
|
|
|
|
|
|
|
948
|
0
|
|
|
|
|
0
|
$str = "($state & PDLA_BADVAL) $opcode"; |
|
949
|
|
|
|
|
|
|
} elsif ( $op eq 'SET' ) { |
|
950
|
0
|
|
|
|
|
0
|
$str = "$state ${opcode}PDLA_BADVAL"; |
|
951
|
|
|
|
|
|
|
} |
|
952
|
|
|
|
|
|
|
|
|
953
|
0
|
0
|
|
|
|
0
|
print "DBG: [$str]\n" if $::PP_VERBOSE; |
|
954
|
0
|
|
|
|
|
0
|
return $str; |
|
955
|
|
|
|
|
|
|
} |
|
956
|
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
########################### |
|
959
|
|
|
|
|
|
|
# |
|
960
|
|
|
|
|
|
|
# Encapsulate a Pointeraccess |
|
961
|
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
package PDLA::PP::PointerAccess; |
|
963
|
2
|
|
|
2
|
|
10
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
405
|
|
|
964
|
|
|
|
|
|
|
our @CARP_NOT; |
|
965
|
|
|
|
|
|
|
|
|
966
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
967
|
|
|
|
|
|
|
|
|
968
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
969
|
|
|
|
|
|
|
croak ("can't access undefined pdl ".$this->[0]) |
|
970
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{ParObjs}{$this->[0]}); |
|
971
|
|
|
|
|
|
|
# $parent->{ParObjs}{$this->[0]}->{FlagPaccess} = 1; |
|
972
|
0
|
|
|
|
|
0
|
$parent->{ParObjs}{$this->[0]}->{FlagPhys} = 1; |
|
973
|
0
|
|
|
|
|
0
|
$parent->{ParObjs}{$this->[0]}->do_pointeraccess(); |
|
974
|
|
|
|
|
|
|
} |
|
975
|
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
########################### |
|
978
|
|
|
|
|
|
|
# |
|
979
|
|
|
|
|
|
|
# Encapsulate a PhysPointeraccess |
|
980
|
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
package PDLA::PP::PhysPointerAccess; |
|
982
|
2
|
|
|
2
|
|
14
|
use Carp; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
277
|
|
|
983
|
|
|
|
|
|
|
our @CARP_NOT; |
|
984
|
|
|
|
|
|
|
|
|
985
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
986
|
|
|
|
|
|
|
|
|
987
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
988
|
|
|
|
|
|
|
$parent->{ParObjs}{$this->[0]}->do_physpointeraccess() |
|
989
|
0
|
0
|
|
|
|
0
|
if defined($parent->{ParObjs}{$this->[0]}); |
|
990
|
|
|
|
|
|
|
} |
|
991
|
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
########################### |
|
993
|
|
|
|
|
|
|
# |
|
994
|
|
|
|
|
|
|
# Encapsulate a PDLAaccess |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
package PDLA::PP::PdlAccess; |
|
997
|
2
|
|
|
2
|
|
8
|
use Carp; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
312
|
|
|
998
|
|
|
|
|
|
|
our @CARP_NOT; |
|
999
|
|
|
|
|
|
|
|
|
1000
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
1001
|
|
|
|
|
|
|
|
|
1002
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
1003
|
|
|
|
|
|
|
croak ("can't access undefined pdl ".$this->[0]) |
|
1004
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{ParObjs}{$this->[0]}); |
|
1005
|
0
|
|
|
|
|
0
|
$parent->{ParObjs}{$this->[0]}->do_pdlaccess(); |
|
1006
|
|
|
|
|
|
|
} |
|
1007
|
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
########################### |
|
1009
|
|
|
|
|
|
|
# |
|
1010
|
|
|
|
|
|
|
# Encapsulate a macroaccess |
|
1011
|
|
|
|
|
|
|
|
|
1012
|
|
|
|
|
|
|
package PDLA::PP::MacroAccess; |
|
1013
|
2
|
|
|
2
|
|
8
|
use Carp; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
93
|
|
|
1014
|
2
|
|
|
2
|
|
14
|
use PDLA::Types ':All'; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
1292
|
|
|
1015
|
|
|
|
|
|
|
my $types = join '',ppdefs; |
|
1016
|
|
|
|
|
|
|
our @CARP_NOT; |
|
1017
|
|
|
|
|
|
|
|
|
1018
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds,$gentypes,$name) = @_; |
|
1019
|
0
|
0
|
|
|
|
0
|
$pdl =~ /^\s*T([A-Z]+)\s*$/ or confess("Macroaccess wrong: $pdl\n"); |
|
1020
|
0
|
|
|
|
|
0
|
my @ilst = split '',$1; |
|
1021
|
0
|
|
|
|
|
0
|
for my $gt (@$gentypes) { |
|
1022
|
|
|
|
|
|
|
warn "$name has no Macro for generic type $gt (has $pdl)\n" |
|
1023
|
0
|
0
|
|
|
|
0
|
unless grep {$gt eq $_} @ilst } |
|
|
0
|
|
|
|
|
0
|
|
|
1024
|
0
|
|
|
|
|
0
|
for my $mtype (@ilst) { |
|
1025
|
|
|
|
|
|
|
warn "Macro for unsupported generic type identifier $mtype". |
|
1026
|
|
|
|
|
|
|
" (probably harmless)\n" |
|
1027
|
0
|
0
|
|
|
|
0
|
unless grep {$mtype eq $_} @$gentypes; |
|
|
0
|
|
|
|
|
0
|
|
|
1028
|
|
|
|
|
|
|
} |
|
1029
|
0
|
|
|
|
|
0
|
return bless [$pdl,$inds,$name], |
|
1030
|
|
|
|
|
|
|
$type; } |
|
1031
|
|
|
|
|
|
|
|
|
1032
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
1033
|
0
|
|
|
|
|
0
|
my ($pdl,$inds,$name) = @{$this}; |
|
|
0
|
|
|
|
|
0
|
|
|
1034
|
0
|
0
|
|
|
|
0
|
$pdl =~ /^\s*T([A-Z]+)\s*$/ |
|
1035
|
|
|
|
|
|
|
or confess("Macroaccess wrong in $name (allowed types $types): was '$pdl'\n"); |
|
1036
|
0
|
|
|
|
|
0
|
my @lst = split ',',$inds; |
|
1037
|
0
|
|
|
|
|
0
|
my @ilst = split '',$1; |
|
1038
|
0
|
0
|
|
|
|
0
|
if($#lst != $#ilst) {confess("Macroaccess: different nos of args $pdl $inds\n");} |
|
|
0
|
|
|
|
|
0
|
|
|
1039
|
|
|
|
|
|
|
croak "generic type access outside a generic loop in $name" |
|
1040
|
0
|
0
|
|
|
|
0
|
unless defined $parent->{Gencurtype}->[-1]; |
|
1041
|
0
|
|
|
|
|
0
|
my $type = mapfld $parent->{Gencurtype}->[-1], 'ctype' => 'ppsym'; |
|
1042
|
|
|
|
|
|
|
# print "Type access: $type\n"; |
|
1043
|
0
|
0
|
|
|
|
0
|
croak "unknown Type in $name (generic type currently $parent->{Gencurtype}->[-1]" |
|
1044
|
|
|
|
|
|
|
unless defined $type; |
|
1045
|
0
|
|
|
|
|
0
|
for (0..$#lst) { |
|
1046
|
0
|
0
|
|
|
|
0
|
return "$lst[$_]" if $ilst[$_] =~ /$type/; |
|
1047
|
|
|
|
|
|
|
} |
|
1048
|
|
|
|
|
|
|
} |
|
1049
|
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
########################### |
|
1052
|
|
|
|
|
|
|
# |
|
1053
|
|
|
|
|
|
|
# Encapsulate a SizeAccess |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
package PDLA::PP::SizeAccess; |
|
1056
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
347
|
|
|
1057
|
|
|
|
|
|
|
our @CARP_NOT; |
|
1058
|
|
|
|
|
|
|
|
|
1059
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
1060
|
|
|
|
|
|
|
|
|
1061
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
1062
|
|
|
|
|
|
|
croak "can't get SIZE of undefined dimension $this->[0]" |
|
1063
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{IndObjs}{$this->[0]}); |
|
1064
|
0
|
|
|
|
|
0
|
$parent->{IndObjs}{$this->[0]}->get_size(); |
|
1065
|
|
|
|
|
|
|
} |
|
1066
|
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
########################### |
|
1068
|
|
|
|
|
|
|
# |
|
1069
|
|
|
|
|
|
|
# Encapsulate a ReSizeAccess |
|
1070
|
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
package PDLA::PP::ReSizeAccess; |
|
1072
|
2
|
|
|
2
|
|
9
|
use Carp; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
675
|
|
|
1073
|
|
|
|
|
|
|
our @CARP_NOT; |
|
1074
|
|
|
|
|
|
|
|
|
1075
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
1076
|
|
|
|
|
|
|
|
|
1077
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
1078
|
0
|
0
|
|
|
|
0
|
$this->[0] =~ /^([^,]+),([^,]+)$/ or |
|
1079
|
|
|
|
|
|
|
croak "Can't interpret resize str $this->[0]"; |
|
1080
|
|
|
|
|
|
|
croak "can't RESIZE undefined dimension $1" |
|
1081
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{IndObjs}{$1}); |
|
1082
|
|
|
|
|
|
|
|
|
1083
|
0
|
|
|
|
|
0
|
my $s = $parent->{IndObjs}{$1}->get_size(); |
|
1084
|
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
# XXX NOTE: All piddles must be output piddles, there must not be |
|
1086
|
|
|
|
|
|
|
# a loop over this var (at all!) etc. Should check for these, |
|
1087
|
|
|
|
|
|
|
# this is why not yet documented. |
|
1088
|
|
|
|
|
|
|
# FURTHER NOTE: RESIZE DOESN'T COPY DATA PROPERLY! |
|
1089
|
|
|
|
|
|
|
|
|
1090
|
0
|
|
|
|
|
0
|
my($ord,$pdls) = $parent->get_pdls(); |
|
1091
|
0
|
|
|
|
|
0
|
my @p; |
|
1092
|
|
|
|
|
|
|
|
|
1093
|
0
|
|
|
|
|
0
|
for(@$ord) { |
|
1094
|
|
|
|
|
|
|
push @p, $_ |
|
1095
|
0
|
0
|
|
|
|
0
|
if $pdls->{$_}->has_dim($1); |
|
1096
|
|
|
|
|
|
|
} |
|
1097
|
0
|
|
|
|
|
0
|
print "RESIZEACC: $1 $2, (",(join ',',@p),")\n"; |
|
1098
|
0
|
|
|
|
|
0
|
warn "RESIZE USED: DO YOU KNOW WHAT YOU ARE DOING???\n"; |
|
1099
|
|
|
|
|
|
|
|
|
1100
|
0
|
|
|
|
|
0
|
return "$s = $2; ".(join '',map {$pdls->{$_}->do_resize($1,$2)} @p); |
|
|
0
|
|
|
|
|
0
|
|
|
1101
|
|
|
|
|
|
|
} |
|
1102
|
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
########################### |
|
1105
|
|
|
|
|
|
|
# |
|
1106
|
|
|
|
|
|
|
# Encapsulate a GentypeAccess |
|
1107
|
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
package PDLA::PP::GentypeAccess; |
|
1109
|
2
|
|
|
2
|
|
96
|
use Carp; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
408
|
|
|
1110
|
|
|
|
|
|
|
our @CARP_NOT; |
|
1111
|
|
|
|
|
|
|
|
|
1112
|
0
|
|
|
0
|
|
0
|
sub new { my($type,$pdl,$inds) = @_; bless [$inds],$type; } |
|
|
0
|
|
|
|
|
0
|
|
|
1113
|
|
|
|
|
|
|
|
|
1114
|
0
|
|
|
0
|
|
0
|
sub get_str {my($this,$parent,$context) = @_; |
|
1115
|
|
|
|
|
|
|
croak "generic type access outside a generic loop" |
|
1116
|
0
|
0
|
|
|
|
0
|
unless defined $parent->{Gencurtype}->[-1]; |
|
1117
|
0
|
|
|
|
|
0
|
my $type = $parent->{Gencurtype}->[-1]; |
|
1118
|
0
|
0
|
|
|
|
0
|
if ($this->[0]) { |
|
1119
|
|
|
|
|
|
|
croak "not a defined name" |
|
1120
|
0
|
0
|
|
|
|
0
|
unless defined($parent->{ParObjs}{$this->[0]}); |
|
1121
|
0
|
|
|
|
|
0
|
$type = $parent->{ParObjs}{$this->[0]}->ctype($type); |
|
1122
|
|
|
|
|
|
|
} |
|
1123
|
0
|
|
|
|
|
0
|
return $type; |
|
1124
|
|
|
|
|
|
|
} |
|
1125
|
|
|
|
|
|
|
|
|
1126
|
|
|
|
|
|
|
######################## |
|
1127
|
|
|
|
|
|
|
# |
|
1128
|
|
|
|
|
|
|
# Type coercion |
|
1129
|
|
|
|
|
|
|
# |
|
1130
|
|
|
|
|
|
|
# Now, if TYPES:F given and double arguments, will coerce. |
|
1131
|
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
package PDLA::PP::TypeConv; |
|
1133
|
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
# make the typetable from info in PDLA::Types |
|
1135
|
2
|
|
|
2
|
|
13
|
use PDLA::Types ':All'; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
934
|
|
|
1136
|
|
|
|
|
|
|
my @typetable = map {[$typehash{$_}->{ppsym}, |
|
1137
|
|
|
|
|
|
|
$typehash{$_}->{ctype}, |
|
1138
|
|
|
|
|
|
|
$typehash{$_}->{numval}, |
|
1139
|
|
|
|
|
|
|
]} typesrtkeys; |
|
1140
|
|
|
|
|
|
|
|
|
1141
|
0
|
|
|
0
|
|
0
|
sub print_xscoerce { my($this) = @_; |
|
1142
|
0
|
|
|
|
|
0
|
$this->printxs("\t__priv->datatype=PDLA_B;\n"); |
|
1143
|
|
|
|
|
|
|
# First, go through all the types, selecting the most general. |
|
1144
|
0
|
|
|
|
|
0
|
for(@{$this->{PdlOrder}}) { |
|
|
0
|
|
|
|
|
0
|
|
|
1145
|
0
|
|
|
|
|
0
|
$this->printxs($this->{Pdls}{$_}->get_xsdatatypetest()); |
|
1146
|
|
|
|
|
|
|
} |
|
1147
|
|
|
|
|
|
|
# See which types we are allowed to use. |
|
1148
|
0
|
|
|
|
|
0
|
$this->printxs("\tif(0) {}\n"); |
|
1149
|
0
|
|
|
|
|
0
|
for(@{$this->get_generictypes()}) { |
|
|
0
|
|
|
|
|
0
|
|
|
1150
|
0
|
|
|
|
|
0
|
$this->printxs("\telse if(__priv->datatype <= $_->[2]) __priv->datatype = $_->[2];\n"); |
|
1151
|
|
|
|
|
|
|
} |
|
1152
|
0
|
0
|
|
|
|
0
|
$this->{Types} =~ /F/ and ( |
|
1153
|
|
|
|
|
|
|
$this->printxs("\telse if(__priv->datatype == PDLA_D) {__priv->datatype = PDLA_F; PDLA_COMMENT(\"Cast double to float\")}\n")); |
|
1154
|
0
|
|
|
|
|
0
|
$this->printxs(qq[\telse {croak("Too high type \%d given!\\n",__priv->datatype);}]); |
|
1155
|
|
|
|
|
|
|
# Then, coerce everything to this type. |
|
1156
|
0
|
|
|
|
|
0
|
for(@{$this->{PdlOrder}}) { |
|
|
0
|
|
|
|
|
0
|
|
|
1157
|
0
|
|
|
|
|
0
|
$this->printxs($this->{Pdls}{$_}->get_xscoerce()); |
|
1158
|
|
|
|
|
|
|
} |
|
1159
|
|
|
|
|
|
|
} |
|
1160
|
|
|
|
|
|
|
# XXX Should use PDLA::Core::Dev; |
|
1161
|
|
|
|
|
|
|
|
|
1162
|
2
|
|
|
2
|
|
10
|
no strict 'vars'; |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
2895
|
|
|
1163
|
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
# STATIC! |
|
1165
|
2
|
|
|
2
|
0
|
4
|
sub PDLA::PP::get_generictyperecs { my($types) = @_; |
|
1166
|
2
|
|
|
|
|
2
|
my $foo; |
|
1167
|
2
|
|
|
|
|
4
|
return [map {$foo = $_; |
|
|
18
|
|
|
|
|
20
|
|
|
1168
|
18
|
100
|
|
|
|
24
|
( grep {/$foo->[0]/} (@$types) ) ? |
|
|
36
|
|
|
|
|
197
|
|
|
1169
|
|
|
|
|
|
|
[mapfld($_->[0],'ppsym'=>'sym'),$_->[1],$_->[2],$_->[0]] |
|
1170
|
|
|
|
|
|
|
: () |
|
1171
|
|
|
|
|
|
|
} |
|
1172
|
|
|
|
|
|
|
@typetable]; |
|
1173
|
|
|
|
|
|
|
} |
|
1174
|
|
|
|
|
|
|
|
|
1175
|
0
|
|
|
0
|
|
0
|
sub xxx_get_generictypes { my($this) = @_; |
|
1176
|
|
|
|
|
|
|
return [map { |
|
1177
|
0
|
0
|
|
|
|
0
|
$this->{Types} =~ /$_->[0]/ ? [mapfld($_->[0],'ppsym'=>'sym'),$_->[1],$_->[2],$_->[0]] : () |
|
|
0
|
|
|
|
|
0
|
|
|
1178
|
|
|
|
|
|
|
} |
|
1179
|
|
|
|
|
|
|
@typetable]; |
|
1180
|
|
|
|
|
|
|
} |
|
1181
|
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
|
|
1183
|
|
|
|
|
|
|
package PDLA::PP::Code; |
|
1184
|
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# my ( $threadloops, $coderef, $sizeprivs ) = $this->separate_code( $code ); |
|
1186
|
|
|
|
|
|
|
# |
|
1187
|
|
|
|
|
|
|
# umm, can't call classes defined later on in code ... |
|
1188
|
|
|
|
|
|
|
# hence moved to end of file |
|
1189
|
|
|
|
|
|
|
# (rather ugly...) |
|
1190
|
|
|
|
|
|
|
# |
|
1191
|
|
|
|
|
|
|
# XXX The above statement is almost certainly false. This module is parsed |
|
1192
|
|
|
|
|
|
|
# before separate_code is ever called, so all of the class definitions |
|
1193
|
|
|
|
|
|
|
# should exist. -- David Mertens, Dec 2 2011 |
|
1194
|
|
|
|
|
|
|
# |
|
1195
|
|
|
|
|
|
|
# separates the code into an array of C fragments (strings), |
|
1196
|
|
|
|
|
|
|
# variable references (strings starting with $) and |
|
1197
|
|
|
|
|
|
|
# loops (array references, 1. item = variable. |
|
1198
|
|
|
|
|
|
|
# |
|
1199
|
|
|
|
|
|
|
sub separate_code { |
|
1200
|
|
|
|
|
|
|
## $DB::single=1; |
|
1201
|
3
|
|
|
3
|
|
7
|
my ( $this, $code ) = @_; |
|
1202
|
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
# First check for standard code errors: |
|
1204
|
3
|
|
|
|
|
8
|
catch_code_errors($code); |
|
1205
|
|
|
|
|
|
|
|
|
1206
|
2
|
|
|
|
|
9
|
my $coderef = new PDLA::PP::Block; |
|
1207
|
|
|
|
|
|
|
|
|
1208
|
2
|
|
|
|
|
4
|
my @stack = ($coderef); |
|
1209
|
2
|
|
|
|
|
3
|
my $threadloops = 0; |
|
1210
|
2
|
|
|
|
|
150
|
my $sizeprivs = {}; |
|
1211
|
|
|
|
|
|
|
|
|
1212
|
2
|
|
|
|
|
4
|
local $_ = $code; |
|
1213
|
|
|
|
|
|
|
## print "Code to parse = [$_]\n" if $::PP_VERBOSE; |
|
1214
|
2
|
|
|
|
|
6
|
while($_) { |
|
1215
|
|
|
|
|
|
|
# Parse next statement |
|
1216
|
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
# I'm not convinced that having the checks twice is a good thing, |
|
1218
|
|
|
|
|
|
|
# since it makes it easy (for me at least) to forget to update one |
|
1219
|
|
|
|
|
|
|
# of them |
|
1220
|
|
|
|
|
|
|
|
|
1221
|
8
|
50
|
|
|
|
222
|
s/^(.*?) # First, some noise is allowed. This may be bad. |
|
1222
|
|
|
|
|
|
|
( \$(ISBAD|ISGOOD|SETBAD)\s*\(\s*\$?[a-zA-Z_]\w*\s*\([^)]*\)\s*\) # $ISBAD($a(..)), ditto for ISGOOD and SETBAD |
|
1223
|
|
|
|
|
|
|
|\$PP(ISBAD|ISGOOD|SETBAD)\s*\(\s*[a-zA-Z_]\w*\s*,\s*[^)]*\s*\) # $PPISBAD(CHILD,[1]) etc |
|
1224
|
|
|
|
|
|
|
### |\$STATE(IS|SET)(BAD|GOOD)\s*\(\s*[^)]*\s*\) # $STATEISBAD(a) etc |
|
1225
|
|
|
|
|
|
|
|\$PDLASTATE(IS|SET)(BAD|GOOD)\s*\(\s*[^)]*\s*\) # $PDLASTATEISBAD(a) etc |
|
1226
|
|
|
|
|
|
|
|\$[a-zA-Z_]\w*\s*\([^)]*\) # $a(...): access |
|
1227
|
|
|
|
|
|
|
|\bloop\s*\([^)]+\)\s*%\{ # loop(..) %{ |
|
1228
|
|
|
|
|
|
|
|\btypes\s*\([^)]+\)\s*%\{ # types(..) %{ |
|
1229
|
|
|
|
|
|
|
|\bthreadloop\s*%\{ # threadloop %{ |
|
1230
|
|
|
|
|
|
|
|%} # %} |
|
1231
|
|
|
|
|
|
|
|$)//xs |
|
1232
|
|
|
|
|
|
|
or confess("Invalid program $_"); |
|
1233
|
8
|
|
|
|
|
18
|
my $control = $2; |
|
1234
|
|
|
|
|
|
|
# Store the user code. |
|
1235
|
|
|
|
|
|
|
# Some day we shall parse everything. |
|
1236
|
8
|
|
|
|
|
8
|
push @{$stack[-1]},$1; |
|
|
8
|
|
|
|
|
25
|
|
|
1237
|
|
|
|
|
|
|
|
|
1238
|
8
|
50
|
|
|
|
19
|
if ( $control =~ /^\$STATE/ ) { print "\nDBG: - got [$control]\n\n"; } |
|
|
0
|
|
|
|
|
0
|
|
|
1239
|
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
# Then, our control. |
|
1241
|
8
|
100
|
|
|
|
14
|
if($control) { |
|
1242
|
6
|
100
|
|
|
|
45
|
if($control =~ /^loop\s*\(([^)]+)\)\s*%\{/) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
1243
|
1
|
|
|
|
|
10
|
my $ob = new PDLA::PP::Loop([split ',',$1], |
|
1244
|
|
|
|
|
|
|
$sizeprivs,$this); |
|
1245
|
1
|
50
|
|
|
|
4
|
print "SIZEPRIVSXX: $sizeprivs,",(join ',',%$sizeprivs),"\n" if $::PP_VERBOSE; |
|
1246
|
1
|
|
|
|
|
2
|
push @{$stack[-1]},$ob; |
|
|
1
|
|
|
|
|
3
|
|
|
1247
|
1
|
|
|
|
|
3
|
push @stack,$ob; |
|
1248
|
|
|
|
|
|
|
} elsif($control =~ /^types\s*\(([^)]+)\)\s*%\{/) { |
|
1249
|
0
|
|
|
|
|
0
|
my $ob = new PDLA::PP::Types($1,$this); |
|
1250
|
0
|
|
|
|
|
0
|
push @{$stack[-1]},$ob; |
|
|
0
|
|
|
|
|
0
|
|
|
1251
|
0
|
|
|
|
|
0
|
push @stack,$ob; |
|
1252
|
|
|
|
|
|
|
} elsif($control =~ /^threadloop\s*%\{/) { |
|
1253
|
1
|
|
|
|
|
7
|
my $ob = new PDLA::PP::ThreadLoop(); |
|
1254
|
1
|
|
|
|
|
1
|
push @{$stack[-1]},$ob; |
|
|
1
|
|
|
|
|
2
|
|
|
1255
|
1
|
|
|
|
|
2
|
push @stack,$ob; |
|
1256
|
1
|
|
|
|
|
3
|
$threadloops ++; |
|
1257
|
|
|
|
|
|
|
} elsif($control =~ /^\$PP(ISBAD|ISGOOD|SETBAD)\s*\(\s*([a-zA-Z_]\w*)\s*,\s*([^)]*)\s*\)/) { |
|
1258
|
0
|
|
|
|
|
0
|
push @{$stack[-1]},new PDLA::PP::PPBadAccess($1,$2,$3,$this); |
|
|
0
|
|
|
|
|
0
|
|
|
1259
|
|
|
|
|
|
|
} elsif($control =~ /^\$(ISBAD|ISGOOD|SETBAD)VAR\s*\(\s*([^)]*)\s*,\s*([^)]*)\s*\)/) { |
|
1260
|
0
|
|
|
|
|
0
|
push @{$stack[-1]},new PDLA::PP::BadVarAccess($1,$2,$3,$this); |
|
|
0
|
|
|
|
|
0
|
|
|
1261
|
|
|
|
|
|
|
} elsif($control =~ /^\$(ISBAD|ISGOOD|SETBAD)\s*\(\s*\$?([a-zA-Z_]\w*)\s*\(([^)]*)\)\s*\)/) { |
|
1262
|
0
|
|
|
|
|
0
|
push @{$stack[-1]},new PDLA::PP::BadAccess($1,$2,$3,$this); |
|
|
0
|
|
|
|
|
0
|
|
|
1263
|
|
|
|
|
|
|
# } elsif($control =~ /^\$STATE(IS|SET)(BAD|GOOD)\s*\(\s*([^)]*)\s*\)/) { |
|
1264
|
|
|
|
|
|
|
# push @{$stack[-1]},new PDLA::PP::StateBadAccess($1,$2,$3,$this); |
|
1265
|
|
|
|
|
|
|
} elsif($control =~ /^\$PDLASTATE(IS|SET)(BAD|GOOD)\s*\(\s*([^)]*)\s*\)/) { |
|
1266
|
0
|
|
|
|
|
0
|
push @{$stack[-1]},new PDLA::PP::PDLAStateBadAccess($1,$2,$3,$this); |
|
|
0
|
|
|
|
|
0
|
|
|
1267
|
|
|
|
|
|
|
} elsif($control =~ /^\$[a-zA-Z_]\w*\s*\([^)]*\)/) { |
|
1268
|
2
|
|
|
|
|
3
|
push @{$stack[-1]},new PDLA::PP::Access($control,$this); |
|
|
2
|
|
|
|
|
10
|
|
|
1269
|
|
|
|
|
|
|
} elsif($control =~ /^%}/) { |
|
1270
|
2
|
|
|
|
|
5
|
pop @stack; |
|
1271
|
|
|
|
|
|
|
} else { |
|
1272
|
0
|
|
|
|
|
0
|
confess("Invalid control: $control\n"); |
|
1273
|
|
|
|
|
|
|
} |
|
1274
|
|
|
|
|
|
|
} else { |
|
1275
|
2
|
50
|
|
|
|
7
|
print("No \$2!\n") if $::PP_VERBOSE; |
|
1276
|
|
|
|
|
|
|
} |
|
1277
|
|
|
|
|
|
|
} # while: $_ |
|
1278
|
|
|
|
|
|
|
|
|
1279
|
2
|
|
|
|
|
16
|
return ( $threadloops, $coderef, $sizeprivs ); |
|
1280
|
|
|
|
|
|
|
|
|
1281
|
|
|
|
|
|
|
} # sub: separate_code() |
|
1282
|
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
# This is essentially a collection of regexes that look for standard code |
|
1284
|
|
|
|
|
|
|
# errors and croaks with an explanation if they are found. |
|
1285
|
|
|
|
|
|
|
sub catch_code_errors { |
|
1286
|
3
|
|
|
3
|
|
6
|
my $code_string = shift; |
|
1287
|
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
# Look for constructs like |
|
1289
|
|
|
|
|
|
|
# loop %{ |
|
1290
|
|
|
|
|
|
|
# which is invalid - you need to specify the dimension over which it |
|
1291
|
|
|
|
|
|
|
# should loop |
|
1292
|
3
|
100
|
|
|
|
38
|
report_error('Expected dimension name after "loop" and before "%{"', $1) |
|
1293
|
|
|
|
|
|
|
if $code_string =~ /(.*\bloop\s*%\{)/s; |
|
1294
|
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
} |
|
1296
|
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
# Report an error as precisely as possible. If they have #line directives |
|
1298
|
|
|
|
|
|
|
# in the code string, use that in the reporting; otherwise, use standard |
|
1299
|
|
|
|
|
|
|
# Carp mechanisms |
|
1300
|
|
|
|
|
|
|
my $line_re = qr/#\s*line\s+(\d+)\s+"([^"]*)"/; |
|
1301
|
|
|
|
|
|
|
sub report_error { |
|
1302
|
1
|
|
|
1
|
|
3
|
my ($message, $code) = @_; |
|
1303
|
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
# Just croak if they didn't supply a #line directive: |
|
1305
|
1
|
50
|
|
|
|
299
|
croak($message) if $code !~ $line_re; |
|
1306
|
|
|
|
|
|
|
|
|
1307
|
|
|
|
|
|
|
# Find the line at which the error occurred: |
|
1308
|
0
|
|
|
|
|
|
my $line = 0; |
|
1309
|
0
|
|
|
|
|
|
my $filename; |
|
1310
|
0
|
|
|
|
|
|
LINE: foreach (split /\n/, $code) { |
|
1311
|
0
|
|
|
|
|
|
$line++; |
|
1312
|
0
|
0
|
|
|
|
|
if (/$line_re/) { |
|
1313
|
0
|
|
|
|
|
|
$line = $1; |
|
1314
|
0
|
|
|
|
|
|
$filename = $2; |
|
1315
|
|
|
|
|
|
|
} |
|
1316
|
|
|
|
|
|
|
} |
|
1317
|
|
|
|
|
|
|
|
|
1318
|
0
|
|
|
|
|
|
die "$message at $filename line $line\n"; |
|
1319
|
|
|
|
|
|
|
} |
|
1320
|
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
# return true |
|
1322
|
|
|
|
|
|
|
1; |