Algorithm-LUHN_XS
view release on metacpan or search on metacpan
lib/Algorithm/LUHN_XS.pm view on Meta::CPAN
my %map = map { $_ => $_ } 0..9;
valid_chars(%map);
_al_init_vc(\%map);
=pod
=head1 NAME
Algorithm::LUHN_XS - Very Fast XS Version of the original Algorithm::LUHN
=head1 SYNOPSIS
use Algorithm::LUHN_XS qw/check_digit is_valid/;
my $c;
$c = check_digit("43881234567");
print "It works\n" if is_valid("43881234567$c");
$c = check_digit("A2C4E6G8"); # this will return undef
if (!defined($c)) {
# couldn't create a check digit
}
print "Valid LUHN characters are:\n";
my %vc = Algorithm::LUHN_XS::valid_chars();
for (sort keys %vc) {
print "$_ => $vc{$_}\n";
}
Algorithm::LUHN_XS::valid_chars(map {$_ => ord($_)-ord('A')+10} A..Z);
$c = check_digit("A2C4E6G8");
print "It worked again\n" if is_valid("A2C4E6G8$c");
=head1 DESCRIPTION
This module is an XS version of the original Perl Module Algorithm::LUHN, which
was written by Tim Ayers. It should work exactly the same, only substantially
faster. The supplied check_digit() routine is 100% compatible with the pure
Perl Algorithm::LUHN module, while the faster check_digit_fast() and really fast
check_digit_rff() are not.
How much faster? Here's a benchmark, running on a 3.4GHz i7-2600:
C<Benchmark: timing 100 iterations>
C<Algorithm::LUHN: 69 secs (69.37 usr 0.00 sys) 1.44/s>
C<check_digit: 2 secs ( 1.98 usr 0.00 sys) 50.51/s>
C<check_digit_fast: 2 secs ( 1.68 usr 0.00 sys) 59.52/s>
C<check_digit_rff: 1 secs ( 1.29 usr 0.00 sys) 77.52/s>
So, it's 35x to 53x faster than the original pure Perl module, depending on
how much compatibility with the original module you need.
The rest of the documentation is mostly a copy of the original docs, with some
additions for functions that are new.
This module calculates the Modulus 10 Double Add Double checksum, also known as
the LUHN Formula. This algorithm is used to verify credit card numbers and
Standard & Poor's security identifiers such as CUSIP's and CSIN's.
You can find plenty of information about the algorithm by searching the web for
"modulus 10 double add double".
=head1 FUNCTION
=over 4
=cut
=item is_valid CHECKSUMMED_NUM
This function takes a credit-card number and returns true if
the number passes the LUHN check.
Ie it returns true if the final character of CHECKSUMMED_NUM is the
correct checksum for the rest of the number and false if not. Obviously the
final character does not factor into the checksum calculation. False will also
be returned if NUM contains in an invalid character as defined by
valid_chars(). If NUM is not valid, $Algorithm::LUHN_XS::ERROR will contain the
reason.
This function is equivalent to
substr $N,length($N)-1 eq check_digit(substr $N,0,length($N)-1)
For example, C<4242 4242 4242 4242> is a valid Visa card number,
that is provided for test purposes. The final digit is '2',
which is the right check digit. If you change it to a '3', it's not
a valid card number. Ie:
is_valid('4242424242424242'); # true
is_valid('4242424242424243'); # false
=cut
=item is_valid_fast CHECKSUMMED_NUM
=cut
=item is_valid_rff CHECKSUMMED_NUM
As with check_digit(), we have 3 versions of is_valid(), each one progressively
faster than the check_digit() that comes in the original pure Perl
Algorithm::LUHN module. Here's a benchmark of 1M total calls to is_valid():
C<Benchmark: timing 100 iterations>
C<Algorithm::LUHN: 100 secs (100.29 usr 0.01 sys) 1.00/s>
C<is_valid: 3 secs ( 2.46 usr 0.11 sys) 38.91/s>
C<is_valid_fast: 2 secs ( 2.38 usr 0.05 sys) 41.15/s>
C<is_valid_rff: 2 secs ( 1.97 usr 0.08 sys) 48.78/s>
Algorithm::LUHN_XS varies from 38x to 48x times faster than the original
pure perl Algorithm::LUHN module. The is_valid() routine is 100% compatible
with the original, returning either '1' for success or the empty string ''
for failure. The is_valid_fast() routine returns 1 for success and 0 for
failure. Finally, the is_valid_rff() function also returns 1 for success
( run in 1.355 second using v1.01-cache-2.11-cpan-13bb782fe5a )