The Damm algorithm is a checksum algorithm which detects all single digit errors and adjacent transposition errors.



The algorithm is named after H. Michael Damm.



Task

Verify the checksum, stored as last digit of an input.



      LOGICAL FUNCTION DAMM(DIGIT)	!Check that a sequence of digits checks out..
Calculates according to the method of H. Michael Damm, described in 2004.
       CHARACTER*(*) DIGIT		!A sequence of digits only.
       INTEGER*1 OPTABLE(0:9,0:9)	!The special "Operation table" of the method.
       PARAMETER (OPTABLE = (/		!A set of constants...
     o  0, 3, 1, 7, 5, 9, 8, 6, 4, 2,	!        CAREFUL!
     1  7, 0, 9, 2, 1, 5, 4, 8, 6, 3,	!Fortran stores arrays in column-major order.
     2  4, 2, 0, 6, 8, 7, 1, 3, 5, 9,	!Despite the manifest row and column layout apparent here
     3  1, 7, 5, 0, 9, 8, 3, 4, 2, 6,	!This sequence of consecutive items will go into storage order.
     4  6, 1, 2, 3, 0, 4, 5, 9, 7, 8,	!The table resulting from this sequence of constants
     5  3, 6, 7, 4, 2, 0, 9, 5, 8, 1,	!Will appear to be transposed if referenced as (row,column)
     6  5, 8, 6, 9, 7, 2, 0, 1, 3, 4,	!What appears to be row=6 column=1 (counting from zero)
     7  8, 9, 4, 5, 3, 6, 2, 0, 1, 7,	!is to be accessed as OPTABLE(1,6) = 8, not OPTABLE(6,1)
     8  9, 4, 3, 8, 6, 1, 7, 2, 0, 5,	!Storage order is (0,0), (1,0), (2,0), ... (9,0)
     9  2, 5, 8, 1, 4, 3, 6, 7, 9, 0/))	!Followed by      (0,1), (1,1), (2,1), ... (9,1)
       INTEGER I,D,ID	!Assistants.
        ID = 0		!Here we go.
        DO I = 1,LEN(DIGIT)	!Step through the text.
          D = ICHAR(DIGIT(I:I)) - ICHAR("0")	!Convert to an integer. (ASCII or EBCDIC)
          IF (D.LT.0 .OR. D.GT.9) STOP "DAMM! Not a digit!"	!This shouldn't happen!
          ID = OPTABLE(D,ID)		!Transposed: D is the column index and ID the row.
        END DO			!On to the next.
        DAMM = ID .EQ. 0	!Somewhere, a check digit should ensure this.
      END FUNCTION DAMM	!Simple, fast, and alas, rarely used.
 
      LOGICAL DAMM	!Not a default type.
 
      WRITE (6,*) DAMM("5724"),"5724"
      WRITE (6,*) DAMM("5727"),"5727"
      WRITE (6,*) DAMM("112946"),"112946"
 
      END