// Single-sum checksum examples -- Chapter 5 // Copyright 2024 Philip Koopman // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "chapter5_examples.h" static const uint32_t initialSeed = SEED; // Initial sum // ---------------------- // Example from section 5.7.1 // LRC // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: must be 256 for an 8-bit LRC uint8_t LRC(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { assert(modulus == 256); // Does nothing for LRC uint32_t sum = initialSeed; // Initialize running sum // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // XOR the next byte from the data word sum = sum ^ (uint32_t)dataWord[index]; } // Modulus can be ignored if we convert to 8 bit value return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example from section 5.7.2 // Baseline modular checksum implementation // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: for computing modulo for addition uint8_t Add8_A(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { uint32_t sum = initialSeed; // Initialize running sum // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte with modulus sum = (sum + (uint32_t)dataWord[index]) % modulus; } return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example from section 5.7.3 // Avoiding division entirely // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: for computing modulo after addition uint8_t Add8_B(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { uint32_t sum = initialSeed; // Initialize running sum // Loop over all blocks in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte sum = (sum + (uint32_t)dataWord[index]); // Repeat subtraction until less than the modulus while (sum >= modulus) { sum -= modulus; } } return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example from section 5.7.4 // Delayed modulo // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: for computing modulo after addition uint8_t Add8_C(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { assert(dwSize<=0xFFFFFF); // Avoid overflow uint32_t sum = initialSeed; // Initialize running sum // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte; skip mod operation sum = (sum + (uint32_t)dataWord[index]); } // Upper 24-bits of sum have captured the carry-outs sum = sum % modulus; return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example from section 5.7.5 // Periodic modulo // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: for computing modulo after addition uint8_t Add8_D(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { uint32_t sum = initialSeed; // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte sum += dataWord[index]; // Modulus when there have been 255 carry-outs if( sum >= 0xFF00) { sum %= modulus; } } // Final modulus for any remaining carry-outs sum %= modulus; return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example from section 5.7.6 // Two's complement via masking // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: must be 256 for two's complement uint8_t Add8_Twos(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { assert(modulus==256); uint32_t sum = initialSeed; // Initialize running sum // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte; skip mod operation sum = (sum + (uint32_t)dataWord[index]); } // Only care about lowest 8 bits sum = sum & 0x000000FF; return((uint8_t)sum); // Return final checksum value } // ---------------------- // Example supporting section 5.7.7 // Ones' complement special technique // dataWord: data word in 8-bit blocks // dwSize: number of blocks in the data word // modulus: must be 255 for ones' complement uint8_t Add8_Ones(uint8_t dataWord[], uint32_t dwSize, uint32_t modulus) { assert(modulus==255); uint32_t sum = initialSeed; // Initialize running sum // Loop over all bytes in data word for(uint32_t index = 0; index < dwSize; index++) { // Add next data word byte sum = sum + dataWord[index]; // Modulus when there have been many carry-outs if( (sum & 0xC0000000) != 0 ) { sum = (sum & 0xFF) + (sum >> 8); } } // Final modulus for any remaining carry-outs while (sum > 0xFF) { sum = (sum & 0xFF) + (sum >> 8); } return((uint8_t)sum); // Return final checksum value }