use zeroize::{Zeroize, ZeroizeOnDrop};
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const MUL_ALPHA: [u64; 256] = [
0x0000000000000000, 0xd73f04125e000004, 0xb37e0824bc000008, 0x64410c36e200000c,
0x7bfc104865000010, 0xacc3145a3b000014, 0xc882186cd9000018, 0x1fbd1c7e8700001c,
0xf6e52090ca000020, 0x21da248294000024, 0x459b28b476000028, 0x92a42ca62800002c,
0x8d1930d8af000030, 0x5a2634caf1000034, 0x3e6738fc13000038, 0xe9583cee4d00003c,
0xf1d7403d89000040, 0x26e8442fd7000044, 0x42a9481935000048, 0x95964c0b6b00004c,
0x8a2b5075ec000050, 0x5d145467b2000054, 0x3955585150000058, 0xee6a5c430e00005c,
0x073260ad43000060, 0xd00d64bf1d000064, 0xb44c6889ff000068, 0x63736c9ba100006c,
0x7cce70e526000070, 0xabf174f778000074, 0xcfb078c19a000078, 0x188f7cd3c400007c,
0xffb3807a0f000080, 0x288c846851000084, 0x4ccd885eb3000088, 0x9bf28c4ced00008c,
0x844f90326a000090, 0x5370942034000094, 0x37319816d6000098, 0xe00e9c048800009c,
0x0956a0eac50000a0, 0xde69a4f89b0000a4, 0xba28a8ce790000a8, 0x6d17acdc270000ac,
0x72aab0a2a00000b0, 0xa595b4b0fe0000b4, 0xc1d4b8861c0000b8, 0x16ebbc94420000bc,
0x0e64c047860000c0, 0xd95bc455d80000c4, 0xbd1ac8633a0000c8, 0x6a25cc71640000cc,
0x7598d00fe30000d0, 0xa2a7d41dbd0000d4, 0xc6e6d82b5f0000d8, 0x11d9dc39010000dc,
0xf881e0d74c0000e0, 0x2fbee4c5120000e4, 0x4bffe8f3f00000e8, 0x9cc0ece1ae0000ec,
0x837df09f290000f0, 0x5442f48d770000f4, 0x3003f8bb950000f8, 0xe73cfca9cb0000fc,
0xe37b1df41e00001d, 0x344419e640000019, 0x500515d0a2000015, 0x873a11c2fc000011,
0x98870dbc7b00000d, 0x4fb809ae25000009, 0x2bf90598c7000005, 0xfcc6018a99000001,
0x159e3d64d400003d, 0xc2a139768a000039, 0xa6e0354068000035, 0x71df315236000031,
0x6e622d2cb100002d, 0xb95d293eef000029, 0xdd1c25080d000025, 0x0a23211a53000021,
0x12ac5dc99700005d, 0xc59359dbc9000059, 0xa1d255ed2b000055, 0x76ed51ff75000051,
0x69504d81f200004d, 0xbe6f4993ac000049, 0xda2e45a54e000045, 0x0d1141b710000041,
0xe4497d595d00007d, 0x3376794b03000079, 0x5737757de1000075, 0x8008716fbf000071,
0x9fb56d113800006d, 0x488a690366000069, 0x2ccb653584000065, 0xfbf46127da000061,
0x1cc89d8e1100009d, 0xcbf7999c4f000099, 0xafb695aaad000095, 0x788991b8f3000091,
0x67348dc67400008d, 0xb00b89d42a000089, 0xd44a85e2c8000085, 0x037581f096000081,
0xea2dbd1edb0000bd, 0x3d12b90c850000b9, 0x5953b53a670000b5, 0x8e6cb128390000b1,
0x91d1ad56be0000ad, 0x46eea944e00000a9, 0x22afa572020000a5, 0xf590a1605c0000a1,
0xed1fddb3980000dd, 0x3a20d9a1c60000d9, 0x5e61d597240000d5, 0x895ed1857a0000d1,
0x96e3cdfbfd0000cd, 0x41dcc9e9a30000c9, 0x259dc5df410000c5, 0xf2a2c1cd1f0000c1,
0x1bfafd23520000fd, 0xccc5f9310c0000f9, 0xa884f507ee0000f5, 0x7fbbf115b00000f1,
0x6006ed6b370000ed, 0xb739e979690000e9, 0xd378e54f8b0000e5, 0x0447e15dd50000e1,
0xdbf63af53c00003a, 0x0cc93ee76200003e, 0x688832d180000032, 0xbfb736c3de000036,
0xa00a2abd5900002a, 0x77352eaf0700002e, 0x13742299e5000022, 0xc44b268bbb000026,
0x2d131a65f600001a, 0xfa2c1e77a800001e, 0x9e6d12414a000012, 0x4952165314000016,
0x56ef0a2d9300000a, 0x81d00e3fcd00000e, 0xe59102092f000002, 0x32ae061b71000006,
0x2a217ac8b500007a, 0xfd1e7edaeb00007e, 0x995f72ec09000072, 0x4e6076fe57000076,
0x51dd6a80d000006a, 0x86e26e928e00006e, 0xe2a362a46c000062, 0x359c66b632000066,
0xdcc45a587f00005a, 0x0bfb5e4a2100005e, 0x6fba527cc3000052, 0xb885566e9d000056,
0xa7384a101a00004a, 0x70074e024400004e, 0x14464234a6000042, 0xc3794626f8000046,
0x2445ba8f330000ba, 0xf37abe9d6d0000be, 0x973bb2ab8f0000b2, 0x4004b6b9d10000b6,
0x5fb9aac7560000aa, 0x8886aed5080000ae, 0xecc7a2e3ea0000a2, 0x3bf8a6f1b40000a6,
0xd2a09a1ff900009a, 0x059f9e0da700009e, 0x61de923b45000092, 0xb6e196291b000096,
0xa95c8a579c00008a, 0x7e638e45c200008e, 0x1a22827320000082, 0xcd1d86617e000086,
0xd592fab2ba0000fa, 0x02adfea0e40000fe, 0x66ecf296060000f2, 0xb1d3f684580000f6,
0xae6eeafadf0000ea, 0x7951eee8810000ee, 0x1d10e2de630000e2, 0xca2fe6cc3d0000e6,
0x2377da22700000da, 0xf448de302e0000de, 0x9009d206cc0000d2, 0x4736d614920000d6,
0x588bca6a150000ca, 0x8fb4ce784b0000ce, 0xebf5c24ea90000c2, 0x3ccac65cf70000c6,
0x388d270122000027, 0xefb223137c000023, 0x8bf32f259e00002f, 0x5ccc2b37c000002b,
0x4371374947000037, 0x944e335b19000033, 0xf00f3f6dfb00003f, 0x27303b7fa500003b,
0xce680791e8000007, 0x19570383b6000003, 0x7d160fb55400000f, 0xaa290ba70a00000b,
0xb59417d98d000017, 0x62ab13cbd3000013, 0x06ea1ffd3100001f, 0xd1d51bef6f00001b,
0xc95a673cab000067, 0x1e65632ef5000063, 0x7a246f181700006f, 0xad1b6b0a4900006b,
0xb2a67774ce000077, 0x6599736690000073, 0x01d87f507200007f, 0xd6e77b422c00007b,
0x3fbf47ac61000047, 0xe88043be3f000043, 0x8cc14f88dd00004f, 0x5bfe4b9a8300004b,
0x444357e404000057, 0x937c53f65a000053, 0xf73d5fc0b800005f, 0x20025bd2e600005b,
0xc73ea77b2d0000a7, 0x1001a369730000a3, 0x7440af5f910000af, 0xa37fab4dcf0000ab,
0xbcc2b733480000b7, 0x6bfdb321160000b3, 0x0fbcbf17f40000bf, 0xd883bb05aa0000bb,
0x31db87ebe7000087, 0xe6e483f9b9000083, 0x82a58fcf5b00008f, 0x559a8bdd0500008b,
0x4a2797a382000097, 0x9d1893b1dc000093, 0xf9599f873e00009f, 0x2e669b956000009b,
0x36e9e746a40000e7, 0xe1d6e354fa0000e3, 0x8597ef62180000ef, 0x52a8eb70460000eb,
0x4d15f70ec10000f7, 0x9a2af31c9f0000f3, 0xfe6bff2a7d0000ff, 0x2954fb38230000fb,
0xc00cc7d66e0000c7, 0x1733c3c4300000c3, 0x7372cff2d20000cf, 0xa44dcbe08c0000cb,
0xbbf0d79e0b0000d7, 0x6ccfd38c550000d3, 0x088edfbab70000df, 0xdfb1dba8e90000db,
];
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const MUL_ALPHA_INV: [u64; 256] = [
0x0000000000000000, 0x47fcc6018a990000, 0x8ee59102092f0000, 0xc919570383b60000,
0x01d73f04125e0000, 0x462bf90598c70000, 0x8f32ae061b710000, 0xc8ce680791e80000,
0x02b37e0824bc0000, 0x454fb809ae250000, 0x8c56ef0a2d930000, 0xcbaa290ba70a0000,
0x0364410c36e20000, 0x4498870dbc7b0000, 0x8d81d00e3fcd0000, 0xca7d160fb5540000,
0x047bfc1048650000, 0x43873a11c2fc0000, 0x8a9e6d12414a0000, 0xcd62ab13cbd30000,
0x05acc3145a3b0000, 0x42500515d0a20000, 0x8b49521653140000, 0xccb59417d98d0000,
0x06c882186cd90000, 0x41344419e6400000, 0x882d131a65f60000, 0xcfd1d51bef6f0000,
0x071fbd1c7e870000, 0x40e37b1df41e0000, 0x89fa2c1e77a80000, 0xce06ea1ffd310000,
0x08f6e52090ca0000, 0x4f0a23211a530000, 0x8613742299e50000, 0xc1efb223137c0000,
0x0921da2482940000, 0x4edd1c25080d0000, 0x87c44b268bbb0000, 0xc0388d2701220000,
0x0a459b28b4760000, 0x4db95d293eef0000, 0x84a00a2abd590000, 0xc35ccc2b37c00000,
0x0b92a42ca6280000, 0x4c6e622d2cb10000, 0x8577352eaf070000, 0xc28bf32f259e0000,
0x0c8d1930d8af0000, 0x4b71df3152360000, 0x82688832d1800000, 0xc5944e335b190000,
0x0d5a2634caf10000, 0x4aa6e03540680000, 0x83bfb736c3de0000, 0xc443713749470000,
0x0e3e6738fc130000, 0x49c2a139768a0000, 0x80dbf63af53c0000, 0xc727303b7fa50000,
0x0fe9583cee4d0000, 0x48159e3d64d40000, 0x810cc93ee7620000, 0xc6f00f3f6dfb0000,
0x10f1d7403d890000, 0x570d1141b7100000, 0x9e14464234a60000, 0xd9e88043be3f0000,
0x1126e8442fd70000, 0x56da2e45a54e0000, 0x9fc3794626f80000, 0xd83fbf47ac610000,
0x1242a94819350000, 0x55be6f4993ac0000, 0x9ca7384a101a0000, 0xdb5bfe4b9a830000,
0x1395964c0b6b0000, 0x5469504d81f20000, 0x9d70074e02440000, 0xda8cc14f88dd0000,
0x148a2b5075ec0000, 0x5376ed51ff750000, 0x9a6fba527cc30000, 0xdd937c53f65a0000,
0x155d145467b20000, 0x52a1d255ed2b0000, 0x9bb885566e9d0000, 0xdc444357e4040000,
0x1639555851500000, 0x51c59359dbc90000, 0x98dcc45a587f0000, 0xdf20025bd2e60000,
0x17ee6a5c430e0000, 0x5012ac5dc9970000, 0x990bfb5e4a210000, 0xdef73d5fc0b80000,
0x18073260ad430000, 0x5ffbf46127da0000, 0x96e2a362a46c0000, 0xd11e65632ef50000,
0x19d00d64bf1d0000, 0x5e2ccb6535840000, 0x97359c66b6320000, 0xd0c95a673cab0000,
0x1ab44c6889ff0000, 0x5d488a6903660000, 0x9451dd6a80d00000, 0xd3ad1b6b0a490000,
0x1b63736c9ba10000, 0x5c9fb56d11380000, 0x9586e26e928e0000, 0xd27a246f18170000,
0x1c7cce70e5260000, 0x5b8008716fbf0000, 0x92995f72ec090000, 0xd565997366900000,
0x1dabf174f7780000, 0x5a5737757de10000, 0x934e6076fe570000, 0xd4b2a67774ce0000,
0x1ecfb078c19a0000, 0x593376794b030000, 0x902a217ac8b50000, 0xd7d6e77b422c0000,
0x1f188f7cd3c40000, 0x58e4497d595d0000, 0x91fd1e7edaeb0000, 0xd601d87f50720000,
0x20ffb3807a0f0000, 0x67037581f0960000, 0xae1a228273200000, 0xe9e6e483f9b90000,
0x21288c8468510000, 0x66d44a85e2c80000, 0xafcd1d86617e0000, 0xe831db87ebe70000,
0x224ccd885eb30000, 0x65b00b89d42a0000, 0xaca95c8a579c0000, 0xeb559a8bdd050000,
0x239bf28c4ced0000, 0x6467348dc6740000, 0xad7e638e45c20000, 0xea82a58fcf5b0000,
0x24844f90326a0000, 0x63788991b8f30000, 0xaa61de923b450000, 0xed9d1893b1dc0000,
0x2553709420340000, 0x62afb695aaad0000, 0xabb6e196291b0000, 0xec4a2797a3820000,
0x2637319816d60000, 0x61cbf7999c4f0000, 0xa8d2a09a1ff90000, 0xef2e669b95600000,
0x27e00e9c04880000, 0x601cc89d8e110000, 0xa9059f9e0da70000, 0xeef9599f873e0000,
0x280956a0eac50000, 0x6ff590a1605c0000, 0xa6ecc7a2e3ea0000, 0xe11001a369730000,
0x29de69a4f89b0000, 0x6e22afa572020000, 0xa73bf8a6f1b40000, 0xe0c73ea77b2d0000,
0x2aba28a8ce790000, 0x6d46eea944e00000, 0xa45fb9aac7560000, 0xe3a37fab4dcf0000,
0x2b6d17acdc270000, 0x6c91d1ad56be0000, 0xa58886aed5080000, 0xe27440af5f910000,
0x2c72aab0a2a00000, 0x6b8e6cb128390000, 0xa2973bb2ab8f0000, 0xe56bfdb321160000,
0x2da595b4b0fe0000, 0x6a5953b53a670000, 0xa34004b6b9d10000, 0xe4bcc2b733480000,
0x2ec1d4b8861c0000, 0x693d12b90c850000, 0xa02445ba8f330000, 0xe7d883bb05aa0000,
0x2f16ebbc94420000, 0x68ea2dbd1edb0000, 0xa1f37abe9d6d0000, 0xe60fbcbf17f40000,
0x300e64c047860000, 0x77f2a2c1cd1f0000, 0xbeebf5c24ea90000, 0xf91733c3c4300000,
0x31d95bc455d80000, 0x76259dc5df410000, 0xbf3ccac65cf70000, 0xf8c00cc7d66e0000,
0x32bd1ac8633a0000, 0x7541dcc9e9a30000, 0xbc588bca6a150000, 0xfba44dcbe08c0000,
0x336a25cc71640000, 0x7496e3cdfbfd0000, 0xbd8fb4ce784b0000, 0xfa7372cff2d20000,
0x347598d00fe30000, 0x73895ed1857a0000, 0xba9009d206cc0000, 0xfd6ccfd38c550000,
0x35a2a7d41dbd0000, 0x725e61d597240000, 0xbb4736d614920000, 0xfcbbf0d79e0b0000,
0x36c6e6d82b5f0000, 0x713a20d9a1c60000, 0xb82377da22700000, 0xffdfb1dba8e90000,
0x3711d9dc39010000, 0x70ed1fddb3980000, 0xb9f448de302e0000, 0xfe088edfbab70000,
0x38f881e0d74c0000, 0x7f0447e15dd50000, 0xb61d10e2de630000, 0xf1e1d6e354fa0000,
0x392fbee4c5120000, 0x7ed378e54f8b0000, 0xb7ca2fe6cc3d0000, 0xf036e9e746a40000,
0x3a4bffe8f3f00000, 0x7db739e979690000, 0xb4ae6eeafadf0000, 0xf352a8eb70460000,
0x3b9cc0ece1ae0000, 0x7c6006ed6b370000, 0xb57951eee8810000, 0xf28597ef62180000,
0x3c837df09f290000, 0x7b7fbbf115b00000, 0xb266ecf296060000, 0xf59a2af31c9f0000,
0x3d5442f48d770000, 0x7aa884f507ee0000, 0xb3b1d3f684580000, 0xf44d15f70ec10000,
0x3e3003f8bb950000, 0x79ccc5f9310c0000, 0xb0d592fab2ba0000, 0xf72954fb38230000,
0x3fe73cfca9cb0000, 0x781bfafd23520000, 0xb102adfea0e40000, 0xf6fe6bff2a7d0000,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T0: [u64; 256] = [
0xA832A829D77F9AA8, 0x4352432297D41143, 0x5F3E5FC2DF80615F, 0x061E063014121806,
0x6BDA6B7F670CB16B, 0x75BC758F2356C975, 0x6CC16C477519AD6C, 0x592059F2CB927959,
0x71A871AF3B4AD971, 0xDF84DFB6F8275BDF, 0x87A1874C35B22687, 0x95FB95DC59CC6E95,
0x174B17B872655C17, 0xF017F0D31AEAE7F0, 0xD89FD88EEA3247D8, 0x092D0948363F2409,
0x6DC46D4F731EA96D, 0xF318F3CB10E3EBF3, 0x1D691DE84E53741D, 0xCBC0CB16804B0BCB,
0xC9CAC9068C4503C9, 0x4D644D52B3FE294D, 0x2C9C2C7DE8C4B02C, 0xAF29AF11C56A86AF,
0x798079EF0B72F979, 0xE047E0537A9AA7E0, 0x97F197CC55C26697, 0xFD2EFDBB34C9D3FD,
0x6FCE6F5F7F10A16F, 0x4B7A4B62A7EC314B, 0x454C451283C60945, 0x39DD39D596AFE439,
0x3EC63EED84BAF83E, 0xDD8EDDA6F42953DD, 0xA315A371ED4EB6A3, 0x4F6E4F42BFF0214F,
0xB45EB4C99F2BEAB4, 0xB654B6D99325E2B6, 0x9AC89AA47BE1529A, 0x0E360E70242A380E,
0x1F631FF8425D7C1F, 0xBF79BF91A51AC6BF, 0x154115A87E6B5415, 0xE142E15B7C9DA3E1,
0x49704972ABE23949, 0xD2BDD2DED6046FD2, 0x93E593EC4DDE7693, 0xC6F9C67EAE683FC6,
0x92E092E44BD97292, 0x72A772B73143D572, 0x9EDC9E8463FD429E, 0x61F8612F5B3A9961,
0xD1B2D1C6DC0D63D1, 0x63F2633F57349163, 0xFA35FA8326DCCFFA, 0xEE71EE235EB09FEE,
0xF403F4F302F6F7F4, 0x197D19C8564F6419, 0xD5A6D5E6C41173D5, 0xAD23AD01C9648EAD,
0x582558FACD957D58, 0xA40EA449FF5BAAA4, 0xBB6DBBB1BD06D6BB, 0xA11FA161E140BEA1,
0xDC8BDCAEF22E57DC, 0xF21DF2C316E4EFF2, 0x83B5836C2DAE3683, 0x37EB37A5B285DC37,
0x4257422A91D31542, 0xE453E4736286B7E4, 0x7A8F7AF7017BF57A, 0x32FA328DAC9EC832,
0x9CD69C946FF34A9C, 0xCCDBCC2E925E17CC, 0xAB3DAB31DD7696AB, 0x4A7F4A6AA1EB354A,
0x8F898F0C058A068F, 0x6ECB6E577917A56E, 0x04140420181C1004, 0x27BB2725D2F59C27,
0x2E962E6DE4CAB82E, 0xE75CE76B688FBBE7, 0xE24DE2437694AFE2, 0x5A2F5AEAC19B755A,
0x96F496C453C56296, 0x164E16B074625816, 0x23AF2305CAE98C23, 0x2B872B45FAD1AC2B,
0xC2EDC25EB6742FC2, 0x65EC650F43268965, 0x66E36617492F8566, 0x0F330F78222D3C0F,
0xBC76BC89AF13CABC, 0xA937A921D1789EA9, 0x474647028FC80147, 0x415841329BDA1941,
0x34E434BDB88CD034, 0x4875487AADE53D48, 0xFC2BFCB332CED7FC, 0xB751B7D19522E6B7,
0x6ADF6A77610BB56A, 0x88928834179F1A88, 0xA50BA541F95CAEA5, 0x530253A2F7A45153,
0x86A4864433B52286, 0xF93AF99B2CD5C3F9, 0x5B2A5BE2C79C715B, 0xDB90DB96E03B4BDB,
0x38D838DD90A8E038, 0x7B8A7BFF077CF17B, 0xC3E8C356B0732BC3, 0x1E661EF0445A781E,
0x22AA220DCCEE8822, 0x33FF3385AA99CC33, 0x24B4243DD8FC9024, 0x2888285DF0D8A028,
0x36EE36ADB482D836, 0xC7FCC776A86F3BC7, 0xB240B2F98B39F2B2, 0x3BD73BC59AA1EC3B,
0x8E8C8E04038D028E, 0x77B6779F2F58C177, 0xBA68BAB9BB01D2BA, 0xF506F5FB04F1F3F5,
0x144414A0786C5014, 0x9FD99F8C65FA469F, 0x0828084030382008, 0x551C5592E3B64955,
0x9BCD9BAC7DE6569B, 0x4C614C5AB5F92D4C, 0xFE21FEA33EC0DFFE, 0x60FD60275D3D9D60,
0x5C315CDAD5896D5C, 0xDA95DA9EE63C4FDA, 0x187818C050486018, 0x4643460A89CF0546,
0xCDDECD26945913CD, 0x7D947DCF136EE97D, 0x21A52115C6E78421, 0xB04AB0E98737FAB0,
0x3FC33FE582BDFC3F, 0x1B771BD85A416C1B, 0x8997893C11981E89, 0xFF24FFAB38C7DBFF,
0xEB60EB0B40AB8BEB, 0x84AE84543FBB2A84, 0x69D0696F6B02B969, 0x3AD23ACD9CA6E83A,
0x9DD39D9C69F44E9D, 0xD7ACD7F6C81F7BD7, 0xD3B8D3D6D0036BD3, 0x70AD70A73D4DDD70,
0x67E6671F4F288167, 0x405D403A9DDD1D40, 0xB55BB5C1992CEEB5, 0xDE81DEBEFE205FDE,
0x5D345DD2D38E695D, 0x30F0309DA090C030, 0x91EF91FC41D07E91, 0xB14FB1E18130FEB1,
0x788578E70D75FD78, 0x1155118866774411, 0x0105010806070401, 0xE556E57B6481B3E5,
0x0000000000000000, 0x68D568676D05BD68, 0x98C298B477EF5A98, 0xA01AA069E747BAA0,
0xC5F6C566A46133C5, 0x020A02100C0E0802, 0xA604A659F355A2A6, 0x74B974872551CD74,
0x2D992D75EEC3B42D, 0x0B270B583A312C0B, 0xA210A279EB49B2A2, 0x76B37697295FC576,
0xB345B3F18D3EF6B3, 0xBE7CBE99A31DC2BE, 0xCED1CE3E9E501FCE, 0xBD73BD81A914CEBD,
0xAE2CAE19C36D82AE, 0xE96AE91B4CA583E9, 0x8A988A241B91128A, 0x31F53195A697C431,
0x1C6C1CE04854701C, 0xEC7BEC3352BE97EC, 0xF112F1DB1CEDE3F1, 0x99C799BC71E85E99,
0x94FE94D45FCB6A94, 0xAA38AA39DB7192AA, 0xF609F6E30EF8FFF6, 0x26BE262DD4F29826,
0x2F932F65E2CDBC2F, 0xEF74EF2B58B79BEF, 0xE86FE8134AA287E8, 0x8C868C140F830A8C,
0x35E135B5BE8BD435, 0x030F03180A090C03, 0xD4A3D4EEC21677D4, 0x7F9E7FDF1F60E17F,
0xFB30FB8B20DBCBFB, 0x051105281E1B1405, 0xC1E2C146BC7D23C1, 0x5E3B5ECAD987655E,
0x90EA90F447D77A90, 0x20A0201DC0E08020, 0x3DC93DF58EB3F43D, 0x82B082642BA93282,
0xF70CF7EB08FFFBF7, 0xEA65EA0346AC8FEA, 0x0A220A503C36280A, 0x0D390D682E23340D,
0x7E9B7ED71967E57E, 0xF83FF8932AD2C7F8, 0x500D50BAFDAD5D50, 0x1A721AD05C46681A,
0xC4F3C46EA26637C4, 0x071B073812151C07, 0x57165782EFB84157, 0xB862B8A9B70FDAB8,
0x3CCC3CFD88B4F03C, 0x62F7623751339562, 0xE348E34B7093ABE3, 0xC8CFC80E8A4207C8,
0xAC26AC09CF638AAC, 0x520752AAF1A35552, 0x64E9640745218D64, 0x1050108060704010,
0xD0B7D0CEDA0A67D0, 0xD99AD986EC3543D9, 0x135F13986A794C13, 0x0C3C0C602824300C,
0x125A12906C7E4812, 0x298D2955F6DFA429, 0x510851B2FBAA5951, 0xB967B9A1B108DEB9,
0xCFD4CF3698571BCF, 0xD6A9D6FECE187FD6, 0x73A273BF3744D173, 0x8D838D1C09840E8D,
0x81BF817C21A03E81, 0x5419549AE5B14D54, 0xC0E7C04EBA7A27C0, 0xED7EED3B54B993ED,
0x4E6B4E4AB9F7254E, 0x4449441A85C10D44, 0xA701A751F552A6A7, 0x2A822A4DFCD6A82A,
0x85AB855C39BC2E85, 0x25B12535DEFB9425, 0xE659E6636E88BFE6, 0xCAC5CA1E864C0FCA,
0x7C917CC71569ED7C, 0x8B9D8B2C1D96168B, 0x5613568AE9BF4556, 0x80BA807427A73A80,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T1: [u64; 256] = [
0xD1CE3E9E501FCECE, 0x6DBBB1BD06D6BBBB, 0x60EB0B40AB8BEBEB, 0xE092E44BD9729292,
0x65EA0346AC8FEAEA, 0xC0CB16804B0BCBCB, 0x5F13986A794C1313, 0xE2C146BC7D23C1C1,
0x6AE91B4CA583E9E9, 0xD23ACD9CA6E83A3A, 0xA9D6FECE187FD6D6, 0x40B2F98B39F2B2B2,
0xBDD2DED6046FD2D2, 0xEA90F447D77A9090, 0x4B17B872655C1717, 0x3FF8932AD2C7F8F8,
0x57422A91D3154242, 0x4115A87E6B541515, 0x13568AE9BF455656, 0x5EB4C99F2BEAB4B4,
0xEC650F4326896565, 0x6C1CE04854701C1C, 0x928834179F1A8888, 0x52432297D4114343,
0xF6C566A46133C5C5, 0x315CDAD5896D5C5C, 0xEE36ADB482D83636, 0x68BAB9BB01D2BABA,
0x06F5FB04F1F3F5F5, 0x165782EFB8415757, 0xE6671F4F28816767, 0x838D1C09840E8D8D,
0xF53195A697C43131, 0x09F6E30EF8FFF6F6, 0xE9640745218D6464, 0x2558FACD957D5858,
0xDC9E8463FD429E9E, 0x03F4F302F6F7F4F4, 0xAA220DCCEE882222, 0x38AA39DB7192AAAA,
0xBC758F2356C97575, 0x330F78222D3C0F0F, 0x0A02100C0E080202, 0x4FB1E18130FEB1B1,
0x84DFB6F8275BDFDF, 0xC46D4F731EA96D6D, 0xA273BF3744D17373, 0x644D52B3FE294D4D,
0x917CC71569ED7C7C, 0xBE262DD4F2982626, 0x962E6DE4CAB82E2E, 0x0CF7EB08FFFBF7F7,
0x2808403038200808, 0x345DD2D38E695D5D, 0x49441A85C10D4444, 0xC63EED84BAF83E3E,
0xD99F8C65FA469F9F, 0x4414A0786C501414, 0xCFC80E8A4207C8C8, 0x2CAE19C36D82AEAE,
0x19549AE5B14D5454, 0x5010806070401010, 0x9FD88EEA3247D8D8, 0x76BC89AF13CABCBC,
0x721AD05C46681A1A, 0xDA6B7F670CB16B6B, 0xD0696F6B02B96969, 0x18F3CB10E3EBF3F3,
0x73BD81A914CEBDBD, 0xFF3385AA99CC3333, 0x3DAB31DD7696ABAB, 0x35FA8326DCCFFAFA,
0xB2D1C6DC0D63D1D1, 0xCD9BAC7DE6569B9B, 0xD568676D05BD6868, 0x6B4E4AB9F7254E4E,
0x4E16B07462581616, 0xFB95DC59CC6E9595, 0xEF91FC41D07E9191, 0x71EE235EB09FEEEE,
0x614C5AB5F92D4C4C, 0xF2633F5734916363, 0x8C8E04038D028E8E, 0x2A5BE2C79C715B5B,
0xDBCC2E925E17CCCC, 0xCC3CFD88B4F03C3C, 0x7D19C8564F641919, 0x1FA161E140BEA1A1,
0xBF817C21A03E8181, 0x704972ABE2394949, 0x8A7BFF077CF17B7B, 0x9AD986EC3543D9D9,
0xCE6F5F7F10A16F6F, 0xEB37A5B285DC3737, 0xFD60275D3D9D6060, 0xC5CA1E864C0FCACA,
0x5CE76B688FBBE7E7, 0x872B45FAD1AC2B2B, 0x75487AADE53D4848, 0x2EFDBB34C9D3FDFD,
0xF496C453C5629696, 0x4C451283C6094545, 0x2BFCB332CED7FCFC, 0x5841329BDA194141,
0x5A12906C7E481212, 0x390D682E23340D0D, 0x8079EF0B72F97979, 0x56E57B6481B3E5E5,
0x97893C11981E8989, 0x868C140F830A8C8C, 0x48E34B7093ABE3E3, 0xA0201DC0E0802020,
0xF0309DA090C03030, 0x8BDCAEF22E57DCDC, 0x51B7D19522E6B7B7, 0xC16C477519AD6C6C,
0x7F4A6AA1EB354A4A, 0x5BB5C1992CEEB5B5, 0xC33FE582BDFC3F3F, 0xF197CC55C2669797,
0xA3D4EEC21677D4D4, 0xF762375133956262, 0x992D75EEC3B42D2D, 0x1E06301412180606,
0x0EA449FF5BAAA4A4, 0x0BA541F95CAEA5A5, 0xB5836C2DAE368383, 0x3E5FC2DF80615F5F,
0x822A4DFCD6A82A2A, 0x95DA9EE63C4FDADA, 0xCAC9068C4503C9C9, 0x0000000000000000,
0x9B7ED71967E57E7E, 0x10A279EB49B2A2A2, 0x1C5592E3B6495555, 0x79BF91A51AC6BFBF,
0x5511886677441111, 0xA6D5E6C41173D5D5, 0xD69C946FF34A9C9C, 0xD4CF3698571BCFCF,
0x360E70242A380E0E, 0x220A503C36280A0A, 0xC93DF58EB3F43D3D, 0x0851B2FBAA595151,
0x947DCF136EE97D7D, 0xE593EC4DDE769393, 0x771BD85A416C1B1B, 0x21FEA33EC0DFFEFE,
0xF3C46EA26637C4C4, 0x4647028FC8014747, 0x2D0948363F240909, 0xA4864433B5228686,
0x270B583A312C0B0B, 0x898F0C058A068F8F, 0xD39D9C69F44E9D9D, 0xDF6A77610BB56A6A,
0x1B073812151C0707, 0x67B9A1B108DEB9B9, 0x4AB0E98737FAB0B0, 0xC298B477EF5A9898,
0x7818C05048601818, 0xFA328DAC9EC83232, 0xA871AF3B4AD97171, 0x7A4B62A7EC314B4B,
0x74EF2B58B79BEFEF, 0xD73BC59AA1EC3B3B, 0xAD70A73D4DDD7070, 0x1AA069E747BAA0A0,
0x53E4736286B7E4E4, 0x5D403A9DDD1D4040, 0x24FFAB38C7DBFFFF, 0xE8C356B0732BC3C3,
0x37A921D1789EA9A9, 0x59E6636E88BFE6E6, 0x8578E70D75FD7878, 0x3AF99B2CD5C3F9F9,
0x9D8B2C1D96168B8B, 0x43460A89CF054646, 0xBA807427A73A8080, 0x661EF0445A781E1E,
0xD838DD90A8E03838, 0x42E15B7C9DA3E1E1, 0x62B8A9B70FDAB8B8, 0x32A829D77F9AA8A8,
0x47E0537A9AA7E0E0, 0x3C0C602824300C0C, 0xAF2305CAE98C2323, 0xB37697295FC57676,
0x691DE84E53741D1D, 0xB12535DEFB942525, 0xB4243DD8FC902424, 0x1105281E1B140505,
0x12F1DB1CEDE3F1F1, 0xCB6E577917A56E6E, 0xFE94D45FCB6A9494, 0x88285DF0D8A02828,
0xC89AA47BE1529A9A, 0xAE84543FBB2A8484, 0x6FE8134AA287E8E8, 0x15A371ED4EB6A3A3,
0x6E4F42BFF0214F4F, 0xB6779F2F58C17777, 0xB8D3D6D0036BD3D3, 0xAB855C39BC2E8585,
0x4DE2437694AFE2E2, 0x0752AAF1A3555252, 0x1DF2C316E4EFF2F2, 0xB082642BA9328282,
0x0D50BAFDAD5D5050, 0x8F7AF7017BF57A7A, 0x932F65E2CDBC2F2F, 0xB974872551CD7474,
0x0253A2F7A4515353, 0x45B3F18D3EF6B3B3, 0xF8612F5B3A996161, 0x29AF11C56A86AFAF,
0xDD39D596AFE43939, 0xE135B5BE8BD43535, 0x81DEBEFE205FDEDE, 0xDECD26945913CDCD,
0x631FF8425D7C1F1F, 0xC799BC71E85E9999, 0x26AC09CF638AACAC, 0x23AD01C9648EADAD,
0xA772B73143D57272, 0x9C2C7DE8C4B02C2C, 0x8EDDA6F42953DDDD, 0xB7D0CEDA0A67D0D0,
0xA1874C35B2268787, 0x7CBE99A31DC2BEBE, 0x3B5ECAD987655E5E, 0x04A659F355A2A6A6,
0x7BEC3352BE97ECEC, 0x140420181C100404, 0xF9C67EAE683FC6C6, 0x0F03180A090C0303,
0xE434BDB88CD03434, 0x30FB8B20DBCBFBFB, 0x90DB96E03B4BDBDB, 0x2059F2CB92795959,
0x54B6D99325E2B6B6, 0xEDC25EB6742FC2C2, 0x0501080607040101, 0x17F0D31AEAE7F0F0,
0x2F5AEAC19B755A5A, 0x7EED3B54B993EDED, 0x01A751F552A6A7A7, 0xE36617492F856666,
0xA52115C6E7842121, 0x9E7FDF1F60E17F7F, 0x988A241B91128A8A, 0xBB2725D2F59C2727,
0xFCC776A86F3BC7C7, 0xE7C04EBA7A27C0C0, 0x8D2955F6DFA42929, 0xACD7F6C81F7BD7D7,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T2: [u64; 256] = [
0x93EC4DDE769393E5, 0xD986EC3543D9D99A, 0x9AA47BE1529A9AC8, 0xB5C1992CEEB5B55B,
0x98B477EF5A9898C2, 0x220DCCEE882222AA, 0x451283C60945454C, 0xFCB332CED7FCFC2B,
0xBAB9BB01D2BABA68, 0x6A77610BB56A6ADF, 0xDFB6F8275BDFDF84, 0x02100C0E0802020A,
0x9F8C65FA469F9FD9, 0xDCAEF22E57DCDC8B, 0x51B2FBAA59515108, 0x59F2CB9279595920,
0x4A6AA1EB354A4A7F, 0x17B872655C17174B, 0x2B45FAD1AC2B2B87, 0xC25EB6742FC2C2ED,
0x94D45FCB6A9494FE, 0xF4F302F6F7F4F403, 0xBBB1BD06D6BBBB6D, 0xA371ED4EB6A3A315,
0x62375133956262F7, 0xE4736286B7E4E453, 0x71AF3B4AD97171A8, 0xD4EEC21677D4D4A3,
0xCD26945913CDCDDE, 0x70A73D4DDD7070AD, 0x16B074625816164E, 0xE15B7C9DA3E1E142,
0x4972ABE239494970, 0x3CFD88B4F03C3CCC, 0xC04EBA7A27C0C0E7, 0xD88EEA3247D8D89F,
0x5CDAD5896D5C5C31, 0x9BAC7DE6569B9BCD, 0xAD01C9648EADAD23, 0x855C39BC2E8585AB,
0x53A2F7A451535302, 0xA161E140BEA1A11F, 0x7AF7017BF57A7A8F, 0xC80E8A4207C8C8CF,
0x2D75EEC3B42D2D99, 0xE0537A9AA7E0E047, 0xD1C6DC0D63D1D1B2, 0x72B73143D57272A7,
0xA659F355A2A6A604, 0x2C7DE8C4B02C2C9C, 0xC46EA26637C4C4F3, 0xE34B7093ABE3E348,
0x7697295FC57676B3, 0x78E70D75FD787885, 0xB7D19522E6B7B751, 0xB4C99F2BEAB4B45E,
0x0948363F2409092D, 0x3BC59AA1EC3B3BD7, 0x0E70242A380E0E36, 0x41329BDA19414158,
0x4C5AB5F92D4C4C61, 0xDEBEFE205FDEDE81, 0xB2F98B39F2B2B240, 0x90F447D77A9090EA,
0x2535DEFB942525B1, 0xA541F95CAEA5A50B, 0xD7F6C81F7BD7D7AC, 0x03180A090C03030F,
0x1188667744111155, 0x0000000000000000, 0xC356B0732BC3C3E8, 0x2E6DE4CAB82E2E96,
0x92E44BD9729292E0, 0xEF2B58B79BEFEF74, 0x4E4AB9F7254E4E6B, 0x12906C7E4812125A,
0x9D9C69F44E9D9DD3, 0x7DCF136EE97D7D94, 0xCB16804B0BCBCBC0, 0x35B5BE8BD43535E1,
0x1080607040101050, 0xD5E6C41173D5D5A6, 0x4F42BFF0214F4F6E, 0x9E8463FD429E9EDC,
0x4D52B3FE294D4D64, 0xA921D1789EA9A937, 0x5592E3B64955551C, 0xC67EAE683FC6C6F9,
0xD0CEDA0A67D0D0B7, 0x7BFF077CF17B7B8A, 0x18C0504860181878, 0x97CC55C2669797F1,
0xD3D6D0036BD3D3B8, 0x36ADB482D83636EE, 0xE6636E88BFE6E659, 0x487AADE53D484875,
0x568AE9BF45565613, 0x817C21A03E8181BF, 0x8F0C058A068F8F89, 0x779F2F58C17777B6,
0xCC2E925E17CCCCDB, 0x9C946FF34A9C9CD6, 0xB9A1B108DEB9B967, 0xE2437694AFE2E24D,
0xAC09CF638AACAC26, 0xB8A9B70FDAB8B862, 0x2F65E2CDBC2F2F93, 0x15A87E6B54151541,
0xA449FF5BAAA4A40E, 0x7CC71569ED7C7C91, 0xDA9EE63C4FDADA95, 0x38DD90A8E03838D8,
0x1EF0445A781E1E66, 0x0B583A312C0B0B27, 0x05281E1B14050511, 0xD6FECE187FD6D6A9,
0x14A0786C50141444, 0x6E577917A56E6ECB, 0x6C477519AD6C6CC1, 0x7ED71967E57E7E9B,
0x6617492F856666E3, 0xFDBB34C9D3FDFD2E, 0xB1E18130FEB1B14F, 0xE57B6481B3E5E556,
0x60275D3D9D6060FD, 0xAF11C56A86AFAF29, 0x5ECAD987655E5E3B, 0x3385AA99CC3333FF,
0x874C35B2268787A1, 0xC9068C4503C9C9CA, 0xF0D31AEAE7F0F017, 0x5DD2D38E695D5D34,
0x6D4F731EA96D6DC4, 0x3FE582BDFC3F3FC3, 0x8834179F1A888892, 0x8D1C09840E8D8D83,
0xC776A86F3BC7C7FC, 0xF7EB08FFFBF7F70C, 0x1DE84E53741D1D69, 0xE91B4CA583E9E96A,
0xEC3352BE97ECEC7B, 0xED3B54B993EDED7E, 0x807427A73A8080BA, 0x2955F6DFA429298D,
0x2725D2F59C2727BB, 0xCF3698571BCFCFD4, 0x99BC71E85E9999C7, 0xA829D77F9AA8A832,
0x50BAFDAD5D50500D, 0x0F78222D3C0F0F33, 0x37A5B285DC3737EB, 0x243DD8FC902424B4,
0x285DF0D8A0282888, 0x309DA090C03030F0, 0x95DC59CC6E9595FB, 0xD2DED6046FD2D2BD,
0x3EED84BAF83E3EC6, 0x5BE2C79C715B5B2A, 0x403A9DDD1D40405D, 0x836C2DAE368383B5,
0xB3F18D3EF6B3B345, 0x696F6B02B96969D0, 0x5782EFB841575716, 0x1FF8425D7C1F1F63,
0x073812151C07071B, 0x1CE04854701C1C6C, 0x8A241B91128A8A98, 0xBC89AF13CABCBC76,
0x201DC0E0802020A0, 0xEB0B40AB8BEBEB60, 0xCE3E9E501FCECED1, 0x8E04038D028E8E8C,
0xAB31DD7696ABAB3D, 0xEE235EB09FEEEE71, 0x3195A697C43131F5, 0xA279EB49B2A2A210,
0x73BF3744D17373A2, 0xF99B2CD5C3F9F93A, 0xCA1E864C0FCACAC5, 0x3ACD9CA6E83A3AD2,
0x1AD05C46681A1A72, 0xFB8B20DBCBFBFB30, 0x0D682E23340D0D39, 0xC146BC7D23C1C1E2,
0xFEA33EC0DFFEFE21, 0xFA8326DCCFFAFA35, 0xF2C316E4EFF2F21D, 0x6F5F7F10A16F6FCE,
0xBD81A914CEBDBD73, 0x96C453C5629696F4, 0xDDA6F42953DDDD8E, 0x432297D411434352,
0x52AAF1A355525207, 0xB6D99325E2B6B654, 0x0840303820080828, 0xF3CB10E3EBF3F318,
0xAE19C36D82AEAE2C, 0xBE99A31DC2BEBE7C, 0x19C8564F6419197D, 0x893C11981E898997,
0x328DAC9EC83232FA, 0x262DD4F2982626BE, 0xB0E98737FAB0B04A, 0xEA0346AC8FEAEA65,
0x4B62A7EC314B4B7A, 0x640745218D6464E9, 0x84543FBB2A8484AE, 0x82642BA9328282B0,
0x6B7F670CB16B6BDA, 0xF5FB04F1F3F5F506, 0x79EF0B72F9797980, 0xBF91A51AC6BFBF79,
0x0108060704010105, 0x5FC2DF80615F5F3E, 0x758F2356C97575BC, 0x633F5734916363F2,
0x1BD85A416C1B1B77, 0x2305CAE98C2323AF, 0x3DF58EB3F43D3DC9, 0x68676D05BD6868D5,
0x2A4DFCD6A82A2A82, 0x650F4326896565EC, 0xE8134AA287E8E86F, 0x91FC41D07E9191EF,
0xF6E30EF8FFF6F609, 0xFFAB38C7DBFFFF24, 0x13986A794C13135F, 0x58FACD957D585825,
0xF1DB1CEDE3F1F112, 0x47028FC801474746, 0x0A503C36280A0A22, 0x7FDF1F60E17F7F9E,
0xC566A46133C5C5F6, 0xA751F552A6A7A701, 0xE76B688FBBE7E75C, 0x612F5B3A996161F8,
0x5AEAC19B755A5A2F, 0x063014121806061E, 0x460A89CF05464643, 0x441A85C10D444449,
0x422A91D315424257, 0x0420181C10040414, 0xA069E747BAA0A01A, 0xDB96E03B4BDBDB90,
0x39D596AFE43939DD, 0x864433B5228686A4, 0x549AE5B14D545419, 0xAA39DB7192AAAA38,
0x8C140F830A8C8C86, 0x34BDB88CD03434E4, 0x2115C6E7842121A5, 0x8B2C1D96168B8B9D,
0xF8932AD2C7F8F83F, 0x0C602824300C0C3C, 0x74872551CD7474B9, 0x671F4F28816767E6,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T3: [u64; 256] = [
0x676D05BD6868D568, 0x1C09840E8D8D838D, 0x1E864C0FCACAC5CA, 0x52B3FE294D4D644D,
0xBF3744D17373A273, 0x62A7EC314B4B7A4B, 0x4AB9F7254E4E6B4E, 0x4DFCD6A82A2A822A,
0xEEC21677D4D4A3D4, 0xAAF1A35552520752, 0x2DD4F2982626BE26, 0xF18D3EF6B3B345B3,
0x9AE5B14D54541954, 0xF0445A781E1E661E, 0xC8564F6419197D19, 0xF8425D7C1F1F631F,
0x0DCCEE882222AA22, 0x180A090C03030F03, 0x0A89CF0546464346, 0xF58EB3F43D3DC93D,
0x75EEC3B42D2D992D, 0x6AA1EB354A4A7F4A, 0xA2F7A45153530253, 0x6C2DAE368383B583,
0x986A794C13135F13, 0x241B91128A8A988A, 0xD19522E6B7B751B7, 0xE6C41173D5D5A6D5,
0x35DEFB942525B125, 0xEF0B72F979798079, 0xFB04F1F3F5F506F5, 0x81A914CEBDBD73BD,
0xFACD957D58582558, 0x65E2CDBC2F2F932F, 0x682E23340D0D390D, 0x100C0E0802020A02,
0x3B54B993EDED7EED, 0xB2FBAA5951510851, 0x8463FD429E9EDC9E, 0x8866774411115511,
0xC316E4EFF2F21DF2, 0xED84BAF83E3EC63E, 0x92E3B64955551C55, 0xCAD987655E5E3B5E,
0xC6DC0D63D1D1B2D1, 0xB074625816164E16, 0xFD88B4F03C3CCC3C, 0x17492F856666E366,
0xA73D4DDD7070AD70, 0xD2D38E695D5D345D, 0xCB10E3EBF3F318F3, 0x1283C60945454C45,
0x3A9DDD1D40405D40, 0x2E925E17CCCCDBCC, 0x134AA287E8E86FE8, 0xD45FCB6A9494FE94,
0x8AE9BF4556561356, 0x4030382008082808, 0x3E9E501FCECED1CE, 0xD05C46681A1A721A,
0xCD9CA6E83A3AD23A, 0xDED6046FD2D2BDD2, 0x5B7C9DA3E1E142E1, 0xB6F8275BDFDF84DF,
0xC1992CEEB5B55BB5, 0xDD90A8E03838D838, 0x577917A56E6ECB6E, 0x70242A380E0E360E,
0x7B6481B3E5E556E5, 0xF302F6F7F4F403F4, 0x9B2CD5C3F9F93AF9, 0x4433B5228686A486,
0x1B4CA583E9E96AE9, 0x42BFF0214F4F6E4F, 0xFECE187FD6D6A9D6, 0x5C39BC2E8585AB85,
0x05CAE98C2323AF23, 0x3698571BCFCFD4CF, 0x8DAC9EC83232FA32, 0xBC71E85E9999C799,
0x95A697C43131F531, 0xA0786C5014144414, 0x19C36D82AEAE2CAE, 0x235EB09FEEEE71EE,
0x0E8A4207C8C8CFC8, 0x7AADE53D48487548, 0xD6D0036BD3D3B8D3, 0x9DA090C03030F030,
0x61E140BEA1A11FA1, 0xE44BD9729292E092, 0x329BDA1941415841, 0xE18130FEB1B14FB1,
0xC050486018187818, 0x6EA26637C4C4F3C4, 0x7DE8C4B02C2C9C2C, 0xAF3B4AD97171A871,
0xB73143D57272A772, 0x1A85C10D44444944, 0xA87E6B5415154115, 0xBB34C9D3FDFD2EFD,
0xA5B285DC3737EB37, 0x99A31DC2BEBE7CBE, 0xC2DF80615F5F3E5F, 0x39DB7192AAAA38AA,
0xAC7DE6569B9BCD9B, 0x34179F1A88889288, 0x8EEA3247D8D89FD8, 0x31DD7696ABAB3DAB,
0x3C11981E89899789, 0x946FF34A9C9CD69C, 0x8326DCCFFAFA35FA, 0x275D3D9D6060FD60,
0x0346AC8FEAEA65EA, 0x89AF13CABCBC76BC, 0x375133956262F762, 0x602824300C0C3C0C,
0x3DD8FC902424B424, 0x59F355A2A6A604A6, 0x29D77F9AA8A832A8, 0x3352BE97ECEC7BEC,
0x1F4F28816767E667, 0x1DC0E0802020A020, 0x96E03B4BDBDB90DB, 0xC71569ED7C7C917C,
0x5DF0D8A028288828, 0xA6F42953DDDD8EDD, 0x09CF638AACAC26AC, 0xE2C79C715B5B2A5B,
0xBDB88CD03434E434, 0xD71967E57E7E9B7E, 0x8060704010105010, 0xDB1CEDE3F1F112F1,
0xFF077CF17B7B8A7B, 0x0C058A068F8F898F, 0x3F5734916363F263, 0x69E747BAA0A01AA0,
0x281E1B1405051105, 0xA47BE1529A9AC89A, 0x2297D41143435243, 0x9F2F58C17777B677,
0x15C6E7842121A521, 0x91A51AC6BFBF79BF, 0x25D2F59C2727BB27, 0x48363F2409092D09,
0x56B0732BC3C3E8C3, 0x8C65FA469F9FD99F, 0xD99325E2B6B654B6, 0xF6C81F7BD7D7ACD7,
0x55F6DFA429298D29, 0x5EB6742FC2C2EDC2, 0x0B40AB8BEBEB60EB, 0x4EBA7A27C0C0E7C0,
0x49FF5BAAA4A40EA4, 0x2C1D96168B8B9D8B, 0x140F830A8C8C868C, 0xE84E53741D1D691D,
0x8B20DBCBFBFB30FB, 0xAB38C7DBFFFF24FF, 0x46BC7D23C1C1E2C1, 0xF98B39F2B2B240B2,
0xCC55C2669797F197, 0x6DE4CAB82E2E962E, 0x932AD2C7F8F83FF8, 0x0F4326896565EC65,
0xE30EF8FFF6F609F6, 0x8F2356C97575BC75, 0x3812151C07071B07, 0x20181C1004041404,
0x72ABE23949497049, 0x85AA99CC3333FF33, 0x736286B7E4E453E4, 0x86EC3543D9D99AD9,
0xA1B108DEB9B967B9, 0xCEDA0A67D0D0B7D0, 0x2A91D31542425742, 0x76A86F3BC7C7FCC7,
0x477519AD6C6CC16C, 0xF447D77A9090EA90, 0x0000000000000000, 0x04038D028E8E8C8E,
0x5F7F10A16F6FCE6F, 0xBAFDAD5D50500D50, 0x0806070401010501, 0x66A46133C5C5F6C5,
0x9EE63C4FDADA95DA, 0x028FC80147474647, 0xE582BDFC3F3FC33F, 0x26945913CDCDDECD,
0x6F6B02B96969D069, 0x79EB49B2A2A210A2, 0x437694AFE2E24DE2, 0xF7017BF57A7A8F7A,
0x51F552A6A7A701A7, 0x7EAE683FC6C6F9C6, 0xEC4DDE769393E593, 0x78222D3C0F0F330F,
0x503C36280A0A220A, 0x3014121806061E06, 0x636E88BFE6E659E6, 0x45FAD1AC2B2B872B,
0xC453C5629696F496, 0x71ED4EB6A3A315A3, 0xE04854701C1C6C1C, 0x11C56A86AFAF29AF,
0x77610BB56A6ADF6A, 0x906C7E4812125A12, 0x543FBB2A8484AE84, 0xD596AFE43939DD39,
0x6B688FBBE7E75CE7, 0xE98737FAB0B04AB0, 0x642BA9328282B082, 0xEB08FFFBF7F70CF7,
0xA33EC0DFFEFE21FE, 0x9C69F44E9D9DD39D, 0x4C35B2268787A187, 0xDAD5896D5C5C315C,
0x7C21A03E8181BF81, 0xB5BE8BD43535E135, 0xBEFE205FDEDE81DE, 0xC99F2BEAB4B45EB4,
0x41F95CAEA5A50BA5, 0xB332CED7FCFC2BFC, 0x7427A73A8080BA80, 0x2B58B79BEFEF74EF,
0x16804B0BCBCBC0CB, 0xB1BD06D6BBBB6DBB, 0x7F670CB16B6BDA6B, 0x97295FC57676B376,
0xB9BB01D2BABA68BA, 0xEAC19B755A5A2F5A, 0xCF136EE97D7D947D, 0xE70D75FD78788578,
0x583A312C0B0B270B, 0xDC59CC6E9595FB95, 0x4B7093ABE3E348E3, 0x01C9648EADAD23AD,
0x872551CD7474B974, 0xB477EF5A9898C298, 0xC59AA1EC3B3BD73B, 0xADB482D83636EE36,
0x0745218D6464E964, 0x4F731EA96D6DC46D, 0xAEF22E57DCDC8BDC, 0xD31AEAE7F0F017F0,
0xF2CB927959592059, 0x21D1789EA9A937A9, 0x5AB5F92D4C4C614C, 0xB872655C17174B17,
0xDF1F60E17F7F9E7F, 0xFC41D07E9191EF91, 0xA9B70FDAB8B862B8, 0x068C4503C9C9CAC9,
0x82EFB84157571657, 0xD85A416C1B1B771B, 0x537A9AA7E0E047E0, 0x2F5B3A996161F861,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T4: [u64; 256] = [
0xD77F9AA8A832A829, 0x97D4114343524322, 0xDF80615F5F3E5FC2, 0x14121806061E0630,
0x670CB16B6BDA6B7F, 0x2356C97575BC758F, 0x7519AD6C6CC16C47, 0xCB927959592059F2,
0x3B4AD97171A871AF, 0xF8275BDFDF84DFB6, 0x35B2268787A1874C, 0x59CC6E9595FB95DC,
0x72655C17174B17B8, 0x1AEAE7F0F017F0D3, 0xEA3247D8D89FD88E, 0x363F2409092D0948,
0x731EA96D6DC46D4F, 0x10E3EBF3F318F3CB, 0x4E53741D1D691DE8, 0x804B0BCBCBC0CB16,
0x8C4503C9C9CAC906, 0xB3FE294D4D644D52, 0xE8C4B02C2C9C2C7D, 0xC56A86AFAF29AF11,
0x0B72F979798079EF, 0x7A9AA7E0E047E053, 0x55C2669797F197CC, 0x34C9D3FDFD2EFDBB,
0x7F10A16F6FCE6F5F, 0xA7EC314B4B7A4B62, 0x83C60945454C4512, 0x96AFE43939DD39D5,
0x84BAF83E3EC63EED, 0xF42953DDDD8EDDA6, 0xED4EB6A3A315A371, 0xBFF0214F4F6E4F42,
0x9F2BEAB4B45EB4C9, 0x9325E2B6B654B6D9, 0x7BE1529A9AC89AA4, 0x242A380E0E360E70,
0x425D7C1F1F631FF8, 0xA51AC6BFBF79BF91, 0x7E6B5415154115A8, 0x7C9DA3E1E142E15B,
0xABE2394949704972, 0xD6046FD2D2BDD2DE, 0x4DDE769393E593EC, 0xAE683FC6C6F9C67E,
0x4BD9729292E092E4, 0x3143D57272A772B7, 0x63FD429E9EDC9E84, 0x5B3A996161F8612F,
0xDC0D63D1D1B2D1C6, 0x5734916363F2633F, 0x26DCCFFAFA35FA83, 0x5EB09FEEEE71EE23,
0x02F6F7F4F403F4F3, 0x564F6419197D19C8, 0xC41173D5D5A6D5E6, 0xC9648EADAD23AD01,
0xCD957D58582558FA, 0xFF5BAAA4A40EA449, 0xBD06D6BBBB6DBBB1, 0xE140BEA1A11FA161,
0xF22E57DCDC8BDCAE, 0x16E4EFF2F21DF2C3, 0x2DAE368383B5836C, 0xB285DC3737EB37A5,
0x91D315424257422A, 0x6286B7E4E453E473, 0x017BF57A7A8F7AF7, 0xAC9EC83232FA328D,
0x6FF34A9C9CD69C94, 0x925E17CCCCDBCC2E, 0xDD7696ABAB3DAB31, 0xA1EB354A4A7F4A6A,
0x058A068F8F898F0C, 0x7917A56E6ECB6E57, 0x181C100404140420, 0xD2F59C2727BB2725,
0xE4CAB82E2E962E6D, 0x688FBBE7E75CE76B, 0x7694AFE2E24DE243, 0xC19B755A5A2F5AEA,
0x53C5629696F496C4, 0x74625816164E16B0, 0xCAE98C2323AF2305, 0xFAD1AC2B2B872B45,
0xB6742FC2C2EDC25E, 0x4326896565EC650F, 0x492F856666E36617, 0x222D3C0F0F330F78,
0xAF13CABCBC76BC89, 0xD1789EA9A937A921, 0x8FC8014747464702, 0x9BDA194141584132,
0xB88CD03434E434BD, 0xADE53D484875487A, 0x32CED7FCFC2BFCB3, 0x9522E6B7B751B7D1,
0x610BB56A6ADF6A77, 0x179F1A8888928834, 0xF95CAEA5A50BA541, 0xF7A45153530253A2,
0x33B5228686A48644, 0x2CD5C3F9F93AF99B, 0xC79C715B5B2A5BE2, 0xE03B4BDBDB90DB96,
0x90A8E03838D838DD, 0x077CF17B7B8A7BFF, 0xB0732BC3C3E8C356, 0x445A781E1E661EF0,
0xCCEE882222AA220D, 0xAA99CC3333FF3385, 0xD8FC902424B4243D, 0xF0D8A0282888285D,
0xB482D83636EE36AD, 0xA86F3BC7C7FCC776, 0x8B39F2B2B240B2F9, 0x9AA1EC3B3BD73BC5,
0x038D028E8E8C8E04, 0x2F58C17777B6779F, 0xBB01D2BABA68BAB9, 0x04F1F3F5F506F5FB,
0x786C5014144414A0, 0x65FA469F9FD99F8C, 0x3038200808280840, 0xE3B64955551C5592,
0x7DE6569B9BCD9BAC, 0xB5F92D4C4C614C5A, 0x3EC0DFFEFE21FEA3, 0x5D3D9D6060FD6027,
0xD5896D5C5C315CDA, 0xE63C4FDADA95DA9E, 0x50486018187818C0, 0x89CF05464643460A,
0x945913CDCDDECD26, 0x136EE97D7D947DCF, 0xC6E7842121A52115, 0x8737FAB0B04AB0E9,
0x82BDFC3F3FC33FE5, 0x5A416C1B1B771BD8, 0x11981E898997893C, 0x38C7DBFFFF24FFAB,
0x40AB8BEBEB60EB0B, 0x3FBB2A8484AE8454, 0x6B02B96969D0696F, 0x9CA6E83A3AD23ACD,
0x69F44E9D9DD39D9C, 0xC81F7BD7D7ACD7F6, 0xD0036BD3D3B8D3D6, 0x3D4DDD7070AD70A7,
0x4F28816767E6671F, 0x9DDD1D40405D403A, 0x992CEEB5B55BB5C1, 0xFE205FDEDE81DEBE,
0xD38E695D5D345DD2, 0xA090C03030F0309D, 0x41D07E9191EF91FC, 0x8130FEB1B14FB1E1,
0x0D75FD78788578E7, 0x6677441111551188, 0x0607040101050108, 0x6481B3E5E556E57B,
0x0000000000000000, 0x6D05BD6868D56867, 0x77EF5A9898C298B4, 0xE747BAA0A01AA069,
0xA46133C5C5F6C566, 0x0C0E0802020A0210, 0xF355A2A6A604A659, 0x2551CD7474B97487,
0xEEC3B42D2D992D75, 0x3A312C0B0B270B58, 0xEB49B2A2A210A279, 0x295FC57676B37697,
0x8D3EF6B3B345B3F1, 0xA31DC2BEBE7CBE99, 0x9E501FCECED1CE3E, 0xA914CEBDBD73BD81,
0xC36D82AEAE2CAE19, 0x4CA583E9E96AE91B, 0x1B91128A8A988A24, 0xA697C43131F53195,
0x4854701C1C6C1CE0, 0x52BE97ECEC7BEC33, 0x1CEDE3F1F112F1DB, 0x71E85E9999C799BC,
0x5FCB6A9494FE94D4, 0xDB7192AAAA38AA39, 0x0EF8FFF6F609F6E3, 0xD4F2982626BE262D,
0xE2CDBC2F2F932F65, 0x58B79BEFEF74EF2B, 0x4AA287E8E86FE813, 0x0F830A8C8C868C14,
0xBE8BD43535E135B5, 0x0A090C03030F0318, 0xC21677D4D4A3D4EE, 0x1F60E17F7F9E7FDF,
0x20DBCBFBFB30FB8B, 0x1E1B140505110528, 0xBC7D23C1C1E2C146, 0xD987655E5E3B5ECA,
0x47D77A9090EA90F4, 0xC0E0802020A0201D, 0x8EB3F43D3DC93DF5, 0x2BA9328282B08264,
0x08FFFBF7F70CF7EB, 0x46AC8FEAEA65EA03, 0x3C36280A0A220A50, 0x2E23340D0D390D68,
0x1967E57E7E9B7ED7, 0x2AD2C7F8F83FF893, 0xFDAD5D50500D50BA, 0x5C46681A1A721AD0,
0xA26637C4C4F3C46E, 0x12151C07071B0738, 0xEFB8415757165782, 0xB70FDAB8B862B8A9,
0x88B4F03C3CCC3CFD, 0x5133956262F76237, 0x7093ABE3E348E34B, 0x8A4207C8C8CFC80E,
0xCF638AACAC26AC09, 0xF1A35552520752AA, 0x45218D6464E96407, 0x6070401010501080,
0xDA0A67D0D0B7D0CE, 0xEC3543D9D99AD986, 0x6A794C13135F1398, 0x2824300C0C3C0C60,
0x6C7E4812125A1290, 0xF6DFA429298D2955, 0xFBAA5951510851B2, 0xB108DEB9B967B9A1,
0x98571BCFCFD4CF36, 0xCE187FD6D6A9D6FE, 0x3744D17373A273BF, 0x09840E8D8D838D1C,
0x21A03E8181BF817C, 0xE5B14D545419549A, 0xBA7A27C0C0E7C04E, 0x54B993EDED7EED3B,
0xB9F7254E4E6B4E4A, 0x85C10D444449441A, 0xF552A6A7A701A751, 0xFCD6A82A2A822A4D,
0x39BC2E8585AB855C, 0xDEFB942525B12535, 0x6E88BFE6E659E663, 0x864C0FCACAC5CA1E,
0x1569ED7C7C917CC7, 0x1D96168B8B9D8B2C, 0xE9BF45565613568A, 0x27A73A8080BA8074,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T5: [u64; 256] = [
0x501FCECED1CE3E9E, 0x06D6BBBB6DBBB1BD, 0xAB8BEBEB60EB0B40, 0xD9729292E092E44B,
0xAC8FEAEA65EA0346, 0x4B0BCBCBC0CB1680, 0x794C13135F13986A, 0x7D23C1C1E2C146BC,
0xA583E9E96AE91B4C, 0xA6E83A3AD23ACD9C, 0x187FD6D6A9D6FECE, 0x39F2B2B240B2F98B,
0x046FD2D2BDD2DED6, 0xD77A9090EA90F447, 0x655C17174B17B872, 0xD2C7F8F83FF8932A,
0xD315424257422A91, 0x6B5415154115A87E, 0xBF45565613568AE9, 0x2BEAB4B45EB4C99F,
0x26896565EC650F43, 0x54701C1C6C1CE048, 0x9F1A888892883417, 0xD411434352432297,
0x6133C5C5F6C566A4, 0x896D5C5C315CDAD5, 0x82D83636EE36ADB4, 0x01D2BABA68BAB9BB,
0xF1F3F5F506F5FB04, 0xB8415757165782EF, 0x28816767E6671F4F, 0x840E8D8D838D1C09,
0x97C43131F53195A6, 0xF8FFF6F609F6E30E, 0x218D6464E9640745, 0x957D58582558FACD,
0xFD429E9EDC9E8463, 0xF6F7F4F403F4F302, 0xEE882222AA220DCC, 0x7192AAAA38AA39DB,
0x56C97575BC758F23, 0x2D3C0F0F330F7822, 0x0E0802020A02100C, 0x30FEB1B14FB1E181,
0x275BDFDF84DFB6F8, 0x1EA96D6DC46D4F73, 0x44D17373A273BF37, 0xFE294D4D644D52B3,
0x69ED7C7C917CC715, 0xF2982626BE262DD4, 0xCAB82E2E962E6DE4, 0xFFFBF7F70CF7EB08,
0x3820080828084030, 0x8E695D5D345DD2D3, 0xC10D444449441A85, 0xBAF83E3EC63EED84,
0xFA469F9FD99F8C65, 0x6C5014144414A078, 0x4207C8C8CFC80E8A, 0x6D82AEAE2CAE19C3,
0xB14D545419549AE5, 0x7040101050108060, 0x3247D8D89FD88EEA, 0x13CABCBC76BC89AF,
0x46681A1A721AD05C, 0x0CB16B6BDA6B7F67, 0x02B96969D0696F6B, 0xE3EBF3F318F3CB10,
0x14CEBDBD73BD81A9, 0x99CC3333FF3385AA, 0x7696ABAB3DAB31DD, 0xDCCFFAFA35FA8326,
0x0D63D1D1B2D1C6DC, 0xE6569B9BCD9BAC7D, 0x05BD6868D568676D, 0xF7254E4E6B4E4AB9,
0x625816164E16B074, 0xCC6E9595FB95DC59, 0xD07E9191EF91FC41, 0xB09FEEEE71EE235E,
0xF92D4C4C614C5AB5, 0x34916363F2633F57, 0x8D028E8E8C8E0403, 0x9C715B5B2A5BE2C7,
0x5E17CCCCDBCC2E92, 0xB4F03C3CCC3CFD88, 0x4F6419197D19C856, 0x40BEA1A11FA161E1,
0xA03E8181BF817C21, 0xE2394949704972AB, 0x7CF17B7B8A7BFF07, 0x3543D9D99AD986EC,
0x10A16F6FCE6F5F7F, 0x85DC3737EB37A5B2, 0x3D9D6060FD60275D, 0x4C0FCACAC5CA1E86,
0x8FBBE7E75CE76B68, 0xD1AC2B2B872B45FA, 0xE53D484875487AAD, 0xC9D3FDFD2EFDBB34,
0xC5629696F496C453, 0xC60945454C451283, 0xCED7FCFC2BFCB332, 0xDA1941415841329B,
0x7E4812125A12906C, 0x23340D0D390D682E, 0x72F979798079EF0B, 0x81B3E5E556E57B64,
0x981E898997893C11, 0x830A8C8C868C140F, 0x93ABE3E348E34B70, 0xE0802020A0201DC0,
0x90C03030F0309DA0, 0x2E57DCDC8BDCAEF2, 0x22E6B7B751B7D195, 0x19AD6C6CC16C4775,
0xEB354A4A7F4A6AA1, 0x2CEEB5B55BB5C199, 0xBDFC3F3FC33FE582, 0xC2669797F197CC55,
0x1677D4D4A3D4EEC2, 0x33956262F7623751, 0xC3B42D2D992D75EE, 0x121806061E063014,
0x5BAAA4A40EA449FF, 0x5CAEA5A50BA541F9, 0xAE368383B5836C2D, 0x80615F5F3E5FC2DF,
0xD6A82A2A822A4DFC, 0x3C4FDADA95DA9EE6, 0x4503C9C9CAC9068C, 0x0000000000000000,
0x67E57E7E9B7ED719, 0x49B2A2A210A279EB, 0xB64955551C5592E3, 0x1AC6BFBF79BF91A5,
0x7744111155118866, 0x1173D5D5A6D5E6C4, 0xF34A9C9CD69C946F, 0x571BCFCFD4CF3698,
0x2A380E0E360E7024, 0x36280A0A220A503C, 0xB3F43D3DC93DF58E, 0xAA5951510851B2FB,
0x6EE97D7D947DCF13, 0xDE769393E593EC4D, 0x416C1B1B771BD85A, 0xC0DFFEFE21FEA33E,
0x6637C4C4F3C46EA2, 0xC80147474647028F, 0x3F2409092D094836, 0xB5228686A4864433,
0x312C0B0B270B583A, 0x8A068F8F898F0C05, 0xF44E9D9DD39D9C69, 0x0BB56A6ADF6A7761,
0x151C07071B073812, 0x08DEB9B967B9A1B1, 0x37FAB0B04AB0E987, 0xEF5A9898C298B477,
0x486018187818C050, 0x9EC83232FA328DAC, 0x4AD97171A871AF3B, 0xEC314B4B7A4B62A7,
0xB79BEFEF74EF2B58, 0xA1EC3B3BD73BC59A, 0x4DDD7070AD70A73D, 0x47BAA0A01AA069E7,
0x86B7E4E453E47362, 0xDD1D40405D403A9D, 0xC7DBFFFF24FFAB38, 0x732BC3C3E8C356B0,
0x789EA9A937A921D1, 0x88BFE6E659E6636E, 0x75FD78788578E70D, 0xD5C3F9F93AF99B2C,
0x96168B8B9D8B2C1D, 0xCF05464643460A89, 0xA73A8080BA807427, 0x5A781E1E661EF044,
0xA8E03838D838DD90, 0x9DA3E1E142E15B7C, 0x0FDAB8B862B8A9B7, 0x7F9AA8A832A829D7,
0x9AA7E0E047E0537A, 0x24300C0C3C0C6028, 0xE98C2323AF2305CA, 0x5FC57676B3769729,
0x53741D1D691DE84E, 0xFB942525B12535DE, 0xFC902424B4243DD8, 0x1B1405051105281E,
0xEDE3F1F112F1DB1C, 0x17A56E6ECB6E5779, 0xCB6A9494FE94D45F, 0xD8A0282888285DF0,
0xE1529A9AC89AA47B, 0xBB2A8484AE84543F, 0xA287E8E86FE8134A, 0x4EB6A3A315A371ED,
0xF0214F4F6E4F42BF, 0x58C17777B6779F2F, 0x036BD3D3B8D3D6D0, 0xBC2E8585AB855C39,
0x94AFE2E24DE24376, 0xA35552520752AAF1, 0xE4EFF2F21DF2C316, 0xA9328282B082642B,
0xAD5D50500D50BAFD, 0x7BF57A7A8F7AF701, 0xCDBC2F2F932F65E2, 0x51CD7474B9748725,
0xA45153530253A2F7, 0x3EF6B3B345B3F18D, 0x3A996161F8612F5B, 0x6A86AFAF29AF11C5,
0xAFE43939DD39D596, 0x8BD43535E135B5BE, 0x205FDEDE81DEBEFE, 0x5913CDCDDECD2694,
0x5D7C1F1F631FF842, 0xE85E9999C799BC71, 0x638AACAC26AC09CF, 0x648EADAD23AD01C9,
0x43D57272A772B731, 0xC4B02C2C9C2C7DE8, 0x2953DDDD8EDDA6F4, 0x0A67D0D0B7D0CEDA,
0xB2268787A1874C35, 0x1DC2BEBE7CBE99A3, 0x87655E5E3B5ECAD9, 0x55A2A6A604A659F3,
0xBE97ECEC7BEC3352, 0x1C10040414042018, 0x683FC6C6F9C67EAE, 0x090C03030F03180A,
0x8CD03434E434BDB8, 0xDBCBFBFB30FB8B20, 0x3B4BDBDB90DB96E0, 0x927959592059F2CB,
0x25E2B6B654B6D993, 0x742FC2C2EDC25EB6, 0x0704010105010806, 0xEAE7F0F017F0D31A,
0x9B755A5A2F5AEAC1, 0xB993EDED7EED3B54, 0x52A6A7A701A751F5, 0x2F856666E3661749,
0xE7842121A52115C6, 0x60E17F7F9E7FDF1F, 0x91128A8A988A241B, 0xF59C2727BB2725D2,
0x6F3BC7C7FCC776A8, 0x7A27C0C0E7C04EBA, 0xDFA429298D2955F6, 0x1F7BD7D7ACD7F6C8,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T6: [u64; 256] = [
0x769393E593EC4DDE, 0x43D9D99AD986EC35, 0x529A9AC89AA47BE1, 0xEEB5B55BB5C1992C,
0x5A9898C298B477EF, 0x882222AA220DCCEE, 0x0945454C451283C6, 0xD7FCFC2BFCB332CE,
0xD2BABA68BAB9BB01, 0xB56A6ADF6A77610B, 0x5BDFDF84DFB6F827, 0x0802020A02100C0E,
0x469F9FD99F8C65FA, 0x57DCDC8BDCAEF22E, 0x5951510851B2FBAA, 0x7959592059F2CB92,
0x354A4A7F4A6AA1EB, 0x5C17174B17B87265, 0xAC2B2B872B45FAD1, 0x2FC2C2EDC25EB674,
0x6A9494FE94D45FCB, 0xF7F4F403F4F302F6, 0xD6BBBB6DBBB1BD06, 0xB6A3A315A371ED4E,
0x956262F762375133, 0xB7E4E453E4736286, 0xD97171A871AF3B4A, 0x77D4D4A3D4EEC216,
0x13CDCDDECD269459, 0xDD7070AD70A73D4D, 0x5816164E16B07462, 0xA3E1E142E15B7C9D,
0x394949704972ABE2, 0xF03C3CCC3CFD88B4, 0x27C0C0E7C04EBA7A, 0x47D8D89FD88EEA32,
0x6D5C5C315CDAD589, 0x569B9BCD9BAC7DE6, 0x8EADAD23AD01C964, 0x2E8585AB855C39BC,
0x5153530253A2F7A4, 0xBEA1A11FA161E140, 0xF57A7A8F7AF7017B, 0x07C8C8CFC80E8A42,
0xB42D2D992D75EEC3, 0xA7E0E047E0537A9A, 0x63D1D1B2D1C6DC0D, 0xD57272A772B73143,
0xA2A6A604A659F355, 0xB02C2C9C2C7DE8C4, 0x37C4C4F3C46EA266, 0xABE3E348E34B7093,
0xC57676B37697295F, 0xFD78788578E70D75, 0xE6B7B751B7D19522, 0xEAB4B45EB4C99F2B,
0x2409092D0948363F, 0xEC3B3BD73BC59AA1, 0x380E0E360E70242A, 0x1941415841329BDA,
0x2D4C4C614C5AB5F9, 0x5FDEDE81DEBEFE20, 0xF2B2B240B2F98B39, 0x7A9090EA90F447D7,
0x942525B12535DEFB, 0xAEA5A50BA541F95C, 0x7BD7D7ACD7F6C81F, 0x0C03030F03180A09,
0x4411115511886677, 0x0000000000000000, 0x2BC3C3E8C356B073, 0xB82E2E962E6DE4CA,
0x729292E092E44BD9, 0x9BEFEF74EF2B58B7, 0x254E4E6B4E4AB9F7, 0x4812125A12906C7E,
0x4E9D9DD39D9C69F4, 0xE97D7D947DCF136E, 0x0BCBCBC0CB16804B, 0xD43535E135B5BE8B,
0x4010105010806070, 0x73D5D5A6D5E6C411, 0x214F4F6E4F42BFF0, 0x429E9EDC9E8463FD,
0x294D4D644D52B3FE, 0x9EA9A937A921D178, 0x4955551C5592E3B6, 0x3FC6C6F9C67EAE68,
0x67D0D0B7D0CEDA0A, 0xF17B7B8A7BFF077C, 0x6018187818C05048, 0x669797F197CC55C2,
0x6BD3D3B8D3D6D003, 0xD83636EE36ADB482, 0xBFE6E659E6636E88, 0x3D484875487AADE5,
0x45565613568AE9BF, 0x3E8181BF817C21A0, 0x068F8F898F0C058A, 0xC17777B6779F2F58,
0x17CCCCDBCC2E925E, 0x4A9C9CD69C946FF3, 0xDEB9B967B9A1B108, 0xAFE2E24DE2437694,
0x8AACAC26AC09CF63, 0xDAB8B862B8A9B70F, 0xBC2F2F932F65E2CD, 0x5415154115A87E6B,
0xAAA4A40EA449FF5B, 0xED7C7C917CC71569, 0x4FDADA95DA9EE63C, 0xE03838D838DD90A8,
0x781E1E661EF0445A, 0x2C0B0B270B583A31, 0x1405051105281E1B, 0x7FD6D6A9D6FECE18,
0x5014144414A0786C, 0xA56E6ECB6E577917, 0xAD6C6CC16C477519, 0xE57E7E9B7ED71967,
0x856666E36617492F, 0xD3FDFD2EFDBB34C9, 0xFEB1B14FB1E18130, 0xB3E5E556E57B6481,
0x9D6060FD60275D3D, 0x86AFAF29AF11C56A, 0x655E5E3B5ECAD987, 0xCC3333FF3385AA99,
0x268787A1874C35B2, 0x03C9C9CAC9068C45, 0xE7F0F017F0D31AEA, 0x695D5D345DD2D38E,
0xA96D6DC46D4F731E, 0xFC3F3FC33FE582BD, 0x1A8888928834179F, 0x0E8D8D838D1C0984,
0x3BC7C7FCC776A86F, 0xFBF7F70CF7EB08FF, 0x741D1D691DE84E53, 0x83E9E96AE91B4CA5,
0x97ECEC7BEC3352BE, 0x93EDED7EED3B54B9, 0x3A8080BA807427A7, 0xA429298D2955F6DF,
0x9C2727BB2725D2F5, 0x1BCFCFD4CF369857, 0x5E9999C799BC71E8, 0x9AA8A832A829D77F,
0x5D50500D50BAFDAD, 0x3C0F0F330F78222D, 0xDC3737EB37A5B285, 0x902424B4243DD8FC,
0xA0282888285DF0D8, 0xC03030F0309DA090, 0x6E9595FB95DC59CC, 0x6FD2D2BDD2DED604,
0xF83E3EC63EED84BA, 0x715B5B2A5BE2C79C, 0x1D40405D403A9DDD, 0x368383B5836C2DAE,
0xF6B3B345B3F18D3E, 0xB96969D0696F6B02, 0x415757165782EFB8, 0x7C1F1F631FF8425D,
0x1C07071B07381215, 0x701C1C6C1CE04854, 0x128A8A988A241B91, 0xCABCBC76BC89AF13,
0x802020A0201DC0E0, 0x8BEBEB60EB0B40AB, 0x1FCECED1CE3E9E50, 0x028E8E8C8E04038D,
0x96ABAB3DAB31DD76, 0x9FEEEE71EE235EB0, 0xC43131F53195A697, 0xB2A2A210A279EB49,
0xD17373A273BF3744, 0xC3F9F93AF99B2CD5, 0x0FCACAC5CA1E864C, 0xE83A3AD23ACD9CA6,
0x681A1A721AD05C46, 0xCBFBFB30FB8B20DB, 0x340D0D390D682E23, 0x23C1C1E2C146BC7D,
0xDFFEFE21FEA33EC0, 0xCFFAFA35FA8326DC, 0xEFF2F21DF2C316E4, 0xA16F6FCE6F5F7F10,
0xCEBDBD73BD81A914, 0x629696F496C453C5, 0x53DDDD8EDDA6F429, 0x11434352432297D4,
0x5552520752AAF1A3, 0xE2B6B654B6D99325, 0x2008082808403038, 0xEBF3F318F3CB10E3,
0x82AEAE2CAE19C36D, 0xC2BEBE7CBE99A31D, 0x6419197D19C8564F, 0x1E898997893C1198,
0xC83232FA328DAC9E, 0x982626BE262DD4F2, 0xFAB0B04AB0E98737, 0x8FEAEA65EA0346AC,
0x314B4B7A4B62A7EC, 0x8D6464E964074521, 0x2A8484AE84543FBB, 0x328282B082642BA9,
0xB16B6BDA6B7F670C, 0xF3F5F506F5FB04F1, 0xF979798079EF0B72, 0xC6BFBF79BF91A51A,
0x0401010501080607, 0x615F5F3E5FC2DF80, 0xC97575BC758F2356, 0x916363F2633F5734,
0x6C1B1B771BD85A41, 0x8C2323AF2305CAE9, 0xF43D3DC93DF58EB3, 0xBD6868D568676D05,
0xA82A2A822A4DFCD6, 0x896565EC650F4326, 0x87E8E86FE8134AA2, 0x7E9191EF91FC41D0,
0xFFF6F609F6E30EF8, 0xDBFFFF24FFAB38C7, 0x4C13135F13986A79, 0x7D58582558FACD95,
0xE3F1F112F1DB1CED, 0x0147474647028FC8, 0x280A0A220A503C36, 0xE17F7F9E7FDF1F60,
0x33C5C5F6C566A461, 0xA6A7A701A751F552, 0xBBE7E75CE76B688F, 0x996161F8612F5B3A,
0x755A5A2F5AEAC19B, 0x1806061E06301412, 0x05464643460A89CF, 0x0D444449441A85C1,
0x15424257422A91D3, 0x100404140420181C, 0xBAA0A01AA069E747, 0x4BDBDB90DB96E03B,
0xE43939DD39D596AF, 0x228686A4864433B5, 0x4D545419549AE5B1, 0x92AAAA38AA39DB71,
0x0A8C8C868C140F83, 0xD03434E434BDB88C, 0x842121A52115C6E7, 0x168B8B9D8B2C1D96,
0xC7F8F83FF8932AD2, 0x300C0C3C0C602824, 0xCD7474B974872551, 0x816767E6671F4F28,
];
#[cfg(not(feature = "small-tables"))]
#[rustfmt::skip]
#[allow(clippy::unreadable_literal)] const T7: [u64; 256] = [
0x6868D568676D05BD, 0x8D8D838D1C09840E, 0xCACAC5CA1E864C0F, 0x4D4D644D52B3FE29,
0x7373A273BF3744D1, 0x4B4B7A4B62A7EC31, 0x4E4E6B4E4AB9F725, 0x2A2A822A4DFCD6A8,
0xD4D4A3D4EEC21677, 0x52520752AAF1A355, 0x2626BE262DD4F298, 0xB3B345B3F18D3EF6,
0x545419549AE5B14D, 0x1E1E661EF0445A78, 0x19197D19C8564F64, 0x1F1F631FF8425D7C,
0x2222AA220DCCEE88, 0x03030F03180A090C, 0x464643460A89CF05, 0x3D3DC93DF58EB3F4,
0x2D2D992D75EEC3B4, 0x4A4A7F4A6AA1EB35, 0x53530253A2F7A451, 0x8383B5836C2DAE36,
0x13135F13986A794C, 0x8A8A988A241B9112, 0xB7B751B7D19522E6, 0xD5D5A6D5E6C41173,
0x2525B12535DEFB94, 0x79798079EF0B72F9, 0xF5F506F5FB04F1F3, 0xBDBD73BD81A914CE,
0x58582558FACD957D, 0x2F2F932F65E2CDBC, 0x0D0D390D682E2334, 0x02020A02100C0E08,
0xEDED7EED3B54B993, 0x51510851B2FBAA59, 0x9E9EDC9E8463FD42, 0x1111551188667744,
0xF2F21DF2C316E4EF, 0x3E3EC63EED84BAF8, 0x55551C5592E3B649, 0x5E5E3B5ECAD98765,
0xD1D1B2D1C6DC0D63, 0x16164E16B0746258, 0x3C3CCC3CFD88B4F0, 0x6666E36617492F85,
0x7070AD70A73D4DDD, 0x5D5D345DD2D38E69, 0xF3F318F3CB10E3EB, 0x45454C451283C609,
0x40405D403A9DDD1D, 0xCCCCDBCC2E925E17, 0xE8E86FE8134AA287, 0x9494FE94D45FCB6A,
0x565613568AE9BF45, 0x0808280840303820, 0xCECED1CE3E9E501F, 0x1A1A721AD05C4668,
0x3A3AD23ACD9CA6E8, 0xD2D2BDD2DED6046F, 0xE1E142E15B7C9DA3, 0xDFDF84DFB6F8275B,
0xB5B55BB5C1992CEE, 0x3838D838DD90A8E0, 0x6E6ECB6E577917A5, 0x0E0E360E70242A38,
0xE5E556E57B6481B3, 0xF4F403F4F302F6F7, 0xF9F93AF99B2CD5C3, 0x8686A4864433B522,
0xE9E96AE91B4CA583, 0x4F4F6E4F42BFF021, 0xD6D6A9D6FECE187F, 0x8585AB855C39BC2E,
0x2323AF2305CAE98C, 0xCFCFD4CF3698571B, 0x3232FA328DAC9EC8, 0x9999C799BC71E85E,
0x3131F53195A697C4, 0x14144414A0786C50, 0xAEAE2CAE19C36D82, 0xEEEE71EE235EB09F,
0xC8C8CFC80E8A4207, 0x484875487AADE53D, 0xD3D3B8D3D6D0036B, 0x3030F0309DA090C0,
0xA1A11FA161E140BE, 0x9292E092E44BD972, 0x41415841329BDA19, 0xB1B14FB1E18130FE,
0x18187818C0504860, 0xC4C4F3C46EA26637, 0x2C2C9C2C7DE8C4B0, 0x7171A871AF3B4AD9,
0x7272A772B73143D5, 0x444449441A85C10D, 0x15154115A87E6B54, 0xFDFD2EFDBB34C9D3,
0x3737EB37A5B285DC, 0xBEBE7CBE99A31DC2, 0x5F5F3E5FC2DF8061, 0xAAAA38AA39DB7192,
0x9B9BCD9BAC7DE656, 0x8888928834179F1A, 0xD8D89FD88EEA3247, 0xABAB3DAB31DD7696,
0x898997893C11981E, 0x9C9CD69C946FF34A, 0xFAFA35FA8326DCCF, 0x6060FD60275D3D9D,
0xEAEA65EA0346AC8F, 0xBCBC76BC89AF13CA, 0x6262F76237513395, 0x0C0C3C0C60282430,
0x2424B4243DD8FC90, 0xA6A604A659F355A2, 0xA8A832A829D77F9A, 0xECEC7BEC3352BE97,
0x6767E6671F4F2881, 0x2020A0201DC0E080, 0xDBDB90DB96E03B4B, 0x7C7C917CC71569ED,
0x282888285DF0D8A0, 0xDDDD8EDDA6F42953, 0xACAC26AC09CF638A, 0x5B5B2A5BE2C79C71,
0x3434E434BDB88CD0, 0x7E7E9B7ED71967E5, 0x1010501080607040, 0xF1F112F1DB1CEDE3,
0x7B7B8A7BFF077CF1, 0x8F8F898F0C058A06, 0x6363F2633F573491, 0xA0A01AA069E747BA,
0x05051105281E1B14, 0x9A9AC89AA47BE152, 0x434352432297D411, 0x7777B6779F2F58C1,
0x2121A52115C6E784, 0xBFBF79BF91A51AC6, 0x2727BB2725D2F59C, 0x09092D0948363F24,
0xC3C3E8C356B0732B, 0x9F9FD99F8C65FA46, 0xB6B654B6D99325E2, 0xD7D7ACD7F6C81F7B,
0x29298D2955F6DFA4, 0xC2C2EDC25EB6742F, 0xEBEB60EB0B40AB8B, 0xC0C0E7C04EBA7A27,
0xA4A40EA449FF5BAA, 0x8B8B9D8B2C1D9616, 0x8C8C868C140F830A, 0x1D1D691DE84E5374,
0xFBFB30FB8B20DBCB, 0xFFFF24FFAB38C7DB, 0xC1C1E2C146BC7D23, 0xB2B240B2F98B39F2,
0x9797F197CC55C266, 0x2E2E962E6DE4CAB8, 0xF8F83FF8932AD2C7, 0x6565EC650F432689,
0xF6F609F6E30EF8FF, 0x7575BC758F2356C9, 0x07071B073812151C, 0x0404140420181C10,
0x4949704972ABE239, 0x3333FF3385AA99CC, 0xE4E453E4736286B7, 0xD9D99AD986EC3543,
0xB9B967B9A1B108DE, 0xD0D0B7D0CEDA0A67, 0x424257422A91D315, 0xC7C7FCC776A86F3B,
0x6C6CC16C477519AD, 0x9090EA90F447D77A, 0x0000000000000000, 0x8E8E8C8E04038D02,
0x6F6FCE6F5F7F10A1, 0x50500D50BAFDAD5D, 0x0101050108060704, 0xC5C5F6C566A46133,
0xDADA95DA9EE63C4F, 0x47474647028FC801, 0x3F3FC33FE582BDFC, 0xCDCDDECD26945913,
0x6969D0696F6B02B9, 0xA2A210A279EB49B2, 0xE2E24DE2437694AF, 0x7A7A8F7AF7017BF5,
0xA7A701A751F552A6, 0xC6C6F9C67EAE683F, 0x9393E593EC4DDE76, 0x0F0F330F78222D3C,
0x0A0A220A503C3628, 0x06061E0630141218, 0xE6E659E6636E88BF, 0x2B2B872B45FAD1AC,
0x9696F496C453C562, 0xA3A315A371ED4EB6, 0x1C1C6C1CE0485470, 0xAFAF29AF11C56A86,
0x6A6ADF6A77610BB5, 0x12125A12906C7E48, 0x8484AE84543FBB2A, 0x3939DD39D596AFE4,
0xE7E75CE76B688FBB, 0xB0B04AB0E98737FA, 0x8282B082642BA932, 0xF7F70CF7EB08FFFB,
0xFEFE21FEA33EC0DF, 0x9D9DD39D9C69F44E, 0x8787A1874C35B226, 0x5C5C315CDAD5896D,
0x8181BF817C21A03E, 0x3535E135B5BE8BD4, 0xDEDE81DEBEFE205F, 0xB4B45EB4C99F2BEA,
0xA5A50BA541F95CAE, 0xFCFC2BFCB332CED7, 0x8080BA807427A73A, 0xEFEF74EF2B58B79B,
0xCBCBC0CB16804B0B, 0xBBBB6DBBB1BD06D6, 0x6B6BDA6B7F670CB1, 0x7676B37697295FC5,
0xBABA68BAB9BB01D2, 0x5A5A2F5AEAC19B75, 0x7D7D947DCF136EE9, 0x78788578E70D75FD,
0x0B0B270B583A312C, 0x9595FB95DC59CC6E, 0xE3E348E34B7093AB, 0xADAD23AD01C9648E,
0x7474B974872551CD, 0x9898C298B477EF5A, 0x3B3BD73BC59AA1EC, 0x3636EE36ADB482D8,
0x6464E9640745218D, 0x6D6DC46D4F731EA9, 0xDCDC8BDCAEF22E57, 0xF0F017F0D31AEAE7,
0x59592059F2CB9279, 0xA9A937A921D1789E, 0x4C4C614C5AB5F92D, 0x17174B17B872655C,
0x7F7F9E7FDF1F60E1, 0x9191EF91FC41D07E, 0xB8B862B8A9B70FDA, 0xC9C9CAC9068C4503,
0x5757165782EFB841, 0x1B1B771BD85A416C, 0xE0E047E0537A9AA7, 0x6161F8612F5B3A99,
];
fn mul_alpha(w: u64) -> u64 {
(w << 8) ^ MUL_ALPHA[(w >> 56) as usize]
}
fn mul_alpha_inv(w: u64) -> u64 {
(w >> 8) ^ MUL_ALPHA_INV[(w & 0xff) as usize]
}
#[cfg(not(feature = "small-tables"))]
fn t_function(w: u64) -> u64 {
T0[(w & 0xff) as usize]
^ T1[((w >> 8) & 0xff) as usize]
^ T2[((w >> 16) & 0xff) as usize]
^ T3[((w >> 24) & 0xff) as usize]
^ T4[((w >> 32) & 0xff) as usize]
^ T5[((w >> 40) & 0xff) as usize]
^ T6[((w >> 48) & 0xff) as usize]
^ T7[((w >> 56) & 0xff) as usize]
}
#[cfg(feature = "small-tables")]
fn t_function(w: u64) -> u64 {
let mut column = w.to_le_bytes();
for (row, byte) in column.iter_mut().enumerate() {
*byte = super::tables::SBOXES[row % 4][*byte as usize];
}
super::tables::apply_forward_matrix(core::slice::from_mut(&mut column));
u64::from_le_bytes(column)
}
fn fsm(x: u64, y: u64, z: u64) -> u64 {
x.wrapping_add(y) ^ z
}
fn word_le(bytes: &[u8], index: usize) -> u64 {
let start = index * 8;
let mut word = [0u8; 8];
word.copy_from_slice(&bytes[start..start + 8]);
u64::from_le_bytes(word)
}
fn init_state(key: &[u8], iv: &[u8; 32]) -> [u64; 16] {
let ivw = |i: usize| word_le(iv, i);
let kw = |i: usize| word_le(key, i);
let mut s = [0u64; 16];
if key.len() == 32 {
s[0] = kw(3) ^ ivw(0);
s[1] = kw(2);
s[2] = kw(1) ^ ivw(1);
s[3] = kw(0) ^ ivw(2);
s[4] = kw(3);
s[5] = kw(2) ^ ivw(3);
s[6] = !kw(1);
s[7] = !kw(0);
s[8] = kw(3);
s[9] = kw(2);
s[10] = !kw(1);
s[11] = kw(0);
s[12] = kw(3);
s[13] = !kw(2);
s[14] = kw(1);
s[15] = !kw(0);
} else {
s[0] = kw(7) ^ ivw(0);
s[1] = kw(6);
s[2] = kw(5);
s[3] = kw(4) ^ ivw(1);
s[4] = kw(3);
s[5] = kw(2) ^ ivw(2);
s[6] = kw(1);
s[7] = !kw(0);
s[8] = kw(4) ^ ivw(3);
s[9] = !kw(6);
s[10] = kw(5);
s[11] = !kw(7);
s[12] = kw(3);
s[13] = kw(2);
s[14] = !kw(1);
s[15] = kw(0);
}
s
}
fn next_step(s: &mut [u64; 16], head: &mut usize, r0: &mut u64, r1: &mut u64, init_mode: bool) {
let s0 = s[*head];
let s11 = s[(*head + 11) & 15];
let s13 = s[(*head + 13) & 15];
let s15 = s[(*head + 15) & 15];
let new_r1 = t_function(*r0);
let new_r0 = r1.wrapping_add(s13);
let mut feedback = mul_alpha(s0) ^ mul_alpha_inv(s11) ^ s13;
if init_mode {
feedback ^= fsm(s15, *r0, *r1);
}
s[*head] = feedback;
*head = (*head + 1) & 15;
*r0 = new_r0;
*r1 = new_r1;
}
fn strm(s: &[u64; 16], head: usize, r0: u64, r1: u64) -> u64 {
fsm(s[(head + 15) & 15], r0, r1) ^ s[head]
}
fn next_block(s: &mut [u64; 16], r0: &mut u64, r1: &mut u64, input: &[u64; 16]) -> [u64; 16] {
let mut out = [0u64; 16];
macro_rules! step {
($k:expr, $prev:expr, $p11:expr, $p13:expr) => {{
let sk = s[$k];
out[$k] = input[$k] ^ fsm(s[$prev], *r0, *r1) ^ sk;
let new_r1 = t_function(*r0);
let new_r0 = r1.wrapping_add(s[$p13]);
let feedback = mul_alpha(sk) ^ mul_alpha_inv(s[$p11]) ^ s[$p13];
s[$k] = feedback;
*r0 = new_r0;
*r1 = new_r1;
}};
}
step!(0, 15, 11, 13);
step!(1, 0, 12, 14);
step!(2, 1, 13, 15);
step!(3, 2, 14, 0);
step!(4, 3, 15, 1);
step!(5, 4, 0, 2);
step!(6, 5, 1, 3);
step!(7, 6, 2, 4);
step!(8, 7, 3, 5);
step!(9, 8, 4, 6);
step!(10, 9, 5, 7);
step!(11, 10, 6, 8);
step!(12, 11, 7, 9);
step!(13, 12, 8, 10);
step!(14, 13, 9, 11);
step!(15, 14, 10, 12);
out
}
#[derive(Zeroize, ZeroizeOnDrop)]
struct Core {
s: [u64; 16],
head: usize,
r0: u64,
r1: u64,
block: [u8; 8],
block_pos: usize,
}
impl Core {
fn new(key: &[u8], iv: &[u8; 32]) -> Self {
let mut s = init_state(key, iv);
let mut head = 0usize;
let (mut r0, mut r1) = (0u64, 0u64);
for _ in 0..32 {
next_step(&mut s, &mut head, &mut r0, &mut r1, true);
}
next_step(&mut s, &mut head, &mut r0, &mut r1, false);
Self {
s,
head,
r0,
r1,
block: [0u8; 8],
block_pos: 8,
}
}
fn apply_keystream(&mut self, data: &mut [u8]) {
let pos = self.drain(data, 0);
let pos = self.bulk(data, pos);
self.remainder(data, pos);
}
fn drain(&mut self, data: &mut [u8], mut pos: usize) -> usize {
while pos < data.len() && self.block_pos < 8 {
data[pos] ^= self.block[self.block_pos];
self.block_pos += 1;
pos += 1;
}
pos
}
fn bulk(&mut self, data: &mut [u8], mut pos: usize) -> usize {
if self.block_pos != 8 || data.len() - pos < 128 {
return pos;
}
if self.head != 0 {
self.s.rotate_left(self.head);
self.head = 0;
}
while data.len() - pos >= 128 {
let mut input = [0u64; 16];
for (word, chunk) in input.iter_mut().zip(data[pos..pos + 128].chunks_exact(8)) {
let mut bytes = [0u8; 8];
bytes.copy_from_slice(chunk);
*word = u64::from_le_bytes(bytes);
}
let out = next_block(&mut self.s, &mut self.r0, &mut self.r1, &input);
for (chunk, word) in data[pos..pos + 128].chunks_exact_mut(8).zip(out.iter()) {
chunk.copy_from_slice(&word.to_le_bytes());
}
pos += 128;
}
pos
}
fn remainder(&mut self, data: &mut [u8], mut pos: usize) {
while pos < data.len() {
if self.block_pos == 8 {
let z = strm(&self.s, self.head, self.r0, self.r1);
self.block = z.to_le_bytes();
next_step(
&mut self.s,
&mut self.head,
&mut self.r0,
&mut self.r1,
false,
);
self.block_pos = 0;
}
data[pos] ^= self.block[self.block_pos];
self.block_pos += 1;
pos += 1;
}
}
}
macro_rules! strumok_variant {
($name:ident, $key_bytes:literal) => {
#[doc = concat!(stringify!($key_bytes), "-byte key, 32-byte IV.")]
pub struct $name(Core);
impl $name {
#[must_use]
pub fn new(key: &[u8; $key_bytes], iv: &[u8; 32]) -> Self {
Self(Core::new(key, iv))
}
pub fn apply_keystream(&mut self, data: &mut [u8]) {
self.0.apply_keystream(data);
}
}
};
}
strumok_variant!(Strumok256, 32);
strumok_variant!(Strumok512, 64);
#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;
fn scalar_reference_apply_keystream(core: &mut Core, data: &mut [u8]) {
for byte in data {
if core.block_pos == 8 {
let z = strm(&core.s, core.head, core.r0, core.r1);
core.block = z.to_le_bytes();
next_step(
&mut core.s,
&mut core.head,
&mut core.r0,
&mut core.r1,
false,
);
core.block_pos = 0;
}
*byte ^= core.block[core.block_pos];
core.block_pos += 1;
}
}
fn apply_chunked(
core: &mut Core,
data: &mut [u8],
chunk_sizes: &[usize],
apply: fn(&mut Core, &mut [u8]),
) {
let len = data.len();
let mut pos = 0;
let mut idx = 0;
while pos < len {
let want = chunk_sizes[idx % chunk_sizes.len()].max(1);
let end = (pos + want).min(len);
apply(core, &mut data[pos..end]);
pos = end;
idx += 1;
}
}
macro_rules! batched_matches_scalar_reference_proptest {
($test_name:ident, $key_len:literal) => {
proptest! {
#[test]
fn $test_name(
key_bytes in prop::collection::vec(any::<u8>(), $key_len),
iv_bytes in prop::collection::vec(any::<u8>(), 32),
data in prop::collection::vec(any::<u8>(), 0..600),
chunk_sizes in prop::collection::vec(1usize..300, 1..20),
) {
let mut iv = [0u8; 32];
iv.copy_from_slice(&iv_bytes);
let mut new_whole = data.clone();
Core::new(&key_bytes, &iv).apply_keystream(&mut new_whole);
let mut new_chunked = data.clone();
apply_chunked(
&mut Core::new(&key_bytes, &iv),
&mut new_chunked,
&chunk_sizes,
Core::apply_keystream,
);
let mut old_whole = data.clone();
scalar_reference_apply_keystream(&mut Core::new(&key_bytes, &iv), &mut old_whole);
prop_assert_eq!(&new_whole, &old_whole);
prop_assert_eq!(&new_chunked, &old_whole);
}
}
};
}
batched_matches_scalar_reference_proptest!(strumok_256_batched_matches_scalar_reference, 32);
batched_matches_scalar_reference_proptest!(strumok_512_batched_matches_scalar_reference, 64);
#[test]
fn boundary_lengths_match_scalar_reference() {
let key = [0x39u8; 32];
let iv = [0x5au8; 32];
for &len in &[127usize, 128, 129, 135, 256, 263] {
let data = vec![0u8; len];
let mut new_out = data.clone();
Core::new(&key, &iv).apply_keystream(&mut new_out);
let mut old_out = data.clone();
scalar_reference_apply_keystream(&mut Core::new(&key, &iv), &mut old_out);
assert_eq!(
new_out, old_out,
"length {len} diverged from scalar reference"
);
}
}
#[test]
fn mid_word_carry_crosses_bulk_boundary_within_one_call() {
let key = [0x71u8; 64];
let iv = [0x2du8; 32];
let total = 261;
let data = vec![0u8; total];
let mut new_out = data.clone();
{
let mut cipher = Core::new(&key, &iv);
cipher.apply_keystream(&mut new_out[0..3]);
cipher.apply_keystream(&mut new_out[3..total]);
}
let mut old_out = data.clone();
scalar_reference_apply_keystream(&mut Core::new(&key, &iv), &mut old_out);
assert_eq!(new_out, old_out);
}
}