#!/usr/bin/perl -s # use v5.16; use PDL; use Test2::V0 '!float'; use Benchmark 'cmpthese'; use experimental 'signatures'; our ($tests, $examples); run_tests() if $tests || $examples; # does not return die <[$l / @$m][$l % @$m]; } # Turn the argument into an independent, writable value. # Enforces call-by-value when applied to a subroutine parameter. sub v ($v) {$v} # Alternative PDL solution. Simple and fast, though not optimal. sub scan_matrix($pdl, $value) { any $pdl == $value; } ### Examples and tests sub run_tests { my $m = [ [ 1, 2, 3, 5, 7 ], [ 9, 11, 15, 19, 20 ], [ 23, 24, 25, 29, 31 ], [ 32, 33, 39, 40, 42 ], [ 45, 47, 48, 49, 50 ]]; my $high = @$m**2; SKIP: { skip "examples" unless $examples; my $pdl = long $m; ok !bsearch_matrix($m, v(0), v($high), 35), 'example 1, bsearch'; ok !scan_matrix($pdl, 35), 'example 1, scan'; ok bsearch_matrix($m, v(0), v($high), 39), 'example 2, bsearch'; ok scan_matrix($pdl, 39), 'example 2, scan'; } SKIP: { skip "tests" unless $tests; # Some edge cases. ok bsearch_matrix($m, v(0), v($high), 1), 'first element'; ok bsearch_matrix($m, v(0), v($high), 50), 'last element'; ok !bsearch_matrix($m, v(0), v($high), 0), 'below min'; ok !bsearch_matrix($m, v(0), v($high), 51), 'above max'; # bsearch is taking over: for (5, 80, 160) { my $pdl = sequence long, $_, $_; my $matrix = $pdl->unpdl; my $high = @$matrix**2; my $value = $high - 1; say "\n${_}x${_}:"; cmpthese(-1, { scan => sub {scan_matrix($pdl, $value)}, bsearch => sub { bsearch_matrix($matrix, v(0), v($high), $value) } }); } } done_testing; exit; } __DATA__ 5x5: Rate scan bsearch scan 115925/s -- -0% bsearch 115925/s 0% -- 80x80: Rate bsearch scan bsearch 47999/s -- -21% scan 60703/s 26% -- 160x160: Rate scan bsearch scan 25599/s -- -39% bsearch 42309/s 65% --