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