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"; } #### use Number::Interval; use strict; use warnings; my @x_int = ( Number::Interval->new( Max => 1 ), Number::Interval->new( Min => 1, Max => 3.3 ), Number::Interval->new( Min => 3.3 ), ); my @y_int = ( Number::Interval->new( Max => 2.5 ), Number::Interval->new( Min => 2.5, Max => 3.5 ), Number::Interval->new( Min => 3.5 ), ); my %f; $f{0,0} = 4; $f{1,0} = 6; # . . . $f{0,1} = 3; # . . . for ( # x, y [ 0, 0 ], [ 2, 0 ], [ 0, 3 ], ) { my( $x, $y ) = @$_; my( $xkey ) = grep { $x_int[$_]->contains($x) } 0 .. $#x_int; my( $ykey ) = grep { $y_int[$_]->contains($y) } 0 .. $#y_int; my $z = $f{$xkey,$ykey}; print "( $x $y ) -> $z\n"; }