in reply to Getting around nested conditionals
You could use Number::Interval to represent each interval on each axis; then testing a coordinate against an interval is if ( $int->contains( $x ) )
To improve performance, you'd want to do a binary search on each array of intervals, rather than a linear search.
Update: Number::Interval won't work well for binary searches, since it only tells you whether the value is inside the interval or not — not whether (in the latter case) it is above or below the interval.
And since your intervals are contiguous, you're better off simply binary-searching the intervals.
Here's a solution using Search::Binary:
use Search::Binary; use strict; use warnings; # # Define the intervals in terms of the "critical points" between them: # my @x_int = ( 1.0, 3.3 ); my @y_int = ( 2.5, 3.5 ); # # Define the function on each interval: # (that is, what should be the "output" value for each interval) # my %f; $f{0,0} = 4; $f{1,0} = 6; # . . . $f{0,1} = 3; # . . . $f{2,2} = 5; # # Construct the mapping function for each dimension: # sub intervalF { my $points_ar = shift; my $prev; my $read = sub { # ugliness necessitated by Search::Binary :-( my( $cpar, $v, $p ) = @_; if ( defined $p ) { $prev = $p; } else { $p = ++$prev; } ( defined $cpar->[$p] ? ( $v <=> $cpar->[$p] ) : 1, $p ) }; sub { my $val = shift; (scalar binary_search( 0, $#{$points_ar}, $val, $read, $points_ar )) } } my $xF = intervalF( \@x_int ); my $yF = intervalF( \@y_int ); # # test: # for ( # x, y [ 0, 0 ], [ 2, 0 ], [ 0, 3 ], [ 4, 4 ], ) { my( $x, $y ) = @$_; # voila! my $z = $f{$xF->($x),$yF->($y)}; print "( $x $y ) -> $z\n"; }
|
|---|