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 }