File Coverage

blib/lib/Digest/SipHash/PP.pm
Criterion Covered Total %
statement 75 75 100.0
branch 2 2 100.0
condition 2 4 50.0
subroutine 17 17 100.0
pod 1 1 100.0
total 97 99 97.9


line stmt bran cond sub pod time code
1             package Digest::SipHash::PP;
2 1     1   28169 use strict;
  1         3  
  1         116  
3 1     1   6 use warnings;
  1         3  
  1         30  
4 1     1   1770 use Math::BigInt;
  1         24428  
  1         5  
5              
6             our $VERSION = sprintf "%d.%02d", q$Revision: 0.12 $ =~ /(\d+)/g;
7 1     1   22016 use base 'Exporter';
  1         2  
  1         129  
8             our @EXPORT_OK = qw/siphash siphash32/;
9              
10 1     1   6 use constant USE64BITINT => eval { pack 'Q', 1 };
  1         2  
  1         3  
  1         65  
11 1     1   5 use constant MASK64 => Math::BigInt->new('0xffff_ffff_ffff_ffff');
  1         2  
  1         6  
12              
13             push @EXPORT_OK, 'siphash64' if USE64BITINT;
14             our %EXPORT_TAGS = ( all => [@EXPORT_OK] );
15             our $DEFAULT_SEED = pack 'C16', map { int( rand(256) ) } ( 0 .. 0xF );
16              
17 32     32   498 sub _new { Math::BigInt->new(shift) }
18 16     16   72 sub _u64 { _new($_[1])->blsft(32)->bior($_[0]) }
19 128     128   736 sub _add { $_[0]->badd($_[1])->band(MASK64) }
20 176     176   4325 sub _xor { $_[0]->bxor($_[1]) }
21             sub _rot {
22 192     192   9467 my $lo = $_[0]->copy->brsft(64 - $_[1]);
23 192         133318 $_[0]->blsft($_[1])->bior($lo)->band(MASK64);
24             }
25              
26             sub _compress {
27 32     32   57348 _add( $_[0], $_[1] );
28 32         17418 _add( $_[2], $_[3] );
29 32         19925 _rot( $_[1], 13 );
30 32         56044 _rot( $_[3], 16 );
31 32         65805 _xor( $_[1], $_[0] );
32 32         18567 _xor( $_[3], $_[2] );
33 32         18197 _rot( $_[0], 32 );
34 32         66992 _add( $_[2], $_[1] );
35 32         29587 _add( $_[0], $_[3] );
36 32         26047 _rot( $_[1], 17 );
37 32         46684 _rot( $_[3], 21 );
38 32         54787 _xor( $_[1], $_[2] );
39 32         19213 _xor( $_[3], $_[0] );
40 32         16516 _rot( $_[2], 32 );
41             }
42              
43             sub _digest {
44 1     1   2683 use bytes;
  1         12  
  1         5  
45 4   50 4   20 my $str = shift || '';
46 4   50     16 my $seed = shift || "\0" x 16;
47 4         36 my @k = unpack 'V4', $seed;
48 4         22 my $k0 = _u64( @k[ 0, 1 ] );
49 4         5908 my $k1 = _u64( @k[ 2, 3 ] );
50 4         11045 my $v0 = _new('0x736f6d6570736575');
51 4         1252 my $v1 = _new('0x646f72616e646f6d');
52 4         924 my $v2 = _new('0x6c7967656e657261');
53 4         897 my $v3 = _new('0x7465646279746573');
54 4         1157 _xor( $v0, $k0 );
55 4         7841 _xor( $v1, $k1 );
56 4         2315 _xor( $v2, $k0 );
57 4         1574 _xor( $v3, $k1 );
58 4         1651 my $slen = length($str);
59 4         20 $str .= "\0" x ( 7 - $slen % 8 ) . chr( $slen % 256 );
60 4         29 my @u32 = unpack 'V*', $str;
61              
62 4         55 while ( my ( $lo, $hi ) = splice @u32, 0, 2 ) {
63 8         2760 my $u64 = _u64( $lo, $hi );
64 8         8619 _xor( $v3, $u64 );
65 8         5670 _compress( $v0, $v1, $v2, $v3 ) for 0 .. 1;
66 8         11188 _xor( $v0, $u64 );
67             }
68 4         1635 _xor( $v2, 0xff );
69 4         1089 _compress( $v0, $v1, $v2, $v3 ) for 0 .. 3;
70 4         4224 _xor( _xor( $v0, $v1 ), _xor( $v2, $v3 ) );
71             }
72              
73             sub siphash {
74 3     3 1 218 my $u64 = _digest(@_);
75 3         1501 my $lo = 0 + $u64->copy->band(0xffff_ffff);
76 3 100       3884 return $lo unless wantarray;
77 1         9 my $hi = 0 + $u64->brsft(32);
78 1         810 return ( $lo, $hi );
79             }
80              
81             *siphash32 = \&siphash;
82              
83             if (USE64BITINT) {
84             *siphash64 = sub {
85 1     1   445 use integer;
  1         3  
  1         15  
86 1     1   1124 0+_digest(@_);
87             };
88             }
89              
90             1;
91              
92             __END__