1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*!
# CRC Any

To compute CRC values by providing the length of bits, expression, reflection, an initial value and a final xor value. It has built-in CRC-8-ATM, CRC-8-CDMA, CRC-16-IBM, CRC16-CCITT, CRC-32-IEEE, CRC-32-C, CRC-64-ISO and CRC-64-ECMA functions.

## Usage

You can use `create_crc` associated function to create a CRC instance by providing the length of bits, expression, reflection, an initial value and a final xor value. For example, if you want to compute a CRC-24 value.

```rust
extern crate crc_any;

use crc_any::CRC;

let mut crc24 = CRC::create_crc(0x0000000000864cfb, 24, 0x0000000000b704ce, 0x0000000000000000, false);

crc24.digest(b"hello");

assert_eq!([71, 245, 138].to_vec(), crc24.get_crc_vec());
```

To simplify the usage, there are several common versions of CRC whose computing functions are already built-in.

 * crc8(crc8atm)
 * crc8cdma
 * crc16(crc16ibm)
 * crc16ccitt(crcccitt)
 * crc32(crc32ieee, also called crc32b in `mhash`)
 * crc32mhash
   * `mhash` is a common library which has two weird versions of CRC32 called `crc32` and `crc32b`. `crc32` and `crc32mhash` in this module are `crc32b` and `crc32` in mhash respectively.
 * crc32c
 * crc64(crc64ecma)
 * crc64iso

For instance,

```rust
extern crate crc_any;

use crc_any::CRC;

let mut crc64ecma = CRC::crc64ecma();

crc64ecma.digest(b"hello");

assert_eq!([236, 83, 136, 71, 154, 124, 145, 63].to_vec(), crc64ecma.get_crc_vec());
```

After getting a CRC value, you can still use the `digest` method to continue computing the next CRC values.
*/

use std::mem::transmute;

/// This struct can help you compute a CRC value.
pub struct CRC {
    lookup_table: [u64; 256],
    sum: u64,
    bits: u8,
    final_xor: u64,
    reflect: bool,
    special_case: u8,
}

impl CRC {
    /// Create a CRC instance by providing the length of bits, expression, reflection, an initial value and a final xor value.
    pub fn create_crc(poly64: u64, bits: u8, initial: u64, final_xor: u64, reflect: bool) -> CRC {
        let lookup_table = if reflect {
            CRC::crc_reflect_table(poly64)
        } else {
            CRC::crc_table(poly64, bits)
        };

        CRC::create_crc_with_exists_lookup_table(lookup_table, bits, initial, final_xor, reflect)
    }

    /// Create a CRC instance by providing an existing lookup table, the length of bits, expression, reflection, an initial value and a final xor value.
    pub fn create_crc_with_exists_lookup_table(lookup_table: [u64; 256], bits: u8, initial: u64, final_xor: u64, reflect: bool) -> CRC {
        CRC {
            lookup_table,
            sum: initial,
            bits,
            final_xor,
            reflect,
            special_case: 0,
        }
    }

    /// Digest some data.
    pub fn digest<T: ?Sized + AsRef<[u8]>>(&mut self, data: &T) {
        let mut index: u8;

        if self.reflect || self.bits <= 8 {
            for n in data.as_ref() {
                index = (self.sum as u8) ^ n;
                self.sum = (self.sum >> 8) ^ self.lookup_table[index as usize];
            }
        } else {
            for n in data.as_ref() {
                index = (self.sum >> ((self.bits - 8) as u64)) as u8 ^ n;
                self.sum = (self.sum << 8) ^ self.lookup_table[index as usize];
            }
        }
    }

    /// Get the current CRC value (it always returns a u64 value). You can continue calling `digest` method even after getting a CRC value.
    pub fn get_crc(&mut self) -> u64 {
        if self.special_case == 1 {
            let sum = self.sum ^ self.final_xor;
            let mut new_sum = 0u64;
            for i in 0..4u8 {
                new_sum |= ((sum >> ((3 - i) * 8)) & 0xff) << (i * 8);
            }

            return new_sum;
        }

        self.sum ^ self.final_xor
    }

    /// Get the current CRC value (it always returns a ([u8; 8], usize) tuple, where the second value of the tuple means the actual length of this CRC value). You can continue calling `digest` method even after getting a CRC value.
    pub fn get_crc_array(&mut self) -> ([u8; 8], usize) {
        let array = unsafe {
            transmute(self.get_crc().to_be())
        };

        (array, (self.bits / 8) as usize)
    }

    /// Get the current CRC value (it always returns a vec instance with a length corresponding to the CRC bits). You can continue calling `digest` method even after getting a CRC value.
    pub fn get_crc_vec(&mut self) -> Vec<u8> {
        let (array, length) = self.get_crc_array();

        array[(8 - length)..].to_vec()
    }

    pub fn crc64iso() -> CRC {
        // CRC::create_crc(0xD800000000000000u64, 64, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, true)

        let lookup_table = [0u64, 121597189939003392, 243194379878006784u64, 202661983231672320u64, 486388759756013568u64, 535928355657089024u64, 405323966463344640u64, 292733975779082240u64, 972777519512027136u64, 878201927337246720u64, 1071856711314178048u64, 1103381908705771520u64, 810647932926689280u64, 788129934789836800u64, 585467951558164480u64, 689050742987685888u64, 1945555039024054272u64, 1923037040887201792u64, 1756403854674493440u64, 1859986646104014848u64, 2143713422628356096u64, 2049137830453575680u64, 2206763817411543040u64, 2238289014803136512u64, 1621295865853378560u64, 1670835461754454016u64, 1576259869579673600u64, 1463669878895411200u64, 1170935903116328960u64, 1292533093055332352u64, 1378101485975371776u64, 1337569089329037312u64, 3891110078048108544u64, 4012707267987111936u64, 3846074081774403584u64, 3805541685128069120u64, 3512807709348986880u64, 3562347305250062336u64, 3719973292208029696u64, 3607383301523767296u64, 4287426845256712192u64, 4192851253081931776u64, 4098275660907151360u64, 4129800858298744832u64, 4413527634823086080u64, 4391009636686233600u64, 4476578029606273024u64, 4580160821035794432u64, 3242591731706757120u64, 3220073733569904640u64, 3341670923508908032u64, 3445253714938429440u64, 3152519739159347200u64, 3057944146984566784u64, 2927339757790822400u64, 2958864955182415872u64, 2341871806232657920u64, 2391411402133733376u64, 2585066186110664704u64, 2472476195426402304u64, 2756202971950743552u64, 2877800161889746944u64, 2675138178658074624u64, 2634605782011740160u64, 7782220156096217088u64, 7903817346035220480u64, 8025414535974223872u64, 7984882139327889408u64, 7692148163548807168u64, 7741687759449882624u64, 7611083370256138240u64, 7498493379571875840u64, 7025615418697973760u64, 6931039826523193344u64, 7124694610500124672u64, 7156219807891718144u64, 7439946584416059392u64, 7417428586279206912u64, 7214766603047534592u64, 7318349394477056000u64, 8574853690513424384u64, 8552335692376571904u64, 8385702506163863552u64, 8489285297593384960u64, 8196551321814302720u64, 8101975729639522304u64, 8259601716597489664u64, 8291126913989083136u64, 8827055269646172160u64, 8876594865547247616u64, 8782019273372467200u64, 8669429282688204800u64, 8953156059212546048u64, 9074753249151549440u64, 9160321642071588864u64, 9119789245425254400u64, 6485183463413514240u64, 6606780653352517632u64, 6440147467139809280u64, 6399615070493474816u64, 6683341847017816064u64, 6732881442918891520u64, 6890507429876858880u64, 6777917439192596480u64, 6305039478318694400u64, 6210463886143913984u64, 6115888293969133568u64, 6147413491360727040u64, 5854679515581644800u64, 5832161517444792320u64, 5917729910364831744u64, 6021312701794353152u64, 4683743612465315840u64, 4661225614328463360u64, 4782822804267466752u64, 4886405595696988160u64, 5170132372221329408u64, 5075556780046548992u64, 4944952390852804608u64, 4976477588244398080u64, 5512405943901487104u64, 5561945539802562560u64, 5755600323779493888u64, 5643010333095231488u64, 5350276357316149248u64, 5471873547255152640u64, 5269211564023480320u64, 5228679167377145856u64, 15564440312192434176u64, 15686037502131437568u64, 15807634692070440960u64, 15767102295424106496u64, 16050829071948447744u64, 16100368667849523200u64, 15969764278655778816u64, 15857174287971516416u64, 15384296327097614336u64, 15289720734922833920u64, 15483375518899765248u64, 15514900716291358720u64, 15222166740512276480u64, 15199648742375424000u64, 14996986759143751680u64, 15100569550573273088u64, 14051230837395947520u64, 14028712839259095040u64, 13862079653046386688u64, 13965662444475908096u64, 14249389221000249344u64, 14154813628825468928u64, 14312439615783436288u64, 14343964813175029760u64, 14879893168832118784u64, 14929432764733194240u64, 14834857172558413824u64, 14722267181874151424u64, 14429533206095069184u64, 14551130396034072576u64, 14636698788954112000u64, 14596166392307777536u64, 17149707381026848768u64, 17271304570965852160u64, 17104671384753143808u64, 17064138988106809344u64, 16771405012327727104u64, 16820944608228802560u64, 16978570595186769920u64, 16865980604502507520u64, 16393102643628605440u64, 16298527051453825024u64, 16203951459279044608u64, 16235476656670638080u64, 16519203433194979328u64, 16496685435058126848u64, 16582253827978166272u64, 16685836619407687680u64, 17654110539292344320u64, 17631592541155491840u64, 17753189731094495232u64, 17856772522524016640u64, 17564038546744934400u64, 17469462954570153984u64, 17338858565376409600u64, 17370383762768003072u64, 17906312118425092096u64, 17955851714326167552u64, 18149506498303098880u64, 18036916507618836480u64, 18320643284143177728u64, 18442240474082181120u64, 18239578490850508800u64, 18199046094204174336u64, 12970366926827028480u64, 13091964116766031872u64, 13213561306705035264u64, 13173028910058700800u64, 12880294934279618560u64, 12929834530180694016u64, 12799230140986949632u64, 12686640150302687232u64, 13366683694035632128u64, 13272108101860851712u64, 13465762885837783040u64, 13497288083229376512u64, 13781014859753717760u64, 13758496861616865280u64, 13555834878385192960u64, 13659417669814714368u64, 12610078956637388800u64, 12587560958500536320u64, 12420927772287827968u64, 12524510563717349376u64, 12231776587938267136u64, 12137200995763486720u64, 12294826982721454080u64, 12326352180113047552u64, 11709359031163289600u64, 11758898627064365056u64, 11664323034889584640u64, 11551733044205322240u64, 11835459820729663488u64, 11957057010668666880u64, 12042625403588706304u64, 12002093006942371840u64, 9367487224930631680u64, 9489084414869635072u64, 9322451228656926720u64, 9281918832010592256u64, 9565645608534933504u64, 9615185204436008960u64, 9772811191393976320u64, 9660221200709713920u64, 10340264744442658816u64, 10245689152267878400u64, 10151113560093097984u64, 10182638757484691456u64, 9889904781705609216u64, 9867386783568756736u64, 9952955176488796160u64, 10056537967918317568u64, 11024811887802974208u64, 11002293889666121728u64, 11123891079605125120u64, 11227473871034646528u64, 11511200647558987776u64, 11416625055384207360u64, 11286020666190462976u64, 11317545863582056448u64, 10700552714632298496u64, 10750092310533373952u64, 10943747094510305280u64, 10831157103826042880u64, 10538423128046960640u64, 10660020317985964032u64, 10457358334754291712u64, 10416825938107957248u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 64, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, true)
    }

    pub fn crc64ecma() -> CRC {
        // CRC::create_crc(0x42F0E1EBA9EA3693, 64, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, false)

        let lookup_table = [0u64, 4823603603198064275u64, 9647207206396128550u64, 14344283933443513269u64, 5274672035359026399u64, 847670339082705484u64, 14759040976900489721u64, 10241823793177474922u64, 10549344070718052798u64, 15030250704074698541u64, 1695340678165410968u64, 6158653484774949387u64, 15804726273676621153u64, 11071337880091427826u64, 6824194888265062471u64, 2036903512645398228u64, 7367177604490692079u64, 2651944067726553980u64, 16419204125234161865u64, 11613757334439845466u64, 3390681356330821936u64, 7926053118503640995u64, 12317306969549898774u64, 16726154088988619397u64, 17607865585094646865u64, 13162708473643690690u64, 8194994013375312247u64, 3695931686473304036u64, 13648389776530124942u64, 18417527692557321757u64, 4073807025290796456u64, 8825348881154370363u64, 14734355208981384158u64, 10271039580541631821u64, 5303888135453107960u64, 822984195088142443u64, 9604374506261047041u64, 14391664176758772114u64, 47380625301539367u64, 4780770595170139316u64, 6781362712661643872u64, 2084283301222999283u64, 15852106237007281990u64, 11028505464239851989u64, 1670654249350217407u64, 6187869865390245932u64, 10578560694269006745u64, 15005564104267687178u64, 12269926345859042865u64, 16768987096479742114u64, 3433514057002836759u64, 7878672873577829764u64, 16389988026750624494u64, 11638443477897467005u64, 7391863372946608072u64, 2622728278751721819u64, 4044590402276644751u64, 8850035479350698268u64, 13673076206955870889u64, 18388311311405091898u64, 8147614050581592912u64, 3738764100714335683u64, 17650697762308740726u64, 13115328684529279205u64, 15709965168302367023u64, 11021966344253216700u64, 6909860770376862729u64, 2095335087373712026u64, 10607776270906215920u64, 15115916238825782115u64, 1645968390176284886u64, 6063892853452478021u64, 5216239979862816913u64, 762004938812542466u64, 14808413130408695223u64, 10336584279807992612u64, 94761250603078734u64, 4872975272980325085u64, 9561541190340278632u64, 14285852213486374907u64, 13562725425323287744u64, 18359094313119879763u64, 4168566602445998566u64, 8874722219015798645u64, 17657238303940757535u64, 13257468400305012364u64, 8136561383943382329u64, 3610266854770152362u64, 3341308498700434814u64, 7831293060043656173u64, 12375739730780491864u64, 16811819059476047563u64, 7452841817450123681u64, 2710377314828461874u64, 16324444680414493831u64, 11564384134825822740u64, 1621282580641819377u64, 6093108618008534114u64, 10636992411005044695u64, 15091230119249932612u64, 6867028114005673518u64, 2142715359940571325u64, 15757345747155659528u64, 10979133309658045851u64, 9518708972583580495u64, 14333231979791697372u64, 142141253402664553u64, 4830142882085382394u64, 14783726745893216144u64, 10365800689136969987u64, 5245456557503443638u64, 737318311902463013u64, 8089180804553289502u64, 3653099890976004493u64, 17700070958701396536u64, 13210088128275084459u64, 4139350461810230209u64, 8899408340202190162u64, 13587411233247080167u64, 18329878549100632180u64, 16295228101163185824u64, 11589070762272702515u64, 7477528201428671366u64, 2681160907110034709u64, 12328359726370364031u64, 16854651450907929836u64, 3384140715920324441u64, 7783913295349006794u64, 17796789492404876493u64, 12973186262895182430u64, 8294265019745835499u64, 3597188614796881784u64, 13819721540753725458u64, 18246723593521770113u64, 4190670174747424052u64, 8707887697765516199u64, 7249714899603402099u64, 2768808468102880224u64, 16248400991498780757u64, 11785088403942012614u64, 3291936780352569772u64, 8025325358597240639u64, 12127785706904956042u64, 16915077318774037017u64, 10432479959725633826u64, 15147713122803500977u64, 1524009877625084932u64, 6329456346323069591u64, 15705454305770282493u64, 11170082187107838830u64, 6635271944638132443u64, 2226424485906433608u64, 189522501206157468u64, 4634679410803088911u64, 9745950545960650170u64, 14245012653811987241u64, 5445476407655580739u64, 676338306971005648u64, 14876502445374089573u64, 10124960353263198198u64, 4215391513593610003u64, 8678706776937023872u64, 13790540925671641653u64, 18271444552530207910u64, 8337133204891997132u64, 3549843186494580063u64, 17749444438031597290u64, 13016054137459951737u64, 12170653315997410989u64, 16867732534171963454u64, 3244592164593781643u64, 8068192726900473112u64, 16273122767886764658u64, 11755906975779290337u64, 7220533709540304724u64, 2793530071884239303u64, 6682616997400869628u64, 2183556611878603887u64, 15662586120087312346u64, 11217427617020813641u64, 1553190491096487459u64, 6304735387851432112u64, 10407758620342516485u64, 15176894045242543510u64, 14905683634900247362u64, 10100238751092381137u64, 5420754629656923748u64, 705519735670536439u64, 9793295161182637981u64, 14202145287119436046u64, 146654890503152315u64, 4682024195942093864u64, 3242565161283638754u64, 7930564333232481137u64, 12186217236017068228u64, 17000743249723264599u64, 7335380351123765565u64, 2827240748300537774u64, 16153640314560107547u64, 11735716164790313608u64, 13734056228011347036u64, 18188291445129067215u64, 4285430719881142650u64, 8757259798139230185u64, 17846161249714921603u64, 13067947420601767440u64, 8235833358291897765u64, 3511522545606540086u64, 5387043107155988493u64, 590673871457609374u64, 14925875833148783915u64, 10219719885873843128u64, 284282506805329106u64, 4684052045342640705u64, 9660285764170764788u64, 14186579979835500391u64, 15610694155489642931u64, 11120709418076880672u64, 6720936860919424149u64, 2284857304564388358u64, 10490913115006887276u64, 15233377424362361855u64, 1474636623804926026u64, 6234696958930763481u64, 16178361609106579004u64, 11706535215248140463u64, 7306199781952008986u64, 2851961734412043657u64, 12229085463316509411u64, 16953397843693241456u64, 3195220067441434565u64, 7973432182840617302u64, 8278700923620460418u64, 3464177731752866065u64, 17798816680404380324u64, 13110814815472245815u64, 4310152537884486493u64, 8728078392784608718u64, 13704874997943502459u64, 18213013024491712744u64, 9707630858549910483u64, 14143712128616820032u64, 241414281116563189u64, 4731397450835853414u64, 14955056402857342732u64, 10194998898151653791u64, 5362321814220069418u64, 619854820462849209u64, 1503817855483314797u64, 6209975379031176446u64, 10466191297540353867u64, 15262558828106308056u64, 6768281431840648882u64, 2241989909157107745u64, 15567826590698013588u64, 11168054230320002311u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 64, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, false)
    }


    pub fn crc32ieee() -> CRC {
        // CRC::create_crc(0x00000000EDB88320, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, true)

        let lookup_table = [0u64, 1996959894u64, 3993919788u64, 2567524794u64, 124634137u64, 1886057615u64, 3915621685u64, 2657392035u64, 249268274u64, 2044508324u64, 3772115230u64, 2547177864u64, 162941995u64, 2125561021u64, 3887607047u64, 2428444049u64, 498536548u64, 1789927666u64, 4089016648u64, 2227061214u64, 450548861u64, 1843258603u64, 4107580753u64, 2211677639u64, 325883990u64, 1684777152u64, 4251122042u64, 2321926636u64, 335633487u64, 1661365465u64, 4195302755u64, 2366115317u64, 997073096u64, 1281953886u64, 3579855332u64, 2724688242u64, 1006888145u64, 1258607687u64, 3524101629u64, 2768942443u64, 901097722u64, 1119000684u64, 3686517206u64, 2898065728u64, 853044451u64, 1172266101u64, 3705015759u64, 2882616665u64, 651767980u64, 1373503546u64, 3369554304u64, 3218104598u64, 565507253u64, 1454621731u64, 3485111705u64, 3099436303u64, 671266974u64, 1594198024u64, 3322730930u64, 2970347812u64, 795835527u64, 1483230225u64, 3244367275u64, 3060149565u64, 1994146192u64, 31158534u64, 2563907772u64, 4023717930u64, 1907459465u64, 112637215u64, 2680153253u64, 3904427059u64, 2013776290u64, 251722036u64, 2517215374u64, 3775830040u64, 2137656763u64, 141376813u64, 2439277719u64, 3865271297u64, 1802195444u64, 476864866u64, 2238001368u64, 4066508878u64, 1812370925u64, 453092731u64, 2181625025u64, 4111451223u64, 1706088902u64, 314042704u64, 2344532202u64, 4240017532u64, 1658658271u64, 366619977u64, 2362670323u64, 4224994405u64, 1303535960u64, 984961486u64, 2747007092u64, 3569037538u64, 1256170817u64, 1037604311u64, 2765210733u64, 3554079995u64, 1131014506u64, 879679996u64, 2909243462u64, 3663771856u64, 1141124467u64, 855842277u64, 2852801631u64, 3708648649u64, 1342533948u64, 654459306u64, 3188396048u64, 3373015174u64, 1466479909u64, 544179635u64, 3110523913u64, 3462522015u64, 1591671054u64, 702138776u64, 2966460450u64, 3352799412u64, 1504918807u64, 783551873u64, 3082640443u64, 3233442989u64, 3988292384u64, 2596254646u64, 62317068u64, 1957810842u64, 3939845945u64, 2647816111u64, 81470997u64, 1943803523u64, 3814918930u64, 2489596804u64, 225274430u64, 2053790376u64, 3826175755u64, 2466906013u64, 167816743u64, 2097651377u64, 4027552580u64, 2265490386u64, 503444072u64, 1762050814u64, 4150417245u64, 2154129355u64, 426522225u64, 1852507879u64, 4275313526u64, 2312317920u64, 282753626u64, 1742555852u64, 4189708143u64, 2394877945u64, 397917763u64, 1622183637u64, 3604390888u64, 2714866558u64, 953729732u64, 1340076626u64, 3518719985u64, 2797360999u64, 1068828381u64, 1219638859u64, 3624741850u64, 2936675148u64, 906185462u64, 1090812512u64, 3747672003u64, 2825379669u64, 829329135u64, 1181335161u64, 3412177804u64, 3160834842u64, 628085408u64, 1382605366u64, 3423369109u64, 3138078467u64, 570562233u64, 1426400815u64, 3317316542u64, 2998733608u64, 733239954u64, 1555261956u64, 3268935591u64, 3050360625u64, 752459403u64, 1541320221u64, 2607071920u64, 3965973030u64, 1969922972u64, 40735498u64, 2617837225u64, 3943577151u64, 1913087877u64, 83908371u64, 2512341634u64, 3803740692u64, 2075208622u64, 213261112u64, 2463272603u64, 3855990285u64, 2094854071u64, 198958881u64, 2262029012u64, 4057260610u64, 1759359992u64, 534414190u64, 2176718541u64, 4139329115u64, 1873836001u64, 414664567u64, 2282248934u64, 4279200368u64, 1711684554u64, 285281116u64, 2405801727u64, 4167216745u64, 1634467795u64, 376229701u64, 2685067896u64, 3608007406u64, 1308918612u64, 956543938u64, 2808555105u64, 3495958263u64, 1231636301u64, 1047427035u64, 2932959818u64, 3654703836u64, 1088359270u64, 936918000u64, 2847714899u64, 3736837829u64, 1202900863u64, 817233897u64, 3183342108u64, 3401237130u64, 1404277552u64, 615818150u64, 3134207493u64, 3453421203u64, 1423857449u64, 601450431u64, 3009837614u64, 3294710456u64, 1567103746u64, 711928724u64, 3020668471u64, 3272380065u64, 1510334235u64, 755167117u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, true)
    }


    pub fn crc32mhash() -> CRC {
        let mut crc;

        // crc = CRC::create_crc(0x0000000004C11DB7, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, false);

        let lookup_table = [0u64, 79764919u64, 159529838u64, 222504665u64, 319059676u64, 398814059u64, 445009330u64, 507990021u64, 638119352u64, 583659535u64, 797628118u64, 726387553u64, 890018660u64, 835552979u64, 1015980042u64, 944750013u64, 1276238704u64, 1221641927u64, 1167319070u64, 1095957929u64, 1595256236u64, 1540665371u64, 1452775106u64, 1381403509u64, 1780037320u64, 1859660671u64, 1671105958u64, 1733955601u64, 2031960084u64, 2111593891u64, 1889500026u64, 1952343757u64, 2552477408u64, 2632100695u64, 2443283854u64, 2506133561u64, 2334638140u64, 2414271883u64, 2191915858u64, 2254759653u64, 3190512472u64, 3135915759u64, 3081330742u64, 3009969537u64, 2905550212u64, 2850959411u64, 2762807018u64, 2691435357u64, 3560074640u64, 3505614887u64, 3719321342u64, 3648080713u64, 3342211916u64, 3287746299u64, 3467911202u64, 3396681109u64, 4063920168u64, 4143685023u64, 4223187782u64, 4286162673u64, 3779000052u64, 3858754371u64, 3904687514u64, 3967668269u64, 881225847u64, 809987520u64, 1023691545u64, 969234094u64, 662832811u64, 591600412u64, 771767749u64, 717299826u64, 311336399u64, 374308984u64, 453813921u64, 533576470u64, 25881363u64, 88864420u64, 134795389u64, 214552010u64, 2023205639u64, 2086057648u64, 1897238633u64, 1976864222u64, 1804852699u64, 1867694188u64, 1645340341u64, 1724971778u64, 1587496639u64, 1516133128u64, 1461550545u64, 1406951526u64, 1302016099u64, 1230646740u64, 1142491917u64, 1087903418u64, 2896545431u64, 2825181984u64, 2770861561u64, 2716262478u64, 3215044683u64, 3143675388u64, 3055782693u64, 3001194130u64, 2326604591u64, 2389456536u64, 2200899649u64, 2280525302u64, 2578013683u64, 2640855108u64, 2418763421u64, 2498394922u64, 3769900519u64, 3832873040u64, 3912640137u64, 3992402750u64, 4088425275u64, 4151408268u64, 4197601365u64, 4277358050u64, 3334271071u64, 3263032808u64, 3476998961u64, 3422541446u64, 3585640067u64, 3514407732u64, 3694837229u64, 3640369242u64, 1762451694u64, 1842216281u64, 1619975040u64, 1682949687u64, 2047383090u64, 2127137669u64, 1938468188u64, 2001449195u64, 1325665622u64, 1271206113u64, 1183200824u64, 1111960463u64, 1543535498u64, 1489069629u64, 1434599652u64, 1363369299u64, 622672798u64, 568075817u64, 748617968u64, 677256519u64, 907627842u64, 853037301u64, 1067152940u64, 995781531u64, 51762726u64, 131386257u64, 177728840u64, 240578815u64, 269590778u64, 349224269u64, 429104020u64, 491947555u64, 4046411278u64, 4126034873u64, 4172115296u64, 4234965207u64, 3794477266u64, 3874110821u64, 3953728444u64, 4016571915u64, 3609705398u64, 3555108353u64, 3735388376u64, 3664026991u64, 3290680682u64, 3236090077u64, 3449943556u64, 3378572211u64, 3174993278u64, 3120533705u64, 3032266256u64, 2961025959u64, 2923101090u64, 2868635157u64, 2813903052u64, 2742672763u64, 2604032198u64, 2683796849u64, 2461293480u64, 2524268063u64, 2284983834u64, 2364738477u64, 2175806836u64, 2238787779u64, 1569362073u64, 1498123566u64, 1409854455u64, 1355396672u64, 1317987909u64, 1246755826u64, 1192025387u64, 1137557660u64, 2072149281u64, 2135122070u64, 1912620623u64, 1992383480u64, 1753615357u64, 1816598090u64, 1627664531u64, 1707420964u64, 295390185u64, 358241886u64, 404320391u64, 483945776u64, 43990325u64, 106832002u64, 186451547u64, 266083308u64, 932423249u64, 861060070u64, 1041341759u64, 986742920u64, 613929101u64, 542559546u64, 756411363u64, 701822548u64, 3316196985u64, 3244833742u64, 3425377559u64, 3370778784u64, 3601682597u64, 3530312978u64, 3744426955u64, 3689838204u64, 3819031489u64, 3881883254u64, 3928223919u64, 4007849240u64, 4037393693u64, 4100235434u64, 4180117107u64, 4259748804u64, 2310601993u64, 2373574846u64, 2151335527u64, 2231098320u64, 2596047829u64, 2659030626u64, 2470359227u64, 2550115596u64, 2947551409u64, 2876312838u64, 2788305887u64, 2733848168u64, 3165939309u64, 3094707162u64, 3040238851u64, 2985771188u64];
        crc = CRC::create_crc_with_exists_lookup_table(lookup_table, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, false);

        crc.special_case = 1;

        crc
    }


    pub fn crc32c() -> CRC {
        // CRC::create_crc(0x0000000082F63B78, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, true)

        let lookup_table = [0u64, 4067132163u64, 3778769143u64, 324072436u64, 3348797215u64, 904991772u64, 648144872u64, 3570033899u64, 2329499855u64, 2024987596u64, 1809983544u64, 2575936315u64, 1296289744u64, 3207089363u64, 2893594407u64, 1578318884u64, 274646895u64, 3795141740u64, 4049975192u64, 51262619u64, 3619967088u64, 632279923u64, 922689671u64, 3298075524u64, 2592579488u64, 1760304291u64, 2075979607u64, 2312596564u64, 1562183871u64, 2943781820u64, 3156637768u64, 1313733451u64, 549293790u64, 3537243613u64, 3246849577u64, 871202090u64, 3878099393u64, 357341890u64, 102525238u64, 4101499445u64, 2858735121u64, 1477399826u64, 1264559846u64, 3107202533u64, 1845379342u64, 2677391885u64, 2361733625u64, 2125378298u64, 820201905u64, 3263744690u64, 3520608582u64, 598981189u64, 4151959214u64, 85089709u64, 373468761u64, 3827903834u64, 3124367742u64, 1213305469u64, 1526817161u64, 2842354314u64, 2107672161u64, 2412447074u64, 2627466902u64, 1861252501u64, 1098587580u64, 3004210879u64, 2688576843u64, 1378610760u64, 2262928035u64, 1955203488u64, 1742404180u64, 2511436119u64, 3416409459u64, 969524848u64, 714683780u64, 3639785095u64, 205050476u64, 4266873199u64, 3976438427u64, 526918040u64, 1361435347u64, 2739821008u64, 2954799652u64, 1114974503u64, 2529119692u64, 1691668175u64, 2005155131u64, 2247081528u64, 3690758684u64, 697762079u64, 986182379u64, 3366744552u64, 476452099u64, 3993867776u64, 4250756596u64, 255256311u64, 1640403810u64, 2477592673u64, 2164122517u64, 1922457750u64, 2791048317u64, 1412925310u64, 1197962378u64, 3037525897u64, 3944729517u64, 427051182u64, 170179418u64, 4165941337u64, 746937522u64, 3740196785u64, 3451792453u64, 1070968646u64, 1905808397u64, 2213795598u64, 2426610938u64, 1657317369u64, 3053634322u64, 1147748369u64, 1463399397u64, 2773627110u64, 4215344322u64, 153784257u64, 444234805u64, 3893493558u64, 1021025245u64, 3467647198u64, 3722505002u64, 797665321u64, 2197175160u64, 1889384571u64, 1674398607u64, 2443626636u64, 1164749927u64, 3070701412u64, 2757221520u64, 1446797203u64, 137323447u64, 4198817972u64, 3910406976u64, 461344835u64, 3484808360u64, 1037989803u64, 781091935u64, 3705997148u64, 2460548119u64, 1623424788u64, 1939049696u64, 2180517859u64, 1429367560u64, 2807687179u64, 3020495871u64, 1180866812u64, 410100952u64, 3927582683u64, 4182430767u64, 186734380u64, 3756733383u64, 763408580u64, 1053836080u64, 3434856499u64, 2722870694u64, 1344288421u64, 1131464017u64, 2971354706u64, 1708204729u64, 2545590714u64, 2229949006u64, 1988219213u64, 680717673u64, 3673779818u64, 3383336350u64, 1002577565u64, 4010310262u64, 493091189u64, 238226049u64, 4233660802u64, 2987750089u64, 1082061258u64, 1395524158u64, 2705686845u64, 1972364758u64, 2279892693u64, 2494862625u64, 1725896226u64, 952904198u64, 3399985413u64, 3656866545u64, 731699698u64, 4283874585u64, 222117402u64, 510512622u64, 3959836397u64, 3280807620u64, 837199303u64, 582374963u64, 3504198960u64, 68661723u64, 4135334616u64, 3844915500u64, 390545967u64, 1230274059u64, 3141532936u64, 2825850620u64, 1510247935u64, 2395924756u64, 2091215383u64, 1878366691u64, 2644384480u64, 3553878443u64, 565732008u64, 854102364u64, 3229815391u64, 340358836u64, 3861050807u64, 4117890627u64, 119113024u64, 1493875044u64, 2875275879u64, 3090270611u64, 1247431312u64, 2660249211u64, 1828433272u64, 2141937292u64, 2378227087u64, 3811616794u64, 291187481u64, 34330861u64, 4032846830u64, 615137029u64, 3603020806u64, 3314634738u64, 939183345u64, 1776939221u64, 2609017814u64, 2295496738u64, 2058945313u64, 2926798794u64, 1545135305u64, 1330124605u64, 3173225534u64, 4084100981u64, 17165430u64, 307568514u64, 3762199681u64, 888469610u64, 3332340585u64, 3587147933u64, 665062302u64, 2042050490u64, 2346497209u64, 2559330125u64, 1793573966u64, 3190661285u64, 1279665062u64, 1595330642u64, 2910671697u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 32, 0x00000000FFFFFFFF, 0x00000000FFFFFFFF, true)
    }

    pub fn crc16ibm() -> CRC {
        // CRC::create_crc(0x000000000000A001, 16, 0x0000000000000000, 0x0000000000000000, true)

        let lookup_table = [0u64, 49345u64, 49537u64, 320u64, 49921u64, 960u64, 640u64, 49729u64, 50689u64, 1728u64, 1920u64, 51009u64, 1280u64, 50625u64, 50305u64, 1088u64, 52225u64, 3264u64, 3456u64, 52545u64, 3840u64, 53185u64, 52865u64, 3648u64, 2560u64, 51905u64, 52097u64, 2880u64, 51457u64, 2496u64, 2176u64, 51265u64, 55297u64, 6336u64, 6528u64, 55617u64, 6912u64, 56257u64, 55937u64, 6720u64, 7680u64, 57025u64, 57217u64, 8000u64, 56577u64, 7616u64, 7296u64, 56385u64, 5120u64, 54465u64, 54657u64, 5440u64, 55041u64, 6080u64, 5760u64, 54849u64, 53761u64, 4800u64, 4992u64, 54081u64, 4352u64, 53697u64, 53377u64, 4160u64, 61441u64, 12480u64, 12672u64, 61761u64, 13056u64, 62401u64, 62081u64, 12864u64, 13824u64, 63169u64, 63361u64, 14144u64, 62721u64, 13760u64, 13440u64, 62529u64, 15360u64, 64705u64, 64897u64, 15680u64, 65281u64, 16320u64, 16000u64, 65089u64, 64001u64, 15040u64, 15232u64, 64321u64, 14592u64, 63937u64, 63617u64, 14400u64, 10240u64, 59585u64, 59777u64, 10560u64, 60161u64, 11200u64, 10880u64, 59969u64, 60929u64, 11968u64, 12160u64, 61249u64, 11520u64, 60865u64, 60545u64, 11328u64, 58369u64, 9408u64, 9600u64, 58689u64, 9984u64, 59329u64, 59009u64, 9792u64, 8704u64, 58049u64, 58241u64, 9024u64, 57601u64, 8640u64, 8320u64, 57409u64, 40961u64, 24768u64, 24960u64, 41281u64, 25344u64, 41921u64, 41601u64, 25152u64, 26112u64, 42689u64, 42881u64, 26432u64, 42241u64, 26048u64, 25728u64, 42049u64, 27648u64, 44225u64, 44417u64, 27968u64, 44801u64, 28608u64, 28288u64, 44609u64, 43521u64, 27328u64, 27520u64, 43841u64, 26880u64, 43457u64, 43137u64, 26688u64, 30720u64, 47297u64, 47489u64, 31040u64, 47873u64, 31680u64, 31360u64, 47681u64, 48641u64, 32448u64, 32640u64, 48961u64, 32000u64, 48577u64, 48257u64, 31808u64, 46081u64, 29888u64, 30080u64, 46401u64, 30464u64, 47041u64, 46721u64, 30272u64, 29184u64, 45761u64, 45953u64, 29504u64, 45313u64, 29120u64, 28800u64, 45121u64, 20480u64, 37057u64, 37249u64, 20800u64, 37633u64, 21440u64, 21120u64, 37441u64, 38401u64, 22208u64, 22400u64, 38721u64, 21760u64, 38337u64, 38017u64, 21568u64, 39937u64, 23744u64, 23936u64, 40257u64, 24320u64, 40897u64, 40577u64, 24128u64, 23040u64, 39617u64, 39809u64, 23360u64, 39169u64, 22976u64, 22656u64, 38977u64, 34817u64, 18624u64, 18816u64, 35137u64, 19200u64, 35777u64, 35457u64, 19008u64, 19968u64, 36545u64, 36737u64, 20288u64, 36097u64, 19904u64, 19584u64, 35905u64, 17408u64, 33985u64, 34177u64, 17728u64, 34561u64, 18368u64, 18048u64, 34369u64, 33281u64, 17088u64, 17280u64, 33601u64, 16640u64, 33217u64, 32897u64, 16448u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 16, 0x0000000000000000, 0x0000000000000000, true)
    }

    pub fn crc16ccitt() -> CRC {
        // CRC::create_crc(0x0000000000001021, 16, 0x000000000000FFFF, 0x0000000000000000, false)

        let lookup_table = [0u64, 4129u64, 8258u64, 12387u64, 16516u64, 20645u64, 24774u64, 28903u64, 33032u64, 37161u64, 41290u64, 45419u64, 49548u64, 53677u64, 57806u64, 61935u64, 4657u64, 528u64, 12915u64, 8786u64, 21173u64, 17044u64, 29431u64, 25302u64, 37689u64, 33560u64, 45947u64, 41818u64, 54205u64, 50076u64, 62463u64, 58334u64, 9314u64, 13379u64, 1056u64, 5121u64, 25830u64, 29895u64, 17572u64, 21637u64, 42346u64, 46411u64, 34088u64, 38153u64, 58862u64, 62927u64, 50604u64, 54669u64, 13907u64, 9842u64, 5649u64, 1584u64, 30423u64, 26358u64, 22165u64, 18100u64, 46939u64, 42874u64, 38681u64, 34616u64, 63455u64, 59390u64, 55197u64, 51132u64, 18628u64, 22757u64, 26758u64, 30887u64, 2112u64, 6241u64, 10242u64, 14371u64, 51660u64, 55789u64, 59790u64, 63919u64, 35144u64, 39273u64, 43274u64, 47403u64, 23285u64, 19156u64, 31415u64, 27286u64, 6769u64, 2640u64, 14899u64, 10770u64, 56317u64, 52188u64, 64447u64, 60318u64, 39801u64, 35672u64, 47931u64, 43802u64, 27814u64, 31879u64, 19684u64, 23749u64, 11298u64, 15363u64, 3168u64, 7233u64, 60846u64, 64911u64, 52716u64, 56781u64, 44330u64, 48395u64, 36200u64, 40265u64, 32407u64, 28342u64, 24277u64, 20212u64, 15891u64, 11826u64, 7761u64, 3696u64, 65439u64, 61374u64, 57309u64, 53244u64, 48923u64, 44858u64, 40793u64, 36728u64, 37256u64, 33193u64, 45514u64, 41451u64, 53516u64, 49453u64, 61774u64, 57711u64, 4224u64, 161u64, 12482u64, 8419u64, 20484u64, 16421u64, 28742u64, 24679u64, 33721u64, 37784u64, 41979u64, 46042u64, 49981u64, 54044u64, 58239u64, 62302u64, 689u64, 4752u64, 8947u64, 13010u64, 16949u64, 21012u64, 25207u64, 29270u64, 46570u64, 42443u64, 38312u64, 34185u64, 62830u64, 58703u64, 54572u64, 50445u64, 13538u64, 9411u64, 5280u64, 1153u64, 29798u64, 25671u64, 21540u64, 17413u64, 42971u64, 47098u64, 34713u64, 38840u64, 59231u64, 63358u64, 50973u64, 55100u64, 9939u64, 14066u64, 1681u64, 5808u64, 26199u64, 30326u64, 17941u64, 22068u64, 55628u64, 51565u64, 63758u64, 59695u64, 39368u64, 35305u64, 47498u64, 43435u64, 22596u64, 18533u64, 30726u64, 26663u64, 6336u64, 2273u64, 14466u64, 10403u64, 52093u64, 56156u64, 60223u64, 64286u64, 35833u64, 39896u64, 43963u64, 48026u64, 19061u64, 23124u64, 27191u64, 31254u64, 2801u64, 6864u64, 10931u64, 14994u64, 64814u64, 60687u64, 56684u64, 52557u64, 48554u64, 44427u64, 40424u64, 36297u64, 31782u64, 27655u64, 23652u64, 19525u64, 15522u64, 11395u64, 7392u64, 3265u64, 61215u64, 65342u64, 53085u64, 57212u64, 44955u64, 49082u64, 36825u64, 40952u64, 28183u64, 32310u64, 20053u64, 24180u64, 11923u64, 16050u64, 3793u64, 7920u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 16, 0x000000000000FFFF, 0x0000000000000000, false)
    }

    pub fn crc8atm() -> CRC {
        // CRC::create_crc(0x0000000000000007, 8, 0x0000000000000000, 0x0000000000000000, false)

        let lookup_table = [0u64, 7u64, 14u64, 9u64, 28u64, 27u64, 18u64, 21u64, 56u64, 63u64, 54u64, 49u64, 36u64, 35u64, 42u64, 45u64, 112u64, 119u64, 126u64, 121u64, 108u64, 107u64, 98u64, 101u64, 72u64, 79u64, 70u64, 65u64, 84u64, 83u64, 90u64, 93u64, 224u64, 231u64, 238u64, 233u64, 252u64, 251u64, 242u64, 245u64, 216u64, 223u64, 214u64, 209u64, 196u64, 195u64, 202u64, 205u64, 144u64, 151u64, 158u64, 153u64, 140u64, 139u64, 130u64, 133u64, 168u64, 175u64, 166u64, 161u64, 180u64, 179u64, 186u64, 189u64, 199u64, 192u64, 201u64, 206u64, 219u64, 220u64, 213u64, 210u64, 255u64, 248u64, 241u64, 246u64, 227u64, 228u64, 237u64, 234u64, 183u64, 176u64, 185u64, 190u64, 171u64, 172u64, 165u64, 162u64, 143u64, 136u64, 129u64, 134u64, 147u64, 148u64, 157u64, 154u64, 39u64, 32u64, 41u64, 46u64, 59u64, 60u64, 53u64, 50u64, 31u64, 24u64, 17u64, 22u64, 3u64, 4u64, 13u64, 10u64, 87u64, 80u64, 89u64, 94u64, 75u64, 76u64, 69u64, 66u64, 111u64, 104u64, 97u64, 102u64, 115u64, 116u64, 125u64, 122u64, 137u64, 142u64, 135u64, 128u64, 149u64, 146u64, 155u64, 156u64, 177u64, 182u64, 191u64, 184u64, 173u64, 170u64, 163u64, 164u64, 249u64, 254u64, 247u64, 240u64, 229u64, 226u64, 235u64, 236u64, 193u64, 198u64, 207u64, 200u64, 221u64, 218u64, 211u64, 212u64, 105u64, 110u64, 103u64, 96u64, 117u64, 114u64, 123u64, 124u64, 81u64, 86u64, 95u64, 88u64, 77u64, 74u64, 67u64, 68u64, 25u64, 30u64, 23u64, 16u64, 5u64, 2u64, 11u64, 12u64, 33u64, 38u64, 47u64, 40u64, 61u64, 58u64, 51u64, 52u64, 78u64, 73u64, 64u64, 71u64, 82u64, 85u64, 92u64, 91u64, 118u64, 113u64, 120u64, 127u64, 106u64, 109u64, 100u64, 99u64, 62u64, 57u64, 48u64, 55u64, 34u64, 37u64, 44u64, 43u64, 6u64, 1u64, 8u64, 15u64, 26u64, 29u64, 20u64, 19u64, 174u64, 169u64, 160u64, 167u64, 178u64, 181u64, 188u64, 187u64, 150u64, 145u64, 152u64, 159u64, 138u64, 141u64, 132u64, 131u64, 222u64, 217u64, 208u64, 215u64, 194u64, 197u64, 204u64, 203u64, 230u64, 225u64, 232u64, 239u64, 250u64, 253u64, 244u64, 243u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 8, 0x0000000000000000, 0x0000000000000000, false)
    }

    pub fn crc8cdma() -> CRC {
        // CRC::create_crc(0x000000000000009B, 8, 0x00000000000000FF, 0x0000000000000000, false)

        let lookup_table = [0u64, 155u64, 173u64, 54u64, 193u64, 90u64, 108u64, 247u64, 25u64, 130u64, 180u64, 47u64, 216u64, 67u64, 117u64, 238u64, 50u64, 169u64, 159u64, 4u64, 243u64, 104u64, 94u64, 197u64, 43u64, 176u64, 134u64, 29u64, 234u64, 113u64, 71u64, 220u64, 100u64, 255u64, 201u64, 82u64, 165u64, 62u64, 8u64, 147u64, 125u64, 230u64, 208u64, 75u64, 188u64, 39u64, 17u64, 138u64, 86u64, 205u64, 251u64, 96u64, 151u64, 12u64, 58u64, 161u64, 79u64, 212u64, 226u64, 121u64, 142u64, 21u64, 35u64, 184u64, 200u64, 83u64, 101u64, 254u64, 9u64, 146u64, 164u64, 63u64, 209u64, 74u64, 124u64, 231u64, 16u64, 139u64, 189u64, 38u64, 250u64, 97u64, 87u64, 204u64, 59u64, 160u64, 150u64, 13u64, 227u64, 120u64, 78u64, 213u64, 34u64, 185u64, 143u64, 20u64, 172u64, 55u64, 1u64, 154u64, 109u64, 246u64, 192u64, 91u64, 181u64, 46u64, 24u64, 131u64, 116u64, 239u64, 217u64, 66u64, 158u64, 5u64, 51u64, 168u64, 95u64, 196u64, 242u64, 105u64, 135u64, 28u64, 42u64, 177u64, 70u64, 221u64, 235u64, 112u64, 11u64, 144u64, 166u64, 61u64, 202u64, 81u64, 103u64, 252u64, 18u64, 137u64, 191u64, 36u64, 211u64, 72u64, 126u64, 229u64, 57u64, 162u64, 148u64, 15u64, 248u64, 99u64, 85u64, 206u64, 32u64, 187u64, 141u64, 22u64, 225u64, 122u64, 76u64, 215u64, 111u64, 244u64, 194u64, 89u64, 174u64, 53u64, 3u64, 152u64, 118u64, 237u64, 219u64, 64u64, 183u64, 44u64, 26u64, 129u64, 93u64, 198u64, 240u64, 107u64, 156u64, 7u64, 49u64, 170u64, 68u64, 223u64, 233u64, 114u64, 133u64, 30u64, 40u64, 179u64, 195u64, 88u64, 110u64, 245u64, 2u64, 153u64, 175u64, 52u64, 218u64, 65u64, 119u64, 236u64, 27u64, 128u64, 182u64, 45u64, 241u64, 106u64, 92u64, 199u64, 48u64, 171u64, 157u64, 6u64, 232u64, 115u64, 69u64, 222u64, 41u64, 178u64, 132u64, 31u64, 167u64, 60u64, 10u64, 145u64, 102u64, 253u64, 203u64, 80u64, 190u64, 37u64, 19u64, 136u64, 127u64, 228u64, 210u64, 73u64, 149u64, 14u64, 56u64, 163u64, 84u64, 207u64, 249u64, 98u64, 140u64, 23u64, 33u64, 186u64, 77u64, 214u64, 224u64, 123u64];
        CRC::create_crc_with_exists_lookup_table(lookup_table, 8, 0x00000000000000FF, 0x0000000000000000, false)
    }


    fn crc_reflect_table(poly64_rev: u64) -> [u64; 256] {
        let mut lookup_table = [0u64; 256];

        let mut v: u64;

        for i in 0..256u16 {
            v = i as u64;

            for _ in 0..8u16 {
                if (v & 1) == 1 {
                    v >>= 1;
                    v ^= poly64_rev;
                } else {
                    v >>= 1;
                }
            }

            lookup_table[i as usize] = v;
        }

        lookup_table
    }

    fn crc_table(poly64: u64, bits: u8) -> [u64; 256] {
        let mut lookup_table = [0u64; 256];

        let mask1 = 1u64 << (bits - 1) as u64;

        let mut mask2 = 1u64;

        let mut v: u64;

        for _ in 1..bits {
            mask2 = (mask2 << 1) + 1;
        }

        for i in 0..256u16 {
            v = i as u64;

            for _ in 0..bits {
                if (v & mask1) == 0 {
                    v <<= 1;
                } else {
                    v <<= 1;
                    v ^= poly64;
                }
            }

            lookup_table[i as usize] = v & mask2;
        }

        lookup_table
    }
}

#[cfg(all(feature = "develop", test))]
mod tests {
    use super::CRC;

    use std::fmt::Write;

    #[test]
    fn print_lookup_table() {
        let crc = CRC::crc8cdma();

        let mut s = String::new();

        for n in crc.lookup_table.iter().take(255) {
            s.write_fmt(format_args!("{}u64, ", n)).unwrap();
        }

        s.write_fmt(format_args!("{}u64", crc.lookup_table[255])).unwrap();

        println!("[{}]", s);
    }
}