Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^18: Module for 128-bit integer math? (updated)

by salva (Canon)
on Feb 23, 2011 at 17:08 UTC ( [id://889834]=note: print w/replies, xml ) Need Help??


in reply to Re^17: Module for 128-bit integer math? (updated)
in thread Module for 128-bit integer math?

Let me introduce Math::GMPn, providing fixed length arithmetic on top of the GMP library:
#! perl -slw use strict; use Benchmark qw[ cmpthese ]; use Math::Int128 qw[ uint128 uint128_to_hex :op ]; use Math::GMPn; use Math::GMPz qw[ Rmpz_init_set_str ]; sub FNV_1_128 { my $s = shift; my $h = uint128( '144066263297769815596495629667062367629' ); my $p = uint128( '309485009821345068724781371' ); $h *= $p, $h ^= $_ for unpack 'C*', $s; return $h; } sub FNV_1a_128 { my $s = shift; my $h = uint128( '144066263297769815596495629667062367629' ); my $p = uint128( '309485009821345068724781371' ); $h ^= $_, $h *= $p for unpack 'C*', $s; return $h; } sub FNV_1_128_gmpn { my $s = shift; mpn_set_str(my $h, '144066263297769815596495629667062367629', 10, +128); mpn_set_str(my $p, '309485009821345068724781371', 10, 128); for (unpack 'C*', $s) { my $h2 = $h; mpn_mul($h, $h2, $p); mpn_xor_uint($h, $h, $_); } return $h; } sub FNV_1a_128_gmpn { my $s = shift; mpn_set_str(my $h, '144066263297769815596495629667062367629', 10, +128); mpn_set_str(my $p, '309485009821345068724781371', 10, 128 ); for (unpack 'C*', $s) { mpn_xor_uint($h, $h, $_); my $h2 = $h; mpn_mul($h, $h2, $p); } return $h; } sub FNV_1_128_gmpz { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); my $m = Math::GMPz->new( 1 ) << 128; $h *= $p, $h ^= $_ for unpack 'C*', $s; return $h % $m; } sub FNV_1a_128_gmpz { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); my $m = Math::GMPz->new( 1 ) << 128; $h ^= $_, $h *= $p for unpack 'C*', $s; return $h % $m; } sub FNV_1_128_gmpz2 { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); my $m = Math::GMPz->new( 1 ) << 128; $h *= $p, $h ^= $_, $h %= $m for unpack 'C*', $s; return $h; } sub FNV_1a_128_gmpz2 { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); my $m = Math::GMPz->new( 1 ) << 128; $h ^= $_, $h *= $p, $h %= $m for unpack 'C*', $s; return $h; } my $mod128_mask = (Math::GMPz->new( 1 ) << 128) - 1; sub FNV_1_128_gmpz3 { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); $h *= $p, $h &= $mod128_mask, $h ^= $_ for unpack 'C*', $s; return $h; } sub FNV_1a_128_gmpz3 { my $s = shift; my $h = Rmpz_init_set_str('144066263297769815596495629667062367629 +', 10); my $p = Rmpz_init_set_str('309485009821345068724781371', 10); $h ^= $_, $h *= $p, $h &= $mod128_mask for unpack 'C*', $s; return $h; } sub FNV_1_128_gmpz4 { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); $h *= $p, $h ^= $_ for unpack 'C*', $s; return $h; } sub FNV_1a_128_gmpz4 { my $s = shift; my $h = Math::GMPz->new( '144066263297769815596495629667062367629' + ); my $p = Math::GMPz->new( '309485009821345068724781371' ); $h ^= $_, $h *= $p for unpack 'C*', $s; return $h; } our $text = do{ local( @ARGV, $/ ) = $0; <> }; print length $text; cmpthese -1, { int128 => q[ my $fnv1 = uint128_to_hex( FNV_1_128( $text ) ); my $fnv1a = uint128_to_hex( FNV_1a_128( $text ) ); ], GMPn => q[ my $fnv1 = mpn_get_str(FNV_1_128_gmpn( $text ), 16); my $fnv1a = mpn_get_str(FNV_1a_128_gmpn( $text ), 16); ], GMPz => q[ my $fnv1 = Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz( $text ), + 16 ); my $fnv1a = Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz( $text ) +, 16 ); ], GMPz2 => q[ my $fnv1 = Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz2( $text ) +, 16 ); my $fnv1a = Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz2( $text +), 16 ); ], GMPz3 => q[ my $fnv1 = Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz3( $text ) +, 16 ); my $fnv1a = Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz3( $text +), 16 ); ], GMPz4 => q[ my $fnv1 = Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz4( $text ) +, 16 ); my $fnv1a = Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz4( $text +), 16 ); ], }; use Data::Dumper; print Dumper [ uint128_to_hex( FNV_1_128( $text ) ), uint128_to_hex( FNV_1a_128( $text ) ), mpn_get_str(FNV_1_128_gmpn( $text ), 16), mpn_get_str(FNV_1a_128_gmpn( $text ), 16), Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz( $text ), 16 ) +, Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz( $text ), 16 +), Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz2( $text ), 16 +), Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz2( $text ), 16 + ), Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz3( $text ), 16 +), Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz3( $text ), 16 + ), #Math::GMPz::Rmpz_get_str( FNV_1_128_gmpz4( $text ), 16 + ), #Math::GMPz::Rmpz_get_str( FNV_1a_128_gmpz4( $text ), 1 +6 ) ]; ];
says...
Rate GMPz4 GMPz GMPz2 GMPz3 int128 GMPn GMPz4 2.19/s -- -1% -92% -93% -98% -98% GMPz 2.21/s 1% -- -92% -93% -98% -98% GMPz2 28.1/s 1182% 1173% -- -16% -71% -76% GMPz3 33.3/s 1422% 1411% 19% -- -66% -71% int128 97.2/s 4339% 4306% 246% 192% -- -17% GMPn 117/s 5220% 5182% 315% 250% 20% --

update: as pointed out by BrowserUk below, there was an error in the benchmark script that has been corrected.

Replies are listed 'Best First'.
Re^19: Module for 128-bit integer math? (updated)
by BrowserUk (Patriarch) on Feb 23, 2011 at 21:13 UTC

    I haven't tried to build this yet, ((I think?)I would need to use MPIR on 64-bit), so I haven't seen the full output, but am I missing something with regard to your use of ior rather than xor?

    sub FNV_1_128_gmpn { my $s = shift; mpn_set_str(my $h, '144066263297769815596495629667062367629', 10, +128); mpn_set_str(my $p, '309485009821345068724781371', 10, 128); for (unpack 'C*', $s) { my $h2 = $h; mpn_mul($h, $h2, $p); mpn_ior_uint($h, $h, $_); } return $h; } sub FNV_1a_128_gmpn { my $s = shift; mpn_set_str(my $h, '144066263297769815596495629667062367629', 10, +128); mpn_set_str(my $p, '309485009821345068724781371', 10, 128 ); for (unpack 'C*', $s) { mpn_ior_uint($h, $h, $_); my $h2 = $h; mpn_mul($h, $h2, $p); } return $h; }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      but am I missing something with regard to your use of ior rather than xor?

      Oops, that was an error on the benchmark script. It has been corrected now (and a new version of the module released).

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://889834]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-04-20 00:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found