Algorithm-Damm

 view release on metacpan or  search on metacpan

lib/Algorithm/Damm.pm  view on Meta::CPAN

package Algorithm::Damm;

use strict;
use Exporter;

use vars qw/$VERSION @ISA @EXPORT @EXPORT_OK $ERROR/;

@ISA       = qw/Exporter/;
@EXPORT    = qw//;
@EXPORT_OK = qw/check_digit is_valid/;

$VERSION = '1.001.002';

=pod

=head1 NAME

Algorithm::Damm - Calculate the Damm error correction check digit.

=head1 SYNOPSIS

  use Algorithm::Damm qw/check_digit is_valid/;

  $c = check_digit("43881234567");
  print "It works\n" if is_valid("43881234567$c");

=head1 DESCRIPTION

This module implements the Damm algorithm for calculating a check
digit.

You can find information about the algorithm by searching the web for
"Damm ECC".  In particular, see the L<SEE ALSO> section (below).

=head1 FUNCTIONS

=over 4

=cut

=item is_valid CHECKSUMMED_NUM

This function returns 1 if the final character of CHECKSUMMED_NUM is
the correct checksum for the rest of the number, 0 if not, and undef
if CHECKSUMMED_NUM contains an invalid character or does not contain
at least two digits (one for the number, and one for the checksum).

This function is equivalent to

  substr $N,length($N)-1 eq check_digit(substr $N,0,length($N)-1)

Additionally, due to the way this algorithm works, if you crank the
checksum calculation through the last digit (checkdigit included), you
will end up with a value of 0.

=cut

sub is_valid {
    my $N = shift;

    return undef unless defined( $N );
    return undef unless length( $N ) >= 2;
    return undef unless $N =~ /^\d+$/;

    return check_digit( $N ) == 0;
}

=item check_digit NUM

This function returns the checksum of the given number.  It will
return undef if it is not able to calculate the checksum.

=cut

{
    # This table is defined at
    # http://en.wikipedia.org/wiki/Damm_algorithm
    my @table = (
        [ qw( 0 3 1 7 5 9 8 6 4 2 ) ],
        [ qw( 7 0 9 2 1 5 4 8 6 3 ) ],
        [ qw( 4 2 0 6 8 7 1 3 5 9 ) ],
        [ qw( 1 7 5 0 9 8 3 4 2 6 ) ],
        [ qw( 6 1 2 3 0 4 5 9 7 8 ) ],
        [ qw( 3 6 7 4 2 0 9 5 8 1 ) ],
        [ qw( 5 8 6 9 7 2 0 1 3 4 ) ],
        [ qw( 8 9 4 5 3 6 2 0 1 7 ) ],
        [ qw( 9 4 3 8 6 1 7 2 0 5 ) ],
        [ qw( 2 5 8 1 4 3 6 7 9 0 ) ],
        );

    sub check_digit {
        my $N = shift;



( run in 0.745 second using v1.01-cache-2.11-cpan-39bf76dae61 )