| Filename | /usr/share/perl5/Set/Infinite.pm |
| Statements | Executed 38 statements in 8.31ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.67ms | 3.24ms | Set::Infinite::BEGIN@18 |
| 1 | 1 | 1 | 145µs | 145µs | Set::Infinite::BEGIN@315 |
| 1 | 1 | 1 | 76µs | 124µs | Set::Infinite::BEGIN@21 |
| 1 | 1 | 1 | 31µs | 31µs | Set::Infinite::BEGIN@8 |
| 1 | 1 | 1 | 21µs | 21µs | Set::Infinite::BEGIN@937 |
| 1 | 1 | 1 | 20µs | 88µs | Set::Infinite::BEGIN@17 |
| 1 | 1 | 1 | 13µs | 6.13ms | Set::Infinite::BEGIN@16 |
| 1 | 1 | 1 | 11µs | 16µs | Set::Infinite::BEGIN@15 |
| 1 | 1 | 1 | 11µs | 211µs | Set::Infinite::BEGIN@24 |
| 1 | 1 | 1 | 7µs | 7µs | Set::Infinite::BEGIN@45 |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::DESTROY |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:1145] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:358] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:423] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:475] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:487] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:511] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:522] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:535] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:543] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:584] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:655] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:696] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:720] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:732] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:743] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:760] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:768] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:924] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:929] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:948] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:964] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:974] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::__ANON__[:987] |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_backtrack |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_cleanup |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_first_n |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_function |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_function2 |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_last_n |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_pretty_print |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::_quantize_span |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::as_string |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::compact |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::complement |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::contains |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::count |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::first |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::inf |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::intersected_spans |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::intersection |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::intersects |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::is_null |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::is_too_complex |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::iterate |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::last |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::max_a |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::min_a |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::minus_inf |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::no_cleanup |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::offset |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::quantize |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::select |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::size |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::spaceship |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::tolerance |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::trace |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::trace_close |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::trace_open |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::union |
| 0 | 0 | 0 | 0s | 0s | Set::Infinite::until |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Set::Infinite; | ||||
| 2 | |||||
| 3 | # Copyright (c) 2001, 2002, 2003, 2004 Flavio Soibelmann Glock. | ||||
| 4 | # All rights reserved. | ||||
| 5 | # This program is free software; you can redistribute it and/or | ||||
| 6 | # modify it under the same terms as Perl itself. | ||||
| 7 | |||||
| 8 | 3 | 51µs | 1 | 31µs | # spent 31µs within Set::Infinite::BEGIN@8 which was called:
# once (31µs+0s) by DateTime::Set::BEGIN@10 at line 8 # spent 31µs making 1 call to Set::Infinite::BEGIN@8 |
| 9 | |||||
| 10 | # These methods are inherited from Set::Infinite::Basic "as-is": | ||||
| 11 | # type list fixtype numeric min max integer real new span copy | ||||
| 12 | # start_set end_set universal_set empty_set minus difference | ||||
| 13 | # simmetric_difference is_empty | ||||
| 14 | |||||
| 15 | 3 | 30µs | 2 | 20µs | # spent 16µs (11+4) within Set::Infinite::BEGIN@15 which was called:
# once (11µs+4µs) by DateTime::Set::BEGIN@10 at line 15 # spent 16µs making 1 call to Set::Infinite::BEGIN@15
# spent 4µs making 1 call to strict::import |
| 16 | 3 | 65µs | 2 | 12.2ms | # spent 6.13ms (13µs+6.12) within Set::Infinite::BEGIN@16 which was called:
# once (13µs+6.12ms) by DateTime::Set::BEGIN@10 at line 16 # spent 6.13ms making 1 call to Set::Infinite::BEGIN@16
# spent 6.12ms making 1 call to base::import |
| 17 | 3 | 42µs | 2 | 156µs | # spent 88µs (20+68) within Set::Infinite::BEGIN@17 which was called:
# once (20µs+68µs) by DateTime::Set::BEGIN@10 at line 17 # spent 88µs making 1 call to Set::Infinite::BEGIN@17
# spent 68µs making 1 call to Exporter::import |
| 18 | 3 | 205µs | 2 | 3.24ms | # spent 3.24ms (2.67+568µs) within Set::Infinite::BEGIN@18 which was called:
# once (2.67ms+568µs) by DateTime::Set::BEGIN@10 at line 18 # spent 3.24ms making 1 call to Set::Infinite::BEGIN@18
# spent 4µs making 1 call to UNIVERSAL::import |
| 19 | |||||
| 20 | use overload | ||||
| 21 | 1 | 67µs | 1 | 48µs | # spent 124µs (76+48) within Set::Infinite::BEGIN@21 which was called:
# once (76µs+48µs) by DateTime::Set::BEGIN@10 at line 22 # spent 48µs making 1 call to overload::import |
| 22 | 2 | 42µs | 1 | 124µs | '""' => \&as_string; # spent 124µs making 1 call to Set::Infinite::BEGIN@21 |
| 23 | |||||
| 24 | 1 | 5µs | 1 | 200µs | # spent 211µs (11+200) within Set::Infinite::BEGIN@24 which was called:
# once (11µs+200µs) by DateTime::Set::BEGIN@10 at line 29 # spent 200µs making 1 call to vars::import |
| 25 | $TRACE $DEBUG_BT $PRETTY_PRINT $inf $minus_inf $neg_inf | ||||
| 26 | %_first %_last %_backtrack | ||||
| 27 | $too_complex $backtrack_depth | ||||
| 28 | $max_backtrack_depth $max_intersection_depth | ||||
| 29 | 2 | 150µs | 1 | 211µs | $trace_level %level_title ); # spent 211µs making 1 call to Set::Infinite::BEGIN@24 |
| 30 | |||||
| 31 | 1 | 3µs | @EXPORT_OK = qw(inf $inf trace_open trace_close); | ||
| 32 | |||||
| 33 | 1 | 400ns | $inf = 100**100**100; | ||
| 34 | 1 | 800ns | $neg_inf = $minus_inf = -$inf; | ||
| 35 | |||||
| 36 | |||||
| 37 | # obsolete methods - included for backward compatibility | ||||
| 38 | sub inf () { $inf } | ||||
| 39 | sub minus_inf () { $minus_inf } | ||||
| 40 | sub no_cleanup { $_[0] } | ||||
| 41 | 1 | 4µs | *type = \&Set::Infinite::Basic::type; | ||
| 42 | sub compact { @_ } | ||||
| 43 | |||||
| 44 | |||||
| 45 | # spent 7µs within Set::Infinite::BEGIN@45 which was called:
# once (7µs+0s) by DateTime::Set::BEGIN@10 at line 56 | ||||
| 46 | 1 | 600ns | $VERSION = "0.63"; | ||
| 47 | 1 | 200ns | $TRACE = 0; # enable basic trace method execution | ||
| 48 | 1 | 200ns | $DEBUG_BT = 0; # enable backtrack tracer | ||
| 49 | 1 | 200ns | $PRETTY_PRINT = 0; # 0 = print 'Too Complex'; 1 = describe functions | ||
| 50 | 1 | 200ns | $trace_level = 0; # indentation level when debugging | ||
| 51 | |||||
| 52 | 1 | 300ns | $too_complex = "Too complex"; | ||
| 53 | 1 | 300ns | $backtrack_depth = 0; | ||
| 54 | 1 | 100ns | $max_backtrack_depth = 10; # _backtrack() | ||
| 55 | 1 | 5µs | $max_intersection_depth = 5; # first() | ||
| 56 | 1 | 4.17ms | 1 | 7µs | } # spent 7µs making 1 call to Set::Infinite::BEGIN@45 |
| 57 | |||||
| 58 | sub trace { # title=>'aaa' | ||||
| 59 | return $_[0] unless $TRACE; | ||||
| 60 | my ($self, %parm) = @_; | ||||
| 61 | my @caller = caller(1); | ||||
| 62 | # print "self $self ". ref($self). "\n"; | ||||
| 63 | print "" . ( ' | ' x $trace_level ) . | ||||
| 64 | "$parm{title} ". $self->copy . | ||||
| 65 | ( exists $parm{arg} ? " -- " . $parm{arg}->copy : "" ). | ||||
| 66 | " $caller[1]:$caller[2] ]\n" if $TRACE == 1; | ||||
| 67 | return $self; | ||||
| 68 | } | ||||
| 69 | |||||
| 70 | sub trace_open { | ||||
| 71 | return $_[0] unless $TRACE; | ||||
| 72 | my ($self, %parm) = @_; | ||||
| 73 | my @caller = caller(1); | ||||
| 74 | print "" . ( ' | ' x $trace_level ) . | ||||
| 75 | "\\ $parm{title} ". $self->copy . | ||||
| 76 | ( exists $parm{arg} ? " -- ". $parm{arg}->copy : "" ). | ||||
| 77 | " $caller[1]:$caller[2] ]\n"; | ||||
| 78 | $trace_level++; | ||||
| 79 | $level_title{$trace_level} = $parm{title}; | ||||
| 80 | return $self; | ||||
| 81 | } | ||||
| 82 | |||||
| 83 | sub trace_close { | ||||
| 84 | return $_[0] unless $TRACE; | ||||
| 85 | my ($self, %parm) = @_; | ||||
| 86 | my @caller = caller(0); | ||||
| 87 | print "" . ( ' | ' x ($trace_level-1) ) . | ||||
| 88 | "\/ $level_title{$trace_level} ". | ||||
| 89 | ( exists $parm{arg} ? | ||||
| 90 | ( | ||||
| 91 | defined $parm{arg} ? | ||||
| 92 | "ret ". ( UNIVERSAL::isa($parm{arg}, __PACKAGE__ ) ? | ||||
| 93 | $parm{arg}->copy : | ||||
| 94 | "<$parm{arg}>" ) : | ||||
| 95 | "undef" | ||||
| 96 | ) : | ||||
| 97 | "" # no arg | ||||
| 98 | ). | ||||
| 99 | " $caller[1]:$caller[2] ]\n"; | ||||
| 100 | $trace_level--; | ||||
| 101 | return $self; | ||||
| 102 | } | ||||
| 103 | |||||
| 104 | |||||
| 105 | # creates a 'function' object that can be solved by _backtrack() | ||||
| 106 | sub _function { | ||||
| 107 | my ($self, $method) = (shift, shift); | ||||
| 108 | my $b = $self->empty_set(); | ||||
| 109 | $b->{too_complex} = 1; | ||||
| 110 | $b->{parent} = $self; | ||||
| 111 | $b->{method} = $method; | ||||
| 112 | $b->{param} = [ @_ ]; | ||||
| 113 | return $b; | ||||
| 114 | } | ||||
| 115 | |||||
| 116 | |||||
| 117 | # same as _function, but with 2 arguments | ||||
| 118 | sub _function2 { | ||||
| 119 | my ($self, $method, $arg) = (shift, shift, shift); | ||||
| 120 | unless ( $self->{too_complex} || $arg->{too_complex} ) { | ||||
| 121 | return $self->$method($arg, @_); | ||||
| 122 | } | ||||
| 123 | my $b = $self->empty_set(); | ||||
| 124 | $b->{too_complex} = 1; | ||||
| 125 | $b->{parent} = [ $self, $arg ]; | ||||
| 126 | $b->{method} = $method; | ||||
| 127 | $b->{param} = [ @_ ]; | ||||
| 128 | return $b; | ||||
| 129 | } | ||||
| 130 | |||||
| 131 | |||||
| 132 | sub quantize { | ||||
| 133 | my $self = shift; | ||||
| 134 | $self->trace_open(title=>"quantize") if $TRACE; | ||||
| 135 | my @min = $self->min_a; | ||||
| 136 | my @max = $self->max_a; | ||||
| 137 | if (($self->{too_complex}) or | ||||
| 138 | (defined $min[0] && $min[0] == $neg_inf) or | ||||
| 139 | (defined $max[0] && $max[0] == $inf)) { | ||||
| 140 | |||||
| 141 | return $self->_function( 'quantize', @_ ); | ||||
| 142 | } | ||||
| 143 | |||||
| 144 | my @a; | ||||
| 145 | my %rule = @_; | ||||
| 146 | my $b = $self->empty_set(); | ||||
| 147 | my $parent = $self; | ||||
| 148 | |||||
| 149 | $rule{unit} = 'one' unless $rule{unit}; | ||||
| 150 | $rule{quant} = 1 unless $rule{quant}; | ||||
| 151 | $rule{parent} = $parent; | ||||
| 152 | $rule{strict} = $parent unless exists $rule{strict}; | ||||
| 153 | $rule{type} = $parent->{type}; | ||||
| 154 | |||||
| 155 | my ($min, $open_begin) = $parent->min_a; | ||||
| 156 | |||||
| 157 | unless (defined $min) { | ||||
| 158 | $self->trace_close( arg => $b ) if $TRACE; | ||||
| 159 | return $b; | ||||
| 160 | } | ||||
| 161 | |||||
| 162 | $rule{fixtype} = 1 unless exists $rule{fixtype}; | ||||
| 163 | $Set::Infinite::Arithmetic::Init_quantizer{$rule{unit}}->(\%rule); | ||||
| 164 | |||||
| 165 | $rule{sub_unit} = $Set::Infinite::Arithmetic::Offset_to_value{$rule{unit}}; | ||||
| 166 | carp "Quantize unit '".$rule{unit}."' not implemented" unless ref( $rule{sub_unit} ) eq 'CODE'; | ||||
| 167 | |||||
| 168 | my ($max, $open_end) = $parent->max_a; | ||||
| 169 | $rule{offset} = $Set::Infinite::Arithmetic::Value_to_offset{$rule{unit}}->(\%rule, $min); | ||||
| 170 | my $last_offset = $Set::Infinite::Arithmetic::Value_to_offset{$rule{unit}}->(\%rule, $max); | ||||
| 171 | $rule{size} = $last_offset - $rule{offset} + 1; | ||||
| 172 | my ($index, $tmp, $this, $next); | ||||
| 173 | for $index (0 .. $rule{size} ) { | ||||
| 174 | # ($this, $next) = $rule{sub_unit} (\%rule, $index); | ||||
| 175 | ($this, $next) = $rule{sub_unit}->(\%rule, $index); | ||||
| 176 | unless ( $rule{fixtype} ) { | ||||
| 177 | $tmp = { a => $this , b => $next , | ||||
| 178 | open_begin => 0, open_end => 1 }; | ||||
| 179 | } | ||||
| 180 | else { | ||||
| 181 | $tmp = Set::Infinite::Basic::_simple_new($this,$next, $rule{type} ); | ||||
| 182 | $tmp->{open_end} = 1; | ||||
| 183 | } | ||||
| 184 | next if ( $rule{strict} and not $rule{strict}->intersects($tmp)); | ||||
| 185 | push @a, $tmp; | ||||
| 186 | } | ||||
| 187 | |||||
| 188 | $b->{list} = \@a; # change data | ||||
| 189 | $self->trace_close( arg => $b ) if $TRACE; | ||||
| 190 | return $b; | ||||
| 191 | } | ||||
| 192 | |||||
| 193 | |||||
| 194 | sub _first_n { | ||||
| 195 | my $self = shift; | ||||
| 196 | my $n = shift; | ||||
| 197 | my $tail = $self->copy; | ||||
| 198 | my @result; | ||||
| 199 | my $first; | ||||
| 200 | for ( 1 .. $n ) | ||||
| 201 | { | ||||
| 202 | ( $first, $tail ) = $tail->first if $tail; | ||||
| 203 | push @result, $first; | ||||
| 204 | } | ||||
| 205 | return $tail, @result; | ||||
| 206 | } | ||||
| 207 | |||||
| 208 | sub _last_n { | ||||
| 209 | my $self = shift; | ||||
| 210 | my $n = shift; | ||||
| 211 | my $tail = $self->copy; | ||||
| 212 | my @result; | ||||
| 213 | my $last; | ||||
| 214 | for ( 1 .. $n ) | ||||
| 215 | { | ||||
| 216 | ( $last, $tail ) = $tail->last if $tail; | ||||
| 217 | unshift @result, $last; | ||||
| 218 | } | ||||
| 219 | return $tail, @result; | ||||
| 220 | } | ||||
| 221 | |||||
| 222 | |||||
| 223 | sub select { | ||||
| 224 | my $self = shift; | ||||
| 225 | $self->trace_open(title=>"select") if $TRACE; | ||||
| 226 | |||||
| 227 | my %param = @_; | ||||
| 228 | die "select() - parameter 'freq' is deprecated" if exists $param{freq}; | ||||
| 229 | |||||
| 230 | my $res; | ||||
| 231 | my $count; | ||||
| 232 | my @by; | ||||
| 233 | @by = @{ $param{by} } if exists $param{by}; | ||||
| 234 | $count = delete $param{count} || $inf; | ||||
| 235 | # warn "select: count=$count by=[@by]"; | ||||
| 236 | |||||
| 237 | if ($count <= 0) { | ||||
| 238 | $self->trace_close( arg => $res ) if $TRACE; | ||||
| 239 | return $self->empty_set(); | ||||
| 240 | } | ||||
| 241 | |||||
| 242 | my @set; | ||||
| 243 | my $tail; | ||||
| 244 | my $first; | ||||
| 245 | my $last; | ||||
| 246 | if ( @by ) | ||||
| 247 | { | ||||
| 248 | my @res; | ||||
| 249 | if ( ! $self->is_too_complex ) | ||||
| 250 | { | ||||
| 251 | $res = $self->new; | ||||
| 252 | @res = @{ $self->{list} }[ @by ] ; | ||||
| 253 | } | ||||
| 254 | else | ||||
| 255 | { | ||||
| 256 | my ( @pos_by, @neg_by ); | ||||
| 257 | for ( @by ) { | ||||
| 258 | ( $_ < 0 ) ? push @neg_by, $_ : | ||||
| 259 | push @pos_by, $_; | ||||
| 260 | } | ||||
| 261 | my @first; | ||||
| 262 | if ( @pos_by ) { | ||||
| 263 | @pos_by = sort { $a <=> $b } @pos_by; | ||||
| 264 | ( $tail, @set ) = $self->_first_n( 1 + $pos_by[-1] ); | ||||
| 265 | @first = @set[ @pos_by ]; | ||||
| 266 | } | ||||
| 267 | my @last; | ||||
| 268 | if ( @neg_by ) { | ||||
| 269 | @neg_by = sort { $a <=> $b } @neg_by; | ||||
| 270 | ( $tail, @set ) = $self->_last_n( - $neg_by[0] ); | ||||
| 271 | @last = @set[ @neg_by ]; | ||||
| 272 | } | ||||
| 273 | @res = map { $_->{list}[0] } ( @first , @last ); | ||||
| 274 | } | ||||
| 275 | |||||
| 276 | $res = $self->new; | ||||
| 277 | @res = sort { $a->{a} <=> $b->{a} } grep { defined } @res; | ||||
| 278 | my $last; | ||||
| 279 | my @a; | ||||
| 280 | for ( @res ) { | ||||
| 281 | push @a, $_ if ! $last || $last->{a} != $_->{a}; | ||||
| 282 | $last = $_; | ||||
| 283 | } | ||||
| 284 | $res->{list} = \@a; | ||||
| 285 | } | ||||
| 286 | else | ||||
| 287 | { | ||||
| 288 | $res = $self; | ||||
| 289 | } | ||||
| 290 | |||||
| 291 | return $res if $count == $inf; | ||||
| 292 | my $count_set = $self->empty_set(); | ||||
| 293 | if ( ! $self->is_too_complex ) | ||||
| 294 | { | ||||
| 295 | my @a; | ||||
| 296 | @a = grep { defined } @{ $res->{list} }[ 0 .. $count - 1 ] ; | ||||
| 297 | $count_set->{list} = \@a; | ||||
| 298 | } | ||||
| 299 | else | ||||
| 300 | { | ||||
| 301 | my $last; | ||||
| 302 | while ( $res ) { | ||||
| 303 | ( $first, $res ) = $res->first; | ||||
| 304 | last unless $first; | ||||
| 305 | last if $last && $last->{a} == $first->{list}[0]{a}; | ||||
| 306 | $last = $first->{list}[0]; | ||||
| 307 | push @{$count_set->{list}}, $first->{list}[0]; | ||||
| 308 | $count--; | ||||
| 309 | last if $count <= 0; | ||||
| 310 | } | ||||
| 311 | } | ||||
| 312 | return $count_set; | ||||
| 313 | } | ||||
| 314 | |||||
| 315 | # spent 145µs within Set::Infinite::BEGIN@315 which was called:
# once (145µs+0s) by DateTime::Set::BEGIN@10 at line 770 | ||||
| 316 | |||||
| 317 | # %_first and %_last hashes are used to backtrack the value | ||||
| 318 | # of first() and last() of an infinite set | ||||
| 319 | |||||
| 320 | %_first = ( | ||||
| 321 | 'complement' => | ||||
| 322 | sub { | ||||
| 323 | my $self = $_[0]; | ||||
| 324 | my @parent_min = $self->{parent}->first; | ||||
| 325 | unless ( defined $parent_min[0] ) { | ||||
| 326 | return (undef, 0); | ||||
| 327 | } | ||||
| 328 | my $parent_complement; | ||||
| 329 | my $first; | ||||
| 330 | my @next; | ||||
| 331 | my $parent; | ||||
| 332 | if ( $parent_min[0]->min == $neg_inf ) { | ||||
| 333 | my @parent_second = $parent_min[1]->first; | ||||
| 334 | # (-inf..min) (second..?) | ||||
| 335 | # (min..second) = complement | ||||
| 336 | $first = $self->new( $parent_min[0]->complement ); | ||||
| 337 | $first->{list}[0]{b} = $parent_second[0]->{list}[0]{a}; | ||||
| 338 | $first->{list}[0]{open_end} = ! $parent_second[0]->{list}[0]{open_begin}; | ||||
| 339 | @{ $first->{list} } = () if | ||||
| 340 | ( $first->{list}[0]{a} == $first->{list}[0]{b}) && | ||||
| 341 | ( $first->{list}[0]{open_begin} || | ||||
| 342 | $first->{list}[0]{open_end} ); | ||||
| 343 | @next = $parent_second[0]->max_a; | ||||
| 344 | $parent = $parent_second[1]; | ||||
| 345 | } | ||||
| 346 | else { | ||||
| 347 | # (min..?) | ||||
| 348 | # (-inf..min) = complement | ||||
| 349 | $parent_complement = $parent_min[0]->complement; | ||||
| 350 | $first = $self->new( $parent_complement->{list}[0] ); | ||||
| 351 | @next = $parent_min[0]->max_a; | ||||
| 352 | $parent = $parent_min[1]; | ||||
| 353 | } | ||||
| 354 | my @no_tail = $self->new($neg_inf,$next[0]); | ||||
| 355 | $no_tail[0]->{list}[0]{open_end} = $next[1]; | ||||
| 356 | my $tail = $parent->union($no_tail[0])->complement; | ||||
| 357 | return ($first, $tail); | ||||
| 358 | }, # end: first-complement | ||||
| 359 | 'intersection' => | ||||
| 360 | sub { | ||||
| 361 | my $self = $_[0]; | ||||
| 362 | my @parent = @{ $self->{parent} }; | ||||
| 363 | # warn "$method parents @parent"; | ||||
| 364 | my $retry_count = 0; | ||||
| 365 | my (@first, @min, $which, $first1, $intersection); | ||||
| 366 | SEARCH: while ($retry_count++ < $max_intersection_depth) { | ||||
| 367 | return undef unless defined $parent[0]; | ||||
| 368 | return undef unless defined $parent[1]; | ||||
| 369 | @{$first[0]} = $parent[0]->first; | ||||
| 370 | @{$first[1]} = $parent[1]->first; | ||||
| 371 | unless ( defined $first[0][0] ) { | ||||
| 372 | # warn "don't know first of $method"; | ||||
| 373 | $self->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 374 | return undef; | ||||
| 375 | } | ||||
| 376 | unless ( defined $first[1][0] ) { | ||||
| 377 | # warn "don't know first of $method"; | ||||
| 378 | $self->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 379 | return undef; | ||||
| 380 | } | ||||
| 381 | @{$min[0]} = $first[0][0]->min_a; | ||||
| 382 | @{$min[1]} = $first[1][0]->min_a; | ||||
| 383 | unless ( defined $min[0][0] && defined $min[1][0] ) { | ||||
| 384 | return undef; | ||||
| 385 | } | ||||
| 386 | # $which is the index to the bigger "first". | ||||
| 387 | $which = ($min[0][0] < $min[1][0]) ? 1 : 0; | ||||
| 388 | for my $which1 ( $which, 1 - $which ) { | ||||
| 389 | my $tmp_parent = $parent[$which1]; | ||||
| 390 | ($first1, $parent[$which1]) = @{ $first[$which1] }; | ||||
| 391 | if ( $first1->is_empty ) { | ||||
| 392 | # warn "first1 empty! count $retry_count"; | ||||
| 393 | # trace_close; | ||||
| 394 | # return $first1, undef; | ||||
| 395 | $intersection = $first1; | ||||
| 396 | $which = $which1; | ||||
| 397 | last SEARCH; | ||||
| 398 | } | ||||
| 399 | $intersection = $first1->intersection( $parent[1-$which1] ); | ||||
| 400 | # warn "intersection with $first1 is $intersection"; | ||||
| 401 | unless ( $intersection->is_null ) { | ||||
| 402 | # $self->trace( title=>"got an intersection" ); | ||||
| 403 | if ( $intersection->is_too_complex ) { | ||||
| 404 | $parent[$which1] = $tmp_parent; | ||||
| 405 | } | ||||
| 406 | else { | ||||
| 407 | $which = $which1; | ||||
| 408 | last SEARCH; | ||||
| 409 | } | ||||
| 410 | }; | ||||
| 411 | } | ||||
| 412 | } | ||||
| 413 | if ( $#{ $intersection->{list} } > 0 ) { | ||||
| 414 | my $tail; | ||||
| 415 | ($intersection, $tail) = $intersection->first; | ||||
| 416 | $parent[$which] = $parent[$which]->union( $tail ); | ||||
| 417 | } | ||||
| 418 | my $tmp; | ||||
| 419 | if ( defined $parent[$which] and defined $parent[1-$which] ) { | ||||
| 420 | $tmp = $parent[$which]->intersection ( $parent[1-$which] ); | ||||
| 421 | } | ||||
| 422 | return ($intersection, $tmp); | ||||
| 423 | }, # end: first-intersection | ||||
| 424 | 'union' => | ||||
| 425 | sub { | ||||
| 426 | my $self = $_[0]; | ||||
| 427 | my (@first, @min); | ||||
| 428 | my @parent = @{ $self->{parent} }; | ||||
| 429 | @{$first[0]} = $parent[0]->first; | ||||
| 430 | @{$first[1]} = $parent[1]->first; | ||||
| 431 | unless ( defined $first[0][0] ) { | ||||
| 432 | # looks like one set was empty | ||||
| 433 | return @{$first[1]}; | ||||
| 434 | } | ||||
| 435 | @{$min[0]} = $first[0][0]->min_a; | ||||
| 436 | @{$min[1]} = $first[1][0]->min_a; | ||||
| 437 | |||||
| 438 | # check min1/min2 for undef | ||||
| 439 | unless ( defined $min[0][0] ) { | ||||
| 440 | $self->trace_close( arg => "@{$first[1]}" ) if $TRACE; | ||||
| 441 | return @{$first[1]} | ||||
| 442 | } | ||||
| 443 | unless ( defined $min[1][0] ) { | ||||
| 444 | $self->trace_close( arg => "@{$first[0]}" ) if $TRACE; | ||||
| 445 | return @{$first[0]} | ||||
| 446 | } | ||||
| 447 | |||||
| 448 | my $which = ($min[0][0] < $min[1][0]) ? 0 : 1; | ||||
| 449 | my $first = $first[$which][0]; | ||||
| 450 | |||||
| 451 | # find out the tail | ||||
| 452 | my $parent1 = $first[$which][1]; | ||||
| 453 | # warn $self->{parent}[$which]." - $first = $parent1"; | ||||
| 454 | my $parent2 = ($min[0][0] == $min[1][0]) ? | ||||
| 455 | $self->{parent}[1-$which]->complement($first) : | ||||
| 456 | $self->{parent}[1-$which]; | ||||
| 457 | my $tail; | ||||
| 458 | if (( ! defined $parent1 ) || $parent1->is_null) { | ||||
| 459 | # warn "union parent1 tail is null"; | ||||
| 460 | $tail = $parent2; | ||||
| 461 | } | ||||
| 462 | else { | ||||
| 463 | my $method = $self->{method}; | ||||
| 464 | $tail = $parent1->$method( $parent2 ); | ||||
| 465 | } | ||||
| 466 | |||||
| 467 | if ( $first->intersects( $tail ) ) { | ||||
| 468 | my $first2; | ||||
| 469 | ( $first2, $tail ) = $tail->first; | ||||
| 470 | $first = $first->union( $first2 ); | ||||
| 471 | } | ||||
| 472 | |||||
| 473 | $self->trace_close( arg => "$first $tail" ) if $TRACE; | ||||
| 474 | return ($first, $tail); | ||||
| 475 | }, # end: first-union | ||||
| 476 | 'iterate' => | ||||
| 477 | sub { | ||||
| 478 | my $self = $_[0]; | ||||
| 479 | my $parent = $self->{parent}; | ||||
| 480 | my ($first, $tail) = $parent->first; | ||||
| 481 | $first = $first->iterate( @{$self->{param}} ) if ref($first); | ||||
| 482 | $tail = $tail->_function( 'iterate', @{$self->{param}} ) if ref($tail); | ||||
| 483 | my $more; | ||||
| 484 | ($first, $more) = $first->first if ref($first); | ||||
| 485 | $tail = $tail->_function2( 'union', $more ) if defined $more; | ||||
| 486 | return ($first, $tail); | ||||
| 487 | }, | ||||
| 488 | 'until' => | ||||
| 489 | sub { | ||||
| 490 | my $self = $_[0]; | ||||
| 491 | my ($a1, $b1) = @{ $self->{parent} }; | ||||
| 492 | $a1->trace( title=>"computing first()" ); | ||||
| 493 | my @first1 = $a1->first; | ||||
| 494 | my @first2 = $b1->first; | ||||
| 495 | my ($first, $tail); | ||||
| 496 | if ( $first2[0] <= $first1[0] ) { | ||||
| 497 | # added ->first because it returns 2 spans if $a1 == $a2 | ||||
| 498 | $first = $a1->empty_set()->until( $first2[0] )->first; | ||||
| 499 | $tail = $a1->_function2( "until", $first2[1] ); | ||||
| 500 | } | ||||
| 501 | else { | ||||
| 502 | $first = $a1->new( $first1[0] )->until( $first2[0] ); | ||||
| 503 | if ( defined $first1[1] ) { | ||||
| 504 | $tail = $first1[1]->_function2( "until", $first2[1] ); | ||||
| 505 | } | ||||
| 506 | else { | ||||
| 507 | $tail = undef; | ||||
| 508 | } | ||||
| 509 | } | ||||
| 510 | return ($first, $tail); | ||||
| 511 | }, | ||||
| 512 | 'offset' => | ||||
| 513 | sub { | ||||
| 514 | my $self = $_[0]; | ||||
| 515 | my ($first, $tail) = $self->{parent}->first; | ||||
| 516 | $first = $first->offset( @{$self->{param}} ); | ||||
| 517 | $tail = $tail->_function( 'offset', @{$self->{param}} ); | ||||
| 518 | my $more; | ||||
| 519 | ($first, $more) = $first->first; | ||||
| 520 | $tail = $tail->_function2( 'union', $more ) if defined $more; | ||||
| 521 | return ($first, $tail); | ||||
| 522 | }, | ||||
| 523 | 'quantize' => | ||||
| 524 | sub { | ||||
| 525 | my $self = $_[0]; | ||||
| 526 | my @min = $self->{parent}->min_a; | ||||
| 527 | if ( $min[0] == $neg_inf || $min[0] == $inf ) { | ||||
| 528 | return ( $self->new( $min[0] ) , $self->copy ); | ||||
| 529 | } | ||||
| 530 | my $first = $self->new( $min[0] )->quantize( @{$self->{param}} ); | ||||
| 531 | return ( $first, | ||||
| 532 | $self->{parent}-> | ||||
| 533 | _function2( 'intersection', $first->complement )-> | ||||
| 534 | _function( 'quantize', @{$self->{param}} ) ); | ||||
| 535 | }, | ||||
| 536 | 'tolerance' => | ||||
| 537 | sub { | ||||
| 538 | my $self = $_[0]; | ||||
| 539 | my ($first, $tail) = $self->{parent}->first; | ||||
| 540 | $first = $first->tolerance( @{$self->{param}} ); | ||||
| 541 | $tail = $tail->tolerance( @{$self->{param}} ); | ||||
| 542 | return ($first, $tail); | ||||
| 543 | }, | ||||
| 544 | 1 | 100µs | ); # %_first | ||
| 545 | |||||
| 546 | %_last = ( | ||||
| 547 | 'complement' => | ||||
| 548 | sub { | ||||
| 549 | my $self = $_[0]; | ||||
| 550 | my @parent_max = $self->{parent}->last; | ||||
| 551 | unless ( defined $parent_max[0] ) { | ||||
| 552 | return (undef, 0); | ||||
| 553 | } | ||||
| 554 | my $parent_complement; | ||||
| 555 | my $last; | ||||
| 556 | my @next; | ||||
| 557 | my $parent; | ||||
| 558 | if ( $parent_max[0]->max == $inf ) { | ||||
| 559 | # (inf..min) (second..?) = parent | ||||
| 560 | # (min..second) = complement | ||||
| 561 | my @parent_second = $parent_max[1]->last; | ||||
| 562 | $last = $self->new( $parent_max[0]->complement ); | ||||
| 563 | $last->{list}[0]{a} = $parent_second[0]->{list}[0]{b}; | ||||
| 564 | $last->{list}[0]{open_begin} = ! $parent_second[0]->{list}[0]{open_end}; | ||||
| 565 | @{ $last->{list} } = () if | ||||
| 566 | ( $last->{list}[0]{a} == $last->{list}[0]{b}) && | ||||
| 567 | ( $last->{list}[0]{open_end} || | ||||
| 568 | $last->{list}[0]{open_begin} ); | ||||
| 569 | @next = $parent_second[0]->min_a; | ||||
| 570 | $parent = $parent_second[1]; | ||||
| 571 | } | ||||
| 572 | else { | ||||
| 573 | # (min..?) | ||||
| 574 | # (-inf..min) = complement | ||||
| 575 | $parent_complement = $parent_max[0]->complement; | ||||
| 576 | $last = $self->new( $parent_complement->{list}[-1] ); | ||||
| 577 | @next = $parent_max[0]->min_a; | ||||
| 578 | $parent = $parent_max[1]; | ||||
| 579 | } | ||||
| 580 | my @no_tail = $self->new($next[0], $inf); | ||||
| 581 | $no_tail[0]->{list}[-1]{open_begin} = $next[1]; | ||||
| 582 | my $tail = $parent->union($no_tail[-1])->complement; | ||||
| 583 | return ($last, $tail); | ||||
| 584 | }, | ||||
| 585 | 'intersection' => | ||||
| 586 | sub { | ||||
| 587 | my $self = $_[0]; | ||||
| 588 | my @parent = @{ $self->{parent} }; | ||||
| 589 | # TODO: check max1/max2 for undef | ||||
| 590 | |||||
| 591 | my $retry_count = 0; | ||||
| 592 | my (@last, @max, $which, $last1, $intersection); | ||||
| 593 | |||||
| 594 | SEARCH: while ($retry_count++ < $max_intersection_depth) { | ||||
| 595 | return undef unless defined $parent[0]; | ||||
| 596 | return undef unless defined $parent[1]; | ||||
| 597 | |||||
| 598 | @{$last[0]} = $parent[0]->last; | ||||
| 599 | @{$last[1]} = $parent[1]->last; | ||||
| 600 | unless ( defined $last[0][0] ) { | ||||
| 601 | $self->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 602 | return undef; | ||||
| 603 | } | ||||
| 604 | unless ( defined $last[1][0] ) { | ||||
| 605 | $self->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 606 | return undef; | ||||
| 607 | } | ||||
| 608 | @{$max[0]} = $last[0][0]->max_a; | ||||
| 609 | @{$max[1]} = $last[1][0]->max_a; | ||||
| 610 | unless ( defined $max[0][0] && defined $max[1][0] ) { | ||||
| 611 | $self->trace( title=>"can't find max()" ) if $TRACE; | ||||
| 612 | $self->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 613 | return undef; | ||||
| 614 | } | ||||
| 615 | |||||
| 616 | # $which is the index to the smaller "last". | ||||
| 617 | $which = ($max[0][0] > $max[1][0]) ? 1 : 0; | ||||
| 618 | |||||
| 619 | for my $which1 ( $which, 1 - $which ) { | ||||
| 620 | my $tmp_parent = $parent[$which1]; | ||||
| 621 | ($last1, $parent[$which1]) = @{ $last[$which1] }; | ||||
| 622 | if ( $last1->is_null ) { | ||||
| 623 | $which = $which1; | ||||
| 624 | $intersection = $last1; | ||||
| 625 | last SEARCH; | ||||
| 626 | } | ||||
| 627 | $intersection = $last1->intersection( $parent[1-$which1] ); | ||||
| 628 | |||||
| 629 | unless ( $intersection->is_null ) { | ||||
| 630 | # $self->trace( title=>"got an intersection" ); | ||||
| 631 | if ( $intersection->is_too_complex ) { | ||||
| 632 | $self->trace( title=>"got a too_complex intersection" ) if $TRACE; | ||||
| 633 | # warn "too complex intersection"; | ||||
| 634 | $parent[$which1] = $tmp_parent; | ||||
| 635 | } | ||||
| 636 | else { | ||||
| 637 | $self->trace( title=>"got an intersection" ) if $TRACE; | ||||
| 638 | $which = $which1; | ||||
| 639 | last SEARCH; | ||||
| 640 | } | ||||
| 641 | }; | ||||
| 642 | } | ||||
| 643 | } | ||||
| 644 | $self->trace( title=>"exit loop" ) if $TRACE; | ||||
| 645 | if ( $#{ $intersection->{list} } > 0 ) { | ||||
| 646 | my $tail; | ||||
| 647 | ($intersection, $tail) = $intersection->last; | ||||
| 648 | $parent[$which] = $parent[$which]->union( $tail ); | ||||
| 649 | } | ||||
| 650 | my $tmp; | ||||
| 651 | if ( defined $parent[$which] and defined $parent[1-$which] ) { | ||||
| 652 | $tmp = $parent[$which]->intersection ( $parent[1-$which] ); | ||||
| 653 | } | ||||
| 654 | return ($intersection, $tmp); | ||||
| 655 | }, | ||||
| 656 | 'union' => | ||||
| 657 | sub { | ||||
| 658 | my $self = $_[0]; | ||||
| 659 | my (@last, @max); | ||||
| 660 | my @parent = @{ $self->{parent} }; | ||||
| 661 | @{$last[0]} = $parent[0]->last; | ||||
| 662 | @{$last[1]} = $parent[1]->last; | ||||
| 663 | @{$max[0]} = $last[0][0]->max_a; | ||||
| 664 | @{$max[1]} = $last[1][0]->max_a; | ||||
| 665 | unless ( defined $max[0][0] ) { | ||||
| 666 | return @{$last[1]} | ||||
| 667 | } | ||||
| 668 | unless ( defined $max[1][0] ) { | ||||
| 669 | return @{$last[0]} | ||||
| 670 | } | ||||
| 671 | |||||
| 672 | my $which = ($max[0][0] > $max[1][0]) ? 0 : 1; | ||||
| 673 | my $last = $last[$which][0]; | ||||
| 674 | # find out the tail | ||||
| 675 | my $parent1 = $last[$which][1]; | ||||
| 676 | # warn $self->{parent}[$which]." - $last = $parent1"; | ||||
| 677 | my $parent2 = ($max[0][0] == $max[1][0]) ? | ||||
| 678 | $self->{parent}[1-$which]->complement($last) : | ||||
| 679 | $self->{parent}[1-$which]; | ||||
| 680 | my $tail; | ||||
| 681 | if (( ! defined $parent1 ) || $parent1->is_null) { | ||||
| 682 | $tail = $parent2; | ||||
| 683 | } | ||||
| 684 | else { | ||||
| 685 | my $method = $self->{method}; | ||||
| 686 | $tail = $parent1->$method( $parent2 ); | ||||
| 687 | } | ||||
| 688 | |||||
| 689 | if ( $last->intersects( $tail ) ) { | ||||
| 690 | my $last2; | ||||
| 691 | ( $last2, $tail ) = $tail->last; | ||||
| 692 | $last = $last->union( $last2 ); | ||||
| 693 | } | ||||
| 694 | |||||
| 695 | return ($last, $tail); | ||||
| 696 | }, | ||||
| 697 | 'until' => | ||||
| 698 | sub { | ||||
| 699 | my $self = $_[0]; | ||||
| 700 | my ($a1, $b1) = @{ $self->{parent} }; | ||||
| 701 | $a1->trace( title=>"computing last()" ); | ||||
| 702 | my @last1 = $a1->last; | ||||
| 703 | my @last2 = $b1->last; | ||||
| 704 | my ($last, $tail); | ||||
| 705 | if ( $last2[0] <= $last1[0] ) { | ||||
| 706 | # added ->last because it returns 2 spans if $a1 == $a2 | ||||
| 707 | $last = $last2[0]->until( $a1 )->last; | ||||
| 708 | $tail = $a1->_function2( "until", $last2[1] ); | ||||
| 709 | } | ||||
| 710 | else { | ||||
| 711 | $last = $a1->new( $last1[0] )->until( $last2[0] ); | ||||
| 712 | if ( defined $last1[1] ) { | ||||
| 713 | $tail = $last1[1]->_function2( "until", $last2[1] ); | ||||
| 714 | } | ||||
| 715 | else { | ||||
| 716 | $tail = undef; | ||||
| 717 | } | ||||
| 718 | } | ||||
| 719 | return ($last, $tail); | ||||
| 720 | }, | ||||
| 721 | 'iterate' => | ||||
| 722 | sub { | ||||
| 723 | my $self = $_[0]; | ||||
| 724 | my $parent = $self->{parent}; | ||||
| 725 | my ($last, $tail) = $parent->last; | ||||
| 726 | $last = $last->iterate( @{$self->{param}} ) if ref($last); | ||||
| 727 | $tail = $tail->_function( 'iterate', @{$self->{param}} ) if ref($tail); | ||||
| 728 | my $more; | ||||
| 729 | ($last, $more) = $last->last if ref($last); | ||||
| 730 | $tail = $tail->_function2( 'union', $more ) if defined $more; | ||||
| 731 | return ($last, $tail); | ||||
| 732 | }, | ||||
| 733 | 'offset' => | ||||
| 734 | sub { | ||||
| 735 | my $self = $_[0]; | ||||
| 736 | my ($last, $tail) = $self->{parent}->last; | ||||
| 737 | $last = $last->offset( @{$self->{param}} ); | ||||
| 738 | $tail = $tail->_function( 'offset', @{$self->{param}} ); | ||||
| 739 | my $more; | ||||
| 740 | ($last, $more) = $last->last; | ||||
| 741 | $tail = $tail->_function2( 'union', $more ) if defined $more; | ||||
| 742 | return ($last, $tail); | ||||
| 743 | }, | ||||
| 744 | 'quantize' => | ||||
| 745 | sub { | ||||
| 746 | my $self = $_[0]; | ||||
| 747 | my @max = $self->{parent}->max_a; | ||||
| 748 | if (( $max[0] == $neg_inf ) || ( $max[0] == $inf )) { | ||||
| 749 | return ( $self->new( $max[0] ) , $self->copy ); | ||||
| 750 | } | ||||
| 751 | my $last = $self->new( $max[0] )->quantize( @{$self->{param}} ); | ||||
| 752 | if ($max[1]) { # open_end | ||||
| 753 | if ( $last->min <= $max[0] ) { | ||||
| 754 | $last = $self->new( $last->min - 1e-9 )->quantize( @{$self->{param}} ); | ||||
| 755 | } | ||||
| 756 | } | ||||
| 757 | return ( $last, $self->{parent}-> | ||||
| 758 | _function2( 'intersection', $last->complement )-> | ||||
| 759 | _function( 'quantize', @{$self->{param}} ) ); | ||||
| 760 | }, | ||||
| 761 | 'tolerance' => | ||||
| 762 | sub { | ||||
| 763 | my $self = $_[0]; | ||||
| 764 | my ($last, $tail) = $self->{parent}->last; | ||||
| 765 | $last = $last->tolerance( @{$self->{param}} ); | ||||
| 766 | $tail = $tail->tolerance( @{$self->{param}} ); | ||||
| 767 | return ($last, $tail); | ||||
| 768 | }, | ||||
| 769 | 1 | 44µs | ); # %_last | ||
| 770 | 1 | 1.30ms | 1 | 145µs | } # BEGIN # spent 145µs making 1 call to Set::Infinite::BEGIN@315 |
| 771 | |||||
| 772 | sub first { | ||||
| 773 | my $self = $_[0]; | ||||
| 774 | unless ( exists $self->{first} ) { | ||||
| 775 | $self->trace_open(title=>"first") if $TRACE; | ||||
| 776 | if ( $self->{too_complex} ) { | ||||
| 777 | my $method = $self->{method}; | ||||
| 778 | # warn "method $method ". ( exists $_first{$method} ? "exists" : "does not exist" ); | ||||
| 779 | if ( exists $_first{$method} ) { | ||||
| 780 | @{$self->{first}} = $_first{$method}->($self); | ||||
| 781 | } | ||||
| 782 | else { | ||||
| 783 | my $redo = $self->{parent}->$method ( @{ $self->{param} } ); | ||||
| 784 | @{$self->{first}} = $redo->first; | ||||
| 785 | } | ||||
| 786 | } | ||||
| 787 | else { | ||||
| 788 | return $self->SUPER::first; | ||||
| 789 | } | ||||
| 790 | } | ||||
| 791 | return wantarray ? @{$self->{first}} : $self->{first}[0]; | ||||
| 792 | } | ||||
| 793 | |||||
| 794 | |||||
| 795 | sub last { | ||||
| 796 | my $self = $_[0]; | ||||
| 797 | unless ( exists $self->{last} ) { | ||||
| 798 | $self->trace(title=>"last") if $TRACE; | ||||
| 799 | if ( $self->{too_complex} ) { | ||||
| 800 | my $method = $self->{method}; | ||||
| 801 | if ( exists $_last{$method} ) { | ||||
| 802 | @{$self->{last}} = $_last{$method}->($self); | ||||
| 803 | } | ||||
| 804 | else { | ||||
| 805 | my $redo = $self->{parent}->$method ( @{ $self->{param} } ); | ||||
| 806 | @{$self->{last}} = $redo->last; | ||||
| 807 | } | ||||
| 808 | } | ||||
| 809 | else { | ||||
| 810 | return $self->SUPER::last; | ||||
| 811 | } | ||||
| 812 | } | ||||
| 813 | return wantarray ? @{$self->{last}} : $self->{last}[0]; | ||||
| 814 | } | ||||
| 815 | |||||
| 816 | |||||
| 817 | # offset: offsets subsets | ||||
| 818 | sub offset { | ||||
| 819 | my $self = shift; | ||||
| 820 | if ($self->{too_complex}) { | ||||
| 821 | return $self->_function( 'offset', @_ ); | ||||
| 822 | } | ||||
| 823 | $self->trace_open(title=>"offset") if $TRACE; | ||||
| 824 | |||||
| 825 | my @a; | ||||
| 826 | my %param = @_; | ||||
| 827 | my $b1 = $self->empty_set(); | ||||
| 828 | my ($interval, $ia, $i); | ||||
| 829 | $param{mode} = 'offset' unless $param{mode}; | ||||
| 830 | |||||
| 831 | unless (ref($param{value}) eq 'ARRAY') { | ||||
| 832 | $param{value} = [0 + $param{value}, 0 + $param{value}]; | ||||
| 833 | } | ||||
| 834 | $param{unit} = 'one' unless $param{unit}; | ||||
| 835 | my $parts = ($#{$param{value}}) / 2; | ||||
| 836 | my $sub_unit = $Set::Infinite::Arithmetic::subs_offset2{$param{unit}}; | ||||
| 837 | my $sub_mode = $Set::Infinite::Arithmetic::_MODE{$param{mode}}; | ||||
| 838 | |||||
| 839 | carp "unknown unit $param{unit} for offset()" unless defined $sub_unit; | ||||
| 840 | carp "unknown mode $param{mode} for offset()" unless defined $sub_mode; | ||||
| 841 | |||||
| 842 | my ($j); | ||||
| 843 | my ($cmp, $this, $next, $ib, $part, $open_begin, $open_end, $tmp); | ||||
| 844 | |||||
| 845 | my @value; | ||||
| 846 | foreach $j (0 .. $parts) { | ||||
| 847 | push @value, [ $param{value}[$j+$j], $param{value}[$j+$j + 1] ]; | ||||
| 848 | } | ||||
| 849 | |||||
| 850 | foreach $interval ( @{ $self->{list} } ) { | ||||
| 851 | $ia = $interval->{a}; | ||||
| 852 | $ib = $interval->{b}; | ||||
| 853 | $open_begin = $interval->{open_begin}; | ||||
| 854 | $open_end = $interval->{open_end}; | ||||
| 855 | foreach $j (0 .. $parts) { | ||||
| 856 | # print " [ofs($ia,$ib)] "; | ||||
| 857 | ($this, $next) = $sub_mode->( $sub_unit, $ia, $ib, @{$value[$j]} ); | ||||
| 858 | next if ($this > $next); # skip if a > b | ||||
| 859 | if ($this == $next) { | ||||
| 860 | # TODO: fix this | ||||
| 861 | $open_end = $open_begin; | ||||
| 862 | } | ||||
| 863 | push @a, { a => $this , b => $next , | ||||
| 864 | open_begin => $open_begin , open_end => $open_end }; | ||||
| 865 | } # parts | ||||
| 866 | } # self | ||||
| 867 | @a = sort { $a->{a} <=> $b->{a} } @a; | ||||
| 868 | $b1->{list} = \@a; # change data | ||||
| 869 | $self->trace_close( arg => $b1 ) if $TRACE; | ||||
| 870 | $b1 = $b1->fixtype if $self->{fixtype}; | ||||
| 871 | return $b1; | ||||
| 872 | } | ||||
| 873 | |||||
| 874 | |||||
| 875 | sub is_null { | ||||
| 876 | $_[0]->{too_complex} ? 0 : $_[0]->SUPER::is_null; | ||||
| 877 | } | ||||
| 878 | |||||
| 879 | |||||
| 880 | sub is_too_complex { | ||||
| 881 | $_[0]->{too_complex} ? 1 : 0; | ||||
| 882 | } | ||||
| 883 | |||||
| 884 | |||||
| 885 | # shows how a 'compacted' set looks like after quantize | ||||
| 886 | sub _quantize_span { | ||||
| 887 | my $self = shift; | ||||
| 888 | my %param = @_; | ||||
| 889 | $self->trace_open(title=>"_quantize_span") if $TRACE; | ||||
| 890 | my $res; | ||||
| 891 | if ($self->{too_complex}) { | ||||
| 892 | $res = $self->{parent}; | ||||
| 893 | if ($self->{method} ne 'quantize') { | ||||
| 894 | $self->trace( title => "parent is a ". $self->{method} ); | ||||
| 895 | if ( $self->{method} eq 'union' ) { | ||||
| 896 | my $arg0 = $self->{parent}[0]->_quantize_span(%param); | ||||
| 897 | my $arg1 = $self->{parent}[1]->_quantize_span(%param); | ||||
| 898 | $res = $arg0->union( $arg1 ); | ||||
| 899 | } | ||||
| 900 | elsif ( $self->{method} eq 'intersection' ) { | ||||
| 901 | my $arg0 = $self->{parent}[0]->_quantize_span(%param); | ||||
| 902 | my $arg1 = $self->{parent}[1]->_quantize_span(%param); | ||||
| 903 | $res = $arg0->intersection( $arg1 ); | ||||
| 904 | } | ||||
| 905 | |||||
| 906 | # TODO: other methods | ||||
| 907 | else { | ||||
| 908 | $res = $self; # ->_function( "_quantize_span", %param ); | ||||
| 909 | } | ||||
| 910 | $self->trace_close( arg => $res ) if $TRACE; | ||||
| 911 | return $res; | ||||
| 912 | } | ||||
| 913 | |||||
| 914 | # $res = $self->{parent}; | ||||
| 915 | if ($res->{too_complex}) { | ||||
| 916 | $res->trace( title => "parent is complex" ); | ||||
| 917 | $res = $res->_quantize_span( %param ); | ||||
| 918 | $res = $res->quantize( @{$self->{param}} )->_quantize_span( %param ); | ||||
| 919 | } | ||||
| 920 | else { | ||||
| 921 | $res = $res->iterate ( | ||||
| 922 | sub { | ||||
| 923 | $_[0]->quantize( @{$self->{param}} )->span; | ||||
| 924 | } | ||||
| 925 | ); | ||||
| 926 | } | ||||
| 927 | } | ||||
| 928 | else { | ||||
| 929 | $res = $self->iterate ( sub { $_[0] } ); | ||||
| 930 | } | ||||
| 931 | $self->trace_close( arg => $res ) if $TRACE; | ||||
| 932 | return $res; | ||||
| 933 | } | ||||
| 934 | |||||
| - - | |||||
| 937 | # spent 21µs within Set::Infinite::BEGIN@937 which was called:
# once (21µs+0s) by DateTime::Set::BEGIN@10 at line 990 | ||||
| 938 | |||||
| 939 | %_backtrack = ( | ||||
| 940 | |||||
| 941 | until => sub { | ||||
| 942 | my ($self, $arg) = @_; | ||||
| 943 | my $before = $self->{parent}[0]->intersection( $neg_inf, $arg->min )->max; | ||||
| 944 | $before = $arg->min unless $before; | ||||
| 945 | my $after = $self->{parent}[1]->intersection( $arg->max, $inf )->min; | ||||
| 946 | $after = $arg->max unless $after; | ||||
| 947 | return $arg->new( $before, $after ); | ||||
| 948 | }, | ||||
| 949 | |||||
| 950 | iterate => sub { | ||||
| 951 | my ($self, $arg) = @_; | ||||
| 952 | |||||
| 953 | if ( defined $self->{backtrack_callback} ) | ||||
| 954 | { | ||||
| 955 | return $arg = $self->new( $self->{backtrack_callback}->( $arg ) ); | ||||
| 956 | } | ||||
| 957 | |||||
| 958 | my $before = $self->{parent}->intersection( $neg_inf, $arg->min )->max; | ||||
| 959 | $before = $arg->min unless $before; | ||||
| 960 | my $after = $self->{parent}->intersection( $arg->max, $inf )->min; | ||||
| 961 | $after = $arg->max unless $after; | ||||
| 962 | |||||
| 963 | return $arg->new( $before, $after ); | ||||
| 964 | }, | ||||
| 965 | |||||
| 966 | quantize => sub { | ||||
| 967 | my ($self, $arg) = @_; | ||||
| 968 | if ($arg->{too_complex}) { | ||||
| 969 | return $arg; | ||||
| 970 | } | ||||
| 971 | else { | ||||
| 972 | return $arg->quantize( @{$self->{param}} )->_quantize_span; | ||||
| 973 | } | ||||
| 974 | }, | ||||
| 975 | |||||
| 976 | offset => sub { | ||||
| 977 | my ($self, $arg) = @_; | ||||
| 978 | # offset - apply offset with negative values | ||||
| 979 | my %tmp = @{$self->{param}}; | ||||
| 980 | my @values = sort @{$tmp{value}}; | ||||
| 981 | |||||
| 982 | my $backtrack_arg2 = $arg->offset( | ||||
| 983 | unit => $tmp{unit}, | ||||
| 984 | mode => $tmp{mode}, | ||||
| 985 | value => [ - $values[-1], - $values[0] ] ); | ||||
| 986 | return $arg->union( $backtrack_arg2 ); # fixes some problems with 'begin' mode | ||||
| 987 | }, | ||||
| 988 | |||||
| 989 | 1 | 24µs | ); | ||
| 990 | 1 | 1.99ms | 1 | 21µs | } # spent 21µs making 1 call to Set::Infinite::BEGIN@937 |
| 991 | |||||
| 992 | |||||
| 993 | sub _backtrack { | ||||
| 994 | my ($self, $method, $arg) = @_; | ||||
| 995 | return $self->$method ($arg) unless $self->{too_complex}; | ||||
| 996 | |||||
| 997 | $self->trace_open( title => 'backtrack '.$self->{method} ) if $TRACE; | ||||
| 998 | |||||
| 999 | $backtrack_depth++; | ||||
| 1000 | if ( $backtrack_depth > $max_backtrack_depth ) { | ||||
| 1001 | carp ( __PACKAGE__ . ": Backtrack too deep " . | ||||
| 1002 | "(more than $max_backtrack_depth levels)" ); | ||||
| 1003 | } | ||||
| 1004 | |||||
| 1005 | if (exists $_backtrack{ $self->{method} } ) { | ||||
| 1006 | $arg = $_backtrack{ $self->{method} }->( $self, $arg ); | ||||
| 1007 | } | ||||
| 1008 | |||||
| 1009 | my $result; | ||||
| 1010 | if ( ref($self->{parent}) eq 'ARRAY' ) { | ||||
| 1011 | # has 2 parents (intersection, union, until) | ||||
| 1012 | |||||
| 1013 | my ( $result1, $result2 ) = @{$self->{parent}}; | ||||
| 1014 | $result1 = $result1->_backtrack( $method, $arg ) | ||||
| 1015 | if $result1->{too_complex}; | ||||
| 1016 | $result2 = $result2->_backtrack( $method, $arg ) | ||||
| 1017 | if $result2->{too_complex}; | ||||
| 1018 | |||||
| 1019 | $method = $self->{method}; | ||||
| 1020 | if ( $result1->{too_complex} || $result2->{too_complex} ) { | ||||
| 1021 | $result = $result1->_function2( $method, $result2 ); | ||||
| 1022 | } | ||||
| 1023 | else { | ||||
| 1024 | $result = $result1->$method ($result2); | ||||
| 1025 | } | ||||
| 1026 | } | ||||
| 1027 | else { | ||||
| 1028 | # has 1 parent and parameters (offset, select, quantize, iterate) | ||||
| 1029 | |||||
| 1030 | $result = $self->{parent}->_backtrack( $method, $arg ); | ||||
| 1031 | $method = $self->{method}; | ||||
| 1032 | $result = $result->$method ( @{$self->{param}} ); | ||||
| 1033 | } | ||||
| 1034 | |||||
| 1035 | $backtrack_depth--; | ||||
| 1036 | $self->trace_close( arg => $result ) if $TRACE; | ||||
| 1037 | return $result; | ||||
| 1038 | } | ||||
| 1039 | |||||
| 1040 | |||||
| 1041 | sub intersects { | ||||
| 1042 | my $a1 = shift; | ||||
| 1043 | my $b1 = (ref ($_[0]) eq ref($a1) ) ? shift : $a1->new(@_); | ||||
| 1044 | |||||
| 1045 | $a1->trace(title=>"intersects"); | ||||
| 1046 | if ($a1->{too_complex}) { | ||||
| 1047 | $a1 = $a1->_backtrack('intersection', $b1 ); | ||||
| 1048 | } # don't put 'else' here | ||||
| 1049 | if ($b1->{too_complex}) { | ||||
| 1050 | $b1 = $b1->_backtrack('intersection', $a1); | ||||
| 1051 | } | ||||
| 1052 | if (($a1->{too_complex}) or ($b1->{too_complex})) { | ||||
| 1053 | return undef; # we don't know the answer! | ||||
| 1054 | } | ||||
| 1055 | return $a1->SUPER::intersects( $b1 ); | ||||
| 1056 | } | ||||
| 1057 | |||||
| 1058 | |||||
| 1059 | sub iterate { | ||||
| 1060 | my $self = shift; | ||||
| 1061 | my $callback = shift; | ||||
| 1062 | die "First argument to iterate() must be a subroutine reference" | ||||
| 1063 | unless ref( $callback ) eq 'CODE'; | ||||
| 1064 | my $backtrack_callback; | ||||
| 1065 | if ( @_ && $_[0] eq 'backtrack_callback' ) | ||||
| 1066 | { | ||||
| 1067 | ( undef, $backtrack_callback ) = ( shift, shift ); | ||||
| 1068 | } | ||||
| 1069 | my $set; | ||||
| 1070 | if ($self->{too_complex}) { | ||||
| 1071 | $self->trace(title=>"iterate:backtrack") if $TRACE; | ||||
| 1072 | $set = $self->_function( 'iterate', $callback, @_ ); | ||||
| 1073 | } | ||||
| 1074 | else | ||||
| 1075 | { | ||||
| 1076 | $self->trace(title=>"iterate") if $TRACE; | ||||
| 1077 | $set = $self->SUPER::iterate( $callback, @_ ); | ||||
| 1078 | } | ||||
| 1079 | $set->{backtrack_callback} = $backtrack_callback; | ||||
| 1080 | # warn "set backtrack_callback" if defined $backtrack_callback; | ||||
| 1081 | return $set; | ||||
| 1082 | } | ||||
| 1083 | |||||
| 1084 | |||||
| 1085 | sub intersection { | ||||
| 1086 | my $a1 = shift; | ||||
| 1087 | my $b1 = (ref ($_[0]) eq ref($a1) ) ? shift : $a1->new(@_); | ||||
| 1088 | |||||
| 1089 | $a1->trace_open(title=>"intersection", arg => $b1) if $TRACE; | ||||
| 1090 | if (($a1->{too_complex}) or ($b1->{too_complex})) { | ||||
| 1091 | my $arg0 = $a1->_quantize_span; | ||||
| 1092 | my $arg1 = $b1->_quantize_span; | ||||
| 1093 | unless (($arg0->{too_complex}) or ($arg1->{too_complex})) { | ||||
| 1094 | my $res = $arg0->intersection( $arg1 ); | ||||
| 1095 | $a1->trace_close( arg => $res ) if $TRACE; | ||||
| 1096 | return $res; | ||||
| 1097 | } | ||||
| 1098 | } | ||||
| 1099 | if ($a1->{too_complex}) { | ||||
| 1100 | $a1 = $a1->_backtrack('intersection', $b1) unless $b1->{too_complex}; | ||||
| 1101 | } # don't put 'else' here | ||||
| 1102 | if ($b1->{too_complex}) { | ||||
| 1103 | $b1 = $b1->_backtrack('intersection', $a1) unless $a1->{too_complex}; | ||||
| 1104 | } | ||||
| 1105 | if ( $a1->{too_complex} || $b1->{too_complex} ) { | ||||
| 1106 | $a1->trace_close( ) if $TRACE; | ||||
| 1107 | return $a1->_function2( 'intersection', $b1 ); | ||||
| 1108 | } | ||||
| 1109 | return $a1->SUPER::intersection( $b1 ); | ||||
| 1110 | } | ||||
| 1111 | |||||
| 1112 | |||||
| 1113 | sub intersected_spans { | ||||
| 1114 | my $a1 = shift; | ||||
| 1115 | my $b1 = ref ($_[0]) eq ref($a1) ? $_[0] : $a1->new(@_); | ||||
| 1116 | |||||
| 1117 | if ($a1->{too_complex}) { | ||||
| 1118 | $a1 = $a1->_backtrack('intersection', $b1 ) unless $b1->{too_complex}; | ||||
| 1119 | } # don't put 'else' here | ||||
| 1120 | if ($b1->{too_complex}) { | ||||
| 1121 | $b1 = $b1->_backtrack('intersection', $a1) unless $a1->{too_complex}; | ||||
| 1122 | } | ||||
| 1123 | |||||
| 1124 | if ( ! $b1->{too_complex} && ! $a1->{too_complex} ) | ||||
| 1125 | { | ||||
| 1126 | return $a1->SUPER::intersected_spans ( $b1 ); | ||||
| 1127 | } | ||||
| 1128 | |||||
| 1129 | return $b1->iterate( | ||||
| 1130 | sub { | ||||
| 1131 | my $tmp = $a1->intersection( $_[0] ); | ||||
| 1132 | return $tmp unless defined $tmp->max; | ||||
| 1133 | |||||
| 1134 | my $before = $a1->intersection( $neg_inf, $tmp->min )->last; | ||||
| 1135 | my $after = $a1->intersection( $tmp->max, $inf )->first; | ||||
| 1136 | |||||
| 1137 | $before = $tmp->union( $before )->first; | ||||
| 1138 | $after = $tmp->union( $after )->last; | ||||
| 1139 | |||||
| 1140 | $tmp = $tmp->union( $before ) | ||||
| 1141 | if defined $before && $tmp->intersects( $before ); | ||||
| 1142 | $tmp = $tmp->union( $after ) | ||||
| 1143 | if defined $after && $tmp->intersects( $after ); | ||||
| 1144 | return $tmp; | ||||
| 1145 | } | ||||
| 1146 | ); | ||||
| 1147 | |||||
| 1148 | } | ||||
| 1149 | |||||
| 1150 | |||||
| 1151 | sub complement { | ||||
| 1152 | my $a1 = shift; | ||||
| 1153 | # do we have a parameter? | ||||
| 1154 | if (@_) { | ||||
| 1155 | my $b1 = (ref ($_[0]) eq ref($a1) ) ? shift : $a1->new(@_); | ||||
| 1156 | |||||
| 1157 | $a1->trace_open(title=>"complement", arg => $b1) if $TRACE; | ||||
| 1158 | $b1 = $b1->complement; | ||||
| 1159 | my $tmp =$a1->intersection($b1); | ||||
| 1160 | $a1->trace_close( arg => $tmp ) if $TRACE; | ||||
| 1161 | return $tmp; | ||||
| 1162 | } | ||||
| 1163 | $a1->trace_open(title=>"complement") if $TRACE; | ||||
| 1164 | if ($a1->{too_complex}) { | ||||
| 1165 | $a1->trace_close( ) if $TRACE; | ||||
| 1166 | return $a1->_function( 'complement', @_ ); | ||||
| 1167 | } | ||||
| 1168 | return $a1->SUPER::complement; | ||||
| 1169 | } | ||||
| 1170 | |||||
| 1171 | |||||
| 1172 | sub until { | ||||
| 1173 | my $a1 = shift; | ||||
| 1174 | my $b1 = (ref ($_[0]) eq ref($a1) ) ? shift : $a1->new(@_); | ||||
| 1175 | |||||
| 1176 | if (($a1->{too_complex}) or ($b1->{too_complex})) { | ||||
| 1177 | return $a1->_function2( 'until', $b1 ); | ||||
| 1178 | } | ||||
| 1179 | return $a1->SUPER::until( $b1 ); | ||||
| 1180 | } | ||||
| 1181 | |||||
| 1182 | |||||
| 1183 | sub union { | ||||
| 1184 | my $a1 = shift; | ||||
| 1185 | my $b1 = (ref ($_[0]) eq ref($a1) ) ? shift : $a1->new(@_); | ||||
| 1186 | |||||
| 1187 | $a1->trace_open(title=>"union", arg => $b1) if $TRACE; | ||||
| 1188 | if (($a1->{too_complex}) or ($b1->{too_complex})) { | ||||
| 1189 | $a1->trace_close( ) if $TRACE; | ||||
| 1190 | return $a1 if $b1->is_null; | ||||
| 1191 | return $b1 if $a1->is_null; | ||||
| 1192 | return $a1->_function2( 'union', $b1); | ||||
| 1193 | } | ||||
| 1194 | return $a1->SUPER::union( $b1 ); | ||||
| 1195 | } | ||||
| 1196 | |||||
| 1197 | |||||
| 1198 | # there are some ways to process 'contains': | ||||
| 1199 | # A CONTAINS B IF A == ( A UNION B ) | ||||
| 1200 | # - faster | ||||
| 1201 | # A CONTAINS B IF B == ( A INTERSECTION B ) | ||||
| 1202 | # - can backtrack = works for unbounded sets | ||||
| 1203 | sub contains { | ||||
| 1204 | my $a1 = shift; | ||||
| 1205 | $a1->trace_open(title=>"contains") if $TRACE; | ||||
| 1206 | if ( $a1->{too_complex} ) { | ||||
| 1207 | # we use intersection because it is better for backtracking | ||||
| 1208 | my $b0 = (ref $_[0] eq ref $a1) ? shift : $a1->new(@_); | ||||
| 1209 | my $b1 = $a1->intersection($b0); | ||||
| 1210 | if ( $b1->{too_complex} ) { | ||||
| 1211 | $b1->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 1212 | return undef; | ||||
| 1213 | } | ||||
| 1214 | $a1->trace_close( arg => ($b1 == $b0 ? 1 : 0) ) if $TRACE; | ||||
| 1215 | return ($b1 == $b0) ? 1 : 0; | ||||
| 1216 | } | ||||
| 1217 | my $b1 = $a1->union(@_); | ||||
| 1218 | if ( $b1->{too_complex} ) { | ||||
| 1219 | $b1->trace_close( arg => 'undef' ) if $TRACE; | ||||
| 1220 | return undef; | ||||
| 1221 | } | ||||
| 1222 | $a1->trace_close( arg => ($b1 == $a1 ? 1 : 0) ) if $TRACE; | ||||
| 1223 | return ($b1 == $a1) ? 1 : 0; | ||||
| 1224 | } | ||||
| 1225 | |||||
| 1226 | |||||
| 1227 | sub min_a { | ||||
| 1228 | my $self = $_[0]; | ||||
| 1229 | return @{$self->{min}} if exists $self->{min}; | ||||
| 1230 | if ($self->{too_complex}) { | ||||
| 1231 | my @first = $self->first; | ||||
| 1232 | return @{$self->{min}} = $first[0]->min_a if defined $first[0]; | ||||
| 1233 | return @{$self->{min}} = (undef, 0); | ||||
| 1234 | } | ||||
| 1235 | return $self->SUPER::min_a; | ||||
| 1236 | }; | ||||
| 1237 | |||||
| 1238 | |||||
| 1239 | sub max_a { | ||||
| 1240 | my $self = $_[0]; | ||||
| 1241 | return @{$self->{max}} if exists $self->{max}; | ||||
| 1242 | if ($self->{too_complex}) { | ||||
| 1243 | my @last = $self->last; | ||||
| 1244 | return @{$self->{max}} = $last[0]->max_a if defined $last[0]; | ||||
| 1245 | return @{$self->{max}} = (undef, 0); | ||||
| 1246 | } | ||||
| 1247 | return $self->SUPER::max_a; | ||||
| 1248 | }; | ||||
| 1249 | |||||
| 1250 | |||||
| 1251 | sub count { | ||||
| 1252 | my $self = $_[0]; | ||||
| 1253 | # NOTE: subclasses may return "undef" if necessary | ||||
| 1254 | return $inf if $self->{too_complex}; | ||||
| 1255 | return $self->SUPER::count; | ||||
| 1256 | } | ||||
| 1257 | |||||
| 1258 | |||||
| 1259 | sub size { | ||||
| 1260 | my $self = $_[0]; | ||||
| 1261 | if ($self->{too_complex}) { | ||||
| 1262 | my @min = $self->min_a; | ||||
| 1263 | my @max = $self->max_a; | ||||
| 1264 | return undef unless defined $max[0] && defined $min[0]; | ||||
| 1265 | return $max[0] - $min[0]; | ||||
| 1266 | } | ||||
| 1267 | return $self->SUPER::size; | ||||
| 1268 | }; | ||||
| 1269 | |||||
| 1270 | |||||
| 1271 | sub spaceship { | ||||
| 1272 | my ($tmp1, $tmp2, $inverted) = @_; | ||||
| 1273 | carp "Can't compare unbounded sets" | ||||
| 1274 | if $tmp1->{too_complex} or $tmp2->{too_complex}; | ||||
| 1275 | return $tmp1->SUPER::spaceship( $tmp2, $inverted ); | ||||
| 1276 | } | ||||
| 1277 | |||||
| 1278 | |||||
| 1279 | sub _cleanup { @_ } # this subroutine is obsolete | ||||
| 1280 | |||||
| 1281 | |||||
| 1282 | sub tolerance { | ||||
| 1283 | my $self = shift; | ||||
| 1284 | my $tmp = pop; | ||||
| 1285 | if (ref($self)) { | ||||
| 1286 | # local | ||||
| 1287 | return $self->{tolerance} unless defined $tmp; | ||||
| 1288 | if ($self->{too_complex}) { | ||||
| 1289 | my $b1 = $self->_function( 'tolerance', $tmp ); | ||||
| 1290 | $b1->{tolerance} = $tmp; # for max/min processing | ||||
| 1291 | return $b1; | ||||
| 1292 | } | ||||
| 1293 | return $self->SUPER::tolerance( $tmp ); | ||||
| 1294 | } | ||||
| 1295 | # class method | ||||
| 1296 | __PACKAGE__->SUPER::tolerance( $tmp ) if defined($tmp); | ||||
| 1297 | return __PACKAGE__->SUPER::tolerance; | ||||
| 1298 | } | ||||
| 1299 | |||||
| 1300 | |||||
| 1301 | sub _pretty_print { | ||||
| 1302 | my $self = shift; | ||||
| 1303 | return "$self" unless $self->{too_complex}; | ||||
| 1304 | return $self->{method} . "( " . | ||||
| 1305 | ( ref($self->{parent}) eq 'ARRAY' ? | ||||
| 1306 | $self->{parent}[0] . ' ; ' . $self->{parent}[1] : | ||||
| 1307 | $self->{parent} ) . | ||||
| 1308 | " )"; | ||||
| 1309 | } | ||||
| 1310 | |||||
| 1311 | |||||
| 1312 | sub as_string { | ||||
| 1313 | my $self = shift; | ||||
| 1314 | return ( $PRETTY_PRINT ? $self->_pretty_print : $too_complex ) | ||||
| 1315 | if $self->{too_complex}; | ||||
| 1316 | return $self->SUPER::as_string; | ||||
| 1317 | } | ||||
| 1318 | |||||
| 1319 | |||||
| 1320 | sub DESTROY {} | ||||
| 1321 | |||||
| 1322 | 1 | 7µs | 1; | ||
| 1323 | |||||
| 1324 | __END__ |