CRC32 - Не выходит каменный цветок
От: удусекшл  
Дата: 17.10.19 07:39
Оценка:
Здравствуйте!

Накопал в инетах код для CRC8 и CRC16. Для CRC32 никак не найти бестабличный вариант. Посмотрел на CRC8 и CRC16 — они практически идентичны. Написал универсальную функцию. Она отрабатывает для CRC8 и CRC16 нормально, для CRC32 никак не могу получить то, что вроде бы должно получится.

Прогонял на таких данных:
  Скрытый текст

// Name : CRC-8
// Poly : 0x31 x^8 + x^5 0+ x^4 + 1
// Init : 0xFF
// Revert: false
// XorOut: 0x00
// Check : 0xF7 ("123456789")
// MaxLen: 15 байт(127 бит) — обнаружение одинарных, двойных, тройных и всех нечетных ошибок

// Name : CRC-16 CCITT
// Poly : 0x1021 x^16 + x^12 + x^5 + 1
// Init : 0xFFFF
// Revert: false
// XorOut: 0x0000
// Check : 0x29B1 ("123456789")
// MaxLen: 4095 байт (32767 бит) — обнаружение одинарных, двойных, тройных и всех нечетных ошибок

// Name : CRC-32
// Poly : 0x04C11DB7 x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11
// + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
// Init : 0xFFFFFFFF
// Revert: true
// XorOut: 0xFFFFFFFF
// Check : 0xCBF43926 ("123456789")
// MaxLen: 268 435 455 байт (2 147 483 647 бит) — обнаружение одинарных, двойных, пакетных и всех нечетных ошибок


Для CRC32 и реверсировал, и реципрокалил полином — в итоге всё равно фигня получается
  crc.h
#include <stdint.h>

template<typename BitsType>
BitsType makeMask( )
{
    return ~(BitsType)0;
}

template<typename BitsType>
inline
BitsType makeMostSignificantBit( )
{
    const BitsType mask = makeMask<BitsType>();
    return mask - (mask>>1); //MSBit;
}


uint8_t revertBits( uint8_t u )
{
    // 0x00 (0000)  -> 0x00 (0000)
    // 0x01 (0001)  -> 0x08 (1000)
    // 0x02 (0010)  -> 0x04 (0100)
    // 0x03 (0011)  -> 0x0C (1100)
    // 0x04 (0100)  -> 0x02 (0010)
    // 0x05 (0101)  -> 0x0A (1010)
    // 0x06 (0110)  -> 0x06 (0110)
    // 0x07 (0111)  -> 0x0E (1110)
    // 0x08 (1000)  -> 0x01 (0001)
    // 0x09 (1001)  -> 0x09 (1001)
    // 0x0A (1010)  -> 0x05 (0101)
    // 0x0B (1011)  -> 0x0D (1101)
    // 0x0C (1100)  -> 0x03 (0011)
    // 0x0D (1101)  -> 0x0B (1011)
    // 0x0E (1110)  -> 0x07 (0111)
    // 0x0F (1111)  -> 0x0F (1111)
    static uint8_t revertTable[16] = { 0x00, 0x08, 0x04, 0x0C
                                     , 0x02, 0x0A, 0x06, 0x0E
                                     , 0x01, 0x09, 0x05, 0x0D
                                     , 0x03, 0x0B, 0x07, 0x0F
                                     };
    return  revertTable[ (u&0xF0)>>4 ]
         | (revertTable[ (u&0x0F) ] << 4)
         ;
}

uint16_t revertBits( uint16_t u )
{
    return  (uint16_t)revertBits( (uint8_t)(u>>8  ) )
         | ((uint16_t)revertBits( (uint8_t)(u&0xFF) )<<8)
         ;
}

uint32_t revertBits( uint32_t u )
{
    return  (uint32_t)revertBits( (uint16_t)(u>>16  ) )
         | ((uint32_t)revertBits( (uint16_t)(u&0xFFFF) )<<16)
         ;
}

template<typename BitsType>
BitsType revertBits( BitsType bits, bool revert )
{
    return revert ? revertBits(bits) : bits;
}


// https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials

//   1 [0  0  0  1 |0  0  0  0 |0  0  1  0 |0  0  0  1]  Normal
//  [1  0  0  0 |0  1  0  0 |0  0  0  0 |1  0  0  0] 1   Reverse
//   1 [0  0  0  0 |1  0  0  0 |0  0  0  1 |0  0  0  1]  Reciprocal
//

// Reciprocal - подразымевающаяся в N+1 разряде единица всасывается сдвигом право, 
// затем это число реверсируется

template<typename BitsType>
BitsType reciprocalBits( BitsType bits, bool revert )
{
    //if (!reciprocal) return bits;
    //BitsType mask = ~(CrcType)0;
    BitsType msb = makeMostSignificantBit<BitsType>();
    BitsType res = (bits>>1)|msb;
    return revert ? res : revertBits<BitsType>( res, true);
}


enum class CrcTransformType
{
    normal,
    reversed,
    reciprocal,
    reversed_reciprocal
};


template<typename BitsType>
BitsType crcPrepareValue( BitsType bits, CrcTransformType trt )
{
    switch(trt)
    {
        case CrcTransformType::reversed:
             return revertBits(bits);
        case CrcTransformType::reciprocal:
             return reciprocalBits(bits, false);
        case CrcTransformType::reversed_reciprocal:
             return reciprocalBits(bits, false);
        default:
             return bits;
    }
}



template<typename UintType>
UintType uintUnaryMinus( UintType u )
{
    return -u;
}

template<>
inline
uint8_t uintUnaryMinus<uint8_t>(uint8_t u)
{
    return (uint8_t)(-((int8_t)u));
}

template<>
inline
uint16_t uintUnaryMinus<uint16_t>(uint16_t u)
{
    return (uint16_t)(-((int16_t)u));
}

template<>
inline
uint32_t uintUnaryMinus<uint32_t>(uint32_t u)
{
    return (uint32_t)(-((int32_t)u));
}





// Check : 0xF7 ("123456789")
// Check : 0x29B1 ("123456789")
// Check : 0xCBF43926 ("123456789")

template< typename CrcType, CrcType NBits, CrcType Poly, bool revert >
CrcType crcStepImpl( CrcType crc, uint8_t byte )
{
#if 1

    const CrcType nshift = NBits - 8; //NBits>16 ? 16 : NBits - 8; //NBits - 8; //NShift;
    const CrcType mask   = makeMask<CrcType>();
    const CrcType msbit = makeMostSignificantBit<CrcType>();
    const CrcType poly   = Poly;

    if (nshift)
        crc ^= ((CrcType)byte);// << nshift;
    else
        crc ^= ((CrcType)byte); // << NShift;
 
    for ( auto i = 0u; i != 8u; ++i)
    {
        //crc = crc & 1 ? (crc >> 1) ^ poly : crc >> 1;
        crc = crc & msbit ? (crc << 1) ^ poly : crc << 1;
        crc &= mask;

        //crc = (crc >> 1) ^ (- (CrcType)(crc & 1) & poly);
        //crc = (crc >> 1) ^ (uintUnaryMinus<CrcType>(crc & 1) & poly);
        //crc = (crc << 1) ^ (uintUnaryMinus<CrcType>(crc & msbit) & poly);
        
    }

#else

    if (NShift)
        crc ^= ((CrcType)byte) << NShift;
    else
        crc ^= ((CrcType)byte); // << NShift;
 
    for ( auto i = 0u; i != 8u; ++i)
    {
        crc = crc & MSBit ? (crc << 1) ^ Poly : crc << 1;
    }

#endif

    return crc;
}

//template< typename CrcType, CrcType MSBit, CrcType NShift, CrcType Poly, CrcType Init >
template< typename CrcType, CrcType NBits, CrcType Poly, bool revert, CrcType XorOut, CrcType Init >
CrcType crcImpl( const uint8_t *pBuf, size_t len )
{
    CrcType crc = Init;
    while(len--)
    {
        crc = crcStepImpl< CrcType, NBits, Poly, revert >( crc, *pBuf++ );
    }

    return crc ^ XorOut;
    //return revertBits(crc, revert) ^ XorOut;
    //return revertBits( (CrcType)(crc ^ XorOut), revert) ;
}


template< uint8_t Poly    = 0x31u
        , bool    revert  = false
        , uint8_t XorOut  = 0x00u
        , uint8_t Init    = 0xFFu
        >
uint8_t crc8( const uint8_t *pBuf, size_t len )
{
    return crcImpl< uint8_t, 8u, Poly, revert, XorOut, Init >( pBuf, len );
}

template< uint16_t Poly   = 0x1021u
        , bool     revert = false
        , uint16_t XorOut = 0x0000u
        , uint16_t Init   = 0xFFFFu
        >
uint16_t crc16( const uint8_t *pBuf, size_t len )
{
    return crcImpl< uint16_t, 16u, Poly, revert, XorOut, Init >( pBuf, len );
}

template< uint32_t Poly   = 0x04C11DB7u
        , bool     revert = true
        , uint32_t XorOut = 0xFFFFFFFFu
        , uint32_t Init   = 0xFFFFFFFFu
        >
uint32_t crc32( const uint8_t *pBuf, size_t len )
{
    return crcImpl< uint32_t, 32u, Poly, revert, XorOut, Init >( pBuf, len );
}
  main.cpp
#include <iostream>
#include <iomanip>

#include "../../crc.h"


// Check : 0xF7 ("123456789")
// Check : 0x29B1 ("123456789")
// Check : 0xCBF43926 ("123456789")

using std::cout;
using std::endl;

int main(int argc, char* argv[])
{
    const char data[10] = "123456789";
    size_t sz = 9;

    // http://users.ece.cmu.edu/~koopman/crc/crc32.html
    uint16_t  bits16  = 0x1021;
    uint16_t  rvrt16  = revertBits( bits16, true );
    uint16_t  rcprD16 = reciprocalBits( bits16, false );
    uint16_t  rcprR16 = reciprocalBits( bits16, true );
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<bits16 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rvrt16 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprD16<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprR16<<endl;
    cout<<"---"<<endl;

    // (0x82608edb; 0x104c11db7) <=> (0xedb88320; 0x1db710641) {4294967263,91607,2974,268,171,91,57,34,21,12,10,10,10} | gold | (*p) IEEE 802.3; CRC-32
    //   Normal     Reversed   Reciprocal  Reversed reciprocal
    // 0x04c11db7  0xedb88320  0xdb710641  0x82608edb
    // 0x82608edb  0xdb710641  0xb6e20c83  0xc130476d

    uint32_t  bits32  = 0x04c11db7;
    uint32_t  rvrt32  = revertBits( bits32, true );
    uint32_t  rcprD32 = reciprocalBits( bits32, false );
    uint32_t  rcprR32 = reciprocalBits( bits32, true );
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<bits32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rvrt32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprD32<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprR32<<endl;
    cout<<"---"<<endl;

              bits32  = 0x82608edb;
              rvrt32  = revertBits( bits32, true );
              rcprD32 = reciprocalBits( bits32, false );
              rcprR32 = reciprocalBits( bits32, true );
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<bits32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rvrt32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprD32<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprR32<<endl;
    cout<<"---"<<endl;

              bits32  = 0x82608edb;
              rvrt32  = revertBits( bits32, true );
              rcprD32 = reciprocalBits( bits32, false );
              rcprR32 = reciprocalBits( bits32, true );
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<bits32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rvrt32 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprD32<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<rcprR32<<endl;
    cout<<"---"<<endl;



    unsigned crc_8    = (unsigned)crc8 ( (const uint8_t*)data, sz );
    unsigned crc_16   = (unsigned)crc16( (const uint8_t*)data, sz );
    unsigned crc_32_1 = (unsigned)crc32( (const uint8_t*)data, sz );
    unsigned crc_32_2 = (unsigned)crc32<0x04c11db7u>( (const uint8_t*)data, sz );
    unsigned crc_32_3 = (unsigned)crc32<0xedb88320u>( (const uint8_t*)data, sz );
    unsigned crc_32_4 = (unsigned)crc32<0xdb710641u>( (const uint8_t*)data, sz );
    unsigned crc_32_5 = (unsigned)crc32<0x82608edbu>( (const uint8_t*)data, sz );
    unsigned crc_32_6 = (unsigned)crc32<0xb6e20c83>( (const uint8_t*)data, sz );
    unsigned crc_32_7 = (unsigned)crc32<0xc130476d>( (const uint8_t*)data, sz );
    //unsigned crc32_8 = (unsigned)crc32<>( (const uint8_t*)data, sz );


    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_8 <<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_16<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_1<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_2<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_3<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_4<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_5<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_6<<endl;
    cout<<std::hex<<std::setw(8)<<std::right<<std::setfill('0')<<crc_32_7<<endl;
    //    <<crc8 <<std::endl
    //    <<crc16<<std::endl
    //    <<crc32<<std::endl;
    return 0;
}

Что-то никак не дотумкать, почему оно не работает и где чего еще покрутить можно
crc
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.