| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# Copyright 2002 by Mats Kindahl. All rights reserved. |
|
2
|
|
|
|
|
|
|
# |
|
3
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
|
4
|
|
|
|
|
|
|
# it under the same terms as Perl itself. |
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Algorithm::Tree::NCA::Data; |
|
7
|
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
84678
|
use 5.006; |
|
|
3
|
|
|
|
|
12
|
|
|
|
3
|
|
|
|
|
403
|
|
|
9
|
3
|
|
|
3
|
|
18
|
use strict; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
112
|
|
|
10
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
|
3
|
|
|
|
|
10
|
|
|
|
3
|
|
|
|
|
132
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
3
|
|
|
3
|
|
2732
|
use fields qw(_run _magic _number _parent _leader _max _node); |
|
|
3
|
|
|
|
|
7843
|
|
|
|
3
|
|
|
|
|
30
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub new ($%) { |
|
15
|
572
|
|
|
572
|
|
646
|
my $class = shift; |
|
16
|
|
|
|
|
|
|
# Default values first, then the provided parameters |
|
17
|
572
|
|
|
|
|
2997
|
my %args = (_run => 0, # Corresponds to I(v) |
|
18
|
|
|
|
|
|
|
_magic => 0, # Corresponds to A_v |
|
19
|
|
|
|
|
|
|
_max => 0, # Maximum number assigned to subtree |
|
20
|
|
|
|
|
|
|
_number => 0, # The DFS number assigned to this node |
|
21
|
|
|
|
|
|
|
_parent => undef, # The parent node data for this node |
|
22
|
|
|
|
|
|
|
_leader => undef, # The leader node data for this node |
|
23
|
|
|
|
|
|
|
_node => undef, # The node that the data is for |
|
24
|
|
|
|
|
|
|
@_); |
|
25
|
|
|
|
|
|
|
|
|
26
|
572
|
|
|
|
|
1355
|
my $self = fields::new($class); |
|
27
|
572
|
|
|
|
|
39835
|
@$self{keys %args} = values %args; |
|
28
|
572
|
|
|
|
|
2165
|
return $self; |
|
29
|
|
|
|
|
|
|
} |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
package Algorithm::Tree::NCA; |
|
32
|
|
|
|
|
|
|
|
|
33
|
3
|
|
|
3
|
|
1000
|
use strict; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
94
|
|
|
34
|
3
|
|
|
3
|
|
84
|
use warnings; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
473
|
|
|
35
|
|
|
|
|
|
|
|
|
36
|
3
|
|
|
3
|
|
9200
|
use Data::Dumper; |
|
|
3
|
|
|
|
|
84077
|
|
|
|
3
|
|
|
|
|
704
|
|
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
require Exporter; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
|
43
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
|
44
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
our @EXPORT_OK = (); |
|
47
|
|
|
|
|
|
|
our @EXPORT = (); |
|
48
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Preloaded methods go here. |
|
51
|
|
|
|
|
|
|
|
|
52
|
3
|
|
|
3
|
|
33
|
use fields qw(_get _set _data); |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
28
|
|
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub _set_method { |
|
55
|
572
|
|
|
572
|
|
624
|
my($node,$value) = @_; |
|
56
|
|
|
|
|
|
|
|
|
57
|
572
|
|
|
|
|
1684
|
$node->{'_nca_number'} = $value; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub _get_method { |
|
61
|
41237
|
|
|
41237
|
|
46732
|
my($node) = @_; |
|
62
|
|
|
|
|
|
|
|
|
63
|
41237
|
|
|
|
|
119099
|
return $node->{'_nca_number'}; |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub new ($%) { |
|
68
|
9
|
|
|
9
|
0
|
16896
|
my($class,%o) = @_; |
|
69
|
|
|
|
|
|
|
|
|
70
|
9
|
50
|
|
|
|
89
|
$o{-get} = \&_get_method unless defined $o{-get}; |
|
71
|
9
|
50
|
|
|
|
84
|
$o{-set} = \&_set_method unless defined $o{-set}; |
|
72
|
|
|
|
|
|
|
|
|
73
|
9
|
|
|
|
|
49
|
my $self = fields::new($class); |
|
74
|
|
|
|
|
|
|
|
|
75
|
9
|
|
|
|
|
26099
|
$self->{_get} = $o{'-get'}; # Get method to use |
|
76
|
9
|
|
|
|
|
30
|
$self->{_set} = $o{'-set'}; # Set method to use |
|
77
|
9
|
|
|
|
|
25
|
$self->{_data} = []; # Array of node data |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# Preprocess the tree if there is one supplied |
|
81
|
9
|
100
|
|
|
|
62
|
$self->preprocess($o{-tree}) if exists $o{-tree}; |
|
82
|
|
|
|
|
|
|
|
|
83
|
9
|
|
|
|
|
149
|
return $self; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub _get ($$) { |
|
87
|
41237
|
|
|
41237
|
|
51698
|
my($self,$node) = @_; |
|
88
|
41237
|
|
|
|
|
77729
|
$self->{_get}->($node); |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub _set ($$$) { |
|
92
|
572
|
|
|
572
|
|
716
|
my($self,$node,$val) = @_; |
|
93
|
572
|
|
|
|
|
1038
|
$self->{_set}->($node,$val); |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub _lssb ($) { |
|
97
|
60900
|
|
|
60900
|
|
74035
|
my($v) = @_; |
|
98
|
60900
|
|
|
|
|
92426
|
return $v & -$v; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub _mssb ($) { |
|
102
|
58296
|
|
|
58296
|
|
73834
|
my($v) = @_; |
|
103
|
|
|
|
|
|
|
|
|
104
|
58296
|
|
|
|
|
70726
|
$v |= $v >> 1; |
|
105
|
58296
|
|
|
|
|
58248
|
$v |= $v >> 2; |
|
106
|
58296
|
|
|
|
|
60586
|
$v |= $v >> 4; |
|
107
|
58296
|
|
|
|
|
57649
|
$v |= $v >> 8; |
|
108
|
58296
|
|
|
|
|
64256
|
$v |= $v >> 16; |
|
109
|
|
|
|
|
|
|
|
|
110
|
58296
|
|
|
|
|
101554
|
return $v - ($v >> 1); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub _data ($$) { |
|
114
|
41237
|
|
|
41237
|
|
56968
|
my($self,$node) = @_; |
|
115
|
41237
|
|
|
|
|
95329
|
return $self->{_data}->[$self->_get($node)]; |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub preprocess ($$) { |
|
119
|
9
|
|
|
9
|
0
|
50
|
my($self,$root) = @_; |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Enumeration phase |
|
122
|
9
|
|
|
|
|
41
|
$self->_enumerate($root, 1); |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# Computing magic number and leaders |
|
125
|
9
|
|
|
|
|
39
|
$self->_compute_magic($root, $self->_data($root), 0); |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# Enumerate each node of the tree with a number v and compute the run |
|
129
|
|
|
|
|
|
|
# I(v) for each node. Also set the parent for each node. |
|
130
|
|
|
|
|
|
|
sub _enumerate ($$$;$) { |
|
131
|
572
|
|
|
572
|
|
761
|
my($self,$node,$number,$parent) = @_; |
|
132
|
|
|
|
|
|
|
|
|
133
|
572
|
|
|
|
|
1328
|
my $data = Algorithm::Tree::NCA::Data |
|
134
|
|
|
|
|
|
|
->new(_node => $node, |
|
135
|
|
|
|
|
|
|
_run => $number, |
|
136
|
|
|
|
|
|
|
_parent => $parent, |
|
137
|
|
|
|
|
|
|
_number => $number); |
|
138
|
|
|
|
|
|
|
|
|
139
|
572
|
|
|
|
|
1178
|
$self->{_data}->[$number] = $data; |
|
140
|
|
|
|
|
|
|
|
|
141
|
572
|
|
|
|
|
1171
|
$self->_set($node,$number); |
|
142
|
|
|
|
|
|
|
|
|
143
|
572
|
|
|
|
|
1841
|
my $run = $number++; |
|
144
|
|
|
|
|
|
|
|
|
145
|
572
|
|
|
|
|
1484
|
for my $c ($node->children()) { |
|
146
|
563
|
|
|
|
|
2274
|
($number, $run) = $self->_enumerate($c, $number, $data); |
|
147
|
563
|
100
|
|
|
|
1054
|
if (_lssb($run) > _lssb($data->{_run})) { |
|
148
|
311
|
|
|
|
|
601
|
$data->{_run} = $run; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
} |
|
151
|
572
|
|
|
|
|
2352
|
$data->{_max} = $number; |
|
152
|
572
|
|
|
|
|
1497
|
return ($number,$data->{_run}); |
|
153
|
|
|
|
|
|
|
} |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# Compute the magic number A_v and the leader L(v) for each node v. |
|
156
|
|
|
|
|
|
|
sub _compute_magic ($$$$) { |
|
157
|
572
|
|
|
572
|
|
730
|
my($self,$node,$ldata,$magic) = @_; |
|
158
|
|
|
|
|
|
|
|
|
159
|
572
|
|
|
|
|
948
|
my $ndata = $self->_data($node); |
|
160
|
|
|
|
|
|
|
|
|
161
|
572
|
|
|
|
|
1250
|
$ndata->{_magic} = $magic | _lssb($ndata->{_run}); |
|
162
|
|
|
|
|
|
|
|
|
163
|
572
|
100
|
|
|
|
1074
|
if ($ndata->{_run} != $ldata->{_run}) { |
|
164
|
322
|
|
|
|
|
411
|
$ndata->{_leader} = $ndata; |
|
165
|
|
|
|
|
|
|
} else { |
|
166
|
250
|
|
|
|
|
309
|
$ndata->{_leader} = $ldata; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
572
|
|
|
|
|
1213
|
foreach my $c ($node->children()) { |
|
170
|
563
|
|
|
|
|
3840
|
$self->_compute_magic($c, |
|
171
|
|
|
|
|
|
|
$ndata->{_leader}, |
|
172
|
|
|
|
|
|
|
$ndata->{_magic}); |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub _display_data ($) { |
|
177
|
0
|
|
|
0
|
|
0
|
my($self) = @_; |
|
178
|
|
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
0
|
my(@L,@I,@A); |
|
180
|
0
|
|
|
|
|
0
|
foreach my $d (@{$self->{_data}}) { |
|
|
0
|
|
|
|
|
0
|
|
|
181
|
0
|
0
|
|
|
|
0
|
push(@L, defined $d ? $d->{_leader}->{_number} : "*"); |
|
182
|
0
|
0
|
|
|
|
0
|
push(@I, defined $d ? $d->{_run} : "*"); |
|
183
|
0
|
0
|
|
|
|
0
|
push(@A, defined $d ? $d->{_magic} : "*"); |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
0
|
print STDERR "L = (@L)\n"; |
|
187
|
0
|
|
|
|
|
0
|
print STDERR "I = (@I)\n"; |
|
188
|
0
|
|
|
|
|
0
|
print STDERR "A = (@A)\n"; |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# Compute the nearest common ancestor of nodes I(x) and I(y) |
|
192
|
|
|
|
|
|
|
sub _bin_nca ($$$) { |
|
193
|
19734
|
|
|
19734
|
|
27547
|
my($self,$xd,$yd)= @_; |
|
194
|
|
|
|
|
|
|
|
|
195
|
19734
|
100
|
100
|
|
|
82650
|
if ($xd->{_number} <= $yd->{_number} && $yd->{_number} < $xd->{_max}) { |
|
196
|
36
|
|
|
|
|
89
|
return $xd->{_run}; |
|
197
|
|
|
|
|
|
|
} |
|
198
|
|
|
|
|
|
|
|
|
199
|
19698
|
100
|
100
|
|
|
82696
|
if ($yd->{_number} <= $xd->{_number} && $xd->{_number} < $yd->{_max}) { |
|
200
|
36
|
|
|
|
|
1233
|
return $yd->{_run}; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
|
|
203
|
19662
|
|
|
|
|
48415
|
my $k = _mssb($xd->{_run} ^ $yd->{_run}); |
|
204
|
19662
|
|
|
|
|
30034
|
my $m = $k ^ ($k - 1); # Mask off the k-1 most significant bits |
|
205
|
19662
|
|
|
|
|
32673
|
my $r = ~$m & $xd->{_run}; # Take the k-1 most significant bits |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# Return k-1 least significant bits of I(x) with a 1 in position k |
|
208
|
19662
|
|
|
|
|
37354
|
return ($r | $k); |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# Find the node closest to 'x' but on the same run as the NCA. |
|
213
|
|
|
|
|
|
|
sub _closest ($$$) { |
|
214
|
39468
|
|
|
39468
|
|
103563
|
my($self,$xd,$j) = @_; |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# a. Find the position l of the right-most 1-bit in A_x |
|
217
|
39468
|
|
|
|
|
76841
|
my $l = _lssb($xd->{_magic}); |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# b. If l == j then nx is x (since x and z are on the same run) |
|
220
|
39468
|
100
|
|
|
|
81760
|
if ($l == $j) { |
|
221
|
834
|
|
|
|
|
1507
|
return $xd; |
|
222
|
|
|
|
|
|
|
} |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# c. Find the position k of the left-most 1-bit in A_x that is to |
|
225
|
|
|
|
|
|
|
# the right of position j. |
|
226
|
38634
|
|
|
|
|
92991
|
my $k = _mssb(($j - 1) & $xd->{_magic}); |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Form the number u consisting of the bits of I(x) to the left |
|
229
|
|
|
|
|
|
|
# of position k, followed by a 1-bit in position k, followed by |
|
230
|
|
|
|
|
|
|
# all zeroes. (u will be I(w)) |
|
231
|
38634
|
|
|
|
|
71080
|
my $u = ~(($k - 1) | $k) & $xd->{_run} | $k; |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Look up node L(I(w)), which must be node w. nx is then the parent |
|
234
|
|
|
|
|
|
|
# of node w. |
|
235
|
38634
|
|
|
|
|
74878
|
my $wd = $self->{_data}->[$u]->{_leader}; |
|
236
|
|
|
|
|
|
|
|
|
237
|
38634
|
|
|
|
|
87210
|
return $wd->{_parent}; |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
} |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub nca ($$$) { |
|
242
|
20028
|
|
|
20028
|
0
|
31673899
|
my($self,$x,$y) = @_; |
|
243
|
20028
|
|
|
|
|
43254
|
my $xd = $self->_data($x); |
|
244
|
20028
|
|
|
|
|
40527
|
my $yd = $self->_data($y); |
|
245
|
|
|
|
|
|
|
|
|
246
|
20028
|
100
|
|
|
|
69888
|
if ($xd->{_number} == $yd->{_number}) { |
|
247
|
294
|
|
|
|
|
742
|
return $x; |
|
248
|
|
|
|
|
|
|
} |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# 1. Find the [nearest] common ancestor b in B of nodes I(x) and I(y). |
|
251
|
19734
|
|
|
|
|
41592
|
my $b = $self->_bin_nca($xd,$yd); |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
# 2. Find the smallest position j greater than or equal to h(b) such |
|
254
|
|
|
|
|
|
|
# that both numbers A_x and A_y have 1-bits in position j. j is |
|
255
|
|
|
|
|
|
|
# then h(I(z)). |
|
256
|
19734
|
|
|
|
|
28060
|
my $m = ~$b & ($b - 1); # Mask for the h(b)-1 least significant bits |
|
257
|
19734
|
|
|
|
|
37629
|
my $c = $xd->{_magic} & $yd->{_magic}; |
|
258
|
|
|
|
|
|
|
# The common set bits in A_x and A_y |
|
259
|
19734
|
|
|
|
|
22814
|
my $u = $c & ~$m; # The upper bits of the common set bits |
|
260
|
19734
|
|
|
|
|
34670
|
my $j = _lssb($u); # Isolate the rightmost 1-bit of u |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# 3a. Find node nx, the closest node to x on the same run as z. |
|
263
|
19734
|
|
|
|
|
40786
|
my $nxd = $self->_closest($xd,$j); |
|
264
|
|
|
|
|
|
|
# 3b. Find node ny, the closest node to y on the same run as z. |
|
265
|
19734
|
|
|
|
|
37089
|
my $nyd = $self->_closest($yd,$j); |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# 4. If nx < ny then z is nx, else z is ny |
|
268
|
19734
|
100
|
|
|
|
49718
|
if ($nxd->{_number} < $nyd->{_number}) { |
|
269
|
9764
|
|
|
|
|
29333
|
return $nxd->{_node}; |
|
270
|
|
|
|
|
|
|
} else { |
|
271
|
9970
|
|
|
|
|
32109
|
return $nyd->{_node}; |
|
272
|
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
} |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Autoload methods go after =cut, and are processed by the autosplit program. |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
1; |
|
278
|
|
|
|
|
|
|
__END__ |