| 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__ |