#! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => '_luhn', CLEAN_AFTER_BUILD =>0; int c_luhn( char *s ) { int i, total = 0; for( i=0; i < 15; ++i ) { int d = s[ i ] - '0'; if( !( i & 1 ) ) { d *= 2; if( d > 9 ) d -= 9; } total += d; } total *= 9; return total % 10; } END_C use Time::HiRes qw[ time ]; my @samples = qw[ 4011350000000008 4011350000000016 4011350000000024 4011350000000032 4011350000000040 4011350000000057 4011350000000065 4011350000000073 4011350000000081 4011350000000099 ]; sub luhn { use integer; my $s = $_[ 0 ]; my $total = 0; for my $i ( 0 .. 14 ) { my $d = substr( $s, $i, 1 ); unless( $i & 1 ) { $d *= 2; $d -= 9 if $d > 9; } $total += $d; } $total *= 9; return chop $total; } for ( @samples ) { print "$_: ", luhn( substr $_, 0, 15 ); } my $start = time; for ( 401135000000000..401135000999999 ) { my $chk = luhn( $_ ); } printf "Took %.9f seconds.\n", time() - $start; for ( @samples ) { print "$_: ", c_luhn( $_ ); } my $start = time; for ( 401135000000000..401135000999999 ) { my $chk = c_luhn( $_ ); } printf "Took %.9f seconds.\n", time() - $start;