Skip to main content

p3_mersenne_31/
poseidon1.rs

1//! Poseidon1 permutation for Mersenne31.
2//!
3//! This module provides the Poseidon1 hash permutation instantiated for the
4//! Mersenne31 field (p = 2^31 - 1). It uses the generic Poseidon1 implementation
5//! with Karatsuba MDS convolution from `MdsMatrixMersenne31`.
6//!
7//! # MDS Matrix
8//!
9//! The MDS matrix is a **circulant** matrix sourced from the MDS crate.
10//! At runtime, it is applied via fast Karatsuba convolution (sub-O(t^2)).
11//! During initialization only, it is expanded to dense form for the
12//! sparse matrix decomposition of partial rounds.
13//!
14//! # Round Constants
15//!
16//! Generated by the Grain LFSR (Poseidon1 paper, Appendix E) with SBOX=0 (x^alpha encoding).
17
18use p3_mds::util::first_row_to_first_col;
19use p3_poseidon1::{
20    Poseidon1, Poseidon1Constants, Poseidon1ExternalLayerGeneric, Poseidon1InternalLayerGeneric,
21};
22
23use crate::mds::{MATRIX_CIRC_MDS_16_SML_ROW, MATRIX_CIRC_MDS_32_MERSENNE31_ROW};
24use crate::{MdsMatrixMersenne31, Mersenne31};
25
26/// S-box degree for Mersenne31 Poseidon1.
27///
28/// Since `p - 1 = 2 * 3^2 * 7 * 11 * 31 * 151 * 331`, both 3 and 4 share factors
29/// with `p - 1`. The smallest valid exponent satisfying `gcd(alpha, p - 1) = 1` is 5.
30pub const MERSENNE31_POSEIDON1_S_BOX_DEGREE: u64 = 5;
31
32/// Number of full rounds per half for Mersenne31 Poseidon1 (`RF / 2`).
33///
34/// The total number of full rounds is `RF = 8` (4 beginning + 4 ending).
35/// Follows the Poseidon1 paper's security analysis (Section 5.4) with a +2 RF margin.
36pub const MERSENNE31_POSEIDON1_HALF_FULL_ROUNDS: usize = 4;
37
38/// Number of partial rounds for Mersenne31 Poseidon1 (width 16).
39///
40/// Derived from the interpolation bound in the Poseidon1 paper (Eq. 3):
41///
42///   R_interp >= ceil(min{kappa, n} / log_2(alpha)) + ceil(log_alpha(t)) - 5
43///            = ceil(31 / log_2(5)) + ceil(log_5(16)) - 5 = 14 + 2 - 5 = 11
44///
45/// With the +7.5% security margin: ceil(1.075 * 11) = 12. After brute-force
46/// optimization over all security constraints: R_P = 14.
47pub const MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_16: usize = 14;
48
49/// Number of partial rounds for Mersenne31 Poseidon1 (width 32).
50///
51/// With the +7.5% security margin and brute-force optimization: R_P = 30.
52pub const MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_32: usize = 30;
53
54/// Generic (non-SIMD) Poseidon1 permutation for Mersenne31.
55///
56/// Uses the platform-independent Poseidon1 implementation with Karatsuba
57/// MDS convolution via `MdsMatrixMersenne31`.
58pub type Poseidon1Mersenne31Generic<const WIDTH: usize> = Poseidon1<
59    Mersenne31,
60    Poseidon1ExternalLayerGeneric<Mersenne31, MdsMatrixMersenne31, WIDTH>,
61    Poseidon1InternalLayerGeneric<Mersenne31, WIDTH>,
62    WIDTH,
63    MERSENNE31_POSEIDON1_S_BOX_DEGREE,
64>;
65
66/// Poseidon1 permutation for Mersenne31.
67///
68/// On aarch64 with NEON, uses NEON-optimized layers with pre-packed round
69/// constants and fused AddRC+S-box. On x86_64 with AVX2/AVX512, uses
70/// negative-form packed constants with fused AddRC+S-box. On other platforms,
71/// falls back to the generic Karatsuba-based implementation.
72#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
73pub type Poseidon1Mersenne31<const WIDTH: usize> = Poseidon1<
74    Mersenne31,
75    crate::Poseidon1ExternalLayerMersenne31<WIDTH>,
76    crate::Poseidon1InternalLayerMersenne31<WIDTH>,
77    WIDTH,
78    MERSENNE31_POSEIDON1_S_BOX_DEGREE,
79>;
80
81/// Poseidon1 permutation for Mersenne31 (AVX2, no AVX512).
82///
83/// Uses AVX2-optimized layers with negative-form packed round constants
84/// and fused AddRC+S-box in full rounds.
85#[cfg(all(
86    target_arch = "x86_64",
87    target_feature = "avx2",
88    not(target_feature = "avx512f")
89))]
90pub type Poseidon1Mersenne31<const WIDTH: usize> = Poseidon1<
91    Mersenne31,
92    crate::Poseidon1ExternalLayerMersenne31<WIDTH>,
93    crate::Poseidon1InternalLayerMersenne31<WIDTH>,
94    WIDTH,
95    MERSENNE31_POSEIDON1_S_BOX_DEGREE,
96>;
97
98/// Poseidon1 permutation for Mersenne31 (AVX512).
99///
100/// Uses AVX512-optimized layers with negative-form packed round constants
101/// and fused AddRC+S-box in full rounds.
102#[cfg(all(target_arch = "x86_64", target_feature = "avx512f"))]
103pub type Poseidon1Mersenne31<const WIDTH: usize> = Poseidon1<
104    Mersenne31,
105    crate::Poseidon1ExternalLayerMersenne31<WIDTH>,
106    crate::Poseidon1InternalLayerMersenne31<WIDTH>,
107    WIDTH,
108    MERSENNE31_POSEIDON1_S_BOX_DEGREE,
109>;
110
111/// Poseidon1 permutation for Mersenne31 (generic fallback).
112///
113/// Used on platforms without NEON or AVX2/AVX512 SIMD support.
114#[cfg(not(any(
115    all(target_arch = "aarch64", target_feature = "neon"),
116    all(target_arch = "x86_64", target_feature = "avx2"),
117)))]
118pub type Poseidon1Mersenne31<const WIDTH: usize> = Poseidon1Mersenne31Generic<WIDTH>;
119
120/// Round constants for width-16 Poseidon1 on Mersenne31.
121///
122/// Generated by the Grain LFSR with parameters:
123///     field_type=1, alpha=5 (exp_flag=0), n=31, t=16, R_F=8, R_P=14
124///
125/// Generated by `poseidon1/generate_constants.py --field mersenne31 --width 16`.
126///
127/// Layout: [initial_full (4 rounds), partial (14 rounds), terminal_full (4 rounds)].
128pub const MERSENNE31_POSEIDON1_RC_16: [[Mersenne31; 16]; 22] = [
129    // Initial full rounds (4)
130    Mersenne31::new_array([
131        0x768bab52, 0x70e0ab7d, 0x3d266c8a, 0x6da42045, 0x600fef22, 0x41dace6b, 0x64f9bdd4,
132        0x5d42d4fe, 0x76b1516d, 0x6fc9a717, 0x70ac4fb6, 0x00194ef6, 0x22b644e2, 0x1f7916d5,
133        0x47581be2, 0x2710a123,
134    ]),
135    Mersenne31::new_array([
136        0x6284e867, 0x018d3afe, 0x5df99ef3, 0x4c1e467b, 0x566f6abc, 0x2994e427, 0x538a6d42,
137        0x5d7bf2cf, 0x7fda2dab, 0x0fd854c4, 0x46922fca, 0x3d7763a1, 0x19fd05ca, 0x0a4bbb43,
138        0x15075851, 0x3d903d76,
139    ]),
140    Mersenne31::new_array([
141        0x2d290ff7, 0x40809fa0, 0x59dac6ec, 0x127927a2, 0x6bbf0ea0, 0x0294140f, 0x24742976,
142        0x6e84c081, 0x22484f4a, 0x354cae59, 0x0453ffe1, 0x3f47a3cc, 0x0088204e, 0x6066e109,
143        0x3b7c4b80, 0x6b55665d,
144    ]),
145    Mersenne31::new_array([
146        0x3bc4b897, 0x735bf378, 0x508daf42, 0x1884fc2b, 0x7214f24c, 0x7498be0a, 0x1a60e640,
147        0x3303f928, 0x29b46376, 0x5c96bb68, 0x65d097a5, 0x1d358e9f, 0x4a9a9017, 0x4724cf76,
148        0x347af70f, 0x1e77e59a,
149    ]),
150    // Partial rounds (14)
151    Mersenne31::new_array([
152        0x7f7ec4bf, 0x0421926f, 0x5198e669, 0x34db3148, 0x4368bafd, 0x66685c7f, 0x78d3249a,
153        0x60187881, 0x76dad67a, 0x0690b437, 0x1ea95311, 0x40e5369a, 0x38f103fc, 0x1d226a21,
154        0x57090613, 0x1fa42108,
155    ]),
156    Mersenne31::new_array([
157        0x17bbef50, 0x1ff7e11c, 0x047b24ca, 0x4e140275, 0x4fa086f5, 0x079b309c, 0x1159bd47,
158        0x6d37e4e5, 0x075d8dce, 0x12121ca0, 0x7f6a7c40, 0x68e182ba, 0x5493201b, 0x0444a80e,
159        0x0064f4c6, 0x6467abe6,
160    ]),
161    Mersenne31::new_array([
162        0x66975762, 0x2af68f9b, 0x345b33be, 0x1b70d47f, 0x053db717, 0x381189cb, 0x43b915f8,
163        0x20df3694, 0x0f459d26, 0x77a0e97b, 0x2f73e739, 0x1876c2f9, 0x65a0e29a, 0x4cabefbe,
164        0x5abd1268, 0x4d34a760,
165    ]),
166    Mersenne31::new_array([
167        0x12771799, 0x69a0c9ac, 0x39091e55, 0x7f611cd0, 0x3af055da, 0x7ac0bbdf, 0x6e0f3a24,
168        0x41e3b6f7, 0x49b3756d, 0x568bc538, 0x20c079d8, 0x1701c72c, 0x7670dc6c, 0x5a439035,
169        0x7c93e00e, 0x561fbb4d,
170    ]),
171    Mersenne31::new_array([
172        0x1178907b, 0x02737406, 0x32fb24f1, 0x6323b60a, 0x6ab12418, 0x42c99cea, 0x155a0b97,
173        0x53d1c6aa, 0x2bd20347, 0x279b3d73, 0x4f5f3c70, 0x0245af6c, 0x238359d3, 0x49966a59,
174        0x16562ccc, 0x28b8e2f1,
175    ]),
176    Mersenne31::new_array([
177        0x13e05a67, 0x0322242d, 0x5c17c375, 0x21483598, 0x60aafd6e, 0x36ae6de2, 0x7b378114,
178        0x1125f304, 0x445e936b, 0x331805a2, 0x530c7914, 0x038a6c74, 0x74709937, 0x110f3a56,
179        0x143782e2, 0x757afe85,
180    ]),
181    Mersenne31::new_array([
182        0x321ef96e, 0x0f01c89f, 0x414f7ca6, 0x1f7e326e, 0x4c2e93a1, 0x1d702f38, 0x65047ac7,
183        0x3a0c195d, 0x76505418, 0x66968e77, 0x0f6ae712, 0x7c69b610, 0x4d9f56d2, 0x590edebb,
184        0x2f4b0c02, 0x2d638e28,
185    ]),
186    Mersenne31::new_array([
187        0x685ffa6a, 0x61c4f2ee, 0x397c8793, 0x0d549671, 0x1932849b, 0x4431b3f9, 0x1756c50c,
188        0x38218ca7, 0x5e920b8e, 0x0bcc93d4, 0x2017c5e7, 0x264215a7, 0x68a3ea92, 0x6e223436,
189        0x10fde933, 0x47d19785,
190    ]),
191    Mersenne31::new_array([
192        0x14a370cd, 0x4b1ddfd2, 0x010c7d87, 0x30b31e31, 0x026f76a1, 0x64e562ab, 0x5d1a25dc,
193        0x6c741add, 0x1a118aef, 0x795c8131, 0x7c110827, 0x0520038f, 0x5639490e, 0x4a2e99a2,
194        0x3bfd1c6e, 0x147c461a,
195    ]),
196    Mersenne31::new_array([
197        0x36a88dde, 0x2f022367, 0x45cadcac, 0x32939ad2, 0x41a68d7f, 0x17ca1ea8, 0x121a017d,
198        0x47b8414a, 0x2690bc86, 0x5938ef7c, 0x53198854, 0x0ca8ec5c, 0x0e884400, 0x67e6fd3c,
199        0x16c70b3e, 0x3c551f9b,
200    ]),
201    Mersenne31::new_array([
202        0x4c87d08b, 0x3b023eee, 0x77ac2ad2, 0x75b61edc, 0x7ae29b6a, 0x03dfd274, 0x487c71c6,
203        0x2c9f97ef, 0x01fa9958, 0x7a78a7ad, 0x78519ebc, 0x1305f5c1, 0x31989bd0, 0x31fd37b1,
204        0x38583a0a, 0x700df43a,
205    ]),
206    Mersenne31::new_array([
207        0x789b76c2, 0x74933d40, 0x13350c4f, 0x01b1296a, 0x6d1d5a1c, 0x06587af5, 0x5565eff3,
208        0x5b88a6cf, 0x0c430736, 0x7fb18ed3, 0x64c94d58, 0x318128fe, 0x392ef65e, 0x71b83429,
209        0x0c0b405f, 0x44db668d,
210    ]),
211    Mersenne31::new_array([
212        0x01062150, 0x39f2226d, 0x589e7dec, 0x29f0d5d5, 0x39951315, 0x3eca8ffb, 0x1c4d5c50,
213        0x2917a937, 0x0272222f, 0x548d46c3, 0x592ce973, 0x6e5cbc04, 0x697576d7, 0x51b9d66c,
214        0x6ac07352, 0x2c4b55a0,
215    ]),
216    Mersenne31::new_array([
217        0x27f6bea4, 0x0c967b2f, 0x4453e8ea, 0x568daace, 0x33fc6e77, 0x1ba012d4, 0x018a97e8,
218        0x1a8c1d4a, 0x1e79576b, 0x62469fcf, 0x37b50300, 0x5ab7c661, 0x2a469759, 0x41682375,
219        0x0b762fef, 0x0a7fc88c,
220    ]),
221    // Terminal full rounds (4)
222    Mersenne31::new_array([
223        0x5c23bb9c, 0x5da64dbf, 0x7a2be1dd, 0x1d33a4d8, 0x484a3f8e, 0x007a706a, 0x57bd9767,
224        0x7149341f, 0x2667ecb6, 0x2db9150f, 0x32004141, 0x45c0728f, 0x62934143, 0x32c19c19,
225        0x29bd378d, 0x5b3d502e,
226    ]),
227    Mersenne31::new_array([
228        0x62cb8455, 0x2b147f51, 0x621d052b, 0x11ba7123, 0x59bb54be, 0x61452bf6, 0x30babf3a,
229        0x215b97f7, 0x07700f00, 0x0dda07b1, 0x2ad97715, 0x2c78402d, 0x6096089e, 0x2465e76f,
230        0x5b490daa, 0x27d6349d,
231    ]),
232    Mersenne31::new_array([
233        0x4e9d8c89, 0x7b36a67d, 0x41a27774, 0x71452a2a, 0x4d2f9d8d, 0x5c199518, 0x4c017e2c,
234        0x344f57b3, 0x70afd1ad, 0x5141ba4f, 0x2fe06654, 0x745d98a8, 0x0311922c, 0x335e3407,
235        0x5bfe6359, 0x74fb36b4,
236    ]),
237    Mersenne31::new_array([
238        0x41a1e898, 0x5f17d56c, 0x30d1c4a2, 0x3380e1bb, 0x413b7490, 0x51ad85e6, 0x1a9760a3,
239        0x3533477a, 0x42d9b6cb, 0x284a99fc, 0x04eb39f8, 0x2f2b33ae, 0x5b21e6b2, 0x4ab941a2,
240        0x16ffcaa1, 0x3f02cbe3,
241    ]),
242];
243
244/// Round constants for width-32 Poseidon1 on Mersenne31.
245///
246/// Generated by the Grain LFSR with parameters:
247///     field_type=1, alpha=5 (exp_flag=0), n=31, t=32, R_F=8, R_P=30
248///
249/// Generated by `poseidon1/generate_constants.py --field mersenne31 --width 32`.
250///
251/// Layout: [initial_full (4 rounds), partial (30 rounds), terminal_full (4 rounds)].
252#[rustfmt::skip]
253pub const MERSENNE31_POSEIDON1_RC_32: [[Mersenne31; 32]; 38] = [
254    // Initial full rounds (4)
255    Mersenne31::new_array([
256        0x6710e381, 0x01ab3dad, 0x49bdc51f, 0x41c98c65, 0x23885d8a, 0x24ea7d7c, 0x6b65fc6d, 0x6106615a,
257        0x084957f3, 0x157c3634, 0x4dada10f, 0x6cdfa46d, 0x1bf208be, 0x5bd22fac, 0x79da8fdb, 0x78ebc8ed,
258        0x4c8bcbdf, 0x27f79490, 0x70495412, 0x2a41844e, 0x51bb69f1, 0x3215dc21, 0x67114819, 0x27aa6a09,
259        0x5f4d3cad, 0x5fd6c724, 0x1b4c108d, 0x7ebd949d, 0x5799d04d, 0x568c212f, 0x680821db, 0x62073729,
260    ]),
261    Mersenne31::new_array([
262        0x229ee780, 0x3b4f94c3, 0x17a3ac54, 0x6c388279, 0x4876fe55, 0x3170f20a, 0x33703e4e, 0x03980ab1,
263        0x012fb0fa, 0x145ee8db, 0x49815b30, 0x46ad879c, 0x52bc503d, 0x586530d7, 0x5c36f9e5, 0x028e6503,
264        0x08310368, 0x75546646, 0x732516f1, 0x33483e5a, 0x04a0842c, 0x1a3135d9, 0x537b2eb1, 0x5baf4f77,
265        0x4b78cd6d, 0x5aed2c4a, 0x66c893e1, 0x3c5493a6, 0x46c62bfc, 0x564e591a, 0x52ded7a7, 0x00d1032d,
266    ]),
267    Mersenne31::new_array([
268        0x2b30d801, 0x101dabf7, 0x2efb21cd, 0x4a361c39, 0x49eff572, 0x2e13caf4, 0x016e6799, 0x1b5cdb44,
269        0x17ca2dc6, 0x0e500ee0, 0x0141ca9b, 0x279b2376, 0x6647c40b, 0x0dcaee3c, 0x16e7fcf9, 0x59e6d65c,
270        0x1eb730c9, 0x7ebf0417, 0x28607848, 0x45727f9c, 0x4e543ffb, 0x03ee2550, 0x010cd54b, 0x7b1a1050,
271        0x02dc4b76, 0x2b3a9a3c, 0x2eabb2d9, 0x06928553, 0x2d23b3f5, 0x6da322b1, 0x1527ec07, 0x0e450b7a,
272    ]),
273    Mersenne31::new_array([
274        0x53961612, 0x20f16b10, 0x16f00c60, 0x4c39d50f, 0x41d59d76, 0x5253f822, 0x3b53d381, 0x1b7f470a,
275        0x5e3d895c, 0x52658125, 0x012190d3, 0x65563b80, 0x1d0faa47, 0x3575b3c9, 0x4c0d9d20, 0x18cff09f,
276        0x64a7da5c, 0x2f140b25, 0x139f9e31, 0x66e36bd5, 0x6442c811, 0x58879bce, 0x5fcc87c6, 0x6807ae0c,
277        0x4111c657, 0x633c8929, 0x74962971, 0x3fc18eb8, 0x456cf288, 0x31f6c8d2, 0x6c3a31a8, 0x6d82df50,
278    ]),
279    // Partial rounds (30)
280    Mersenne31::new_array([
281        0x3d432793, 0x4195a297, 0x7fcf576b, 0x6bce9b95, 0x3c822af0, 0x7629e5b3, 0x3dddd04e, 0x5a3d0558,
282        0x763e6c75, 0x676f1d88, 0x77b82255, 0x25df8a51, 0x697c3b10, 0x03cf6edf, 0x12b54f78, 0x6633d534,
283        0x426fbcb7, 0x554665dc, 0x5689bdb2, 0x12e747de, 0x60c28745, 0x11ca4ba5, 0x7c7c7b7a, 0x3f0f9583,
284        0x7a3c8210, 0x56c7d993, 0x20f6875f, 0x69e597c8, 0x3c911573, 0x29c7f702, 0x7818a8d3, 0x1a58e115,
285    ]),
286    Mersenne31::new_array([
287        0x29113198, 0x776b289f, 0x1e922ee2, 0x2165fbf0, 0x28ccaf78, 0x1983287d, 0x492b22e0, 0x77cc4657,
288        0x39005c27, 0x48cd8089, 0x267cfcbb, 0x1c41ca85, 0x41b3943f, 0x20e7727a, 0x64ad78f3, 0x13dd4413,
289        0x1042e3dc, 0x74adeb2c, 0x2dcdd3c7, 0x06006fbc, 0x35a609e9, 0x0daf273c, 0x3a4f694f, 0x7a992693,
290        0x59fd101d, 0x27d2112b, 0x1937b69f, 0x2e8880bc, 0x40c12429, 0x067965a6, 0x6ea1b36d, 0x6e01476e,
291    ]),
292    Mersenne31::new_array([
293        0x29cd718a, 0x5406c693, 0x51de2e9a, 0x6ddc388a, 0x53763473, 0x7fbd6bda, 0x17a25cbf, 0x1f2982cd,
294        0x7af8156c, 0x19ca5afd, 0x2d703c93, 0x0c2840e4, 0x2cda82cd, 0x5c7f51e0, 0x1db58806, 0x3cb62bd1,
295        0x2b45461b, 0x6204ba50, 0x7bcdbe79, 0x6857f0bc, 0x4af2a368, 0x32c146f4, 0x1acfdd93, 0x2dc39570,
296        0x0dbdeb4e, 0x50bef84d, 0x6f83a22c, 0x434c3741, 0x2060e160, 0x68f58f0b, 0x2529b2bd, 0x112c4768,
297    ]),
298    Mersenne31::new_array([
299        0x70409ce2, 0x1b57460e, 0x21dc818c, 0x5f6b5330, 0x443f8fba, 0x211a90de, 0x591d4a30, 0x5b5a3e75,
300        0x635c333a, 0x1efd6a70, 0x5d35445f, 0x5637cf22, 0x6e9ba8b1, 0x10b54e2c, 0x04291eb8, 0x2d4ea543,
301        0x720a5c61, 0x1a5b6323, 0x68e176e7, 0x26149775, 0x58f30beb, 0x450402ab, 0x24928255, 0x32c59955,
302        0x2b5b7261, 0x6279779f, 0x599b6a8e, 0x70d145d3, 0x3786c4d1, 0x11363460, 0x22ff2181, 0x4d06fc50,
303    ]),
304    Mersenne31::new_array([
305        0x27a8a3df, 0x647df984, 0x3a748cc3, 0x4aa91ea2, 0x21ead2a1, 0x50cd5d8d, 0x06d6ffc6, 0x5bc51117,
306        0x45f848bc, 0x12c3d5f1, 0x487f9065, 0x1617243c, 0x5c8774e4, 0x76bcd3ec, 0x783819d0, 0x349c8a4b,
307        0x265d6a36, 0x39fc652e, 0x246831a8, 0x488058fc, 0x0a5c75d6, 0x760d4eed, 0x7acd5d5f, 0x2d2957ad,
308        0x6188b6fe, 0x2084c575, 0x67c5ff60, 0x3d6d899b, 0x2759464a, 0x1e4319d2, 0x09fef836, 0x305660e4,
309    ]),
310    Mersenne31::new_array([
311        0x2437e398, 0x698e8bad, 0x51a1c08a, 0x6f6b42ea, 0x4e7a622c, 0x3359b875, 0x6fc9bf1d, 0x349ecd95,
312        0x402affed, 0x0e7d1f4a, 0x7568ff95, 0x6d26f65b, 0x527b8ff5, 0x13e3a821, 0x76f0683c, 0x7c6b5a3e,
313        0x1ba8baa6, 0x7bf0c2eb, 0x609df788, 0x512ac703, 0x64950065, 0x5e53895a, 0x74b59dea, 0x4a663191,
314        0x1c09524b, 0x30b5b604, 0x13196a5f, 0x787c00d7, 0x3c56db18, 0x7ec1baf0, 0x7f760f44, 0x3a5a1de6,
315    ]),
316    Mersenne31::new_array([
317        0x1b91c3fa, 0x66f3100f, 0x4153c359, 0x0e098a72, 0x1f4abc43, 0x4c8f6c3d, 0x7eff304b, 0x15c1c8dd,
318        0x0ac43795, 0x19e87ea1, 0x535bed09, 0x2466eef0, 0x2cce459b, 0x663b3da6, 0x7b6e46b3, 0x2daa3590,
319        0x302394b0, 0x0de56e75, 0x6fa06cd4, 0x1e0712cc, 0x55801c2d, 0x05fa4531, 0x30746c53, 0x1363fc86,
320        0x17019f68, 0x113e6a01, 0x7dc8674c, 0x713867f4, 0x46dc2aab, 0x073679be, 0x18b9ced4, 0x484bca9e,
321    ]),
322    Mersenne31::new_array([
323        0x39cf2be3, 0x66ae2f79, 0x10d0ae15, 0x6ff9de20, 0x64733e7b, 0x01d7c954, 0x3da5afe0, 0x1a324fbb,
324        0x7ebb4f37, 0x513caeaf, 0x3fa2c6cd, 0x57355b17, 0x253fc4b3, 0x0ea82db4, 0x799d8d38, 0x29eb1235,
325        0x1166db5e, 0x4702280e, 0x4c0a0516, 0x714d46a2, 0x79688b69, 0x143f324b, 0x6c0a36f7, 0x2938f208,
326        0x3eb39324, 0x1f61a856, 0x0a6ed93e, 0x74ec34c6, 0x7266c396, 0x522e81d0, 0x43a932cf, 0x0f17d5b9,
327    ]),
328    Mersenne31::new_array([
329        0x7c31e8a0, 0x09cb4b9c, 0x700c3e5e, 0x249c8c16, 0x3c4fe8e0, 0x03b84f18, 0x4825fa59, 0x1659f2ad,
330        0x031031e3, 0x746de944, 0x094ff5dd, 0x33c629fe, 0x05898337, 0x7c2592cc, 0x51d3f50c, 0x0e045cfc,
331        0x04a0ddd9, 0x61390b16, 0x7fbce1da, 0x0c8e5510, 0x60487f1c, 0x335f280e, 0x61655c16, 0x45f42611,
332        0x11f0c67c, 0x78ae4b41, 0x1714ff99, 0x165f7819, 0x31281c73, 0x38e87026, 0x3818fe79, 0x1d1ad24d,
333    ]),
334    Mersenne31::new_array([
335        0x3b679e6c, 0x3e51606e, 0x617db118, 0x566665cc, 0x2b5fb536, 0x4e9b1e00, 0x679bedc6, 0x5f6c74e5,
336        0x778fd658, 0x40776c3b, 0x063c76d1, 0x2b7652e9, 0x25956cb9, 0x7aed481d, 0x11bda982, 0x37fdfbf7,
337        0x5523be31, 0x56945dd1, 0x7c049305, 0x61c5c56c, 0x7f9ce07e, 0x0bd94fe4, 0x1689c147, 0x78b24a5a,
338        0x23e0ca74, 0x573b0a62, 0x7feea8d4, 0x147e92c9, 0x10751066, 0x197b0dfd, 0x2d1e89b9, 0x19f7f255,
339    ]),
340    Mersenne31::new_array([
341        0x338de8ae, 0x1d3950f5, 0x1cf58e86, 0x5aa7f39d, 0x4f6a8dc0, 0x1f010335, 0x27d6532f, 0x044135f2,
342        0x5f7d6b6c, 0x0d43513e, 0x24e9f9e7, 0x2d6bcf03, 0x40a7458d, 0x58c90caa, 0x4d048865, 0x48b012ad,
343        0x34df70f8, 0x7098ef21, 0x28ee8417, 0x0ea30375, 0x581889f7, 0x3bb682b1, 0x76c1a8c9, 0x34d53516,
344        0x2918fe23, 0x109dfd0a, 0x4d248dab, 0x141fefad, 0x23c4167e, 0x2a51b6a3, 0x70539b59, 0x615b302d,
345    ]),
346    Mersenne31::new_array([
347        0x5ad7ed79, 0x38b26be2, 0x1c63eb82, 0x782caaf3, 0x544ce98f, 0x07ffa066, 0x1984bf64, 0x62809aa1,
348        0x5cf6971c, 0x56cfc9f4, 0x79270e65, 0x6a5ac813, 0x68bb53c5, 0x566ca5b2, 0x1d5f9cdc, 0x4e42ac96,
349        0x45dd828c, 0x02105779, 0x6191e207, 0x7a090906, 0x4f8da1de, 0x41177418, 0x4563c669, 0x70923cc9,
350        0x1b044561, 0x6d1e6d7b, 0x64368db7, 0x1673b755, 0x356a84d9, 0x1b76e2c5, 0x2290c06f, 0x12dcd502,
351    ]),
352    Mersenne31::new_array([
353        0x0426c307, 0x50c707b0, 0x686ed71d, 0x05cb5fcf, 0x2726ef9d, 0x73f04ff5, 0x40361170, 0x07472de8,
354        0x3f23ab1e, 0x2f06b292, 0x620e742b, 0x1f562b80, 0x3bb8429c, 0x6287fca9, 0x77b5c517, 0x781ee01a,
355        0x668916a4, 0x18a7dadf, 0x43d0b3db, 0x53c57452, 0x7f4eb257, 0x49323ba4, 0x0b7d4444, 0x3b00799d,
356        0x268427ab, 0x2b07b82c, 0x00b960f7, 0x5ccb7e2e, 0x7d16c3c5, 0x0de8cca4, 0x491b67b5, 0x10e0c5bd,
357    ]),
358    Mersenne31::new_array([
359        0x75776d6c, 0x45d9b10a, 0x332bc6d5, 0x0babcef1, 0x468dee74, 0x681a15e9, 0x3ef42ea4, 0x2268e7ff,
360        0x7855c5e9, 0x5e2b56c8, 0x6b067779, 0x4f1f8bec, 0x14e98c2f, 0x53aa063c, 0x6c19052b, 0x13774678,
361        0x15d4034e, 0x17315651, 0x1423dae4, 0x30458131, 0x766744c4, 0x5795b834, 0x4ea8993e, 0x276726e1,
362        0x4a6b62d4, 0x07c5d4eb, 0x4ddbdafe, 0x08517a59, 0x7f5590a5, 0x7a5fdda5, 0x27adcd1c, 0x5784b2af,
363    ]),
364    Mersenne31::new_array([
365        0x0b07b8fe, 0x49d4582a, 0x13ff9929, 0x412b9bde, 0x72c5ca57, 0x7db5b928, 0x30b546b0, 0x4eb59327,
366        0x36adf136, 0x180388b9, 0x650c12f6, 0x746327b6, 0x48b21fcc, 0x6aabcae0, 0x281cf1f5, 0x5163bb4c,
367        0x0cee7303, 0x6c7121ce, 0x63f366ef, 0x6032ce95, 0x64d890a4, 0x318f09eb, 0x394a57d0, 0x3a240162,
368        0x66148f52, 0x16c22420, 0x66f8d4d0, 0x37b6cf3e, 0x7f1a683a, 0x65bfe7cb, 0x77ae875c, 0x1dd73c19,
369    ]),
370    Mersenne31::new_array([
371        0x5b403d3d, 0x2ac45eb4, 0x410b9e9c, 0x75b939d2, 0x3968be22, 0x788f61e7, 0x64f46f51, 0x0cbcc05b,
372        0x3f924163, 0x603fa063, 0x4ca1ee10, 0x4846f234, 0x023bd27b, 0x51c5869a, 0x19c8a2b7, 0x706b89e6,
373        0x0ba00de3, 0x3192560b, 0x1aca76c3, 0x15850b0d, 0x7b8cbfb7, 0x6f0caeeb, 0x262ecc36, 0x35587a97,
374        0x053bb4d4, 0x295608b0, 0x066c040f, 0x3aaad479, 0x783345e5, 0x16ec4e0d, 0x71dda99f, 0x5ea8008e,
375    ]),
376    Mersenne31::new_array([
377        0x53d2f000, 0x707758d5, 0x0132416e, 0x1e0c7554, 0x43015759, 0x326868f4, 0x57bee380, 0x3e6b4769,
378        0x422daf4b, 0x0c5319e5, 0x1ccaea92, 0x7faa8be0, 0x3034ca78, 0x23317bf8, 0x4aca4df7, 0x18f89b82,
379        0x363ab441, 0x5054bdf6, 0x7ff58a05, 0x315adbe8, 0x3a1a5a33, 0x3ac4c620, 0x68465616, 0x5a017a95,
380        0x692b3096, 0x6b21450f, 0x1209df32, 0x50bc5af2, 0x590e511a, 0x215201a7, 0x68023bdb, 0x7cd7f4ea,
381    ]),
382    Mersenne31::new_array([
383        0x1469d882, 0x4d147a45, 0x5f404861, 0x2ab807ee, 0x6a5ce35c, 0x2d7bbeff, 0x661c8cda, 0x53b63633,
384        0x414f678c, 0x38512dac, 0x5a32a63b, 0x425edcc1, 0x2a1765da, 0x77361c41, 0x4ab92cf0, 0x776cb3c5,
385        0x066d77c1, 0x31045acb, 0x50ea7b39, 0x65146378, 0x53e53f97, 0x53eee68c, 0x4069c800, 0x5077d8c1,
386        0x627dd5c6, 0x6710c5a7, 0x15911766, 0x095b2a41, 0x74a75545, 0x3075d136, 0x04348e00, 0x10512848,
387    ]),
388    Mersenne31::new_array([
389        0x5bf194c5, 0x45e8863b, 0x00e6d125, 0x0c6da617, 0x1185e319, 0x6e47742a, 0x00e3bacc, 0x3af98cd5,
390        0x03a748c8, 0x73e8429c, 0x3aede390, 0x2ba0b346, 0x3618a1e7, 0x25272815, 0x5413e8e0, 0x687e0305,
391        0x0af5c2c5, 0x0a67556e, 0x39174412, 0x21277515, 0x00549eab, 0x57db34a9, 0x7102106f, 0x14e03ac4,
392        0x32043d83, 0x252a816a, 0x13e53eba, 0x54ec815a, 0x23975136, 0x25db96ef, 0x6965a57c, 0x3acbf737,
393    ]),
394    Mersenne31::new_array([
395        0x1e6b4124, 0x027c2ccb, 0x220a4aea, 0x62267f92, 0x42fc4e53, 0x387d5173, 0x5606eb22, 0x0107ce12,
396        0x1e10fb5c, 0x6c50f9cd, 0x3da3a387, 0x2864339a, 0x3afc062f, 0x0998f6e1, 0x07241691, 0x21fdaa31,
397        0x750adbe8, 0x21974181, 0x796eecf4, 0x4ef280d4, 0x78896585, 0x17a8df5f, 0x6118460f, 0x7cbc0698,
398        0x39ad3fd9, 0x12ea1a76, 0x2634308f, 0x434bd381, 0x2a7797a0, 0x63822326, 0x460c7a49, 0x39e45118,
399    ]),
400    Mersenne31::new_array([
401        0x758ba6a4, 0x5009827a, 0x1aae5c46, 0x50921a89, 0x1520c0b1, 0x5db604f1, 0x2d79d774, 0x1037fba8,
402        0x6b3706c2, 0x069cd371, 0x49c859d7, 0x7a263996, 0x2d04e0bd, 0x43ae8518, 0x28410013, 0x262ca742,
403        0x7809a4c5, 0x6958252e, 0x605767e5, 0x55573da7, 0x079f0a5c, 0x20e7f477, 0x5b87f4f4, 0x34cdca96,
404        0x5a22bb2a, 0x062588ef, 0x3a98fd6f, 0x4045258b, 0x0661fff9, 0x1466dd4b, 0x6f86bf51, 0x5c1c348f,
405    ]),
406    Mersenne31::new_array([
407        0x07dbea9d, 0x54be56dd, 0x3d693a56, 0x7ca27d34, 0x3e96e54b, 0x32f55bff, 0x166a0ec1, 0x16bc9b21,
408        0x1624acb9, 0x7d9f7ac4, 0x452337ef, 0x0371afe4, 0x66b6437c, 0x08fd16ef, 0x36e88e2a, 0x73244c56,
409        0x31a87fbd, 0x647f1290, 0x514b4612, 0x592f4426, 0x074ba95f, 0x32ea4ba9, 0x6dbf08cd, 0x3f1de05a,
410        0x5f837cd2, 0x3dbc2aa1, 0x313ebcf4, 0x25ef0210, 0x63a45cc2, 0x60ec908e, 0x4b07d045, 0x1a5b338e,
411    ]),
412    Mersenne31::new_array([
413        0x7313eaea, 0x2a33061f, 0x5cc7ced8, 0x1c452ab9, 0x6ab7d100, 0x54c265c6, 0x4bbf6c2b, 0x37765cc3,
414        0x7d2d9e33, 0x0eaf1fcf, 0x6981217f, 0x5b6ba0c2, 0x1e0d7873, 0x52363630, 0x6464a079, 0x10543a02,
415        0x680285cf, 0x613fee88, 0x4275d4f8, 0x6279a362, 0x0ce381f2, 0x55a188eb, 0x7e0ab342, 0x76f9966e,
416        0x3c8a2ec2, 0x7a270447, 0x58d7eb39, 0x671c51f6, 0x5e94fc22, 0x5c30fd8a, 0x2aa28958, 0x72f4bfb3,
417    ]),
418    Mersenne31::new_array([
419        0x184bacd9, 0x3422813c, 0x57ac803a, 0x7e2fc74a, 0x783f8d00, 0x5a73e5b6, 0x2a965b52, 0x477dce48,
420        0x0d0baee8, 0x3f442904, 0x24b21822, 0x238d9798, 0x04e2fa43, 0x1743983c, 0x28249bfc, 0x473f570a,
421        0x155d7611, 0x4165e4b5, 0x6d76a047, 0x02a5202c, 0x5f63237f, 0x67f47b96, 0x1dd127d2, 0x0fc54fe2,
422        0x5024ec37, 0x3aa5b9d6, 0x3ad5c930, 0x1ca8ebe8, 0x00b9b791, 0x56ceb219, 0x41943e11, 0x2332bf7b,
423    ]),
424    Mersenne31::new_array([
425        0x00739566, 0x122e9d8e, 0x25cc025e, 0x7e00d52c, 0x3cc12b91, 0x458520be, 0x564d5fbe, 0x6714969b,
426        0x1c41b815, 0x497bba48, 0x592e3fbb, 0x5fcd5f32, 0x2311dfa1, 0x51d6122d, 0x1ddc0251, 0x0e62289f,
427        0x57a52b96, 0x43f4b668, 0x52e162f7, 0x05cb6953, 0x7a9e17fe, 0x29f4ceaa, 0x398e4724, 0x089f08e2,
428        0x20c34191, 0x0f08cb67, 0x1501ddbb, 0x50275cf2, 0x0aacbdaa, 0x58910cb8, 0x173b7582, 0x60f0d694,
429    ]),
430    Mersenne31::new_array([
431        0x6dcf278f, 0x362a9f79, 0x6e16b9b4, 0x57a29ea9, 0x0818e24c, 0x22ac6399, 0x74da2d53, 0x04ec6e36,
432        0x7372dcfd, 0x3f37017a, 0x3562a2d3, 0x4276c6a1, 0x76e44a94, 0x18215b0b, 0x2cc40fec, 0x3f85ae8d,
433        0x4dc6bcd1, 0x77c2f53f, 0x357d1298, 0x328f0f8c, 0x5088da1f, 0x4e987ab6, 0x23ce8328, 0x79713d75,
434        0x05fb1dfb, 0x2a25494c, 0x2dee3415, 0x5edc149a, 0x1afeaa39, 0x3b4adf89, 0x6b9d2b0c, 0x772aa7ba,
435    ]),
436    Mersenne31::new_array([
437        0x07d6df57, 0x14629768, 0x0dbb2361, 0x2e140207, 0x1f700b37, 0x48b86fe9, 0x73c79a7c, 0x75262867,
438        0x047a564f, 0x45934f5e, 0x3a3d9d3a, 0x4b150069, 0x72c1b5fd, 0x6e8340c0, 0x3d6ccffa, 0x17cb0609,
439        0x055a015e, 0x68f838e3, 0x4afb0948, 0x7544f4d9, 0x6f552958, 0x285b8658, 0x570861b9, 0x54b3abe1,
440        0x211e03d4, 0x52d42cf2, 0x421caec7, 0x7356f24a, 0x4e20fd95, 0x4cd33660, 0x52639f70, 0x180c0e3e,
441    ]),
442    Mersenne31::new_array([
443        0x6d366d77, 0x4d855863, 0x3e7875fd, 0x1193ca6a, 0x293d51be, 0x23249aed, 0x4969a773, 0x5047991d,
444        0x7a75f545, 0x6f89e19c, 0x7f0c85cb, 0x1e008c9c, 0x12cf7516, 0x12f3cc0c, 0x6d21837e, 0x73363a53,
445        0x57c27954, 0x47df2f6d, 0x520b20c2, 0x714bf286, 0x715f300d, 0x7f05b211, 0x41ef0f11, 0x66ec9d02,
446        0x66514219, 0x1a5339dc, 0x24a41ddc, 0x7760518d, 0x78e20c07, 0x275e5ffc, 0x4474d20e, 0x0783ae0b,
447    ]),
448    Mersenne31::new_array([
449        0x26d18a03, 0x6eddc8c6, 0x00687507, 0x1bf6e532, 0x2654e686, 0x002161d5, 0x6ea4736a, 0x5e7ca086,
450        0x3364e46b, 0x46e8b9ef, 0x5edb347a, 0x7ba774b0, 0x32c86b0d, 0x74ecbe76, 0x07c3abf7, 0x5e025176,
451        0x61b2fe7e, 0x1c1a1fff, 0x58684b00, 0x08cc0550, 0x3e76c197, 0x003a7cdb, 0x0ed98995, 0x7ca724b3,
452        0x65f9e77e, 0x52123b0a, 0x1efff024, 0x61457b4f, 0x402be38f, 0x56e66878, 0x685e81a5, 0x50ae4132,
453    ]),
454    Mersenne31::new_array([
455        0x51a721c8, 0x049fc8e2, 0x563563a7, 0x72de2637, 0x4d929ffa, 0x7a008564, 0x713d7e97, 0x7b876039,
456        0x2aed4bd2, 0x59553042, 0x45b3f48c, 0x23cb4486, 0x4d5f14ea, 0x49b82d50, 0x54f5a5b6, 0x202e29ee,
457        0x7aec360b, 0x23ab0e09, 0x584be113, 0x63354a5c, 0x16724b23, 0x345d3855, 0x79e473d1, 0x16c32e21,
458        0x08e59413, 0x3a6f1f6a, 0x6cc113c7, 0x01e50dba, 0x626f45a2, 0x55417cec, 0x7ff3fdd4, 0x5d2ce42b,
459    ]),
460    // Terminal full rounds (4)
461    Mersenne31::new_array([
462        0x1c89f089, 0x4bab0cf7, 0x63676f79, 0x6832f3cd, 0x3424bad7, 0x02176051, 0x78e9f924, 0x2c2042a7,
463        0x2e5e5343, 0x7f13dd21, 0x211a2c1c, 0x61a0804c, 0x451f4763, 0x27d04cbb, 0x3ac9f6ce, 0x13553fd0,
464        0x0d8cc4fe, 0x4df983ac, 0x71a83710, 0x5374c3b9, 0x6cb0d5b3, 0x13d607e6, 0x0c895cbf, 0x7711eae5,
465        0x661a88b5, 0x3e972972, 0x58468904, 0x7bb3d1b4, 0x22ef7433, 0x74c8f38a, 0x627f37ae, 0x5a056999,
466    ]),
467    Mersenne31::new_array([
468        0x09f3bfb7, 0x03734ed3, 0x53a6b381, 0x48d9d05d, 0x6bf9b614, 0x4a9f144f, 0x4bca8391, 0x3a1f1299,
469        0x33a33a1f, 0x1ce0389b, 0x1690f939, 0x3d618bc4, 0x18660f42, 0x20e10ec3, 0x0639c084, 0x6c409e98,
470        0x1bf13fb5, 0x3b1e8b8c, 0x086daac8, 0x66249317, 0x0937e002, 0x69810e64, 0x1b488058, 0x37b2667e,
471        0x5974b1d1, 0x68b90b26, 0x762685f6, 0x16773c93, 0x37681a94, 0x226ec818, 0x712880c3, 0x6238a02f,
472    ]),
473    Mersenne31::new_array([
474        0x4160e5f9, 0x2cabb507, 0x60f6ecf0, 0x20e2d0eb, 0x0581d33c, 0x2d898980, 0x5009f9fc, 0x5e80c8a0,
475        0x336952ea, 0x22098481, 0x4d9adbe7, 0x0539e374, 0x713548df, 0x1f46dfb0, 0x0f676c2b, 0x2889ad8b,
476        0x34b6148b, 0x51d868db, 0x7ae605ce, 0x4fdb0e34, 0x6fba849a, 0x4c1caa6c, 0x7631c902, 0x456f878e,
477        0x7e292981, 0x5dfc70a7, 0x2eaba22a, 0x7698fc9b, 0x40233110, 0x1e3a43dd, 0x15d1ab25, 0x142e8c3f,
478    ]),
479    Mersenne31::new_array([
480        0x433edc84, 0x48c6b434, 0x61533702, 0x2acdab18, 0x57807057, 0x1c95fec4, 0x111091cd, 0x2f9e6394,
481        0x52fa8c7c, 0x1898cecb, 0x5fc06816, 0x4c2fd9f5, 0x21b7c60f, 0x0fac6f13, 0x76ed472a, 0x1563a976,
482        0x5f055d85, 0x31864aff, 0x36915cce, 0x7c7b9275, 0x193594a8, 0x74f1d9ca, 0x13345a09, 0x55c49cbf,
483        0x67974c88, 0x725a4445, 0x3513e148, 0x6cb1fcd6, 0x5859e67d, 0x778e0804, 0x3f9e57c5, 0x67ff1751,
484    ]),
485];
486
487/// Create the default width-16 Poseidon1 permutation for Mersenne31.
488pub fn default_mersenne31_poseidon1_16() -> Poseidon1Mersenne31<16> {
489    Poseidon1::new(&Poseidon1Constants {
490        rounds_f: 2 * MERSENNE31_POSEIDON1_HALF_FULL_ROUNDS,
491        rounds_p: MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_16,
492        mds_circ_col: first_row_to_first_col(&MATRIX_CIRC_MDS_16_SML_ROW),
493        round_constants: MERSENNE31_POSEIDON1_RC_16.to_vec(),
494    })
495}
496
497/// Create the default width-32 Poseidon1 permutation for Mersenne31.
498pub fn default_mersenne31_poseidon1_32() -> Poseidon1Mersenne31<32> {
499    Poseidon1::new(&Poseidon1Constants {
500        rounds_f: 2 * MERSENNE31_POSEIDON1_HALF_FULL_ROUNDS,
501        rounds_p: MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_32,
502        mds_circ_col: first_row_to_first_col(&MATRIX_CIRC_MDS_32_MERSENNE31_ROW),
503        round_constants: MERSENNE31_POSEIDON1_RC_32.to_vec(),
504    })
505}
506
507#[cfg(test)]
508mod tests {
509    use p3_symmetric::Permutation;
510    use rand::SeedableRng;
511    use rand::rngs::SmallRng;
512
513    use super::*;
514
515    type F = Mersenne31;
516
517    /// Known-answer test for width 16 (sequential 0..15 input).
518    #[test]
519    fn test_poseidon1_mersenne31_width_16() {
520        let perm = default_mersenne31_poseidon1_16();
521
522        let mut input: [F; 16] =
523            F::new_array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
524        perm.permute_mut(&mut input);
525
526        let expected: [F; 16] = F::new_array([
527            763678880, 1665665156, 138326798, 2029009038, 523315643, 1240724959, 799985579,
528            1533764468, 1851415257, 580298256, 158301910, 1486286674, 1604442932, 919070942,
529            791307160, 922090452,
530        ]);
531        assert_eq!(input, expected);
532    }
533
534    /// Known-answer test for width 32 (sequential 0..31 input).
535    #[test]
536    fn test_poseidon1_mersenne31_width_32() {
537        let perm = default_mersenne31_poseidon1_32();
538
539        let mut input: [F; 32] = F::new_array([
540            0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
541            24, 25, 26, 27, 28, 29, 30, 31,
542        ]);
543        perm.permute_mut(&mut input);
544
545        let expected: [F; 32] = F::new_array([
546            493956664, 1487097341, 1986839634, 1423871566, 183460581, 827438159, 7996988,
547            141241897, 1403482130, 847367286, 2077667889, 1108646476, 1352254530, 1822401306,
548            809224972, 1606586582, 1039326136, 622010047, 1526365331, 1585000638, 1938294847,
549            559133752, 570966981, 1111956911, 1758188893, 1919461707, 940683889, 1707731554,
550            1949319314, 1540753789, 1964681567, 229242586,
551        ]);
552        assert_eq!(input, expected);
553    }
554
555    /// Smoke test for width 16 with random constants.
556    #[test]
557    fn test_poseidon1_mersenne31_width_16_random() {
558        let mut rng = SmallRng::seed_from_u64(1);
559        let poseidon = Poseidon1Mersenne31Generic::<16>::new_from_rng(
560            MERSENNE31_POSEIDON1_HALF_FULL_ROUNDS,
561            MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_16,
562            &MdsMatrixMersenne31,
563            &mut rng,
564        );
565        let input: [F; 16] = rand::RngExt::random(&mut rng);
566        let output = poseidon.permute(input);
567        assert_ne!(output, input);
568    }
569
570    /// Smoke test for width 32 with random constants.
571    #[test]
572    fn test_poseidon1_mersenne31_width_32_random() {
573        let mut rng = SmallRng::seed_from_u64(1);
574        let poseidon = Poseidon1Mersenne31Generic::<32>::new_from_rng(
575            MERSENNE31_POSEIDON1_HALF_FULL_ROUNDS,
576            MERSENNE31_POSEIDON1_PARTIAL_ROUNDS_32,
577            &MdsMatrixMersenne31,
578            &mut rng,
579        );
580        let input: [F; 32] = rand::RngExt::random(&mut rng);
581        let output = poseidon.permute(input);
582        assert_ne!(output, input);
583    }
584}