这是计算fletcher64校验和的正确方法吗

这是计算fletcher64校验和的正确方法吗,c,checksum,reliability,C,Checksum,Reliability,fletcher16源代码如下所示 uint16\u t Fletcher16(uint8\u t*数据,整数计数) { uint16_t sum1=0; uint16_t sum2=0; 整数指数; 对于(索引=0;索引>(sizeof(R)*8)); } //构建最终校验和 return(sum2)注释“UINT_MAX=2^32”是不正确的,因为UINT_MAX对于32位来说是2^32-1。对于较大的字节量,您的B版本是不正确的,因为最终您会遇到溢出,这就是您出错的地方。有关详细信息,请参

fletcher16源代码如下所示

uint16\u t Fletcher16(uint8\u t*数据,整数计数)
{
uint16_t sum1=0;
uint16_t sum2=0;
整数指数;
对于(索引=0;索引<计数;++索引)
{
sum1=(sum1+数据[索引])%255;
sum2=(sum2+sum1)%255;
}

return(sum2是的,它似乎是正确的,但一定要测试它。

大多数哈希算法都会使用内存块的参数和要哈希的字节数(有时是位)。您已将字节数更改为字数,这是一个相当重要的更改


此外,由于您更改了计算大小,因此计算sum2的方式也发生了更改。只要您不尝试复制每个值的原始算法值,这是可以的,但如果这是一个兼容的优化,那么这可能是错误的。

这是错误的。您将丢失0-3字节的后续数据,因为您只是对数据中的DWORD进行求和,但根据数据大小,可能仍有一些字节剩余。我建议:

#包括
#包括
uint64_t fletcher64_A(常数uint8_t*数据,uint64_t计数)
{
//计算输入有多少完整的双字
uint64_t dwords=计数/4;
//现在从双字计算flechter-64校验和
uint64_t sum1=0;
uint64_t sum2=0;
const uint32_t*data32=重新解释转换(数据);
对于(uint64_t index=0;index0)
{
//将多余的字节复制到我们的虚拟变量。您可以在这里使用memcpy。。。
uint32_t虚拟=0;
对于(uint64_t index=0;index0)
{
//将多余的字节复制到我们的虚拟变量。您可以在这里使用memcpy。。。
R=0;
const uint8_t*data8=重新解释广播(dataR);
对于(uint64_t index=0;index>(sizeof(R)*8));
sum2=(sum2&std::numeric_limits::max())+(sum2>>(sizeof(R)*8));
}
//构建最终校验和

return(sum2)注释“UINT_MAX=2^32”是不正确的,因为UINT_MAX对于32位来说是2^32-1。对于较大的字节量,您的B版本是不正确的,因为最终您会遇到溢出,这就是您出错的地方。有关详细信息,请参阅“优化”下的WP文章,和限制值360。但是,对于fletcher64,需要首先确定正确的限制值。请记住,UINT32_MAX不是2^32,而是2^32-1。您可能是正确的。我还没有对它进行足够的数据测试……您能提供正确的实现吗?您必须对和使用64位整数,并添加
sumX=(sumX&UINT32_MAX)+(sumX>>32)
(X分别为1和2)在循环中。但在现代CPU上,模(%)代码可能更快,因为它可以在几个周期内进行模运算,并且所需时间少于and和OR操作。因此,要获得最大速度,请使用优化,计数器最高可达359,如WP文章所示。
uint16_t Fletcher16( uint8_t* data, int count )
{
   uint16_t sum1 = 0;
   uint16_t sum2 = 0;
   int index;

   for( index = 0; index < count; ++index )
   {
      sum1 = (sum1 + data[index]) % 255;
      sum2 = (sum2 + sum1) % 255;
   }

   return (sum2 << 8) | sum1;
}
unsigned long Fletcher64( unsigned int* data, int count )
{
   unsigned long sum1 = 0;
   unsigned long sum2 = 0;
   int index;

   for( index = 0; index < count; ++index )
   {
      sum1 = (sum1 + data[index]) % UINT_MAX; // UINT_MAX = 2^32
      sum2 = (sum2 + sum1) % UINT_MAX;
   }

   return (sum2 << 32) | sum1;
}
#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;
}
#include <iostream>
#include <inttypes.h>
#include <random>
#include <algorithm>
#include <chrono>
#include <limits>

uint64_t test_overflow(uint64_t start, uint64_t add, uint64_t check)
{
    uint64_t count = 0;
    uint64_t sum1 = start;
    uint64_t sum2 = start;
    do
    {
        sum2 += sum1 += add;
        count++;
    } while (sum1 + add < check && sum2 + (sum1 + add) < check);
    return count;
}

template <class T, class R>
T fletcherTA(const uint8_t * data, const T & count, const T & start)
{
    // calculate how many full R-words the input has
    T rwords = count / sizeof(R);
    // calculate how many extra bytes, that do not fit into an R-word, the input has
    T remainingBytes = count - rwords * sizeof(R);
    // now calculate the flechter-T checksum from R-words
    T sum1 = start & std::numeric_limits<R>::max();
    T sum2 = start >> (sizeof(R)*8);
    const R * dataR = reinterpret_cast<const R*>(data);
    while (rwords)
    {
        rwords--;
        sum1 = (sum1 + *dataR++) % std::numeric_limits<R>::max();
        sum2 = (sum2 + sum1) % std::numeric_limits<R>::max();
    }
    if (remainingBytes > 0)
    {
        // copy the excess bytes to our dummy variable. you could use memcpy here...
        R dummy = 0;
        const uint8_t * data8 = reinterpret_cast<const uint8_t*>(dataR);
        for (uint64_t index = 0; index < remainingBytes; ++index)
        {
            reinterpret_cast<uint8_t*>(&dummy)[index] = data8[index];
        }
        // now add the dummy on top
        sum1 = (sum1 + dummy) % std::numeric_limits<R>::max();
        sum2 = (sum2 + sum1) % std::numeric_limits<R>::max();
    }
    // build final checksum
    return (sum2 << sizeof(R)*8) | sum1;
}

template <class T, class R, T overflowAfter>
T fletcherTB(const uint8_t * data, const T & count, const T & start)
{
    // calculate how many full R-words the input has
    T rwords = count / sizeof(R);
    // calculate how many extra bytes, that do not fit into an R-word, the input has
    T remainingBytes = count - rwords * sizeof(R);
    // now calculate the flechter-T checksum from R-words
    T sum1 = start & std::numeric_limits<R>::max();
    T sum2 = start >> (sizeof(R)*8);
    const R * dataR = reinterpret_cast<const R*>(data);
    while (rwords)
    {
        T tlen = ((rwords >= overflowAfter) ? overflowAfter : rwords);     
        rwords -= tlen;
        do 
        {
            sum2 += sum1 += *dataR++;
            tlen--;
        } while (tlen);
        sum1 = (sum1 & std::numeric_limits<R>::max()) + (sum1 >> (sizeof(R)*8));
        sum2 = (sum2 & std::numeric_limits<R>::max()) + (sum2 >> (sizeof(R)*8));
    }
    if (remainingBytes > 0)
    {
        // copy the excess bytes to our dummy variable. you could use memcpy here...
        R dummy = 0;
        const uint8_t * data8 = reinterpret_cast<const uint8_t*>(dataR);
        for (uint64_t index = 0; index < remainingBytes; ++index)
        {
            reinterpret_cast<uint8_t*>(&dummy)[index] = data8[index];
        }
        // now add the dummy on top
        sum2 += sum1 += dummy;
        sum1 = (sum1 & std::numeric_limits<R>::max()) + (sum1 >> (sizeof(R)*8));
        sum2 = (sum2 & std::numeric_limits<R>::max()) + (sum2 >> (sizeof(R)*8));
    }
    // build final checksum
    return (sum2 << (sizeof(R)*8)) | sum1;
}

template <class T, class R, T overflowAfter>
void test_implementations()
{
    std::cout << "Testing " << sizeof(T)*8 << " bit implementations:" << std::endl;
    // test flechter overflow
    std::cout << "Overflow after: " << test_overflow(0, std::numeric_limits<R>::max(), std::numeric_limits<T>::max() - std::numeric_limits<R>::max()) << " rounds (start value 0)." << std::endl;
    // test fletcher checksum in both implementations with the same data
    const uint64_t dataSize = 1 * 1024 * 1024 * 1024; // 1 * 1024 * 1 MB = 1 GB of test data
    const uint64_t blockSize = std::min(std::min(dataSize, (uint64_t)10 * 1024 * 1024), (uint64_t)(std::numeric_limits<T>::max() - std::numeric_limits<T>::max() % 4));
    const T oddBlockSize = static_cast<T>(blockSize - 1);   
    const uint64_t nrOfBlocks = dataSize / blockSize;
    std::vector<uint32_t> data(blockSize / sizeof(uint32_t));
    // initialize random number generator using current time
    std::minstd_rand prng(std::chrono::high_resolution_clock::now().time_since_epoch().count());
    std::cout << "Testing checksums with " << std::dec << dataSize / (1024 * 1024) << " MB of data in " << blockSize / 1024 << " kB blocks..." << std::endl;
    T ca = 0;
    T cb = 0;   
    for (uint64_t block = 0; block < nrOfBlocks; block++)
    {
        // generate random numbers
        std::generate(data.begin(), data.end(), [&prng](){ return prng(); });
        // apply checksum function. make sure to use an odd value to test remaining bytes being captured
        ca = fletcherTA<T, R>(reinterpret_cast<const uint8_t*>(data.data()), oddBlockSize, ca);
        cb = fletcherTB<T, R, overflowAfter>(reinterpret_cast<const uint8_t*>(data.data()), oddBlockSize, cb);
    }
    std::cout << "Checksum A: 0x" << std::hex << ca << std::endl;
    std::cout << "Checksum B: 0x" << std::hex << cb << std::endl;
    // test speed
    const uint64_t runs = nrOfBlocks;
    std::cout << "Testing speed with " << std::dec << dataSize / (1024 * 1024) << " MB of data..." << std::endl;
    auto startA = std::chrono::high_resolution_clock::now();
    for (uint64_t run = 0; run < runs; run++)
    {
        ca = fletcherTA<T, R>(reinterpret_cast<const uint8_t*>(data.data()), oddBlockSize, ca);
    }
    auto endA = std::chrono::high_resolution_clock::now();
    auto startB = std::chrono::high_resolution_clock::now();
    for (uint64_t run = 0; run < runs; run++)
    {
        cb = fletcherTB<T, R, overflowAfter>(reinterpret_cast<const uint8_t*>(data.data()), oddBlockSize, cb);
    }
    auto endB = std::chrono::high_resolution_clock::now();
    std::cout << "Checksum A: 0x" << std::hex << ca << ", took " << std::dec << std::chrono::duration_cast<std::chrono::milliseconds>(endA-startA).count() << " ms" << std::endl;
    std::cout << "Checksum B: 0x" << std::hex << cb << ", took " << std::dec << std::chrono::duration_cast<std::chrono::milliseconds>(endB-startB).count() << " ms" << std::endl;
    std::cout << std::endl;
}

int main() {
    test_implementations<uint16_t, uint8_t, 20>();
    test_implementations<uint32_t, uint16_t, 359>();
    test_implementations<uint64_t, uint32_t, 683442530>();
    return 0;
}