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
Re: CRC32 - Не выходит каменный цветок
От: Maniacal Россия  
Дата: 17.10.19 07:59
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте!


У>Накопал в инетах код для 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;
У>}
У>

У>Что-то никак не дотумкать, почему оно не работает и где чего еще покрутить можно


Тут не оно?
Re: CRC32 - Не выходит каменный цветок
От: Maniacal Россия  
Дата: 17.10.19 08:33
Оценка: 2 (1)
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте!


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


У>Что-то никак не дотумкать, почему оно не работает и где чего еще покрутить можно


Вот, короче, код crc32 для навигаторов novatel, из прошивки, вроде.
#define POLYCRC32   0xEDB88320u /* CRC32 polynomial */

extern unsigned int crc32(const unsigned char *buff, int len)
{
    unsigned int crc=0;
    int i,j;
    
    trace(4,"crc32: len=%d\n",len);
    
    for (i=0;i<len;i++) {
        crc^=buff[i];
        for (j=0;j<8;j++) {
            if (crc&1) crc=(crc>>1)^POLYCRC32; else crc>>=1;
        }
    }
    return crc;
}
Re: CRC32 - Не выходит каменный цветок
От: fk0 Россия https://fk0.name
Дата: 17.10.19 08:50
Оценка: 2 (1) +1
Здравствуйте, удусекшл, Вы писали:

У>Накопал в инетах код для CRC8 и CRC16. Для CRC32 никак не найти бестабличный вариант.


Во-первых алгоритмы CRC отличаются начальным значением направлением сдвига, инверсией данных, полиномом... поэтому CRC-16 -- это ещё неизвестно что именно.

Во-вторых все они в оригинале -- не требуют таблиц. Знай себе полином и ксорь побитово. Таблица лишь способ оптимизации. Можно использовать таблицу из 256 элементов, тогда можно ксорить побайтно. Можно таблицу из 8 элементов, тогда можно её зашить прямо в код (инструкции процессора, а не таблицу), и ксорить 8 раз последовательно (или не ксорить, в зависимости от каждого из 8 битов байта). В последнем случае таблица является 1, 2, 4, 8, 16, 32, 64, 128-м элементом полноценной таблицы (для каждого отдельного бита). Полноценная же таблица генерируется прокручиванием чисел 0-255 через медленный вариант, который прокручивает очередной байт (можно и слово, но размер таблицы вообще чудовищный же будет) побитно и в зависимости от значения бита ксорит или нет с полиномом.
Re[2]: CRC32 - Не выходит каменный цветок
От: удусекшл  
Дата: 08.11.19 11:32
Оценка:
Здравствуйте, fk0, Вы писали:


У>>Накопал в инетах код для CRC8 и CRC16. Для CRC32 никак не найти бестабличный вариант.


fk0> Во-первых алгоритмы CRC отличаются начальным значением направлением сдвига, инверсией данных, полиномом... поэтому CRC-16 -- это ещё неизвестно что именно.


fk0> Во-вторых все они в оригинале -- не требуют таблиц. Знай себе полином и ксорь побитово. Таблица лишь способ оптимизации. Можно использовать таблицу из 256 элементов, тогда можно ксорить побайтно. Можно таблицу из 8 элементов, тогда можно её зашить прямо в код (инструкции процессора, а не таблицу), и ксорить 8 раз последовательно (или не ксорить, в зависимости от каждого из 8 битов байта). В последнем случае таблица является 1, 2, 4, 8, 16, 32, 64, 128-м элементом полноценной таблицы (для каждого отдельного бита). Полноценная же таблица генерируется прокручиванием чисел 0-255 через медленный вариант, который прокручивает очередной байт (можно и слово, но размер таблицы вообще чудовищный же будет) побитно и в зависимости от значения бита ксорит или нет с полиномом.



Спс. Я вроде сделал, но не совсем

Для тестов взял таблицу "Примеры" со странички в вики — https://ru.wikipedia.org/wiki/%D0%A6%D0%B8%D0%BA%D0%BB%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%B8%D0%B7%D0%B1%D1%8B%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4

RefIn — разбил на два булева случая: один флаг — меняем порядок бит в заданном полиноме, и второй флаг в какую сторону сдвигать и по какому биту проверять — по младшему/по старшему.
И каждую строчку таблицы разбил на четыре строки с разными комбинациями этих флагов. До — почти ничего не сходилось, после этого — примерно у половины примеров один вариант из четырех стал выстреливать.
Но стабильно не сходятся все варианты, когда refOut == true. И я вот не понял, в какой момент его применять. Пробовал на выходе реверсить результат до/после финального XORа — поломались и рабочие варианты
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.