| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Text::NumericData::Calc; |
|
2
|
|
|
|
|
|
|
|
|
3
|
9
|
|
|
9
|
|
2274
|
use Math::Trig; |
|
|
9
|
|
|
|
|
61323
|
|
|
|
9
|
|
|
|
|
13572
|
|
|
4
|
|
|
|
|
|
|
require Exporter; |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
# This is just a placeholder because of a past build system bug. |
|
7
|
|
|
|
|
|
|
# The one and only version for Text::NumericData is kept in |
|
8
|
|
|
|
|
|
|
# the Text::NumericData module itself. |
|
9
|
|
|
|
|
|
|
our $VERSION = '1'; |
|
10
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
13
|
|
|
|
|
|
|
our @EXPORT_OK = qw(linear_value parsed_formula formula_function expression_function); |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $epsilon = 1e-15; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
#a hack for gauss() function to use in formulae |
|
18
|
|
|
|
|
|
|
#not fully verified yet - and not normalized! |
|
19
|
|
|
|
|
|
|
our $cache = undef; |
|
20
|
|
|
|
|
|
|
sub gauss |
|
21
|
|
|
|
|
|
|
{ |
|
22
|
|
|
|
|
|
|
#Polar-Methode |
|
23
|
0
|
|
|
0
|
0
|
0
|
my $x; |
|
24
|
0
|
0
|
|
|
|
0
|
if(defined $cache) |
|
25
|
|
|
|
|
|
|
{ |
|
26
|
0
|
|
|
|
|
0
|
$x = $cache; |
|
27
|
0
|
|
|
|
|
0
|
undef $cache; |
|
28
|
|
|
|
|
|
|
} |
|
29
|
|
|
|
|
|
|
else |
|
30
|
|
|
|
|
|
|
{ |
|
31
|
0
|
|
|
|
|
0
|
my ($u1,$u2,$v); |
|
32
|
|
|
|
|
|
|
do |
|
33
|
0
|
|
|
|
|
0
|
{ |
|
34
|
0
|
|
|
|
|
0
|
$u1 = rand(); |
|
35
|
0
|
|
|
|
|
0
|
$u2 = rand(); |
|
36
|
0
|
|
|
|
|
0
|
$v = (2*$u1-1)**2+(2*$u2-1)**2; |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
while($v >= 1); |
|
39
|
0
|
|
|
|
|
0
|
$cache = (2*$u2-1)*sqrt(-2*log($v)/$v); |
|
40
|
0
|
|
|
|
|
0
|
$x = (2*$u1-1)*sqrt(-2*log($v)/$v); |
|
41
|
|
|
|
|
|
|
} |
|
42
|
0
|
|
|
|
|
0
|
return $x; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# helper for floating point comparisons |
|
46
|
|
|
|
|
|
|
sub near |
|
47
|
|
|
|
|
|
|
{ |
|
48
|
0
|
|
|
0
|
0
|
0
|
my ($a, $b, $eps) = @_; |
|
49
|
0
|
0
|
|
|
|
0
|
$eps = $epsilon unless defined $eps; |
|
50
|
|
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
0
|
return (abs($a-$b) < $eps); |
|
52
|
|
|
|
|
|
|
} |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
#linear_value(x,[x1,x2],[y1,y2]) |
|
56
|
|
|
|
|
|
|
sub linear_value |
|
57
|
|
|
|
|
|
|
{ |
|
58
|
180
|
|
|
180
|
1
|
381
|
my ($x,$ox,$oy) = @_; |
|
59
|
180
|
0
|
|
|
|
1104
|
return $ox->[0] != $ox->[1] ? ( $oy->[0] + ($oy->[1]-$oy->[0])*($x-$ox->[0])/($ox->[1]-$ox->[0]) ) : ( $x == $ox->[0] ? ($oy->[0]+$oy->[1])/2 : undef ); |
|
|
|
50
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
#parsed_formula(text, dataarrayname, pararrayname1, pararrayname2) |
|
63
|
|
|
|
|
|
|
#A -> pararray1 |
|
64
|
|
|
|
|
|
|
#C -> pararray2 |
|
65
|
|
|
|
|
|
|
#[a,b] -> data[a][b] |
|
66
|
|
|
|
|
|
|
#parsed_formula(text, dataarrayname, arraynamedef) |
|
67
|
|
|
|
|
|
|
#arraynamedef: { A=>'A->', B=>'B->', X=>'xarr->', Z=>'zulu->' } |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub parsed_formula |
|
70
|
|
|
|
|
|
|
{ |
|
71
|
19
|
|
|
19
|
1
|
60
|
my ($form, $data, $par1, $par2) = @_; |
|
72
|
19
|
|
|
|
|
29
|
my $ardef; |
|
73
|
19
|
50
|
|
|
|
71
|
if(ref $par1 eq 'HASH') |
|
74
|
|
|
|
|
|
|
{ |
|
75
|
19
|
|
|
|
|
35
|
$ardef = $par1; |
|
76
|
|
|
|
|
|
|
} |
|
77
|
|
|
|
|
|
|
else |
|
78
|
|
|
|
|
|
|
{ |
|
79
|
0
|
|
|
|
|
0
|
$ardef = {A=>$par1, C=>$par2}; |
|
80
|
|
|
|
|
|
|
} |
|
81
|
19
|
|
|
|
|
70
|
my @formlines = split("\n", $form); |
|
82
|
19
|
|
|
|
|
36
|
my $nnf = ''; |
|
83
|
|
|
|
|
|
|
|
|
84
|
19
|
|
|
|
|
55
|
foreach my $formula (@formlines) |
|
85
|
|
|
|
|
|
|
{ |
|
86
|
19
|
|
|
|
|
35
|
my $nf = ''; |
|
87
|
|
|
|
|
|
|
#$ord$ord is not translated correctly but is not correct syntax anyway |
|
88
|
|
|
|
|
|
|
{ # Parse shortcut vars. |
|
89
|
19
|
|
|
|
|
32
|
my %defs = |
|
|
19
|
|
|
|
|
65
|
|
|
90
|
|
|
|
|
|
|
( |
|
91
|
|
|
|
|
|
|
'x', '[0,1]' |
|
92
|
|
|
|
|
|
|
,'y', '[0,2]' |
|
93
|
|
|
|
|
|
|
,'z', '[0,3]' |
|
94
|
|
|
|
|
|
|
); |
|
95
|
|
|
|
|
|
|
#print STDERR "shortcut parsing: $formula\n"; |
|
96
|
19
|
|
|
|
|
306
|
while($formula =~ /^(.*)([^a-zA-Z\$]|^)(\$?([xab]|ord))([^(a-zA-Z]|$)(.*)$/m) |
|
97
|
|
|
|
|
|
|
{ |
|
98
|
|
|
|
|
|
|
#print STDERR "found $4 (def=$defs{$4})\n"; |
|
99
|
0
|
|
|
|
|
0
|
$formula = $1.$2.$defs{$4}.$5.$6; |
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
#print STDERR "done shortcut parsing: $formula\n"; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
# Match any relevant [...] and stuff before it; parse and cut from formula. |
|
104
|
|
|
|
|
|
|
#print STDERR "formula: $formula\n"; |
|
105
|
19
|
|
|
|
|
151
|
while($formula =~ s/\A([^[]*[^[a-zA-Z]|)\[\s*(([^[\],]+)(\s*,\s*([^[\],]+)|)\s*)\s*\]//) |
|
106
|
|
|
|
|
|
|
{ |
|
107
|
|
|
|
|
|
|
#print STDERR "results: $1 : $2 : $3 : $4 : $5\n"; |
|
108
|
|
|
|
|
|
|
#print STDERR "formula: $formula\n"; |
|
109
|
63
|
|
|
|
|
167
|
$nf .= $1; |
|
110
|
63
|
|
|
|
|
125
|
my $num1 = $3; |
|
111
|
63
|
|
|
|
|
106
|
my $num2 = $5; |
|
112
|
63
|
100
|
|
|
|
130
|
unless(defined $num2) |
|
113
|
|
|
|
|
|
|
{ |
|
114
|
53
|
|
|
|
|
83
|
$num2 = $num1; |
|
115
|
53
|
|
|
|
|
90
|
$num1 = 0; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
63
|
50
|
66
|
|
|
310
|
if(($num1 =~ /^\d+$/) and ($num1 < 0)) |
|
118
|
|
|
|
|
|
|
{ |
|
119
|
0
|
|
|
|
|
0
|
print STDERR "File index $num1 < 0 !\n"; |
|
120
|
0
|
|
|
|
|
0
|
return undef; |
|
121
|
|
|
|
|
|
|
} |
|
122
|
63
|
50
|
|
|
|
181
|
if($num2 =~ /^\d+$/) |
|
123
|
|
|
|
|
|
|
{ |
|
124
|
63
|
|
|
|
|
155
|
--$num2; |
|
125
|
63
|
50
|
|
|
|
142
|
if($num2 < 0) |
|
126
|
|
|
|
|
|
|
{ |
|
127
|
0
|
|
|
|
|
0
|
print STDERR "Dataset index $num2 < 0 !\n"; |
|
128
|
0
|
|
|
|
|
0
|
return undef; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
} |
|
131
|
0
|
|
|
|
|
0
|
else{ $num2 = "($num2)-1"; } |
|
132
|
63
|
|
|
|
|
334
|
$nf .= '$'.$data."[$num1][$num2]"; |
|
133
|
|
|
|
|
|
|
#print STDERR "nf: $nf\n"; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
19
|
|
|
|
|
45
|
$nf .= $formula; |
|
137
|
19
|
|
|
|
|
27
|
for(keys %{$ardef}) |
|
|
19
|
|
|
|
|
65
|
|
|
138
|
|
|
|
|
|
|
{ |
|
139
|
40
|
|
|
|
|
968
|
$nf =~ s/(^|[^\$a-zA-Z])$_(\d+)/$1\$$ardef->{$_}\[$2\]/g; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
19
|
50
|
|
|
|
84
|
if($nnf ne ''){ $nnf .= "\n"; } |
|
|
0
|
|
|
|
|
0
|
|
|
142
|
19
|
|
|
|
|
63
|
$nnf .= $nf; |
|
143
|
|
|
|
|
|
|
} |
|
144
|
19
|
|
|
|
|
63
|
return $nnf; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
#(formula [, config]) |
|
148
|
|
|
|
|
|
|
sub formula_function |
|
149
|
|
|
|
|
|
|
{ |
|
150
|
15
|
|
|
15
|
1
|
47
|
my ($formula,$cfg) = (shift, shift); |
|
151
|
15
|
|
|
|
|
41
|
my @ar = qw(A C); |
|
152
|
15
|
|
|
|
|
33
|
push(@ar, @_); # additional names arrays to insert |
|
153
|
15
|
|
|
|
|
35
|
my %ardef = map { $_ => $_.'->' } @ar; |
|
|
32
|
|
|
|
|
114
|
|
|
154
|
15
|
100
|
|
|
|
51
|
my $config = defined $cfg |
|
155
|
|
|
|
|
|
|
? $cfg |
|
156
|
|
|
|
|
|
|
: {verbose=>0, plainperl=>0}; |
|
157
|
|
|
|
|
|
|
my $pf = $config->{plainperl} |
|
158
|
15
|
50
|
|
|
|
61
|
? $formula |
|
159
|
|
|
|
|
|
|
: parsed_formula($formula, 'fd->', \%ardef); |
|
160
|
15
|
50
|
|
|
|
44
|
unless(defined $pf) |
|
161
|
|
|
|
|
|
|
{ |
|
162
|
0
|
|
|
|
|
0
|
$@ = "Text::NumericData::Calc: Error parsing the formula!"; |
|
163
|
0
|
|
|
|
|
0
|
return undef; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
15
|
|
|
|
|
40
|
my $ffc = 'sub { my ($fd, '.join(', ', map {'$'.$_} @ar).') = @_; '.$pf.' ; return 0; }'; |
|
|
32
|
|
|
|
|
116
|
|
|
166
|
15
|
50
|
|
|
|
53
|
if(defined $config->{verbose}) |
|
167
|
|
|
|
|
|
|
{ |
|
168
|
|
|
|
|
|
|
print STDERR "Formula code: ".$pf."\n" |
|
169
|
15
|
50
|
|
|
|
48
|
if $config->{verbose}; |
|
170
|
|
|
|
|
|
|
print STDERR "Formula function code: ".$ffc."\n" |
|
171
|
15
|
50
|
|
|
|
43
|
if $config->{verbose} > 1; |
|
172
|
|
|
|
|
|
|
} |
|
173
|
15
|
|
|
|
|
1699
|
return eval $ffc; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# same as above, code differs in that it returns the expression indicated by formula |
|
177
|
|
|
|
|
|
|
sub expression_function |
|
178
|
|
|
|
|
|
|
{ |
|
179
|
4
|
|
|
4
|
0
|
9
|
my $formula = shift; |
|
180
|
4
|
|
|
|
|
4
|
my $verb = shift; |
|
181
|
4
|
|
|
|
|
12
|
my @ar = qw(A C); |
|
182
|
4
|
|
|
|
|
10
|
push(@ar, @_); # additional names arrays to insert |
|
183
|
4
|
|
|
|
|
8
|
my %ardef = map { $_ => $_.'->' } @ar; |
|
|
8
|
|
|
|
|
41
|
|
|
184
|
4
|
|
|
|
|
13
|
my $pf = parsed_formula($formula, 'fd->', \%ardef); |
|
185
|
4
|
50
|
|
|
|
13
|
unless(defined $pf) |
|
186
|
|
|
|
|
|
|
{ |
|
187
|
0
|
|
|
|
|
0
|
$@ = "Text::NumericData::Calc: Error parsing the formula!"; |
|
188
|
0
|
|
|
|
|
0
|
return undef; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
4
|
50
|
|
|
|
11
|
print STDERR "Formula code: ",$pf,"\n" if $verb; |
|
191
|
4
|
|
|
|
|
10
|
return eval 'sub { my ($fd, '.join(', ', map {'$'.$_} @ar).') = @_; return ('.$pf.'); }'; |
|
|
8
|
|
|
|
|
451
|
|
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
1; |
|
195
|
|
|
|
|
|
|
__END__ |