CRC-16 in Swift 3.x+

I have been trying to do this for sometime. Inspired by a LabVIEW implementation at a previous job, I have been trying to implement the same CRC-16 algorithm in Swift. The cyclic redundancy check is a mathematical computation used in various areas of hardware and software to detect false bits in a stream of data. Computing CRCs can be tricky and there are so many ways to compute a CRC. The implementation shared here can compute two types of CRC-16s depending on the specification, either ARC or MODBUS. In both cases, the polynomial used is the bit-reverse of the 0x8005 polynomial show here:


    \[ x^{16} + x^{15} + x^{2}+ 1 \]

which is 0xA001. The initial accumulator value is set depending on the kind of CRC specified, zero for ARC and 0xFFFF for MODBUS. I used this site and this one for external verification.

import Foundation

enum CRCType {
    case MODBUS
    case ARC
}

func crc16(_ data: [UInt8], type: CRCType) -> UInt16? {
    if data.isEmpty {
        return nil
    }
    let polynomial: UInt16 = 0xA001 // A001 is the bit reverse of 8005
    var accumulator: UInt16
    // set the accumulator initial value based on CRC type
    if type == .ARC {
        accumulator = 0
    }
    else {
        // default to MODBUS
        accumulator = 0xFFFF
    }
    // main computation loop
    for byte in data {
        var tempByte = UInt16(byte)
        for _ in 0 ..< 8 {
            let temp1 = accumulator & 0x0001
            accumulator = accumulator >> 1
            let temp2 = tempByte & 0x0001
            tempByte = tempByte >> 1
            if (temp1 ^ temp2) == 1 {
                accumulator = accumulator ^ polynomial
            }
        }
    }
    return accumulator
}

// try it out...

let data = [UInt8]([0x31, 0x32, 0x33])

let arcValue = crc16(data, type: .ARC)

let modbusValue = crc16(data, type: .MODBUS)

if arcValue != nil && modbusValue != nil {
    
    let arcStr = String(format: "0x%4X", arcValue!)
    let modbusStr = String(format: "0x%4X", modbusValue!)
    
    print("CRCs: ARC = " + arcStr + " MODBUS = " + modbusStr)
}

Here is the output in Xcode:

Result as shown in Xcode

Compare the result to the previously mentioned online CRC sites:

Results from crccalc
Results from Lammert Bies’ site

Given more time, this can be improved and expanded to do more CRC-16 computation types.