in reply to Re: Re: Eek! goto?
in thread Eek! goto?

I thought up another approach last night after I had logged out. It still isn't faster than pfauts, but it is an interesting example of using code templates.
#!perl use strict; use warnings; use Benchmark 'cmpthese'; use vars qw/@subs $time/; $time=-10; my @lines=split /\n/,<<'EOF_RULES'; # No-op $a+= $k[0]; $a+= $k[1] <<8; $a+= $k[2] <<16; $a+= $k[3] <<24; $b+= $k[4]; $b+= $k[5] <<8; $b+= $k[6] <<16; $b+= $k[7] <<24; $c+= $k[8] <<8; $c+= $k[9] <<16; $c+= $k[10] <<24; EOF_RULES my $template=<<'EOF_TEMPLATE'; sub { my @k=@_; my ($a, $b, $c) = (0,0,0); #-TEMPLATE-# return $a+$b+$c; } EOF_TEMPLATE for my $num (0..$#lines) { (my $t=$template)=~s[#-TEMPLATE-#] {"#Len:$num\n".join "\n",@lines[0..$num]}me; $subs[$num]=eval($t) or die "Failed to eval\n$t\n$@"; } sub demerphq { my ($len, @k) = @_; my ($a, $b, $c) = (0)x3; { ($len or last) and $a+= $k[0]; ($len >= 2 or last) and $a+= $k[1] <<8; ($len >= 3 or last) and $a+= $k[2] <<16; ($len >= 4 or last) and $a+= $k[3] <<24; ($len >= 5 or last) and $b+= $k[4]; ($len >= 6 or last) and $b+= $k[5] <<8; ($len >= 7 or last) and $b+= $k[6] <<16; ($len >= 8 or last) and $b+= $k[7] <<24; ($len >= 9 or last) and $c+= $k[8] <<8; ($len >= 10 or last) and $c+= $k[9] <<16; ($len >= 11 or last) and $c+= $k[10] <<24; } return ($a+$b+$c); } sub gotoit { my ($len, @k) = @_; my ($a, $b, $c) = (0)x3; goto "LAST".$len; LAST11: $c+= $k[10] <<24; LAST10: $c+= $k[9] <<16; LAST9: $c+= $k[8] <<8; LAST8: $b+= $k[7] <<24; LAST7: $b+= $k[6] <<16; LAST6: $b+= $k[5] <<8; LAST5: $b+= $k[4]; LAST4: $a+= $k[3] <<24; LAST3: $a+= $k[2] <<16; LAST2: $a+= $k[1] <<8; LAST1: $a+= $k[0]; LAST0: return ($a+$b+$c); } sub pfaut { my ($k) = @_; my ($a, $b, $c) = unpack 'L3', $k.(chr(0)x11) ; return ($a||0) + ($b||0) + ($c||0)<<8; } if ($time==1) { print 'template', $subs[$_]->((65) x $_),$/ for 0 ..11; print 'demerphq', demerphq( $_, (65) x $_),$/ for 0 .. 11; print 'gotoit' , gotoit( $_, (65) x $_),$/ for 0 .. 11; print 'pfaut' , pfaut( 'A' x $_),$/ for 0 .. 11; } else { cmpthese( $time, { template => q[$::subs[$_]->((65) x $_) for 0 ..11; ], demerphq => q[demerphq( $_, (65) x $_) for 0 .. 11;], gotoit => q[ gotoit( $_, (65) x $_) for 0 .. 11;], pfaut => q[ pfaut( 'A' x $_) for 0 .. 11;], }); }
Benchmark: running demerphq, gotoit, pfaut, template, each for at least 10 CPU seconds... demerphq: 11 wallclock secs (10.52 usr) @ 4809.81/s (n=50580) gotoit: 10 wallclock secs (10.31 usr) @ 5002.33/s (n=51584) pfaut: 10 wallclock secs (10.52 usr) @ 9265.21/s (n=97433) template: 11 wallclock secs (10.56 usr) @ 5934.77/s (n=62689) Rate demerphq gotoit template pfaut demerphq 4810/s -- -4% -19% -48% gotoit 5002/s 4% -- -16% -46% template 5935/s 23% 19% -- -36% pfaut 9265/s 93% 85% 56% --
TMTOWTDI

;-)

--- demerphq
my friends call me, usually because I'm late....

Replies are listed 'Best First'.
Re: Re: Re: Re: Eek! goto?
by pfaut (Priest) on Feb 12, 2003 at 14:20 UTC

    Mine may be fast but it makes some assumptions about the data. It assumes each value in @k is a byte value (between 0 and 255) and that $a, $b, and $c start out at 0. If the first is true but the second isn't, it might still work if the results of the unpack are stored in different variables and added to $a, $b, and $c. But I think BrowserUK said that this is part of some sort of encryption routine so it's quite possible the first assumption is wrong and thus the whole thing falls apart.

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';