#! 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; } int l[] = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }; int c_luhn2( char *s ) { int total = 0; total += l[ s[ 0] - '0' ]; total += s[ 1] - '0'; total += l[ s[ 2] - '0' ]; total += s[ 3] - '0'; total += l[ s[ 4] - '0' ]; total += s[ 5] - '0'; total += l[ s[ 6] - '0' ]; total += s[ 7] - '0'; total += l[ s[ 8] - '0' ]; total += s[ 9] - '0'; total += l[ s[10] - '0' ]; total += s[11] - '0'; total += l[ s[12] - '0' ]; total += s[13] - '0'; total += l[ s[14] - '0' ]; total *= 9; return total % 10; } int ll[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 }; int c_luhn3( char *s ) { return (( ll[ (int)s[ 0] ] + s[ 1] + ll[ (int)s[ 2] ] + s[ 3] + ll[ (int)s[ 4] ] + s[ 5] + ll[ (int)s[ 6] ] + s[ 7] + ll[ (int)s[ 8] ] + s[ 9] + ll[ (int)s[10] ] + s[11] + ll[ (int)s[12] ] + s[13] + ll[ (int)s[14] ] - 7 * '0' ) * 9) % 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( $_ ); #} $start = time; for ( 401135000000000..401135000999999 ) { my $chk = c_luhn( $_ ); } printf "Took %.9f seconds.\n", time() - $start; for ( @samples ) { print "$_: ", c_luhn2( $_ ); } $start = time; for ( 401135000000000..401135000999999 ) { my $chk = c_luhn2( $_ ); } printf "Took %.9f seconds.\n", time() - $start; for ( @samples ) { print "$_: ", c_luhn3( $_ ); } $start = time; for ( 401135000000000..401135000999999 ) { my $chk = c_luhn3( $_ ); } printf "Took %.9f seconds.\n", time() - $start;