#include <iostream>
#include <inttypes.h>

uint64_t fletcher64_A(const uint8_t * data, uint64_t count)
{
	// calculate how many full double words the input has
	uint64_t dwords = count / 4;
	// now calculate the flechter-64 checksum from double words
	uint64_t sum1 = 0;
	uint64_t sum2 = 0;
	const uint32_t * data32 = reinterpret_cast<const uint32_t*>(data);
	for (uint64_t index = 0; index < dwords; ++index) 
	{
    	sum1 = (sum1 + data32[index]) % UINT32_MAX;
    	sum2 = (sum2 + sum1) % UINT32_MAX;
    }
    // calculate how many extra bytes, that do not fit into a double word, the input has
	uint64_t remainingBytes = count - dwords * 4;
    if (remainingBytes > 0)
    {
    	// copy the excess bytes to our dummy variable. you could use memcpy here...
		uint32_t dummy = 0;
		for (uint64_t index = 0; index < remainingBytes; ++index)
		{
			reinterpret_cast<uint8_t*>(&dummy)[index] = data[dwords * 4 + index];
		}
		// now add the dummy on top
		sum1 = (sum1 + dummy) % UINT32_MAX;
		sum2 = (sum2 + sum1) % UINT32_MAX;
    }
    // build final checksum
    return (sum2 << 32) | sum1;
}

uint64_t fletcher64_B(const uint8_t * data, uint64_t count)
{
	// calculate how many full double words the input has
	uint64_t dwords = count / 4;
	// now calculate the flechter-64 checksum from double words
	uint32_t sum1 = 0;
	uint32_t sum2 = 0;
	const uint32_t * data32 = reinterpret_cast<const uint32_t*>(data);
	for (uint64_t index = 0; index < dwords; ++index) 
	{
		sum1 += data32[index];
		sum2 += sum1;
    }
    // calculate how many extra bytes, that do not fit into a double word, the input has
	uint64_t remainingBytes = count - dwords * 4;
    if (remainingBytes > 0)
    {
    	// copy the excess bytes to our dummy variable. you could use memcpy here...
		uint32_t dummy = 0;
		for (uint64_t index = 0; index < remainingBytes; ++index)
		{
			reinterpret_cast<uint8_t*>(&dummy)[index] = data[dwords * 4 + index];
		}
		// now add the dummy on top
		sum1 += dummy;
		sum2 += sum1;
    }
    // build final checksum
    return ((uint64_t)sum2 << 32) | sum1;
}

int main() {
	const std::string data = "abcdefghijklmnopqrstuvwxyz0123456789helloworld!";
	uint64_t ca = fletcher64_A(reinterpret_cast<const uint8_t*>(data.data()), data.size());
	uint64_t cb = fletcher64_B(reinterpret_cast<const uint8_t*>(data.data()), data.size());
	std::cout << "String size: " << data.size() << ", checksum a: 0x" << std::hex << ca << ", checksum b: 0x" << cb << std::endl;
	return 0;
}