1 module yu.algorithm.checksum; 2 3 @nogc : 4 // see . https://en.wikipedia.org/wiki/Fletcher%27s_checksum 5 ushort Fletcher16(const ubyte[] dt) @system 6 { 7 ushort sum1 = 0xff, sum2 = 0xff; 8 size_t tlen; 9 size_t bytes = dt.length; 10 ubyte * data = cast(ubyte *)dt.ptr; 11 while (bytes) { 12 tlen = ((bytes >= 20) ? 20 : bytes); 13 bytes -= tlen; 14 do { 15 sum2 += sum1 += *data++; 16 tlen--; 17 } while (tlen); 18 sum1 = (sum1 & 0xff) + (sum1 >> 8); 19 sum2 = (sum2 & 0xff) + (sum2 >> 8); 20 } 21 /* Second reduction step to reduce sums to 8 bits */ 22 sum1 = (sum1 & 0xff) + (sum1 >> 8); 23 sum2 = (sum2 & 0xff) + (sum2 >> 8); 24 return cast(ushort)((sum2 << 8) | sum1); 25 } 26 27 // see . https://en.wikipedia.org/wiki/Fletcher%27s_checksum 28 uint Fletcher32(const ushort[] dt) @system 29 { 30 uint sum1 = 0xffff, sum2 = 0xffff; 31 size_t tlen; 32 size_t words = dt.length; 33 ushort * data = cast(ushort *)dt.ptr; 34 while (words) { 35 tlen = ((words >= 359) ? 359 : words); 36 words -= tlen; 37 do { 38 sum2 += sum1 += *data++; 39 tlen--; 40 } while (tlen); 41 sum1 = (sum1 & 0xffff) + (sum1 >> 16); 42 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 43 } 44 /* Second reduction step to reduce sums to 16 bits */ 45 sum1 = (sum1 & 0xffff) + (sum1 >> 16); 46 sum2 = (sum2 & 0xffff) + (sum2 >> 16); 47 return (sum2 << 16) | sum1; 48 } 49 50 // see : https://en.wikipedia.org/wiki/Adler-32 51 uint Adler32(ubyte[] data) 52 { 53 enum MOD_ADLER = 65521; 54 uint a = 1, b = 0; 55 /* Process each byte of the data in order */ 56 foreach(ch; data) 57 { 58 a = (a + ch) % MOD_ADLER; 59 b = (b + a) % MOD_ADLER; 60 } 61 62 return (b << 16) | a; 63 } 64 65 //CRC(Cyclic Redundancy Check/循环冗余校验) 66 ushort CRC(ubyte[] data) 67 { 68 enum ubyte[256] _auchCRCHi = [0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80, 69 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 70 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 71 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 72 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 73 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 74 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 75 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 76 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 77 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 78 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 79 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 80 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 81 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 82 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 83 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 84 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 85 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 86 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 87 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 88 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 89 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 90 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 91 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 92 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 93 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 ]; 94 // CRC低位字节值表 95 enum ubyte[256] _auchCRCLo = [0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 96 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 97 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 98 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 99 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 100 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 101 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 102 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 103 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 104 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 105 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 106 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 107 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 108 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 109 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 110 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 111 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 112 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 113 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 114 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 115 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 116 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 117 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 118 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 119 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 120 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 ] ; 121 122 ubyte crcLo = 0xff; // 初始化校验结果低字节 123 ubyte crcHi = 0xff; // 初始化校验结果高字节 124 foreach(ch; data) 125 { 126 auto crcIndex = crcLo ^ ch; 127 crcLo = cast(ubyte)(crcHi ^ _auchCRCHi[crcIndex]); 128 crcHi = _auchCRCLo[crcIndex]; 129 } 130 return cast(ushort)(crcHi << 8 | crcLo); 131 } 132 133 //Longitudinal Redundancy Check/纵向冗余校验 134 ubyte LRC(ubyte[] data) 135 { 136 size_t rv = 0; 137 foreach(ch; data) 138 rv += ch; 139 return cast(ubyte)((rv ^ 0xFF) + 1); 140 } 141 142 //Block Check Character 143 ubyte XOR(ubyte[] data) 144 { 145 ubyte rv = 0; 146 foreach(ch; data) 147 rv ^= ch; 148 return rv; 149 }