line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!perl -w -I/home/phil/z/Perl/cpanModules/Math-Algebra-Symbols/lib
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 Sums
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Symbolic Algebra using Pure Perl: sums.
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
Operations on sums of terms.
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
PhilipRBrenan@yahoo.com, 2004, Perl License.
|
10
|
|
|
|
|
|
|
PhilipRBrenan@gmail.com, 2016, Perl License. www.appaapps.com
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=cut
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
package Math::Algebra::Symbols::Sum;
|
16
|
45
|
|
|
45
|
|
146
|
use strict;
|
|
45
|
|
|
|
|
42
|
|
|
45
|
|
|
|
|
1542
|
|
17
|
|
|
|
|
|
|
our $VERSION=1.27;
|
18
|
45
|
|
|
45
|
|
18946
|
use Math::Algebra::Symbols::Term;
|
|
45
|
|
|
|
|
87
|
|
|
45
|
|
|
|
|
149
|
|
19
|
45
|
|
|
45
|
|
23266
|
use IO::Handle;
|
|
45
|
|
|
|
|
220854
|
|
|
45
|
|
|
|
|
2758
|
|
20
|
45
|
|
|
45
|
|
1031
|
use Carp;
|
|
45
|
|
|
|
|
44
|
|
|
45
|
|
|
|
|
3586
|
|
21
|
|
|
|
|
|
|
#HashUtil use Hash::Util qw(lock_hash);
|
22
|
45
|
|
|
45
|
|
171
|
use Scalar::Util qw(weaken);
|
|
45
|
|
|
|
|
50
|
|
|
45
|
|
|
|
|
283098
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
=head2 Constructors
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head3 new
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
Constructor
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=cut
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub new
|
36
|
10011
|
|
|
10011
|
1
|
16645
|
{bless {t=>{}};
|
37
|
|
|
|
|
|
|
}
|
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head3 constants
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Variables used to sign and lock each sum that have to be declared early on
|
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=cut
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my $lock = 0; # Hash locking
|
48
|
|
|
|
|
|
|
my $z = 0; # Term counter
|
49
|
|
|
|
|
|
|
my %z; # Terms finalized
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head3 constants
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Useful constants
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=cut
|
56
|
|
|
|
|
|
|
|
57
|
16
|
|
|
16
|
0
|
27
|
my $zero = &sigma(&term('0')); sub zero() {$zero}
|
58
|
33
|
|
|
33
|
0
|
60
|
my $one = &sigma(&term('1')); sub one() {$one}
|
59
|
0
|
|
|
0
|
0
|
0
|
my $two = &sigma(&term('2')); sub two() {$two}
|
60
|
0
|
|
|
0
|
0
|
0
|
my $four = &sigma(&term('4')); sub four() {$four}
|
61
|
0
|
|
|
0
|
0
|
0
|
my $mOne = &sigma(&term('-1')); sub mOne() {$mOne}
|
62
|
0
|
|
|
0
|
0
|
0
|
my $i = &sigma(&term('i')); sub i() {$i}
|
63
|
0
|
|
|
0
|
0
|
0
|
my $mI = &sigma(&term('-i')); sub mI() {$mI}
|
64
|
0
|
|
|
0
|
0
|
0
|
my $half = &sigma(&term('1/2')); sub half() {$half}
|
65
|
0
|
|
|
0
|
0
|
0
|
my $mHalf = &sigma(&term('-1/2')); sub mHalf() {$mHalf}
|
66
|
0
|
|
|
0
|
0
|
0
|
my $pi = &sigma(&term('pi')); sub pi() {$pi}
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head3 newFromString
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
New from String
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=cut
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub newFromString($)
|
77
|
797
|
|
|
797
|
1
|
803
|
{my ($a) = @_;
|
78
|
797
|
100
|
|
|
|
1255
|
return $zero unless $a;
|
79
|
701
|
|
|
|
|
687
|
$a .='+';
|
80
|
701
|
|
|
|
|
2523
|
my @a = $a =~ /(.+?)[\+\-]/g;
|
81
|
701
|
|
|
|
|
833
|
my @t = map {term($_)} @a;
|
|
701
|
|
|
|
|
16445
|
|
82
|
701
|
|
|
|
|
1124
|
sigma(@t);
|
83
|
|
|
|
|
|
|
}
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=head3 n
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
New from Strings
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=cut
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub n(@)
|
94
|
66
|
50
|
|
66
|
1
|
210
|
{return $zero unless @_;
|
95
|
66
|
|
|
|
|
146
|
my @a = map {newFromString($_)} @_;
|
|
156
|
|
|
|
|
278
|
|
96
|
66
|
100
|
|
|
|
292
|
return @a if wantarray;
|
97
|
18
|
|
|
|
|
55
|
$a[0];
|
98
|
|
|
|
|
|
|
}
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head3 sigma
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
Create a sum from a list of terms.
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=cut
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub sigma(@)
|
109
|
10070
|
100
|
|
10070
|
1
|
14901
|
{return $zero unless scalar(@_);
|
110
|
10011
|
|
|
|
|
11507
|
my $z = new();
|
111
|
10011
|
|
|
|
|
11937
|
for my $t(@_)
|
112
|
146557
|
|
|
|
|
237404
|
{my $s = $t->signature;
|
113
|
146557
|
100
|
|
|
|
232099
|
if (exists($z->{t}{$s}))
|
114
|
107926
|
|
|
|
|
224294
|
{my $a = $z->{t}{$s}->add($t);
|
115
|
107926
|
100
|
|
|
|
214478
|
if ($a->c == 0)
|
116
|
3484
|
|
|
|
|
6209
|
{delete $z->{t}{$s};
|
117
|
|
|
|
|
|
|
}
|
118
|
|
|
|
|
|
|
else
|
119
|
104442
|
|
|
|
|
381600
|
{$z->{t}{$s} = $a;
|
120
|
|
|
|
|
|
|
}
|
121
|
|
|
|
|
|
|
}
|
122
|
|
|
|
|
|
|
else
|
123
|
38631
|
|
|
|
|
72541
|
{$z->{t}{$s} = $t
|
124
|
|
|
|
|
|
|
}
|
125
|
|
|
|
|
|
|
}
|
126
|
10011
|
|
|
|
|
13970
|
$z->z;
|
127
|
|
|
|
|
|
|
}
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head3 makeInt
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
Construct an integer
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=cut
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub makeInt($)
|
138
|
13
|
|
|
13
|
1
|
309
|
{sigma(term()->one->clone->c(shift())->z)
|
139
|
|
|
|
|
|
|
}
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 Methods
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head3 isSum
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
Confirm type
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
|
152
|
8
|
|
|
8
|
1
|
5
|
sub isSum($) {1};
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head3 t
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Get list of terms from existing sum
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub t($)
|
163
|
28502
|
|
|
28502
|
1
|
20498
|
{my ($a) = @_;
|
164
|
28502
|
|
|
|
|
18841
|
(map {$a->{t}{$_}} sort(keys(%{$a->{t}})));
|
|
109939
|
|
|
|
|
114720
|
|
|
28502
|
|
|
|
|
104048
|
|
165
|
|
|
|
|
|
|
}
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head3 count
|
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Count terms in sum
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=cut
|
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub count($)
|
176
|
0
|
|
|
0
|
1
|
0
|
{my ($a) = @_;
|
177
|
0
|
|
|
|
|
0
|
scalar(keys(%{$a->{t}}));
|
|
0
|
|
|
|
|
0
|
|
178
|
|
|
|
|
|
|
}
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head3 st
|
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Get the single term from a sum containing just one term
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=cut
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub st($)
|
189
|
4022
|
|
|
4022
|
1
|
3289
|
{my ($a) = @_;
|
190
|
4022
|
100
|
|
|
|
2919
|
return (values(%{$a->{t}}))[0] if scalar(keys(%{$a->{t}})) == 1;
|
|
1546
|
|
|
|
|
2269
|
|
|
4022
|
|
|
|
|
8122
|
|
191
|
2476
|
|
|
|
|
2534
|
undef;
|
192
|
|
|
|
|
|
|
}
|
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head3 negate
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
Multiply each term in a sum by -1
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=cut
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub negate($)
|
203
|
828
|
|
|
828
|
1
|
676
|
{my ($s) = @_;
|
204
|
828
|
|
|
|
|
613
|
my @t;
|
205
|
828
|
|
|
|
|
946
|
for my $t($s->t)
|
206
|
3459
|
|
|
|
|
6337
|
{push @t, $t->clone->timesInt(-1)->z;
|
207
|
|
|
|
|
|
|
}
|
208
|
828
|
|
|
|
|
1774
|
sigma(@t);
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head3 add
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
Add two sums together to make a new sum
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut
|
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub add($$)
|
220
|
3961
|
|
|
3961
|
1
|
3480
|
{my ($a, $b) = @_;
|
221
|
3961
|
|
|
|
|
5156
|
sigma($a->t, $b->t);
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=head3 subtract
|
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Subtract one sum from another
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=cut
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub subtract($$)
|
233
|
529
|
|
|
529
|
1
|
535
|
{my ($a, $b) = @_;
|
234
|
529
|
100
|
|
|
|
1030
|
return $b->negate if $a->{id} == $zero->{id};
|
235
|
454
|
|
|
|
|
727
|
$a->add($b->negate);
|
236
|
|
|
|
|
|
|
}
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head3 Conditional Multiply
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
Multiply two sums if both sums are defined, otherwise return
|
242
|
|
|
|
|
|
|
the defined sum. Assumes that at least one sum is defined.
|
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=cut
|
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub multiplyC($$)
|
248
|
4664
|
|
|
4664
|
0
|
3502
|
{my ($a, $b) = @_;
|
249
|
4664
|
100
|
|
|
|
11026
|
return $a unless defined($b);
|
250
|
747
|
100
|
|
|
|
1663
|
return $b unless defined($a);
|
251
|
183
|
|
|
|
|
329
|
$a->multiply($b);
|
252
|
|
|
|
|
|
|
}
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head3 multiply
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Multiply two sums together
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=cut
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
my %M; # Memoize multiplication
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub multiply($$)
|
265
|
2815
|
|
|
2815
|
1
|
2427
|
{my ($A, $B) = @_;
|
266
|
|
|
|
|
|
|
|
267
|
2815
|
100
|
|
|
|
8136
|
my $m = $M{$A->{id}}{$B->{id}}; return $m if defined($m);
|
|
2815
|
|
|
|
|
5225
|
|
268
|
|
|
|
|
|
|
|
269
|
1758
|
100
|
100
|
|
|
7294
|
return $A if $A->{id} == $zero->{id} or $B->{id} == $one->{id};
|
270
|
1598
|
100
|
100
|
|
|
5175
|
return $B if $B->{id} == $zero->{id} or $A->{id} == $one->{id};
|
271
|
|
|
|
|
|
|
|
272
|
1503
|
|
|
|
|
1120
|
my @t;
|
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# Check for divides that match multiplier
|
275
|
1503
|
|
|
|
|
1934
|
my @a = $A->t;
|
276
|
1503
|
|
|
|
|
2129
|
for my $a(@a)
|
277
|
7088
|
|
|
|
|
10117
|
{my $d = $a->Divide;
|
278
|
7088
|
100
|
|
|
|
9385
|
next unless $d;
|
279
|
1061
|
100
|
|
|
|
1615
|
if ($d->{id} == $B->{id})
|
280
|
725
|
|
|
|
|
1118
|
{push @t, $a->removeDivide;
|
281
|
725
|
|
|
|
|
779
|
$a = undef;
|
282
|
|
|
|
|
|
|
}
|
283
|
|
|
|
|
|
|
}
|
284
|
|
|
|
|
|
|
|
285
|
1503
|
|
|
|
|
1774
|
my @b = $B->t;
|
286
|
1503
|
|
|
|
|
1843
|
for my $b(@b)
|
287
|
5557
|
|
|
|
|
7315
|
{my $d = $b->Divide;
|
288
|
5557
|
100
|
|
|
|
7428
|
next unless $d;
|
289
|
136
|
100
|
|
|
|
263
|
if ($d->{id} == $A->{id})
|
290
|
1
|
|
|
|
|
3
|
{push @t, $b->removeDivide;
|
291
|
1
|
|
|
|
|
2
|
$b = undef;
|
292
|
|
|
|
|
|
|
}
|
293
|
|
|
|
|
|
|
}
|
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Simple multiply
|
296
|
1503
|
|
|
|
|
1559
|
for my $aa(@a)
|
297
|
7088
|
100
|
|
|
|
11860
|
{next unless $aa;
|
298
|
6363
|
|
|
|
|
7186
|
for my $bb(@b)
|
299
|
111271
|
100
|
|
|
|
166485
|
{next unless $bb;
|
300
|
111270
|
|
|
|
|
190866
|
my $m = $aa->multiply($bb);
|
301
|
111270
|
100
|
|
|
|
263491
|
push (@t, $m), next if $m;
|
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# Complicated multiply
|
304
|
3191
|
|
|
|
|
5369
|
my %a = $aa->split; my %b = $bb->split;
|
|
3191
|
|
|
|
|
5798
|
|
305
|
3191
|
|
|
|
|
3493
|
my $a = $a{t}; my $b = $b{t};
|
|
3191
|
|
|
|
|
2146
|
|
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
# Sqrt
|
308
|
3191
|
|
|
|
|
2203
|
my $s = 0;
|
309
|
3191
|
100
|
66
|
|
|
4267
|
$s = $a{s} if $a{s} and $b{s} and $a{s}->{id} == $b{s}->{id}; # Equal sqrts
|
|
|
|
66
|
|
|
|
|
310
|
3191
|
100
|
|
|
|
6451
|
$a->Sqrt(multiplyC($a{s}, $b{s})) unless $s;
|
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# Divide
|
313
|
3191
|
100
|
66
|
|
|
6376
|
$a->Divide(multiplyC($a{d}, $b{d})) if $a{d} or $b{d};
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# Exp
|
316
|
3191
|
50
|
75
|
|
|
4869
|
$a->Exp($a{e} ? $a{e} : $b{e}) if $a{e} xor $b{e};
|
|
|
100
|
|
|
|
|
|
317
|
3191
|
|
|
|
|
2864
|
my $e;
|
318
|
3191
|
50
|
66
|
|
|
3406
|
if ($a{e} and $b{e})
|
319
|
2923
|
|
|
|
|
4355
|
{my $s = $a{e}->add($b{e});
|
320
|
2923
|
|
|
|
|
5255
|
$e = $s->st; # Check for single term
|
321
|
2923
|
100
|
|
|
|
5129
|
$e = $e->exp2 if defined($e); # Simplify single term if possible
|
322
|
2923
|
100
|
|
|
|
7734
|
$a->Exp($s) unless defined($e); # Reinstate Exp as sum of terms if no simplification possible
|
323
|
|
|
|
|
|
|
}
|
324
|
|
|
|
|
|
|
# Log
|
325
|
3191
|
0
|
25
|
|
|
11425
|
$a->Log($a{l} ? $a{l} : $b{l}) if $a{l} xor $b{l};
|
|
|
50
|
|
|
|
|
|
326
|
3191
|
0
|
33
|
|
|
4073
|
die "Cannot multiply logs yet" if $a{l} and $b{l};
|
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
# Combine results
|
329
|
3191
|
|
|
|
|
5172
|
$a = $a->z;
|
330
|
3191
|
|
|
|
|
4988
|
$b = $b->z;
|
331
|
3191
|
|
|
|
|
5989
|
$a = $a->multiply($b);
|
332
|
3191
|
100
|
|
|
|
4490
|
$a = $a->multiply($e) if defined($e);
|
333
|
3191
|
50
|
|
|
|
5554
|
$a or die "Bad multiply";
|
334
|
|
|
|
|
|
|
|
335
|
3191
|
100
|
|
|
|
5426
|
push @t, $a unless $s;
|
336
|
3191
|
100
|
|
|
|
15634
|
push @t, sigma($a)->multiply($s)->t if $s;
|
337
|
|
|
|
|
|
|
}
|
338
|
|
|
|
|
|
|
}
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# Result
|
341
|
1503
|
|
|
|
|
5670
|
my $C = sigma(@t);
|
342
|
1503
|
|
|
|
|
3467
|
$M{$A->{id}}{$B->{id}} = $C;
|
343
|
1503
|
|
|
|
|
188892
|
$C;
|
344
|
|
|
|
|
|
|
}
|
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
=head3 divide
|
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
Divide one sum by another
|
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=cut
|
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub divide($$)
|
355
|
351
|
|
|
351
|
1
|
361
|
{my ($A, $B) = @_;
|
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Obvious cases
|
358
|
351
|
50
|
|
|
|
639
|
$B->{id} == $zero->{id} and croak "Cannot divide by zero";
|
359
|
351
|
50
|
|
|
|
671
|
return $zero if $A->{id} == $zero->{id};
|
360
|
351
|
100
|
|
|
|
613
|
return $A if $B->{id} == $one->{id};
|
361
|
308
|
50
|
|
|
|
538
|
return $A->negate if $B->{id} == $mOne->{id};
|
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
# Divide term by term
|
364
|
308
|
|
|
|
|
441
|
my $a = $A->st; my $b = $B->st;
|
|
308
|
|
|
|
|
375
|
|
365
|
308
|
100
|
100
|
|
|
1177
|
if (defined($a) and defined($b))
|
|
|
100
|
|
|
|
|
|
366
|
106
|
|
|
|
|
294
|
{my $c = $a->divide2($b);
|
367
|
106
|
100
|
|
|
|
279
|
return sigma($c) if $c;
|
368
|
|
|
|
|
|
|
}
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# Divide sum by term
|
371
|
|
|
|
|
|
|
elsif ($b)
|
372
|
55
|
|
|
|
|
112
|
{ST: for(1..1)
|
373
|
55
|
|
|
|
|
52
|
{my @t;
|
374
|
55
|
|
|
|
|
85
|
for my $t($A->t)
|
375
|
101
|
|
|
|
|
206
|
{my $c = $t->divide2($b);
|
376
|
101
|
100
|
|
|
|
207
|
last ST unless $c;
|
377
|
85
|
|
|
|
|
131
|
push @t, $c;
|
378
|
|
|
|
|
|
|
}
|
379
|
39
|
|
|
|
|
80
|
return sigma(@t);
|
380
|
|
|
|
|
|
|
}
|
381
|
|
|
|
|
|
|
}
|
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
# Divide sum by sum
|
384
|
176
|
|
|
|
|
161
|
my @t;
|
385
|
176
|
|
|
|
|
224
|
for my $aa($A->t)
|
386
|
314
|
|
|
|
|
622
|
{my $a = $aa->clone;
|
387
|
314
|
|
|
|
|
644
|
my $d = $a->Divide;
|
388
|
314
|
100
|
|
|
|
441
|
$a->Divide($d->multiply($B)) if $d;
|
389
|
314
|
100
|
|
|
|
702
|
$a->Divide($B) unless $d;
|
390
|
314
|
|
|
|
|
521
|
push @t, $a->z;
|
391
|
|
|
|
|
|
|
}
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# Result
|
394
|
176
|
|
|
|
|
278
|
sigma(@t);
|
395
|
|
|
|
|
|
|
}
|
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head3 sub
|
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
Substitute a sum for a variable.
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=cut
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
sub sub($@)
|
406
|
7
|
|
|
7
|
1
|
20
|
{my $E = shift();
|
407
|
7
|
|
|
|
|
16
|
my @R = @_;
|
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# Each replacement
|
410
|
7
|
|
|
|
|
16
|
for(;@R > 0;)
|
411
|
8
|
|
|
|
|
10
|
{my $s = shift @R; # Replace this variable
|
412
|
8
|
|
|
|
|
5
|
my $w = shift @R; # With this expression
|
413
|
8
|
|
|
|
|
6
|
my $Z = $zero;
|
414
|
|
|
|
|
|
|
|
415
|
8
|
50
|
|
|
|
30
|
$s =~ /^[a-z]+$/i or croak "Can only substitute an expression for a variable, not $s";
|
416
|
8
|
100
|
|
|
|
17
|
$w = newFromString($w) unless ref($w);
|
417
|
8
|
|
|
|
|
13
|
$w->isSum;
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
# Each term of the sum comprising the replacement expression.
|
420
|
8
|
|
|
|
|
10
|
for my $t($E->t)
|
421
|
26
|
|
|
|
|
50
|
{my $n = $t->vp($s);
|
422
|
26
|
|
|
|
|
48
|
my %t = $t->split;
|
423
|
26
|
|
|
|
|
53
|
my $S = sigma($t{t}->vp($s, 0)->z); # Remove substitution variable
|
424
|
26
|
100
|
|
|
|
54
|
$S = $S->multiply(($t{s}->sub(@_))->Sqrt) if defined($t{s});
|
425
|
26
|
100
|
|
|
|
35
|
$S = $S->divide ($t{d}->sub(@_)) if defined($t{d});
|
426
|
26
|
50
|
|
|
|
35
|
$S = $S->multiply(($t{e}->sub(@_))->Exp) if defined($t{e});
|
427
|
26
|
50
|
|
|
|
32
|
$S = $S->multiply(($t{l}->sub(@_))->Log) if defined($t{l});
|
428
|
26
|
100
|
|
|
|
47
|
$S = $S->multiply($w->power(makeInt($n))) if $n;
|
429
|
26
|
|
|
|
|
74
|
$Z = $Z->add($S);
|
430
|
|
|
|
|
|
|
}
|
431
|
8
|
|
|
|
|
21
|
$E = $Z;
|
432
|
|
|
|
|
|
|
}
|
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# Result
|
435
|
7
|
|
|
|
|
16
|
$E;
|
436
|
|
|
|
|
|
|
}
|
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head3 isEqual
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
Check whether one sum is equal to another after multiplying out all
|
442
|
|
|
|
|
|
|
divides and divisors.
|
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
=cut
|
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
sub isEqual($)
|
448
|
91
|
|
|
91
|
1
|
112
|
{my ($C) = @_;
|
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
# Until there are no more divides
|
451
|
91
|
|
|
|
|
124
|
for(;;)
|
452
|
176
|
|
|
|
|
201
|
{my (%c, $D, $N); $N = 0;
|
|
176
|
|
|
|
|
165
|
|
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
# Most frequent divisor
|
455
|
176
|
|
|
|
|
269
|
for my $t($C->t)
|
456
|
1550
|
|
|
|
|
2119
|
{my $d = $t->Divide;
|
457
|
1550
|
100
|
|
|
|
1797
|
next unless $d;
|
458
|
958
|
|
|
|
|
1008
|
my $s = $d->getSignature;
|
459
|
958
|
100
|
|
|
|
1877
|
if (++$c{$s} > $N)
|
460
|
675
|
|
|
|
|
692
|
{$N = $c{$s};
|
461
|
675
|
|
|
|
|
626
|
$D = $d;
|
462
|
|
|
|
|
|
|
}
|
463
|
|
|
|
|
|
|
}
|
464
|
176
|
100
|
|
|
|
440
|
last unless $N;
|
465
|
85
|
|
|
|
|
156
|
$C = $C->multiply($D);
|
466
|
|
|
|
|
|
|
}
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# Until there are no more negative powers
|
469
|
91
|
|
|
|
|
86
|
for(;;)
|
470
|
100
|
|
|
|
|
102
|
{my %v;
|
471
|
100
|
|
|
|
|
157
|
for my $t($C->t)
|
472
|
161
|
|
|
|
|
335
|
{for my $v($t->v)
|
473
|
124
|
|
|
|
|
201
|
{my $p = $t->vp($v);
|
474
|
124
|
100
|
|
|
|
252
|
next unless $p < 0;
|
475
|
12
|
|
|
|
|
13
|
$p = -$p;
|
476
|
12
|
100
|
100
|
|
|
50
|
$v{$v} = $p if !defined($v{$v}) or $v{$v} < $p;
|
477
|
|
|
|
|
|
|
}
|
478
|
|
|
|
|
|
|
}
|
479
|
100
|
100
|
|
|
|
298
|
last unless scalar(keys(%v));
|
480
|
9
|
|
|
|
|
295
|
my $m = term()->one->clone;
|
481
|
9
|
|
|
|
|
51
|
$m->vp($_, $v{$_}) for keys(%v);
|
482
|
9
|
|
|
|
|
24
|
my $M = sigma($m->z);
|
483
|
9
|
|
|
|
|
23
|
$C = $C->multiply($M);
|
484
|
|
|
|
|
|
|
}
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
# Result
|
487
|
91
|
|
|
|
|
556
|
$C;
|
488
|
|
|
|
|
|
|
}
|
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
=head3 normalizeSqrts
|
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
Normalize sqrts in a sum.
|
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
This routine needs fixing.
|
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
It should simplify square roots.
|
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
=cut
|
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
sub normalizeSqrts($)
|
503
|
108
|
|
|
108
|
1
|
115
|
{my ($s) = @_;
|
504
|
108
|
|
|
|
|
143
|
return $s;
|
505
|
0
|
|
|
|
|
0
|
my (@t, @s);
|
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
# Find terms with single simple sqrts that can be normalized.
|
508
|
0
|
|
|
|
|
0
|
for my $t($s->t)
|
509
|
0
|
|
|
|
|
0
|
{push @t, $t;
|
510
|
0
|
0
|
|
|
|
0
|
my $S = $t->Sqrt; next unless $S; # Check for sqrt
|
|
0
|
|
|
|
|
0
|
|
511
|
0
|
0
|
|
|
|
0
|
my $St = $S->st; next unless $St; # Check for single term sqrt
|
|
0
|
|
|
|
|
0
|
|
512
|
|
|
|
|
|
|
|
513
|
0
|
|
|
|
|
0
|
my %T = $St->split; # Split single term sqrt
|
514
|
0
|
0
|
0
|
|
|
0
|
next if $T{s} or $T{d} or $T{e} or $T{l};
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
515
|
0
|
|
|
|
|
0
|
pop @t;
|
516
|
0
|
|
|
|
|
0
|
push @s, {t=>$t, s=>$T{t}->z}; # Sqrt with simple single term
|
517
|
|
|
|
|
|
|
}
|
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
# Already normalized unless there are several such terms
|
520
|
0
|
0
|
|
|
|
0
|
return $s unless scalar(@s) > 1;
|
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
# Remove divisor for each normalized term
|
523
|
0
|
|
|
|
|
0
|
for my $r(@s)
|
524
|
0
|
0
|
|
|
|
0
|
{my $d = $r->{t}->d; next unless $d > 1;
|
|
0
|
|
|
|
|
0
|
|
525
|
0
|
|
|
|
|
0
|
for my $s(@s)
|
526
|
0
|
|
|
|
|
0
|
{$s->{t} = $s->{t}->clone->divideInt($d) ->z;
|
527
|
0
|
|
|
|
|
0
|
$s->{s} = $s->{s}->clone->timesInt ($d*$d)->z;
|
528
|
|
|
|
|
|
|
}
|
529
|
|
|
|
|
|
|
}
|
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# Eliminate duplicate squared factors
|
532
|
0
|
|
|
|
|
0
|
for my $s(@s)
|
533
|
0
|
|
|
|
|
0
|
{my $F = factorize($s->{s}->c);
|
534
|
0
|
|
|
|
|
0
|
my $p = 1;
|
535
|
0
|
|
|
|
|
0
|
for my $f(keys(%$F))
|
536
|
0
|
0
|
|
|
|
0
|
{$p *= $f**(int($F->{$f}/2)) if $F->{$f} > 1;
|
537
|
|
|
|
|
|
|
}
|
538
|
0
|
|
|
|
|
0
|
$s->{t} = $s->{t}->clone->timesInt ($p) ->z;
|
539
|
0
|
|
|
|
|
0
|
$s->{s} = $s->{s}->clone->divideInt($p*$p)->z;
|
540
|
|
|
|
|
|
|
|
541
|
0
|
0
|
|
|
|
0
|
if ($s->{s}->isOne)
|
542
|
0
|
|
|
|
|
0
|
{push @t, $s->{t}->removeSqrt;
|
543
|
|
|
|
|
|
|
}
|
544
|
|
|
|
|
|
|
else
|
545
|
0
|
|
|
|
|
0
|
{push @t, $s->{t}->clone->Sqrt($s->{$s})->z;
|
546
|
|
|
|
|
|
|
}
|
547
|
|
|
|
|
|
|
}
|
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
# Result
|
550
|
0
|
|
|
|
|
0
|
sigma(@t);
|
551
|
|
|
|
|
|
|
}
|
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
=head3 isEqualSqrt
|
555
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
Check whether one sum is equal to another after multiplying out sqrts.
|
557
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
=cut
|
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
sub isEqualSqrt($)
|
562
|
91
|
|
|
91
|
1
|
94
|
{my ($C) = @_;
|
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
#_______________________________________________________________________
|
565
|
|
|
|
|
|
|
# Each sqrt
|
566
|
|
|
|
|
|
|
#_______________________________________________________________________
|
567
|
|
|
|
|
|
|
|
568
|
91
|
|
|
|
|
287
|
for(1..99)
|
569
|
108
|
|
|
|
|
237
|
{$C = $C->normalizeSqrts;
|
570
|
108
|
|
|
|
|
187
|
my @s = grep { defined($_->Sqrt)} $C->t;
|
|
335
|
|
|
|
|
584
|
|
571
|
108
|
|
|
|
|
212
|
my @n = grep {!defined($_->Sqrt)} $C->t;
|
|
335
|
|
|
|
|
500
|
|
572
|
108
|
100
|
|
|
|
290
|
last unless scalar(@s) > 0;
|
573
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
#_______________________________________________________________________
|
575
|
|
|
|
|
|
|
# Partition by square roots.
|
576
|
|
|
|
|
|
|
#_______________________________________________________________________
|
577
|
|
|
|
|
|
|
|
578
|
17
|
|
|
|
|
34
|
my %S = ();
|
579
|
17
|
|
|
|
|
27
|
for my $t(@s)
|
580
|
47
|
|
|
|
|
82
|
{my $s = $t->Sqrt;
|
581
|
47
|
|
|
|
|
57
|
my $S = $s->signature;
|
582
|
47
|
|
|
|
|
41
|
push @{$S{$S}}, $t;
|
|
47
|
|
|
|
|
140
|
|
583
|
|
|
|
|
|
|
}
|
584
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
#_______________________________________________________________________
|
586
|
|
|
|
|
|
|
# Square each partitions, as required by the formulae below.
|
587
|
|
|
|
|
|
|
#_______________________________________________________________________
|
588
|
|
|
|
|
|
|
|
589
|
17
|
|
|
|
|
19
|
my @t;
|
590
|
17
|
100
|
|
|
|
48
|
push @t, sigma(@n)->power($two) if scalar(@n); # Non sqrt partition
|
591
|
17
|
|
|
|
|
62
|
for my $s(keys(%S))
|
592
|
32
|
|
|
|
|
37
|
{push @t, sigma(@{$S{$s}})->power($two); # Sqrt partition
|
|
32
|
|
|
|
|
65
|
|
593
|
|
|
|
|
|
|
}
|
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
#_______________________________________________________________________
|
596
|
|
|
|
|
|
|
# I can multiply out upto 4 square roots using the formulae below.
|
597
|
|
|
|
|
|
|
# There are formula to multiply out more than 4 sqrts, but they are big.
|
598
|
|
|
|
|
|
|
# These formulae are obtained by squaring out and rearranging:
|
599
|
|
|
|
|
|
|
# sqrt(a)+sqrt(b)+sqrt(c)+sqrt(d) == 0 until no sqrts remain, and
|
600
|
|
|
|
|
|
|
# then matching terms to produce optimal execution.
|
601
|
|
|
|
|
|
|
# This remarkable result was obtained with the help of this package:
|
602
|
|
|
|
|
|
|
# demonstrating its utility in optimizing complex calculations written
|
603
|
|
|
|
|
|
|
# in Perl: which in of itself cannot optimize broadly.
|
604
|
|
|
|
|
|
|
#_______________________________________________________________________
|
605
|
|
|
|
|
|
|
|
606
|
17
|
|
|
|
|
25
|
my $ns = scalar(@t);
|
607
|
|
|
|
|
|
|
# 2016/01/26 12:29:28 No need to die
|
608
|
|
|
|
|
|
|
# $ns < 5 or die "There are $ns square roots present. I can handle less than 5";
|
609
|
|
|
|
|
|
|
|
610
|
17
|
|
|
|
|
24
|
my ($a, $b, $c, $d, $e) = @t;
|
611
|
|
|
|
|
|
|
|
612
|
17
|
50
|
|
|
|
72
|
if ($ns == 1)
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
613
|
0
|
|
|
|
|
0
|
{$C = $a;
|
614
|
|
|
|
|
|
|
}
|
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
=pod
|
617
|
|
|
|
|
|
|
𝗮+𝗯 = 0
|
618
|
|
|
|
|
|
|
=> a+b+2𝗮𝗯 = 0
|
619
|
|
|
|
|
|
|
=> 2𝗮𝗯 = -a-b
|
620
|
|
|
|
|
|
|
=> 0 = aa+bb-2ab
|
621
|
|
|
|
|
|
|
= (a-b)**2 or (b-a)**2
|
622
|
|
|
|
|
|
|
=cut
|
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
elsif ($ns == 2)
|
625
|
11
|
|
|
|
|
25
|
{$C = $a-$b;
|
626
|
|
|
|
|
|
|
}
|
627
|
|
|
|
|
|
|
elsif ($ns == 3)
|
628
|
4
|
|
|
|
|
12
|
{$C = -$a**2+2*$a*$b-$b**2+2*$c*$a+2*$c*$b-$c**2;
|
629
|
|
|
|
|
|
|
}
|
630
|
|
|
|
|
|
|
elsif ($ns == 4)
|
631
|
2
|
|
|
|
|
7
|
{my $a2 = $a * $a;
|
632
|
2
|
|
|
|
|
12
|
my $a3 = $a2 * $a;
|
633
|
2
|
|
|
|
|
55
|
my $a4 = $a3 * $a;
|
634
|
2
|
|
|
|
|
11
|
my $b2 = $b * $b;
|
635
|
2
|
|
|
|
|
8
|
my $b3 = $b2 * $b;
|
636
|
2
|
|
|
|
|
9
|
my $b4 = $b3 * $b;
|
637
|
2
|
|
|
|
|
10
|
my $c2 = $c * $c;
|
638
|
2
|
|
|
|
|
5
|
my $c3 = $c2 * $c;
|
639
|
2
|
|
|
|
|
9
|
my $c4 = $c3 * $c;
|
640
|
2
|
|
|
|
|
9
|
my $d2 = $d * $d;
|
641
|
2
|
|
|
|
|
7
|
my $d3 = $d2 * $d;
|
642
|
2
|
|
|
|
|
7
|
my $d4 = $d3 * $d;
|
643
|
2
|
|
|
|
|
10
|
my $bpd = $b + $d;
|
644
|
2
|
|
|
|
|
9
|
my $bpc = $b + $c;
|
645
|
2
|
|
|
|
|
8
|
my $cpd = $c + $d;
|
646
|
2
|
|
|
|
|
10
|
$C =
|
647
|
|
|
|
|
|
|
- ($a4 + $b4 + $c4 + $d4)
|
648
|
|
|
|
|
|
|
+ 4*(
|
649
|
|
|
|
|
|
|
+$a3*($b+$cpd)+$b3*($a+$cpd)+$c3*($a+$bpd)+$d3*($a+$bpc)
|
650
|
|
|
|
|
|
|
-$a2*($b *($cpd)+ $c*$d)
|
651
|
|
|
|
|
|
|
-$a *($b2*($cpd)+$d2*($bpc))
|
652
|
|
|
|
|
|
|
)
|
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
- 6*($a2*$b2+($a2+$b2)*($c2+$d2)+$c2*$d2)
|
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
- 4*$c*($b2*$d+$b*$d2)
|
657
|
|
|
|
|
|
|
- 4*$c2*($a*($bpd)+$b*$d)
|
658
|
|
|
|
|
|
|
+40*$c*$a*$b*$d
|
659
|
|
|
|
|
|
|
;
|
660
|
|
|
|
|
|
|
}
|
661
|
|
|
|
|
|
|
}
|
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
#________________________________________________________________________
|
664
|
|
|
|
|
|
|
# Test result
|
665
|
|
|
|
|
|
|
#________________________________________________________________________
|
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# $C->isEqual($zero);
|
668
|
91
|
|
|
|
|
227
|
$C;
|
669
|
|
|
|
|
|
|
}
|
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
=head3 isZero
|
673
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
Transform a sum assuming that it is equal to zero
|
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
=cut
|
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
sub isZero($)
|
680
|
91
|
|
|
91
|
1
|
104
|
{my ($C) = @_;
|
681
|
91
|
|
|
|
|
182
|
$C->isEqualSqrt->isEqual;
|
682
|
|
|
|
|
|
|
}
|
683
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
|
685
|
|
|
|
|
|
|
=head3 powerOfTwo
|
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
Check that a number is a power of two
|
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
=cut
|
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
sub powerof2($)
|
693
|
1
|
|
|
1
|
0
|
2
|
{my ($N) = @_;
|
694
|
1
|
|
|
|
|
1
|
my $n = 0;
|
695
|
1
|
50
|
|
|
|
2
|
return undef unless $N > 0;
|
696
|
1
|
|
|
|
|
2
|
for (;;)
|
697
|
2
|
100
|
|
|
|
4
|
{return $n if $N == 1;
|
698
|
1
|
50
|
|
|
|
3
|
return undef unless $N % 2 == 0;
|
699
|
1
|
|
|
|
|
1
|
++$n; $N /= 2;
|
|
1
|
|
|
|
|
2
|
|
700
|
|
|
|
|
|
|
}
|
701
|
|
|
|
|
|
|
}
|
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
=head3 solve
|
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
Solve an equation known to be equal to zero for a specified variable.
|
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
=cut
|
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
sub solve($$)
|
712
|
17
|
|
|
17
|
1
|
42
|
{my ($A, @x) = @_;
|
713
|
17
|
50
|
|
|
|
47
|
croak 'Need variable to solve for' unless scalar(@x) > 0;
|
714
|
|
|
|
|
|
|
|
715
|
17
|
100
|
100
|
|
|
124
|
@x = @{$x[0]} if scalar(@x) == 1 and ref($x[0]) eq 'ARRAY'; # Array of variables supplied
|
|
1
|
|
|
|
|
3
|
|
716
|
17
|
|
|
|
|
22
|
my %x;
|
717
|
17
|
|
|
|
|
25
|
for my $x(@x)
|
718
|
56
|
100
|
|
|
|
85
|
{if (!ref $x)
|
|
|
50
|
|
|
|
|
|
719
|
51
|
50
|
|
|
|
115
|
{$x =~ /^[a-z]+$/i or croak "Cannot solve for: $x, not a variable name";
|
720
|
|
|
|
|
|
|
}
|
721
|
|
|
|
|
|
|
elsif (ref $x eq __PACKAGE__)
|
722
|
5
|
50
|
|
|
|
13
|
{my $t = $x->st; $t or die "Cannot solve for multiple terms";
|
|
5
|
|
|
|
|
25
|
|
723
|
5
|
50
|
|
|
|
16
|
my @b = $t->v; scalar(@b) == 1 or die "Can only solve for one variable";
|
|
5
|
|
|
|
|
16
|
|
724
|
5
|
50
|
|
|
|
16
|
my $p = $t->vp($b[0]); $p == 1 or die "Can only solve by variable to power 1";
|
|
5
|
|
|
|
|
13
|
|
725
|
5
|
|
|
|
|
10
|
$x = $b[0];
|
726
|
|
|
|
|
|
|
}
|
727
|
|
|
|
|
|
|
else
|
728
|
0
|
|
|
|
|
0
|
{die "$x is not a variable name";
|
729
|
|
|
|
|
|
|
}
|
730
|
56
|
|
|
|
|
80
|
$x{$x} = 1;
|
731
|
|
|
|
|
|
|
}
|
732
|
17
|
|
|
|
|
20
|
my $x = $x[0];
|
733
|
|
|
|
|
|
|
|
734
|
17
|
|
|
|
|
40
|
my $B = $A->isZero; # Eliminate sqrts and negative powers
|
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
# Strike all terms with free variables other than x: i.e. not x and not one of the named constants
|
737
|
17
|
|
|
|
|
46
|
my @t = ();
|
738
|
17
|
|
|
|
|
32
|
for my $t($B->t)
|
739
|
52
|
|
|
|
|
89
|
{my @v = $t->v;
|
740
|
52
|
|
|
|
|
49
|
push @t, $t;
|
741
|
52
|
|
|
|
|
79
|
for my $v($t->v)
|
742
|
59
|
100
|
|
|
|
113
|
{next if exists($x{$v});
|
743
|
8
|
|
|
|
|
8
|
pop @t;
|
744
|
8
|
|
|
|
|
8
|
last;
|
745
|
|
|
|
|
|
|
}
|
746
|
|
|
|
|
|
|
}
|
747
|
17
|
|
|
|
|
34
|
my $C = sigma(@t);
|
748
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
# Find highest and lowest power of x
|
750
|
17
|
|
|
|
|
24
|
my $n = 0; my $N;
|
|
17
|
|
|
|
|
16
|
|
751
|
17
|
|
|
|
|
30
|
for my $t($C->t)
|
752
|
44
|
|
|
|
|
76
|
{my $p = $t->vp($x);
|
753
|
44
|
100
|
|
|
|
68
|
$n = $p if $p > $n;
|
754
|
44
|
100
|
100
|
|
|
151
|
$N = $p if !defined($N) or $p < $N;
|
755
|
|
|
|
|
|
|
}
|
756
|
17
|
|
|
|
|
21
|
my $D = $C;
|
757
|
17
|
100
|
|
|
|
60
|
$D = $D->multiply(sigma(term()->one->clone->vp($x, -$N)->z)) if $N;
|
758
|
17
|
100
|
|
|
|
35
|
$n -= $N if $N;
|
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
# Find number of terms in x
|
761
|
17
|
|
|
|
|
18
|
my $c = 0;
|
762
|
17
|
|
|
|
|
53
|
for my $t($D->t)
|
763
|
44
|
100
|
|
|
|
67
|
{++$c if $t->vp($x) > 0;
|
764
|
|
|
|
|
|
|
}
|
765
|
|
|
|
|
|
|
|
766
|
17
|
50
|
|
|
|
38
|
$n == 0 and croak "Equation not dependant on $x, so cannot solve for $x";
|
767
|
17
|
50
|
33
|
|
|
50
|
$n > 4 and $c > 1 and croak "Unable to solve polynomial or power $n > 4 in $x (Galois)";
|
768
|
17
|
50
|
33
|
|
|
45
|
($n > 2 and $c > 1) and die "Need solver for polynomial of degree $n in $x";
|
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
# Solve linear equation
|
771
|
17
|
100
|
100
|
|
|
67
|
if ($n == 1 or $c == 1)
|
772
|
8
|
|
|
|
|
12
|
{my (@c, @v);
|
773
|
8
|
|
|
|
|
13
|
for my $t($D->t)
|
774
|
17
|
100
|
|
|
|
39
|
{push(@c, $t), next if $t->vp($x) == 0; # Constants
|
775
|
8
|
|
|
|
|
13
|
push @v, $t; # Powers of x
|
776
|
|
|
|
|
|
|
}
|
777
|
8
|
|
|
|
|
16
|
my $d = sigma(@v)->multiply(sigma(term()->one->clone->vp($x, -$n)->negate->z));
|
778
|
8
|
|
|
|
|
50
|
$D = sigma(@c)->divide($d);
|
779
|
|
|
|
|
|
|
|
780
|
8
|
100
|
|
|
|
54
|
return $D if $n == 1;
|
781
|
|
|
|
|
|
|
|
782
|
1
|
|
|
|
|
2
|
my $p = powerof2($n);
|
783
|
1
|
50
|
|
|
|
3
|
$p or croak "Fractional power 1/$n of $x unconstructable by sqrt";
|
784
|
1
|
|
|
|
|
5
|
$D = $D->Sqrt for(1..$p);
|
785
|
1
|
|
|
|
|
30
|
return $D;
|
786
|
|
|
|
|
|
|
}
|
787
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# Solve quadratic equation
|
789
|
9
|
50
|
|
|
|
25
|
if ($n == 2)
|
790
|
9
|
|
|
|
|
20
|
{my @c = ($one, $one, $one);
|
791
|
9
|
|
|
|
|
14
|
$c[$_->vp($x)] = $_ for $D->t;
|
792
|
9
|
|
|
|
|
30
|
$_ = sigma($_->clone->vp($x, 0)->z) for (@c);
|
793
|
9
|
|
|
|
|
13
|
my ($c, $b, $a) = @c;
|
794
|
|
|
|
|
|
|
return
|
795
|
9
|
|
|
|
|
20
|
[ (-$b->add (($b->power($two)->subtract($four->multiply($a)->multiply($c)))->Sqrt))->divide($two->multiply($a)),
|
796
|
|
|
|
|
|
|
(-$b->subtract(($b->power($two)->subtract($four->multiply($a)->multiply($c)))->Sqrt))->divide($two->multiply($a))
|
797
|
|
|
|
|
|
|
]
|
798
|
|
|
|
|
|
|
}
|
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
# Check that it works
|
801
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
# my $yy = $e->sub($x=>$xx);
|
803
|
|
|
|
|
|
|
# $yy == 0 or die "Proposed solution \$$x=$xx does not zero equation $e";
|
804
|
|
|
|
|
|
|
# $xx;
|
805
|
|
|
|
|
|
|
}
|
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=head3 power
|
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
Raise a sum to an integer power or an integer/2 power.
|
811
|
|
|
|
|
|
|
|
812
|
|
|
|
|
|
|
=cut
|
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
|
815
|
|
|
|
|
|
|
sub power($$)
|
816
|
352
|
|
|
352
|
1
|
378
|
{my ($a, $b) = @_;
|
817
|
|
|
|
|
|
|
|
818
|
352
|
50
|
|
|
|
686
|
return $one if $b->{id} == $zero->{id};
|
819
|
352
|
100
|
|
|
|
1001
|
return $a->multiply($a) if $b->{id} == $two->{id};
|
820
|
61
|
100
|
|
|
|
115
|
return $a if $b->{id} == $one->{id};
|
821
|
57
|
50
|
|
|
|
113
|
return $one->divide($a) if $b->{id} == $mOne->{id};
|
822
|
57
|
50
|
|
|
|
117
|
return $a->sqrt if $b->{id} == $half->{id};
|
823
|
57
|
50
|
|
|
|
108
|
return $one->divide($a->sqrt) if $b->{id} == $mHalf->{id};
|
824
|
|
|
|
|
|
|
|
825
|
57
|
|
|
|
|
98
|
my $T = $b->st;
|
826
|
57
|
50
|
|
|
|
174
|
$T or croak "Power by expression too complicated";
|
827
|
|
|
|
|
|
|
|
828
|
57
|
|
|
|
|
138
|
my %t = $T->split;
|
829
|
57
|
50
|
33
|
|
|
347
|
croak "Power by term too complicated" if $t{s} or $t{d} or $t{e} or $t{l};
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
830
|
|
|
|
|
|
|
|
831
|
57
|
|
|
|
|
55
|
my $t = $t{t};
|
832
|
57
|
50
|
|
|
|
119
|
$t->i == 0 or croak "Complex power not allowed yet";
|
833
|
|
|
|
|
|
|
|
834
|
57
|
|
|
|
|
114
|
my ($p, $d) = ($t->c, $t->d);
|
835
|
57
|
50
|
33
|
|
|
191
|
$d == 1 or $d == 2 or croak "Fractional power other than /2 not allowed yet";
|
836
|
|
|
|
|
|
|
|
837
|
57
|
50
|
|
|
|
108
|
$a = $a->sqrt if $d == 2;
|
838
|
|
|
|
|
|
|
|
839
|
57
|
50
|
|
|
|
101
|
return $one->divide($a)->power(sigma(term()->c($p)->z)) if $p < 0;
|
840
|
|
|
|
|
|
|
|
841
|
57
|
|
|
|
|
56
|
$p = abs($p);
|
842
|
57
|
|
|
|
|
49
|
my $r = $a; $r = $r->multiply($a) for (2..$p);
|
|
57
|
|
|
|
|
232
|
|
843
|
57
|
|
|
|
|
359
|
$r;
|
844
|
|
|
|
|
|
|
}
|
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
=head3 d
|
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
Differentiate.
|
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
=cut
|
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
sub d($;$);
|
855
|
|
|
|
|
|
|
sub d($;$)
|
856
|
195
|
|
|
195
|
1
|
174
|
{my $c = $_[0]; # Differentiate this sum
|
857
|
195
|
|
|
|
|
152
|
my $b = $_[1]; # With this variable
|
858
|
|
|
|
|
|
|
|
859
|
|
|
|
|
|
|
#_______________________________________________________________________
|
860
|
|
|
|
|
|
|
# Get differentrix. Assume 'x', 'y', 'z' or 't' if appropriate.
|
861
|
|
|
|
|
|
|
#_______________________________________________________________________
|
862
|
|
|
|
|
|
|
|
863
|
195
|
100
|
|
|
|
276
|
if (defined($b))
|
864
|
139
|
100
|
|
|
|
191
|
{if (!ref $b)
|
|
|
50
|
|
|
|
|
|
865
|
136
|
50
|
|
|
|
518
|
{$b =~ /^[a-z]+$/i or croak "Cannot differentiate by $b";
|
866
|
|
|
|
|
|
|
}
|
867
|
|
|
|
|
|
|
elsif (ref $b eq __PACKAGE__)
|
868
|
3
|
50
|
|
|
|
8
|
{my $t = $b->st; $t or die "Cannot differentiate by multiple terms";
|
|
3
|
|
|
|
|
9
|
|
869
|
3
|
50
|
|
|
|
8
|
my @b = $t->v; scalar(@b) == 1 or die "Can only differentiate by one variable";
|
|
3
|
|
|
|
|
8
|
|
870
|
3
|
50
|
|
|
|
10
|
my $p = $t->vp($b[0]); $p == 1 or die "Can only differentiate by variable to power 1";
|
|
3
|
|
|
|
|
7
|
|
871
|
3
|
|
|
|
|
5
|
$b = $b[0];
|
872
|
|
|
|
|
|
|
}
|
873
|
|
|
|
|
|
|
else
|
874
|
0
|
|
|
|
|
0
|
{die "Cannot differentiate by $b";
|
875
|
|
|
|
|
|
|
}
|
876
|
|
|
|
|
|
|
}
|
877
|
|
|
|
|
|
|
else
|
878
|
56
|
|
|
|
|
50
|
{my %b;
|
879
|
56
|
|
|
|
|
80
|
for my $t($c->t)
|
880
|
108
|
|
|
|
|
119
|
{my %b; $b{$_}++ for ($t->v);
|
|
108
|
|
|
|
|
186
|
|
881
|
|
|
|
|
|
|
}
|
882
|
56
|
|
|
|
|
59
|
my $i = 0; my $n = scalar(keys(%b));
|
|
56
|
|
|
|
|
52
|
|
883
|
56
|
50
|
|
|
|
111
|
++$i, $b = 'x' if $n == 0; # Constant expression anyway
|
884
|
56
|
50
|
|
|
|
89
|
++$i, $b = (%b)[0] if $n == 1;
|
885
|
56
|
|
|
|
|
59
|
for my $v(qw(t x y z))
|
886
|
224
|
0
|
33
|
|
|
300
|
{++$i, $b = 't' if $n > 1 and exists($b{$v});
|
887
|
|
|
|
|
|
|
}
|
888
|
56
|
50
|
|
|
|
119
|
$i == 1 or croak "Please specify a single variable to differentiate by";
|
889
|
|
|
|
|
|
|
}
|
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
#_______________________________________________________________________
|
892
|
|
|
|
|
|
|
# Each term
|
893
|
|
|
|
|
|
|
#_______________________________________________________________________
|
894
|
|
|
|
|
|
|
|
895
|
195
|
|
|
|
|
203
|
my @t = ();
|
896
|
195
|
|
|
|
|
258
|
for my $t($c->t)
|
897
|
258
|
|
|
|
|
490
|
{my %V = $t->split;
|
898
|
258
|
|
|
|
|
551
|
my $T = $V{t}->z->clone->z;
|
899
|
258
|
|
|
|
|
613
|
my ($S, $D, $E, $L) = @V{qw(s d e l)};
|
900
|
258
|
100
|
|
|
|
339
|
my $s = $S->d($b) if $S;
|
901
|
258
|
100
|
|
|
|
313
|
my $d = $D->d($b) if $D;
|
902
|
258
|
100
|
|
|
|
349
|
my $e = $E->d($b) if $E;
|
903
|
258
|
50
|
|
|
|
368
|
my $l = $L->d($b) if $L;
|
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
#_______________________________________________________________________
|
906
|
|
|
|
|
|
|
# Differentiate Variables: A*v**n->d == A*n*v**(n-1)
|
907
|
|
|
|
|
|
|
#_______________________________________________________________________
|
908
|
|
|
|
|
|
|
|
909
|
258
|
|
|
|
|
188
|
{my $v = $T->clone;
|
|
258
|
|
|
|
|
440
|
|
910
|
258
|
|
|
|
|
469
|
my $p = $v->vp($b);
|
911
|
258
|
100
|
|
|
|
524
|
if ($p != 0)
|
912
|
128
|
|
|
|
|
244
|
{$v->timesInt($p)->vp($b, $p-1);
|
913
|
128
|
100
|
|
|
|
190
|
$v->Sqrt ($S) if $S;
|
914
|
128
|
100
|
|
|
|
159
|
$v->Divide($D) if $D;
|
915
|
128
|
50
|
|
|
|
156
|
$v->Exp ($E) if $E;
|
916
|
128
|
50
|
|
|
|
152
|
$v->Log ($L) if $L;
|
917
|
128
|
|
|
|
|
227
|
push @t, $v->z;
|
918
|
|
|
|
|
|
|
}
|
919
|
|
|
|
|
|
|
}
|
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
#_______________________________________________________________________
|
922
|
|
|
|
|
|
|
# Differentiate Sqrt: A*sqrt(F(x))->d == 1/2*A*f(x)/sqrt(F(x))
|
923
|
|
|
|
|
|
|
#_______________________________________________________________________
|
924
|
|
|
|
|
|
|
|
925
|
258
|
100
|
|
|
|
375
|
if ($S)
|
926
|
5
|
|
|
|
|
8
|
{my $v = $T->clone->divideInt(2);
|
927
|
5
|
50
|
|
|
|
6
|
$v->Divide($D) if $D;
|
928
|
5
|
50
|
|
|
|
7
|
$v->Exp ($E) if $E;
|
929
|
5
|
50
|
|
|
|
6
|
$v->Log ($L) if $L;
|
930
|
5
|
|
|
|
|
16
|
push @t, sigma($v->z)->multiply($s)->divide($S->Sqrt)->t;
|
931
|
|
|
|
|
|
|
}
|
932
|
|
|
|
|
|
|
|
933
|
|
|
|
|
|
|
#_______________________________________________________________________
|
934
|
|
|
|
|
|
|
# Differentiate Divide: A/F(x)->d == -A*f(x)/F(x)**2
|
935
|
|
|
|
|
|
|
#_______________________________________________________________________
|
936
|
|
|
|
|
|
|
|
937
|
258
|
100
|
|
|
|
338
|
if ($D)
|
938
|
10
|
|
|
|
|
20
|
{my $v = $T->clone->negate;
|
939
|
10
|
50
|
|
|
|
17
|
$v->Sqrt($S) if $S;
|
940
|
10
|
100
|
|
|
|
15
|
$v->Exp ($E) if $E;
|
941
|
10
|
50
|
|
|
|
16
|
$v->Log ($L) if $L;
|
942
|
10
|
|
|
|
|
21
|
push @t, sigma($v->z)->multiply($d)->divide($D->multiply($D))->t;
|
943
|
|
|
|
|
|
|
}
|
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
#_______________________________________________________________________
|
946
|
|
|
|
|
|
|
# Differentiate Exp: A*exp(F(x))->d == A*f(x)*exp(F(x))
|
947
|
|
|
|
|
|
|
#_______________________________________________________________________
|
948
|
|
|
|
|
|
|
|
949
|
258
|
100
|
|
|
|
392
|
if ($E)
|
950
|
120
|
|
|
|
|
209
|
{my $v = $T->clone;
|
951
|
120
|
50
|
|
|
|
172
|
$v->Sqrt ($S) if $S;
|
952
|
120
|
100
|
|
|
|
151
|
$v->Divide($D) if $D;
|
953
|
120
|
|
|
|
|
231
|
$v->Exp ($E);
|
954
|
120
|
50
|
|
|
|
147
|
$v->Log ($L) if $L;
|
955
|
120
|
|
|
|
|
224
|
push @t, sigma($v->z)->multiply($e)->t;
|
956
|
|
|
|
|
|
|
}
|
957
|
|
|
|
|
|
|
|
958
|
|
|
|
|
|
|
#_______________________________________________________________________
|
959
|
|
|
|
|
|
|
# Differentiate Log: A*log(F(x))->d == A*f(x)/F(x)
|
960
|
|
|
|
|
|
|
#_______________________________________________________________________
|
961
|
|
|
|
|
|
|
|
962
|
258
|
50
|
|
|
|
927
|
if ($L)
|
963
|
0
|
|
|
|
|
0
|
{my $v = $T->clone;
|
964
|
0
|
0
|
|
|
|
0
|
$v->Sqrt ($S) if $S;
|
965
|
0
|
0
|
|
|
|
0
|
$v->Divide($D) if $D;
|
966
|
0
|
0
|
|
|
|
0
|
$v->Exp ($E) if $E;
|
967
|
0
|
|
|
|
|
0
|
push @t, sigma($v->z)->multiply($l)->divide($L)->t;
|
968
|
|
|
|
|
|
|
}
|
969
|
|
|
|
|
|
|
}
|
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
#_______________________________________________________________________
|
972
|
|
|
|
|
|
|
# Result
|
973
|
|
|
|
|
|
|
#_______________________________________________________________________
|
974
|
|
|
|
|
|
|
|
975
|
195
|
|
|
|
|
299
|
sigma(@t);
|
976
|
|
|
|
|
|
|
}
|
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
=head3 simplify
|
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
Simplify just before assignment.
|
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
There is no general simplification algorithm. So try various methods and
|
984
|
|
|
|
|
|
|
see if any simplifications occur. This is cheating really, because the
|
985
|
|
|
|
|
|
|
examples will represent these specific transformations as general
|
986
|
|
|
|
|
|
|
features which they are not. On the other hand, Mathematics is full of
|
987
|
|
|
|
|
|
|
specifics so I suppose its not entirely unacceptable.
|
988
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
Simplification cannot be done after every operation as it is
|
990
|
|
|
|
|
|
|
inefficient, doing it as part of += ameliorates this inefficiency.
|
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
Note: += only works as a synonym for simplify() if the left hand side is
|
993
|
|
|
|
|
|
|
currently undefined. This can be enforced by using my() as in: my $z +=
|
994
|
|
|
|
|
|
|
($x**2+5x+6)/($x+2);
|
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
=cut
|
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
sub simplify($)
|
1000
|
16
|
|
|
16
|
1
|
20
|
{my ($x) = @_;
|
1001
|
16
|
|
|
|
|
39
|
$x = polynomialDivision($x);
|
1002
|
16
|
|
|
|
|
42
|
$x = eigenValue($x);
|
1003
|
|
|
|
|
|
|
}
|
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1006
|
|
|
|
|
|
|
# Common factor: find the largest factor in one or more expressions
|
1007
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
sub commonFactor(@)
|
1010
|
32
|
50
|
|
32
|
0
|
64
|
{return undef unless scalar(@_);
|
1011
|
32
|
50
|
|
|
|
18
|
return undef unless scalar(keys(%{$_[0]->{t}}));
|
|
32
|
|
|
|
|
75
|
|
1012
|
32
|
|
|
|
|
32
|
my $p = (values(%{$_[0]->{t}}))[0];
|
|
32
|
|
|
|
|
44
|
|
1013
|
|
|
|
|
|
|
|
1014
|
32
|
|
|
|
|
26
|
my %v = %{$p->{v}}; # Variables
|
|
32
|
|
|
|
|
61
|
|
1015
|
32
|
|
|
|
|
70
|
my %s = $p->split;
|
1016
|
32
|
|
|
|
|
63
|
my ($s, $d, $e, $l) = @s{qw(s d e l)}; # Sub expressions
|
1017
|
32
|
|
|
|
|
59
|
my ($C, $D, $I) = ($p->c, $p->d, $p->i);
|
1018
|
|
|
|
|
|
|
|
1019
|
32
|
|
|
|
|
39
|
my @t;
|
1020
|
32
|
|
|
|
|
43
|
for my $a(@_)
|
1021
|
32
|
|
|
|
|
43
|
{for my $b($a->t)
|
1022
|
88
|
|
|
|
|
111
|
{push @t, $b;
|
1023
|
|
|
|
|
|
|
}
|
1024
|
|
|
|
|
|
|
}
|
1025
|
|
|
|
|
|
|
|
1026
|
32
|
|
|
|
|
45
|
for my $t(@t)
|
1027
|
88
|
|
|
|
|
128
|
{my %V = %v;
|
1028
|
88
|
|
|
|
|
84
|
%v = ();
|
1029
|
88
|
|
|
|
|
141
|
for my $v($t->v)
|
1030
|
59
|
100
|
|
|
|
90
|
{next unless $V{$v};
|
1031
|
49
|
|
|
|
|
88
|
my $p = $t->vp($v);
|
1032
|
49
|
100
|
|
|
|
104
|
$v{$v} = ($V{$v} < $p ? $V{$v} : $p);
|
1033
|
|
|
|
|
|
|
}
|
1034
|
88
|
|
|
|
|
144
|
my %S = $t->split;
|
1035
|
88
|
|
|
|
|
119
|
my ($S, $D, $E, $L) = @S{qw(s d e l)}; # Sub expressions
|
1036
|
88
|
0
|
33
|
|
|
156
|
$s = undef unless defined($s) and defined($S) and $S->id eq $s->id;
|
|
|
|
33
|
|
|
|
|
1037
|
88
|
0
|
33
|
|
|
143
|
$d = undef unless defined($d) and defined($D) and $D->id eq $d->id;
|
|
|
|
33
|
|
|
|
|
1038
|
88
|
50
|
66
|
|
|
140
|
$e = undef unless defined($e) and defined($E) and $E->id eq $e->id;
|
|
|
|
66
|
|
|
|
|
1039
|
88
|
0
|
33
|
|
|
140
|
$l = undef unless defined($l) and defined($L) and $L->id eq $l->id;
|
|
|
|
33
|
|
|
|
|
1040
|
88
|
100
|
100
|
|
|
205
|
$C = undef unless defined($C) and $C == $t->c;
|
1041
|
88
|
50
|
33
|
|
|
150
|
$D = undef unless defined($D) and $D == $t->d;
|
1042
|
88
|
100
|
100
|
|
|
214
|
$I = undef unless defined($I) and $I == $t->i;
|
1043
|
|
|
|
|
|
|
}
|
1044
|
32
|
|
|
|
|
857
|
my $r = term()->one->clone;
|
1045
|
32
|
100
|
|
|
|
108
|
$r->c($C) if defined($C);
|
1046
|
32
|
50
|
|
|
|
84
|
$r->d($D) if defined($D);
|
1047
|
32
|
100
|
|
|
|
80
|
$r->i($I) if defined($I);
|
1048
|
32
|
|
|
|
|
62
|
$r->vp($_, $v{$_}) for(keys(%v));
|
1049
|
32
|
50
|
|
|
|
51
|
$r->Sqrt ($s) if defined($s);
|
1050
|
32
|
50
|
|
|
|
50
|
$r->Divide($d) if defined($d);
|
1051
|
32
|
50
|
|
|
|
46
|
$r->Exp ($e) if defined($e);
|
1052
|
32
|
50
|
|
|
|
50
|
$r->Log ($l) if defined($l);
|
1053
|
32
|
|
|
|
|
57
|
sigma($r->z);
|
1054
|
|
|
|
|
|
|
}
|
1055
|
|
|
|
|
|
|
|
1056
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1057
|
|
|
|
|
|
|
# Find term of polynomial of highest degree.
|
1058
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
sub polynomialTermOfHighestDegree($$)
|
1061
|
160
|
|
|
160
|
0
|
136
|
{my ($p, $v) = @_; # Polynomial, variable
|
1062
|
160
|
|
|
|
|
96
|
my $n = 0; # Current highest degree
|
1063
|
160
|
|
|
|
|
108
|
my $t; # Term with this degree
|
1064
|
160
|
|
|
|
|
172
|
for my $T($p->t)
|
1065
|
308
|
|
|
|
|
440
|
{my $N = $T->vp($v);
|
1066
|
308
|
100
|
|
|
|
438
|
if ($N > $n)
|
1067
|
148
|
|
|
|
|
97
|
{$n = $N;
|
1068
|
148
|
|
|
|
|
137
|
$t = $T;
|
1069
|
|
|
|
|
|
|
}
|
1070
|
|
|
|
|
|
|
}
|
1071
|
160
|
|
|
|
|
229
|
($n, $t);
|
1072
|
|
|
|
|
|
|
}
|
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=head3 polynomialDivide
|
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
Polynomial divide - divide one polynomial (a) by another (b) in variable v
|
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
=cut
|
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
sub polynomialDivide($$$)
|
1083
|
16
|
|
|
16
|
1
|
18
|
{my ($p, $q, $v) = @_;
|
1084
|
|
|
|
|
|
|
|
1085
|
16
|
|
|
|
|
36
|
my $r = zero()->clone()->z;
|
1086
|
16
|
|
|
|
|
24
|
for(;;)
|
1087
|
80
|
|
|
|
|
121
|
{my ($np, $mp) = $p->polynomialTermOfHighestDegree($v);
|
1088
|
80
|
|
|
|
|
103
|
my ($nq, $mq) = $q->polynomialTermOfHighestDegree($v);
|
1089
|
80
|
100
|
|
|
|
133
|
last unless $np >= $nq;
|
1090
|
64
|
|
|
|
|
130
|
my $pq = sigma($mp->divide2($mq));
|
1091
|
64
|
|
|
|
|
101
|
$r = $r->add($pq);
|
1092
|
64
|
|
|
|
|
188
|
$p = $p->subtract($q->multiply($pq));
|
1093
|
|
|
|
|
|
|
}
|
1094
|
16
|
100
|
|
|
|
39
|
return $r if $p->isZero()->{id} == $zero->{id};
|
1095
|
2
|
|
|
|
|
3
|
undef;
|
1096
|
|
|
|
|
|
|
}
|
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
=head3 eigenValue
|
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
Eigenvalue check
|
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
=cut
|
1104
|
|
|
|
|
|
|
|
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
sub eigenValue($)
|
1107
|
16
|
|
|
16
|
1
|
16
|
{my ($p) = @_;
|
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
# Find divisors
|
1110
|
16
|
|
|
|
|
18
|
my %d;
|
1111
|
16
|
|
|
|
|
24
|
for my $t($p->t)
|
1112
|
67
|
|
|
|
|
91
|
{my $d = $t->Divide;
|
1113
|
67
|
100
|
|
|
|
99
|
next unless defined($d);
|
1114
|
6
|
|
|
|
|
10
|
$d{$d->id} = $d;
|
1115
|
|
|
|
|
|
|
}
|
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
# Consolidate numerator and denominator
|
1118
|
16
|
|
|
|
|
41
|
my $P = $p ->clone()->z; $P = $P->multiply($d{$_}) for(keys(%d));
|
|
16
|
|
|
|
|
58
|
|
1119
|
16
|
|
|
|
|
33
|
my $Q = one()->clone()->z; $Q = $Q->multiply($d{$_}) for(keys(%d));
|
|
16
|
|
|
|
|
42
|
|
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
# Check for P=nQ i.e. for eigenvalue
|
1122
|
16
|
|
|
|
|
46
|
my $cP = $P->commonFactor; my $dP = $P->divide($cP);
|
|
16
|
|
|
|
|
36
|
|
1123
|
16
|
|
|
|
|
29
|
my $cQ = $Q->commonFactor; my $dQ = $Q->divide($cQ);
|
|
16
|
|
|
|
|
47
|
|
1124
|
|
|
|
|
|
|
|
1125
|
16
|
100
|
|
|
|
36
|
return $cP->divide($cQ) if $dP->id == $dQ->id;
|
1126
|
14
|
|
|
|
|
54
|
$p;
|
1127
|
|
|
|
|
|
|
}
|
1128
|
|
|
|
|
|
|
|
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=head3 polynomialDivision
|
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
Polynomial division.
|
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
=cut
|
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
sub polynomialDivision($)
|
1138
|
16
|
|
|
16
|
1
|
14
|
{my ($p) = @_;
|
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
# Find a plausible indeterminate
|
1141
|
16
|
|
|
|
|
19
|
my %v; # Possible indeterminates
|
1142
|
|
|
|
|
|
|
my $v; # Polynomial indeterminate
|
1143
|
0
|
|
|
|
|
0
|
my %D; # Divisors for each term
|
1144
|
|
|
|
|
|
|
|
1145
|
|
|
|
|
|
|
# Each term
|
1146
|
16
|
|
|
|
|
37
|
for my $t($p->t)
|
1147
|
32
|
|
|
|
|
67
|
{my @v = $t->v;
|
1148
|
32
|
|
|
|
|
83
|
$v{$_}{$t->vp($_)} = 1 for(@v);
|
1149
|
32
|
|
|
|
|
59
|
my %V = $t->split;
|
1150
|
32
|
|
|
|
|
60
|
my ($S, $D, $E, $L) = @V{qw(s d e l)};
|
1151
|
32
|
100
|
66
|
|
|
183
|
return $p if defined($S) or defined($E) or defined($L);
|
|
|
|
66
|
|
|
|
|
1152
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
# Each divisor term
|
1154
|
31
|
100
|
|
|
|
51
|
if (defined($D))
|
1155
|
30
|
|
|
|
|
49
|
{for my $T($D->t)
|
1156
|
60
|
|
|
|
|
97
|
{my @v = $T->v;
|
1157
|
60
|
|
|
|
|
131
|
$v{$_}{$T->vp($_)} = 1 for(@v);
|
1158
|
60
|
|
|
|
|
93
|
my %V = $T->split;
|
1159
|
60
|
|
|
|
|
85
|
my ($S, $D, $E, $L) = @V{qw(s d e l)};
|
1160
|
60
|
50
|
33
|
|
|
487
|
return $p if defined($S) or defined($D) or defined($E) or defined($L);
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
1161
|
|
|
|
|
|
|
}
|
1162
|
30
|
|
|
|
|
63
|
$D{$D->id} = $D;
|
1163
|
|
|
|
|
|
|
}
|
1164
|
|
|
|
|
|
|
}
|
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
# Consolidate numerator and denominator
|
1167
|
15
|
|
|
|
|
36
|
my $P = $p ->clone()->z; $P = $P->multiply($D{$_}) for(keys(%D));
|
|
15
|
|
|
|
|
62
|
|
1168
|
15
|
|
|
|
|
37
|
my $Q = one()->clone()->z; $Q = $Q->multiply($D{$_}) for(keys(%D));
|
|
15
|
|
|
|
|
53
|
|
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
# Pick a possible indeterminate
|
1171
|
15
|
|
|
|
|
31
|
for(keys(%v))
|
1172
|
19
|
50
|
|
|
|
17
|
{delete $v{$_} if scalar(keys(%{$v{$_}})) == 1;
|
|
19
|
|
|
|
|
46
|
|
1173
|
|
|
|
|
|
|
}
|
1174
|
15
|
100
|
|
|
|
32
|
return $p unless scalar(keys(%v));
|
1175
|
14
|
|
|
|
|
23
|
$v = (keys(%v))[0];
|
1176
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
# Divide P by Q
|
1178
|
14
|
|
|
|
|
16
|
my $r;
|
1179
|
14
|
100
|
|
|
|
32
|
$r = $P->polynomialDivide($Q, $v); return $r if defined($r);
|
|
14
|
|
|
|
|
60
|
|
1180
|
2
|
50
|
|
|
|
4
|
$r = $Q->polynomialDivide($P, $v); return one()->divide($r) if defined($r);
|
|
2
|
|
|
|
|
8
|
|
1181
|
0
|
|
|
|
|
0
|
$p;
|
1182
|
|
|
|
|
|
|
}
|
1183
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
=head3 Sqrt
|
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
Square root of a sum
|
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
=cut
|
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
sub Sqrt($)
|
1193
|
140
|
|
|
140
|
1
|
126
|
{my ($x) = @_;
|
1194
|
140
|
|
|
|
|
222
|
my $s = $x->st;
|
1195
|
140
|
100
|
|
|
|
228
|
if (defined($s))
|
1196
|
62
|
|
|
|
|
198
|
{my $r = $s->sqrt2;
|
1197
|
62
|
100
|
|
|
|
138
|
return sigma($r) if defined($r);
|
1198
|
|
|
|
|
|
|
}
|
1199
|
|
|
|
|
|
|
|
1200
|
114
|
|
|
|
|
2936
|
sigma(term()->c(1)->Sqrt($x)->z);
|
1201
|
|
|
|
|
|
|
}
|
1202
|
|
|
|
|
|
|
|
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=head3 Exp
|
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
Exponential (B raised to the power) of a sum
|
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
=cut
|
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
|
1211
|
|
|
|
|
|
|
sub Exp($)
|
1212
|
484
|
|
|
484
|
1
|
428
|
{my ($x) = @_;
|
1213
|
484
|
|
|
|
|
11325
|
my $p = term()->one;
|
1214
|
484
|
|
|
|
|
839
|
my @r;
|
1215
|
484
|
|
|
|
|
624
|
for my $t($x->t)
|
1216
|
548
|
|
|
|
|
964
|
{my $r = $t->exp2;
|
1217
|
548
|
100
|
|
|
|
734
|
$p = $p->multiply($r) if $r;
|
1218
|
548
|
100
|
|
|
|
1424
|
push @r, $t unless $r;
|
1219
|
|
|
|
|
|
|
}
|
1220
|
484
|
100
|
|
|
|
744
|
return sigma($p) if scalar(@r) == 0;
|
1221
|
473
|
|
|
|
|
795
|
return sigma($p->clone->Exp(sigma(@r))->z);
|
1222
|
|
|
|
|
|
|
}
|
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
=head3 Log
|
1226
|
|
|
|
|
|
|
|
1227
|
|
|
|
|
|
|
Log to base B of a sum
|
1228
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
=cut
|
1230
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
|
1232
|
|
|
|
|
|
|
sub Log($)
|
1233
|
1
|
|
|
1
|
1
|
2
|
{my ($x) = @_;
|
1234
|
1
|
|
|
|
|
3
|
my $s = $x->st;
|
1235
|
1
|
50
|
|
|
|
3
|
if (defined($s))
|
1236
|
1
|
|
|
|
|
3
|
{my $r = $s->log2;
|
1237
|
1
|
50
|
|
|
|
3
|
return sigma($r) if defined($r);
|
1238
|
|
|
|
|
|
|
}
|
1239
|
|
|
|
|
|
|
|
1240
|
1
|
|
|
|
|
26
|
sigma(term()->c(1)->Log($x)->z);
|
1241
|
|
|
|
|
|
|
}
|
1242
|
|
|
|
|
|
|
|
1243
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
=head3 Sin
|
1245
|
|
|
|
|
|
|
|
1246
|
|
|
|
|
|
|
Sine of a sum
|
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
=cut
|
1249
|
|
|
|
|
|
|
|
1250
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
sub Sin($)
|
1252
|
136
|
|
|
136
|
1
|
121
|
{my ($x) = @_;
|
1253
|
136
|
|
|
|
|
228
|
my $s = $x->st;
|
1254
|
136
|
100
|
|
|
|
225
|
if (defined($s))
|
1255
|
120
|
|
|
|
|
260
|
{my $r = $s->sin2;
|
1256
|
120
|
100
|
|
|
|
213
|
return sigma($r) if defined($r);
|
1257
|
|
|
|
|
|
|
}
|
1258
|
|
|
|
|
|
|
|
1259
|
113
|
|
|
|
|
181
|
my $a = $i->multiply($x);
|
1260
|
113
|
|
|
|
|
150
|
$i->multiply($half)->multiply($a->negate->Exp->subtract($a->Exp));
|
1261
|
|
|
|
|
|
|
}
|
1262
|
|
|
|
|
|
|
|
1263
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
=head3 Cos
|
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
Cosine of a sum
|
1267
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
=cut
|
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
|
1271
|
|
|
|
|
|
|
sub Cos($)
|
1272
|
141
|
|
|
141
|
1
|
131
|
{my ($x) = @_;
|
1273
|
141
|
|
|
|
|
202
|
my $s = $x->st;
|
1274
|
141
|
100
|
|
|
|
230
|
if (defined($s))
|
1275
|
125
|
|
|
|
|
249
|
{my $r = $s->cos2;
|
1276
|
125
|
100
|
|
|
|
226
|
return sigma($r) if defined($r);
|
1277
|
|
|
|
|
|
|
}
|
1278
|
|
|
|
|
|
|
|
1279
|
118
|
|
|
|
|
169
|
my $a = $i->multiply($x);
|
1280
|
118
|
|
|
|
|
195
|
$half->multiply($a->negate->Exp->add($a->Exp));
|
1281
|
|
|
|
|
|
|
}
|
1282
|
|
|
|
|
|
|
|
1283
|
|
|
|
|
|
|
|
1284
|
|
|
|
|
|
|
=head3 tan, Ssc, csc, cot
|
1285
|
|
|
|
|
|
|
|
1286
|
|
|
|
|
|
|
Tan, sec, csc, cot of a sum
|
1287
|
|
|
|
|
|
|
|
1288
|
|
|
|
|
|
|
=cut
|
1289
|
|
|
|
|
|
|
|
1290
|
|
|
|
|
|
|
|
1291
|
27
|
|
|
27
|
1
|
37
|
sub tan($) {my ($x) = @_; $x->Sin()->divide($x->Cos())}
|
|
27
|
|
|
|
|
50
|
|
1292
|
11
|
|
|
11
|
0
|
15
|
sub sec($) {my ($x) = @_; $one ->divide($x->Cos())}
|
|
11
|
|
|
|
|
21
|
|
1293
|
11
|
|
|
11
|
1
|
13
|
sub csc($) {my ($x) = @_; $one ->divide($x->Sin())}
|
|
11
|
|
|
|
|
20
|
|
1294
|
11
|
|
|
11
|
1
|
11
|
sub cot($) {my ($x) = @_; $x->Cos()->divide($x->Sin())}
|
|
11
|
|
|
|
|
20
|
|
1295
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
|
1297
|
|
|
|
|
|
|
=head3 sinh
|
1298
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
Hyperbolic sine of a sum
|
1300
|
|
|
|
|
|
|
|
1301
|
|
|
|
|
|
|
=cut
|
1302
|
|
|
|
|
|
|
|
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
sub sinh($)
|
1305
|
34
|
|
|
34
|
1
|
34
|
{my ($x) = @_;
|
1306
|
|
|
|
|
|
|
|
1307
|
34
|
50
|
|
|
|
71
|
return $zero if $x->{id} == $zero->{id};
|
1308
|
|
|
|
|
|
|
|
1309
|
34
|
|
|
|
|
50
|
my $n = $x->negate;
|
1310
|
34
|
|
|
|
|
742
|
sigma
|
1311
|
|
|
|
|
|
|
(term()->c( 1)->divideInt(2)->Exp($x)->z,
|
1312
|
|
|
|
|
|
|
term()->c(-1)->divideInt(2)->Exp($n)->z
|
1313
|
|
|
|
|
|
|
)
|
1314
|
|
|
|
|
|
|
}
|
1315
|
|
|
|
|
|
|
|
1316
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
=head3 cosh
|
1318
|
|
|
|
|
|
|
|
1319
|
|
|
|
|
|
|
Hyperbolic cosine of a sum
|
1320
|
|
|
|
|
|
|
|
1321
|
|
|
|
|
|
|
=cut
|
1322
|
|
|
|
|
|
|
|
1323
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
sub cosh($)
|
1325
|
34
|
|
|
34
|
1
|
27
|
{my ($x) = @_;
|
1326
|
|
|
|
|
|
|
|
1327
|
34
|
50
|
|
|
|
69
|
return $one if $x->{id} == $zero->{id};
|
1328
|
|
|
|
|
|
|
|
1329
|
34
|
|
|
|
|
49
|
my $n = $x->negate;
|
1330
|
34
|
|
|
|
|
743
|
sigma
|
1331
|
|
|
|
|
|
|
(term()->c(1)->divideInt(2)->Exp($x)->z,
|
1332
|
|
|
|
|
|
|
term()->c(1)->divideInt(2)->Exp($n)->z
|
1333
|
|
|
|
|
|
|
)
|
1334
|
|
|
|
|
|
|
}
|
1335
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
|
1337
|
|
|
|
|
|
|
=head3 Tanh, Sech, Csch, Coth
|
1338
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
Tanh, Sech, Csch, Coth of a sum
|
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
=cut
|
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
|
1344
|
14
|
|
|
14
|
0
|
16
|
sub tanh($) {my ($x) = @_; $x->sinh()->divide($x->cosh())}
|
|
14
|
|
|
|
|
25
|
|
1345
|
4
|
|
|
4
|
0
|
5
|
sub sech($) {my ($x) = @_; $one ->divide($x->cosh())}
|
|
4
|
|
|
|
|
8
|
|
1346
|
4
|
|
|
4
|
0
|
6
|
sub csch($) {my ($x) = @_; $one ->divide($x->sinh())}
|
|
4
|
|
|
|
|
6
|
|
1347
|
4
|
|
|
4
|
0
|
4
|
sub coth($) {my ($x) = @_; $x->cosh()->divide($x->sinh())}
|
|
4
|
|
|
|
|
9
|
|
1348
|
|
|
|
|
|
|
|
1349
|
|
|
|
|
|
|
|
1350
|
|
|
|
|
|
|
=head3 dot
|
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
Dot - complex dot product of two complex sums
|
1353
|
|
|
|
|
|
|
|
1354
|
|
|
|
|
|
|
=cut
|
1355
|
|
|
|
|
|
|
|
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
sub dot($$)
|
1358
|
51
|
|
|
51
|
1
|
53
|
{my ($a, $b) = @_;
|
1359
|
51
|
50
|
|
|
|
91
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1360
|
51
|
|
|
|
|
88
|
$a->re->multiply($b->re)->add($a->im->multiply($b->im));
|
1361
|
|
|
|
|
|
|
}
|
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
=head3 cross
|
1365
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
The area of the parallelogram formed by two complex sums
|
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
=cut
|
1369
|
|
|
|
|
|
|
|
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
sub cross($$)
|
1372
|
12
|
|
|
12
|
1
|
12
|
{my ($a, $b) = @_;
|
1373
|
12
|
|
|
|
|
39
|
$a->dot($a)->multiply($b->dot($b))->subtract($a->dot($b)->power($two))->Sqrt;
|
1374
|
|
|
|
|
|
|
}
|
1375
|
|
|
|
|
|
|
|
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
=head3 unit
|
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
Intersection of a complex sum with the unit circle.
|
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
=cut
|
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
|
1384
|
|
|
|
|
|
|
sub unit($)
|
1385
|
10
|
|
|
10
|
1
|
13
|
{my ($a) = @_;
|
1386
|
10
|
|
|
|
|
23
|
my $b = $a->modulus;
|
1387
|
10
|
|
|
|
|
70
|
my $c = $a->divide($b);
|
1388
|
10
|
|
|
|
|
18
|
$a->divide($a->modulus);
|
1389
|
|
|
|
|
|
|
}
|
1390
|
|
|
|
|
|
|
|
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
=head3 re
|
1393
|
|
|
|
|
|
|
|
1394
|
|
|
|
|
|
|
Real part of a complex sum
|
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
=cut
|
1397
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
sub re($)
|
1400
|
163
|
|
|
163
|
1
|
127
|
{my ($A) = @_;
|
1401
|
163
|
50
|
|
|
|
288
|
$A = newFromString("$A") unless ref($A) eq __PACKAGE__;
|
1402
|
163
|
|
|
|
|
114
|
my @r;
|
1403
|
163
|
|
|
|
|
205
|
for my $a($A->t)
|
1404
|
328
|
100
|
|
|
|
562
|
{next if $a->i == 1;
|
1405
|
174
|
|
|
|
|
189
|
push @r, $a;
|
1406
|
|
|
|
|
|
|
}
|
1407
|
163
|
|
|
|
|
243
|
sigma(@r);
|
1408
|
|
|
|
|
|
|
}
|
1409
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
|
1411
|
|
|
|
|
|
|
=head3 im
|
1412
|
|
|
|
|
|
|
|
1413
|
|
|
|
|
|
|
Imaginary part of a complex sum
|
1414
|
|
|
|
|
|
|
|
1415
|
|
|
|
|
|
|
=cut
|
1416
|
|
|
|
|
|
|
|
1417
|
|
|
|
|
|
|
|
1418
|
|
|
|
|
|
|
sub im($)
|
1419
|
164
|
|
|
164
|
1
|
148
|
{my ($A) = @_;
|
1420
|
164
|
50
|
|
|
|
373
|
$A = newFromString("$A") unless ref($A) eq __PACKAGE__;
|
1421
|
164
|
|
|
|
|
122
|
my @r;
|
1422
|
164
|
|
|
|
|
196
|
for my $a($A->t)
|
1423
|
333
|
100
|
|
|
|
523
|
{next if $a->i == 0;
|
1424
|
156
|
|
|
|
|
191
|
push @r, $a;
|
1425
|
|
|
|
|
|
|
}
|
1426
|
164
|
|
|
|
|
246
|
$mI->multiply(sigma(@r));
|
1427
|
|
|
|
|
|
|
}
|
1428
|
|
|
|
|
|
|
|
1429
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
=head3 modulus
|
1431
|
|
|
|
|
|
|
|
1432
|
|
|
|
|
|
|
Modulus of a complex sum
|
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
=cut
|
1435
|
|
|
|
|
|
|
|
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
sub modulus($)
|
1438
|
47
|
|
|
47
|
1
|
41
|
{my ($a) = @_;
|
1439
|
47
|
|
|
|
|
80
|
$a->re->power($two)->add($a->im->power($two))->Sqrt;
|
1440
|
|
|
|
|
|
|
}
|
1441
|
|
|
|
|
|
|
|
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
=head3 conjugate
|
1444
|
|
|
|
|
|
|
|
1445
|
|
|
|
|
|
|
Conjugate of a complexs sum
|
1446
|
|
|
|
|
|
|
|
1447
|
|
|
|
|
|
|
=cut
|
1448
|
|
|
|
|
|
|
|
1449
|
|
|
|
|
|
|
|
1450
|
|
|
|
|
|
|
sub conjugate($)
|
1451
|
11
|
|
|
11
|
1
|
6
|
{my ($a) = @_;
|
1452
|
11
|
|
|
|
|
22
|
$a->re->subtract($a->im->multiply($i));
|
1453
|
|
|
|
|
|
|
}
|
1454
|
|
|
|
|
|
|
|
1455
|
|
|
|
|
|
|
|
1456
|
|
|
|
|
|
|
=head3 clone
|
1457
|
|
|
|
|
|
|
|
1458
|
|
|
|
|
|
|
Clone
|
1459
|
|
|
|
|
|
|
|
1460
|
|
|
|
|
|
|
=cut
|
1461
|
|
|
|
|
|
|
|
1462
|
|
|
|
|
|
|
|
1463
|
|
|
|
|
|
|
sub clone($)
|
1464
|
78
|
|
|
78
|
1
|
61
|
{my ($t) = @_;
|
1465
|
78
|
50
|
|
|
|
137
|
$t->{z} or die "Attempt to clone unfinalized sum";
|
1466
|
78
|
|
|
|
|
188
|
my $c = bless {%$t};
|
1467
|
78
|
|
|
|
|
71
|
$c->{t} = {%{$t->{t}}};
|
|
78
|
|
|
|
|
139
|
|
1468
|
78
|
|
|
|
|
88
|
delete $c->{z};
|
1469
|
78
|
|
|
|
|
68
|
delete $c->{s};
|
1470
|
78
|
|
|
|
|
53
|
delete $c->{id};
|
1471
|
78
|
|
|
|
|
124
|
$c;
|
1472
|
|
|
|
|
|
|
}
|
1473
|
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
|
1475
|
|
|
|
|
|
|
=head3 signature
|
1476
|
|
|
|
|
|
|
|
1477
|
|
|
|
|
|
|
Signature of a sum: used to optimize add().
|
1478
|
|
|
|
|
|
|
# Fix the problem of adding different logs
|
1479
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
=cut
|
1481
|
|
|
|
|
|
|
|
1482
|
|
|
|
|
|
|
|
1483
|
|
|
|
|
|
|
sub signature($)
|
1484
|
4212
|
|
|
4212
|
1
|
3318
|
{my ($t) = @_;
|
1485
|
4212
|
|
|
|
|
3387
|
my $s = '';
|
1486
|
4212
|
|
|
|
|
4546
|
for my $a($t->t)
|
1487
|
26160
|
|
|
|
|
35228
|
{$s .= '+'. $a->print;
|
1488
|
|
|
|
|
|
|
}
|
1489
|
4212
|
|
|
|
|
7973
|
$s;
|
1490
|
|
|
|
|
|
|
}
|
1491
|
|
|
|
|
|
|
|
1492
|
|
|
|
|
|
|
|
1493
|
|
|
|
|
|
|
=head3 getSignature
|
1494
|
|
|
|
|
|
|
|
1495
|
|
|
|
|
|
|
Get the signature (see L) of a sum
|
1496
|
|
|
|
|
|
|
|
1497
|
|
|
|
|
|
|
=cut
|
1498
|
|
|
|
|
|
|
|
1499
|
|
|
|
|
|
|
|
1500
|
|
|
|
|
|
|
sub getSignature($)
|
1501
|
958
|
|
|
958
|
1
|
617
|
{my ($t) = @_;
|
1502
|
958
|
50
|
|
|
|
1276
|
exists $t->{z} ? $t->{z} : die "Attempt to get signature of unfinalized sum";
|
1503
|
|
|
|
|
|
|
}
|
1504
|
|
|
|
|
|
|
|
1505
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
=head3 id
|
1507
|
|
|
|
|
|
|
|
1508
|
|
|
|
|
|
|
Get Id of sum: each sum has a unique identifying number.
|
1509
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
=cut
|
1511
|
|
|
|
|
|
|
|
1512
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
sub id($)
|
1514
|
80
|
|
|
80
|
1
|
63
|
{my ($t) = @_;
|
1515
|
80
|
50
|
|
|
|
131
|
$t->{id} or die "Sum $t not yet finalized";
|
1516
|
80
|
|
|
|
|
225
|
$t->{id};
|
1517
|
|
|
|
|
|
|
}
|
1518
|
|
|
|
|
|
|
|
1519
|
|
|
|
|
|
|
|
1520
|
|
|
|
|
|
|
=head3 zz
|
1521
|
|
|
|
|
|
|
|
1522
|
|
|
|
|
|
|
Check sum finalized. See: L.
|
1523
|
|
|
|
|
|
|
|
1524
|
|
|
|
|
|
|
=cut
|
1525
|
|
|
|
|
|
|
|
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
sub zz($)
|
1528
|
0
|
|
|
0
|
1
|
0
|
{my ($t) = @_;
|
1529
|
0
|
0
|
|
|
|
0
|
$t->{z} or die "Sum $t not yet finalized";
|
1530
|
0
|
|
|
|
|
0
|
print $t->{z}, "\n";
|
1531
|
0
|
|
|
|
|
0
|
$t;
|
1532
|
|
|
|
|
|
|
}
|
1533
|
|
|
|
|
|
|
|
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
=head3 z
|
1536
|
|
|
|
|
|
|
|
1537
|
|
|
|
|
|
|
Finalize creation of the sum: Once a sum has been finalized it becomes
|
1538
|
|
|
|
|
|
|
read only.
|
1539
|
|
|
|
|
|
|
|
1540
|
|
|
|
|
|
|
=cut
|
1541
|
|
|
|
|
|
|
|
1542
|
|
|
|
|
|
|
sub z($)
|
1543
|
10089
|
|
|
10089
|
1
|
8597
|
{my ($t) = @_;
|
1544
|
10089
|
50
|
|
|
|
14040
|
!exists($t->{z}) or die "Already finalized this term";
|
1545
|
|
|
|
|
|
|
|
1546
|
10089
|
|
|
|
|
12570
|
my $p = $t->print;
|
1547
|
10089
|
100
|
|
|
|
48870
|
return $z{$p} if defined($z{$p});
|
1548
|
4165
|
|
|
|
|
7657
|
$z{$p} = $t;
|
1549
|
4165
|
|
|
|
|
9297
|
weaken($z{$p}); # Greatly reduces memory usage.
|
1550
|
|
|
|
|
|
|
|
1551
|
4165
|
|
|
|
|
4314
|
$t->{s} = $p;
|
1552
|
4165
|
|
|
|
|
5574
|
$t->{z} = $t->signature;
|
1553
|
4165
|
|
|
|
|
4434
|
$t->{id} = ++$z;
|
1554
|
|
|
|
|
|
|
|
1555
|
|
|
|
|
|
|
#HashUtil lock_hash(%{$t->{v}}) if $lock;
|
1556
|
|
|
|
|
|
|
#HashUtil lock_hash %$t if $lock;
|
1557
|
4165
|
|
|
|
|
10320
|
$t;
|
1558
|
|
|
|
|
|
|
}
|
1559
|
|
|
|
|
|
|
|
1560
|
|
|
|
|
|
|
#sub DESTROY($)
|
1561
|
|
|
|
|
|
|
# {my ($t) = @_;
|
1562
|
|
|
|
|
|
|
# delete $z{$t->{s}} if defined($t) and exists $t->{s};
|
1563
|
|
|
|
|
|
|
# }
|
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
sub lockHashes()
|
1566
|
0
|
|
|
0
|
0
|
0
|
{my ($l) = @_;
|
1567
|
|
|
|
|
|
|
#HashUtil for my $t(values %z)
|
1568
|
|
|
|
|
|
|
#HashUtil {lock_hash(%{$t->{v}});
|
1569
|
|
|
|
|
|
|
#HashUtil lock_hash %$t;
|
1570
|
|
|
|
|
|
|
#HashUtil }
|
1571
|
0
|
|
|
|
|
0
|
$lock = 1;
|
1572
|
|
|
|
|
|
|
}
|
1573
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
|
1575
|
|
|
|
|
|
|
=head3 print
|
1576
|
|
|
|
|
|
|
|
1577
|
|
|
|
|
|
|
Print sum
|
1578
|
|
|
|
|
|
|
|
1579
|
|
|
|
|
|
|
=cut
|
1580
|
|
|
|
|
|
|
|
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
sub print($)
|
1583
|
76236
|
|
|
76236
|
1
|
50074
|
{my ($t) = @_;
|
1584
|
76236
|
100
|
|
|
|
176529
|
return $t->{s} if defined($t->{s});
|
1585
|
10089
|
|
|
|
|
7788
|
my $s = '';
|
1586
|
10089
|
|
|
|
|
12339
|
for my $a($t->t)
|
1587
|
35292
|
|
|
|
|
49882
|
{$s .= $a->print .'+';
|
1588
|
|
|
|
|
|
|
}
|
1589
|
10089
|
100
|
|
|
|
18235
|
chop($s) if $s;
|
1590
|
|
|
|
|
|
|
|
1591
|
10089
|
|
|
|
|
10980
|
$s =~ s/^\+//;
|
1592
|
10089
|
|
|
|
|
15970
|
$s =~ s/\+\-/\-/g;
|
1593
|
10089
|
|
|
|
|
11545
|
$s =~ s/\+1\*/\+/g; # change: +1* to +
|
1594
|
10089
|
|
|
|
|
9124
|
$s =~ s/\*1\*/\*/g; # remove: *1* to *
|
1595
|
10089
|
|
|
|
|
11889
|
$s =~ s/^1\*//g; # remove: 1* at start of expression
|
1596
|
10089
|
|
|
|
|
9880
|
$s =~ s/^\-1\*/\-/g; # change: -1* at start of expression to -
|
1597
|
10089
|
|
|
|
|
7271
|
$s =~ s/^0\+//g; # change: 0+ at start of expression to
|
1598
|
10089
|
|
|
|
|
7557
|
$s =~ s/\+0$//; # remove: +0 at end of expression
|
1599
|
10089
|
|
|
|
|
8319
|
$s =~ s#\(\+0\+#\(#g; # change: (+0+ to (
|
1600
|
10089
|
|
|
|
|
8349
|
$s =~ s/\(\+/\(/g; # change: (+ to (
|
1601
|
10089
|
|
|
|
|
9120
|
$s =~ s/\(1\*/\(/g; # change: (1* to (
|
1602
|
10089
|
|
|
|
|
8628
|
$s =~ s/\(\-1\*/\(\-/g; # change: (-1* to (-
|
1603
|
10089
|
|
|
|
|
12564
|
$s =~ s/([a-zA-Z0-9)])\-1\*/$1\-/g; # change: term-1* to term-
|
1604
|
10089
|
|
|
|
|
8547
|
$s =~ s/\*(\$[a-zA-Z]+)\*\*\-1(?!\d)/\/$1/g; # change: *$y**-1 to /$y
|
1605
|
10089
|
|
|
|
|
8287
|
$s =~ s/\*(\$[a-zA-Z]+)\*\*\-(\d+)/\/$1**$2/g; # change: *$y**-n to /$y**n
|
1606
|
10089
|
|
|
|
|
8539
|
$s =~ s/([\+\-])(\$[a-zA-Z]+)\*\*\-1(?!\d)/1\/$1/g; # change: +-$y**-1 to +-1/$y
|
1607
|
10089
|
|
|
|
|
8091
|
$s =~ s/([\+\-])(\$[a-zA-Z]+)\*\*\-(\d+)/${1}1\/$2**$3/g; # change: +-$y**-n to +-1/$y**n
|
1608
|
10089
|
100
|
|
|
|
14290
|
$s = 0 if $s eq '';
|
1609
|
10089
|
|
|
|
|
12971
|
$s;
|
1610
|
|
|
|
|
|
|
}
|
1611
|
|
|
|
|
|
|
|
1612
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
=head3 factorize
|
1614
|
|
|
|
|
|
|
|
1615
|
|
|
|
|
|
|
Factorize a number.
|
1616
|
|
|
|
|
|
|
|
1617
|
|
|
|
|
|
|
=cut
|
1618
|
|
|
|
|
|
|
|
1619
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
my @primes = qw(
|
1621
|
|
|
|
|
|
|
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61
|
1622
|
|
|
|
|
|
|
67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151
|
1623
|
|
|
|
|
|
|
157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251
|
1624
|
|
|
|
|
|
|
257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359
|
1625
|
|
|
|
|
|
|
367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463
|
1626
|
|
|
|
|
|
|
467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593
|
1627
|
|
|
|
|
|
|
599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701
|
1628
|
|
|
|
|
|
|
709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827
|
1629
|
|
|
|
|
|
|
829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953
|
1630
|
|
|
|
|
|
|
967 971 977 983 991 997);
|
1631
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
sub factorize($)
|
1633
|
0
|
|
|
0
|
1
|
0
|
{my ($n) = @_;
|
1634
|
0
|
|
|
|
|
0
|
my $f;
|
1635
|
|
|
|
|
|
|
|
1636
|
0
|
|
|
|
|
0
|
for my $p(@primes)
|
1637
|
0
|
|
|
|
|
0
|
{for(;$n % $p == 0;)
|
1638
|
0
|
|
|
|
|
0
|
{$f->{$p}++;
|
1639
|
0
|
|
|
|
|
0
|
$n /= $p;
|
1640
|
|
|
|
|
|
|
}
|
1641
|
0
|
0
|
|
|
|
0
|
last unless $n > $p;
|
1642
|
|
|
|
|
|
|
}
|
1643
|
0
|
|
|
|
|
0
|
$f;
|
1644
|
|
|
|
|
|
|
};
|
1645
|
|
|
|
|
|
|
|
1646
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
=head2 import
|
1648
|
|
|
|
|
|
|
|
1649
|
|
|
|
|
|
|
Export L with either the default name B, or a name supplied by
|
1650
|
|
|
|
|
|
|
the caller of this package.
|
1651
|
|
|
|
|
|
|
|
1652
|
|
|
|
|
|
|
=cut
|
1653
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
|
1655
|
|
|
|
|
|
|
sub import
|
1656
|
45
|
|
|
45
|
|
121
|
{my %P = (program=>@_);
|
1657
|
45
|
|
|
|
|
52
|
my %p; $p{lc()} = $P{$_} for(keys(%P));
|
|
45
|
|
|
|
|
182
|
|
1658
|
|
|
|
|
|
|
|
1659
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1660
|
|
|
|
|
|
|
# New sum constructor - export to calling package.
|
1661
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1662
|
|
|
|
|
|
|
|
1663
|
45
|
|
|
|
|
67
|
my $s = "package XXXX;\n". <<'END';
|
1664
|
|
|
|
|
|
|
no warnings 'redefine';
|
1665
|
|
|
|
|
|
|
sub NNNN
|
1666
|
|
|
|
|
|
|
{return SSSSn(@_);
|
1667
|
|
|
|
|
|
|
}
|
1668
|
|
|
|
|
|
|
use warnings 'redefine';
|
1669
|
|
|
|
|
|
|
END
|
1670
|
|
|
|
|
|
|
|
1671
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1672
|
|
|
|
|
|
|
# Export to calling package.
|
1673
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1674
|
|
|
|
|
|
|
|
1675
|
45
|
|
|
|
|
50
|
my $name = 'sum';
|
1676
|
45
|
50
|
|
|
|
120
|
$name = $p{sum} if exists($p{sum});
|
1677
|
45
|
|
|
|
|
110
|
my ($main) = caller();
|
1678
|
45
|
|
|
|
|
59
|
my $pack = __PACKAGE__ . '::';
|
1679
|
|
|
|
|
|
|
|
1680
|
45
|
|
|
|
|
155
|
$s=~ s/XXXX/$main/g;
|
1681
|
45
|
|
|
|
|
122
|
$s=~ s/NNNN/$name/g;
|
1682
|
45
|
|
|
|
|
107
|
$s=~ s/SSSS/$pack/g;
|
1683
|
45
|
|
|
45
|
0
|
199
|
eval($s);
|
|
45
|
|
|
45
|
|
39
|
|
|
45
|
|
|
66
|
|
2803
|
|
|
45
|
|
|
|
|
167
|
|
|
45
|
|
|
|
|
49
|
|
|
45
|
|
|
|
|
1120
|
|
|
45
|
|
|
|
|
3126
|
|
|
66
|
|
|
|
|
273
|
|
1684
|
|
|
|
|
|
|
|
1685
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1686
|
|
|
|
|
|
|
# Check options supplied by user
|
1687
|
|
|
|
|
|
|
#_______________________________________________________________________
|
1688
|
|
|
|
|
|
|
|
1689
|
45
|
|
|
|
|
121
|
delete @p{qw(program sum)};
|
1690
|
|
|
|
|
|
|
|
1691
|
45
|
50
|
|
|
|
999
|
croak "Unknown option(s): ". join(' ', keys(%p))."\n\n". <<'END' if keys(%p);
|
1692
|
|
|
|
|
|
|
|
1693
|
|
|
|
|
|
|
Valid options are:
|
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
sum =>'name' Create a routine with this name in the callers
|
1696
|
|
|
|
|
|
|
namespace to create new symbols. The default is
|
1697
|
|
|
|
|
|
|
'sum'.
|
1698
|
|
|
|
|
|
|
END
|
1699
|
|
|
|
|
|
|
}
|
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
|
1702
|
|
|
|
|
|
|
=head2 Operators
|
1703
|
|
|
|
|
|
|
|
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
=head3 Operator Overloads
|
1706
|
|
|
|
|
|
|
|
1707
|
|
|
|
|
|
|
Overload Perl operators. Beware the low priority of B<^>.
|
1708
|
|
|
|
|
|
|
|
1709
|
|
|
|
|
|
|
=cut
|
1710
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
|
1712
|
|
|
|
|
|
|
use overload
|
1713
|
45
|
|
|
|
|
602
|
'+' =>\&add3,
|
1714
|
|
|
|
|
|
|
'-' =>\&negate3,
|
1715
|
|
|
|
|
|
|
'*' =>\&multiply3,
|
1716
|
|
|
|
|
|
|
'/' =>\÷3,
|
1717
|
|
|
|
|
|
|
'**' =>\&power3,
|
1718
|
|
|
|
|
|
|
'==' =>\&equals3,
|
1719
|
|
|
|
|
|
|
'!=' =>\&nequal3,
|
1720
|
|
|
|
|
|
|
'eq' =>\&negate3,
|
1721
|
|
|
|
|
|
|
'>' =>\&solve3,
|
1722
|
|
|
|
|
|
|
'<=>' =>\&tequals3,
|
1723
|
|
|
|
|
|
|
'sqrt' =>\&sqrt3,
|
1724
|
|
|
|
|
|
|
'exp' =>\&exp3,
|
1725
|
|
|
|
|
|
|
'log' =>\&log3,
|
1726
|
|
|
|
|
|
|
#'tan' =>\&tan3, # 2016/01/20 15:23:53 No longer available
|
1727
|
|
|
|
|
|
|
'sin' =>\&sin3,
|
1728
|
|
|
|
|
|
|
'cos' =>\&cos3,
|
1729
|
|
|
|
|
|
|
'""' =>\&print3,
|
1730
|
|
|
|
|
|
|
'^' =>\&dot3, # Beware the low priority of this operator
|
1731
|
|
|
|
|
|
|
'~' =>\&conjugate3,
|
1732
|
|
|
|
|
|
|
'x' =>\&cross3,
|
1733
|
|
|
|
|
|
|
'abs' =>\&modulus3,
|
1734
|
|
|
|
|
|
|
'!' =>\&unit3,
|
1735
|
45
|
|
|
45
|
|
297
|
fallback=>1;
|
|
45
|
|
|
|
|
52
|
|
1736
|
|
|
|
|
|
|
|
1737
|
|
|
|
|
|
|
|
1738
|
|
|
|
|
|
|
=head3 add3
|
1739
|
|
|
|
|
|
|
|
1740
|
|
|
|
|
|
|
Add operator.
|
1741
|
|
|
|
|
|
|
|
1742
|
|
|
|
|
|
|
=cut
|
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
|
1745
|
|
|
|
|
|
|
sub add3
|
1746
|
282
|
|
|
282
|
1
|
412
|
{my ($a, $b) = @_;
|
1747
|
282
|
100
|
|
|
|
540
|
return simplify($a) unless defined($b); # += : simplify()
|
1748
|
269
|
100
|
|
|
|
643
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1749
|
269
|
50
|
33
|
|
|
967
|
$a->{z} and $b->{z} or die "Add using unfinalized sums";
|
1750
|
269
|
|
|
|
|
550
|
$a->add($b);
|
1751
|
|
|
|
|
|
|
}
|
1752
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
=head3 negate3
|
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
Negate operator. Used in combination with the L operator to
|
1757
|
|
|
|
|
|
|
perform subtraction.
|
1758
|
|
|
|
|
|
|
|
1759
|
|
|
|
|
|
|
=cut
|
1760
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
|
1762
|
|
|
|
|
|
|
sub negate3
|
1763
|
244
|
|
|
244
|
1
|
398
|
{my ($a, $b, $c) = @_;
|
1764
|
|
|
|
|
|
|
|
1765
|
244
|
50
|
|
|
|
420
|
if (defined($b))
|
1766
|
244
|
100
|
|
|
|
695
|
{$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1767
|
244
|
50
|
33
|
|
|
1047
|
$a->{z} and $b->{z} or die "Negate using unfinalized sums";
|
1768
|
244
|
100
|
|
|
|
545
|
return $b->subtract($a) if $c;
|
1769
|
161
|
50
|
|
|
|
454
|
return $a->subtract($b) unless $c;
|
1770
|
|
|
|
|
|
|
}
|
1771
|
|
|
|
|
|
|
else
|
1772
|
0
|
0
|
|
|
|
0
|
{$a->{z} or die "Negate single unfinalized terms";
|
1773
|
0
|
|
|
|
|
0
|
return $a->negate;
|
1774
|
|
|
|
|
|
|
}
|
1775
|
|
|
|
|
|
|
}
|
1776
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
|
1778
|
|
|
|
|
|
|
=head3 multiply3
|
1779
|
|
|
|
|
|
|
|
1780
|
|
|
|
|
|
|
Multiply operator.
|
1781
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
=cut
|
1783
|
|
|
|
|
|
|
|
1784
|
|
|
|
|
|
|
|
1785
|
|
|
|
|
|
|
sub multiply3
|
1786
|
416
|
|
|
416
|
1
|
679
|
{my ($a, $b) = @_;
|
1787
|
416
|
100
|
|
|
|
1132
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1788
|
416
|
50
|
33
|
|
|
2465
|
$a->{z} and $b->{z} or die "Multiply using unfinalized sums";
|
1789
|
416
|
|
|
|
|
793
|
$a->multiply($b);
|
1790
|
|
|
|
|
|
|
}
|
1791
|
|
|
|
|
|
|
|
1792
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
=head3 divide3
|
1794
|
|
|
|
|
|
|
|
1795
|
|
|
|
|
|
|
Divide operator.
|
1796
|
|
|
|
|
|
|
|
1797
|
|
|
|
|
|
|
=cut
|
1798
|
|
|
|
|
|
|
|
1799
|
|
|
|
|
|
|
|
1800
|
|
|
|
|
|
|
sub divide3
|
1801
|
167
|
|
|
167
|
1
|
255
|
{my ($a, $b, $c) = @_;
|
1802
|
167
|
100
|
|
|
|
528
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1803
|
167
|
50
|
33
|
|
|
604
|
$a->{z} and $b->{z} or die "Divide using unfinalized sums";
|
1804
|
167
|
100
|
|
|
|
342
|
return $b->divide($a) if $c;
|
1805
|
143
|
50
|
|
|
|
443
|
return $a->divide($b) unless $c;
|
1806
|
|
|
|
|
|
|
}
|
1807
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
|
1809
|
|
|
|
|
|
|
=head3 power3
|
1810
|
|
|
|
|
|
|
|
1811
|
|
|
|
|
|
|
Power operator.
|
1812
|
|
|
|
|
|
|
|
1813
|
|
|
|
|
|
|
=cut
|
1814
|
|
|
|
|
|
|
|
1815
|
|
|
|
|
|
|
|
1816
|
|
|
|
|
|
|
sub power3
|
1817
|
173
|
|
|
173
|
1
|
390
|
{my ($a, $b) = @_;
|
1818
|
173
|
50
|
|
|
|
629
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1819
|
173
|
50
|
33
|
|
|
632
|
$a->{z} and $b->{z} or die "Power using unfinalized sums";
|
1820
|
173
|
|
|
|
|
367
|
$a->power($b);
|
1821
|
|
|
|
|
|
|
}
|
1822
|
|
|
|
|
|
|
|
1823
|
|
|
|
|
|
|
|
1824
|
|
|
|
|
|
|
=head3 equals3
|
1825
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
Equals operator.
|
1827
|
|
|
|
|
|
|
|
1828
|
|
|
|
|
|
|
=cut
|
1829
|
|
|
|
|
|
|
|
1830
|
|
|
|
|
|
|
|
1831
|
|
|
|
|
|
|
sub equals3
|
1832
|
259
|
|
|
259
|
1
|
446
|
{my ($a, $b) = @_;
|
1833
|
259
|
100
|
|
|
|
653
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
1834
|
259
|
50
|
33
|
|
|
916
|
$a->{z} and $b->{z} or die "Equals using unfinalized sums";
|
1835
|
|
|
|
|
|
|
|
1836
|
259
|
100
|
|
|
|
1123
|
return 1 if $a->{id} == $b->{id}; # Fast equals
|
1837
|
|
|
|
|
|
|
|
1838
|
58
|
|
|
|
|
112
|
my $c = $a->subtract($b);
|
1839
|
|
|
|
|
|
|
|
1840
|
58
|
100
|
|
|
|
221
|
return 1 if $c->isZero()->{id} == $zero->{id};
|
1841
|
9
|
|
|
|
|
62
|
return 0;
|
1842
|
|
|
|
|
|
|
}
|
1843
|
|
|
|
|
|
|
|
1844
|
|
|
|
|
|
|
|
1845
|
|
|
|
|
|
|
=head3 nequal3
|
1846
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
Not equal operator.
|
1848
|
|
|
|
|
|
|
|
1849
|
|
|
|
|
|
|
=cut
|
1850
|
|
|
|
|
|
|
|
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
sub nequal3
|
1853
|
9
|
|
|
9
|
1
|
16
|
{my ($a, $b) = @_;
|
1854
|
9
|
|
|
|
|
22
|
!equals3($a, $b);
|
1855
|
|
|
|
|
|
|
}
|
1856
|
|
|
|
|
|
|
|
1857
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
=head3 tequals
|
1859
|
|
|
|
|
|
|
|
1860
|
|
|
|
|
|
|
Evaluate the expression on the left hand side, stringify it, then
|
1861
|
|
|
|
|
|
|
compare it for string equality with the string on the right hand side.
|
1862
|
|
|
|
|
|
|
This operator is useful for making examples written with Test::Simple
|
1863
|
|
|
|
|
|
|
more readable.
|
1864
|
|
|
|
|
|
|
|
1865
|
|
|
|
|
|
|
=cut
|
1866
|
|
|
|
|
|
|
|
1867
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
sub tequals3
|
1869
|
27
|
|
|
27
|
0
|
49
|
{my ($a, $b) = @_;
|
1870
|
|
|
|
|
|
|
|
1871
|
27
|
100
|
|
|
|
61
|
return 1 if "$a" eq $b;
|
1872
|
|
|
|
|
|
|
|
1873
|
2
|
|
|
|
|
8
|
my $z = simplify($a);
|
1874
|
|
|
|
|
|
|
|
1875
|
2
|
|
|
|
|
6
|
"$z" eq "$b";
|
1876
|
|
|
|
|
|
|
}
|
1877
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
|
1879
|
|
|
|
|
|
|
=head3 solve3
|
1880
|
|
|
|
|
|
|
|
1881
|
|
|
|
|
|
|
Solve operator.
|
1882
|
|
|
|
|
|
|
|
1883
|
|
|
|
|
|
|
=cut
|
1884
|
|
|
|
|
|
|
|
1885
|
|
|
|
|
|
|
|
1886
|
|
|
|
|
|
|
sub solve3
|
1887
|
7
|
|
|
7
|
1
|
16
|
{my ($a, $b) = @_;
|
1888
|
7
|
50
|
|
|
|
22
|
$a->{z} or die "Solve using unfinalized sum";
|
1889
|
|
|
|
|
|
|
# $b =~ /^[a-z]+$/i or croak "Bad variable $b to solve for";
|
1890
|
7
|
|
|
|
|
17
|
solve($a, $b);
|
1891
|
|
|
|
|
|
|
}
|
1892
|
|
|
|
|
|
|
|
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
=head3 print3
|
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
Print operator.
|
1897
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
=cut
|
1899
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
|
1901
|
|
|
|
|
|
|
sub print3
|
1902
|
66147
|
|
|
66147
|
1
|
48469
|
{my ($a) = @_;
|
1903
|
66147
|
50
|
|
|
|
78665
|
$a->{z} or die "Print of unfinalized sum";
|
1904
|
66147
|
|
|
|
|
63536
|
$a->print();
|
1905
|
|
|
|
|
|
|
}
|
1906
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
|
1908
|
|
|
|
|
|
|
=head3 sqrt3
|
1909
|
|
|
|
|
|
|
|
1910
|
|
|
|
|
|
|
Sqrt operator.
|
1911
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
=cut
|
1913
|
|
|
|
|
|
|
|
1914
|
|
|
|
|
|
|
|
1915
|
|
|
|
|
|
|
sub sqrt3
|
1916
|
55
|
|
|
55
|
1
|
64
|
{my ($a) = @_;
|
1917
|
55
|
50
|
|
|
|
114
|
$a->{z} or die "Sqrt of unfinalized sum";
|
1918
|
55
|
|
|
|
|
105
|
$a->Sqrt();
|
1919
|
|
|
|
|
|
|
}
|
1920
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
|
1922
|
|
|
|
|
|
|
=head3 exp3
|
1923
|
|
|
|
|
|
|
|
1924
|
|
|
|
|
|
|
Exp operator.
|
1925
|
|
|
|
|
|
|
|
1926
|
|
|
|
|
|
|
=cut
|
1927
|
|
|
|
|
|
|
|
1928
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
sub exp3
|
1930
|
22
|
|
|
22
|
1
|
38
|
{my ($a) = @_;
|
1931
|
22
|
50
|
|
|
|
46
|
$a->{z} or die "Exp of unfinalized sum";
|
1932
|
22
|
|
|
|
|
48
|
$a->Exp();
|
1933
|
|
|
|
|
|
|
}
|
1934
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
=head3 sin3
|
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
Sine operator.
|
1939
|
|
|
|
|
|
|
|
1940
|
|
|
|
|
|
|
=cut
|
1941
|
|
|
|
|
|
|
|
1942
|
|
|
|
|
|
|
|
1943
|
|
|
|
|
|
|
sub sin3
|
1944
|
87
|
|
|
87
|
1
|
142
|
{my ($a) = @_;
|
1945
|
87
|
50
|
|
|
|
168
|
$a->{z} or die "Sin of unfinalized sum";
|
1946
|
87
|
|
|
|
|
154
|
$a->Sin();
|
1947
|
|
|
|
|
|
|
}
|
1948
|
|
|
|
|
|
|
|
1949
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
=head3 cos3
|
1951
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
Cosine operator.
|
1953
|
|
|
|
|
|
|
|
1954
|
|
|
|
|
|
|
=cut
|
1955
|
|
|
|
|
|
|
|
1956
|
|
|
|
|
|
|
|
1957
|
|
|
|
|
|
|
sub cos3
|
1958
|
92
|
|
|
92
|
1
|
99
|
{my ($a) = @_;
|
1959
|
92
|
50
|
|
|
|
192
|
$a->{z} or die "Cos of unfinalized sum";
|
1960
|
92
|
|
|
|
|
168
|
$a->Cos();
|
1961
|
|
|
|
|
|
|
}
|
1962
|
|
|
|
|
|
|
|
1963
|
|
|
|
|
|
|
|
1964
|
|
|
|
|
|
|
=head3 tan3
|
1965
|
|
|
|
|
|
|
|
1966
|
|
|
|
|
|
|
Tan operator.
|
1967
|
|
|
|
|
|
|
|
1968
|
|
|
|
|
|
|
=cut
|
1969
|
|
|
|
|
|
|
|
1970
|
|
|
|
|
|
|
|
1971
|
|
|
|
|
|
|
sub tan3
|
1972
|
0
|
|
|
0
|
1
|
0
|
{my ($a) = @_;
|
1973
|
0
|
0
|
|
|
|
0
|
$a->{z} or die "Tan of unfinalized sum";
|
1974
|
0
|
|
|
|
|
0
|
$a->tan();
|
1975
|
|
|
|
|
|
|
}
|
1976
|
|
|
|
|
|
|
|
1977
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
=head3 log3
|
1979
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
Log operator.
|
1981
|
|
|
|
|
|
|
|
1982
|
|
|
|
|
|
|
=cut
|
1983
|
|
|
|
|
|
|
|
1984
|
|
|
|
|
|
|
|
1985
|
|
|
|
|
|
|
sub log3
|
1986
|
1
|
|
|
1
|
1
|
4
|
{my ($a) = @_;
|
1987
|
1
|
50
|
|
|
|
3
|
$a->{z} or die "Log of unfinalized sum";
|
1988
|
1
|
|
|
|
|
3
|
$a->Log();
|
1989
|
|
|
|
|
|
|
}
|
1990
|
|
|
|
|
|
|
|
1991
|
|
|
|
|
|
|
|
1992
|
|
|
|
|
|
|
=head3 dot3
|
1993
|
|
|
|
|
|
|
|
1994
|
|
|
|
|
|
|
Dot Product operator.
|
1995
|
|
|
|
|
|
|
|
1996
|
|
|
|
|
|
|
=cut
|
1997
|
|
|
|
|
|
|
|
1998
|
|
|
|
|
|
|
|
1999
|
|
|
|
|
|
|
sub dot3
|
2000
|
14
|
|
|
14
|
1
|
58
|
{my ($a, $b, $c) = @_;
|
2001
|
14
|
100
|
|
|
|
38
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
2002
|
14
|
50
|
33
|
|
|
67
|
$a->{z} and $b->{z} or die "Dot of unfinalized sum";
|
2003
|
14
|
|
|
|
|
28
|
dot($a, $b);
|
2004
|
|
|
|
|
|
|
}
|
2005
|
|
|
|
|
|
|
|
2006
|
|
|
|
|
|
|
|
2007
|
|
|
|
|
|
|
=head3 cross3
|
2008
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
Cross operator.
|
2010
|
|
|
|
|
|
|
|
2011
|
|
|
|
|
|
|
=cut
|
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
|
2014
|
|
|
|
|
|
|
sub cross3
|
2015
|
11
|
|
|
11
|
1
|
155
|
{my ($a, $b, $c) = @_;
|
2016
|
11
|
100
|
|
|
|
35
|
$b = newFromString("$b") unless ref($b) eq __PACKAGE__;
|
2017
|
11
|
50
|
33
|
|
|
56
|
$a->{z} and $b->{z} or die "Cross of unfinalized sum";
|
2018
|
11
|
|
|
|
|
25
|
cross($a, $b);
|
2019
|
|
|
|
|
|
|
}
|
2020
|
|
|
|
|
|
|
|
2021
|
|
|
|
|
|
|
|
2022
|
|
|
|
|
|
|
=head3 unit3
|
2023
|
|
|
|
|
|
|
|
2024
|
|
|
|
|
|
|
Unit operator.
|
2025
|
|
|
|
|
|
|
|
2026
|
|
|
|
|
|
|
=cut
|
2027
|
|
|
|
|
|
|
|
2028
|
|
|
|
|
|
|
|
2029
|
|
|
|
|
|
|
sub unit3
|
2030
|
9
|
|
|
9
|
1
|
18
|
{my ($a, $b, $c) = @_;
|
2031
|
9
|
50
|
|
|
|
19
|
$a->{z} or die "Unit of unfinalized sum";
|
2032
|
9
|
|
|
|
|
28
|
unit($a);
|
2033
|
|
|
|
|
|
|
}
|
2034
|
|
|
|
|
|
|
|
2035
|
|
|
|
|
|
|
|
2036
|
|
|
|
|
|
|
=head3 modulus3
|
2037
|
|
|
|
|
|
|
|
2038
|
|
|
|
|
|
|
Modulus operator.
|
2039
|
|
|
|
|
|
|
|
2040
|
|
|
|
|
|
|
=cut
|
2041
|
|
|
|
|
|
|
|
2042
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
sub modulus3
|
2044
|
26
|
|
|
26
|
1
|
85
|
{my ($a, $b, $c) = @_;
|
2045
|
26
|
50
|
|
|
|
60
|
$a->{z} or die "Modulus of unfinalized sum";
|
2046
|
26
|
|
|
|
|
56
|
modulus($a);
|
2047
|
|
|
|
|
|
|
}
|
2048
|
|
|
|
|
|
|
|
2049
|
|
|
|
|
|
|
|
2050
|
|
|
|
|
|
|
=head3 conjugate3
|
2051
|
|
|
|
|
|
|
|
2052
|
|
|
|
|
|
|
Conjugate.
|
2053
|
|
|
|
|
|
|
|
2054
|
|
|
|
|
|
|
=cut
|
2055
|
|
|
|
|
|
|
|
2056
|
|
|
|
|
|
|
|
2057
|
|
|
|
|
|
|
sub conjugate3
|
2058
|
10
|
|
|
10
|
1
|
12
|
{my ($a, $b, $c) = @_;
|
2059
|
10
|
50
|
|
|
|
20
|
$a->{z} or die "Conjugate of unfinalized sum";
|
2060
|
10
|
|
|
|
|
19
|
conjugate($a);
|
2061
|
|
|
|
|
|
|
}
|
2062
|
|
|
|
|
|
|
|
2063
|
|
|
|
|
|
|
#________________________________________________________________________
|
2064
|
|
|
|
|
|
|
# Package installed successfully
|
2065
|
|
|
|
|
|
|
#________________________________________________________________________
|
2066
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
1;
|