qfall_math/integer/mat_poly_over_z/
get.rs

1// Copyright © 2023 Marvin Beckmann
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementations to get information about a [`MatPolyOverZ`] matrix.
10
11use super::MatPolyOverZ;
12use crate::{
13    integer::PolyOverZ,
14    traits::{MatrixDimensions, MatrixGetEntry, MatrixGetSubmatrix},
15};
16use flint_sys::{
17    fmpz_poly::{fmpz_poly_set, fmpz_poly_struct},
18    fmpz_poly_mat::{
19        fmpz_poly_mat_entry, fmpz_poly_mat_init_set, fmpz_poly_mat_window_clear,
20        fmpz_poly_mat_window_init,
21    },
22};
23use std::mem::MaybeUninit;
24
25impl MatrixDimensions for MatPolyOverZ {
26    /// Returns the number of rows of the matrix as a [`i64`].
27    ///
28    /// # Examples
29    /// ```
30    /// use qfall_math::integer::MatPolyOverZ;
31    /// use qfall_math::traits::*;
32    ///
33    /// let matrix = MatPolyOverZ::new(5, 6);
34    /// let rows = matrix.get_num_rows();
35    /// ```
36    fn get_num_rows(&self) -> i64 {
37        self.matrix.r
38    }
39
40    /// Returns the number of columns of the matrix as a [`i64`].
41    ///
42    /// # Examples
43    /// ```
44    /// use qfall_math::integer::MatPolyOverZ;
45    /// use qfall_math::traits::*;
46    ///
47    /// let matrix = MatPolyOverZ::new(5, 6);
48    /// let columns = matrix.get_num_columns();
49    /// ```
50    fn get_num_columns(&self) -> i64 {
51        self.matrix.c
52    }
53}
54
55impl MatrixGetEntry<PolyOverZ> for MatPolyOverZ {
56    /// Outputs the [`PolyOverZ`] value of a specific matrix entry
57    /// without checking whether it's part of the matrix.
58    ///
59    /// Parameters:
60    /// - `row`: specifies the row in which the entry is located
61    /// - `column`: specifies the column in which the entry is located
62    ///
63    /// Returns the [`PolyOverZ`] value of the matrix at the position of the given
64    /// row and column.
65    ///
66    /// # Safety
67    /// To use this function safely, make sure that the selected entry is part
68    /// of the matrix. If it is not, memory leaks, unexpected panics, etc. might
69    /// occur.
70    ///
71    /// # Examples
72    /// ```
73    /// use qfall_math::integer::{MatPolyOverZ, PolyOverZ};
74    /// use qfall_math::traits::*;
75    /// use std::str::FromStr;
76    ///
77    /// let matrix = MatPolyOverZ::from_str("[[1  1, 1  2],[1  3, 1  4],[0, 1  6]]").unwrap();
78    ///
79    /// assert_eq!(PolyOverZ::from(2), unsafe { matrix.get_entry_unchecked(0, 1) });
80    /// assert_eq!(PolyOverZ::from(4), unsafe { matrix.get_entry_unchecked(1, 1) });
81    /// ```
82    unsafe fn get_entry_unchecked(&self, row: i64, column: i64) -> PolyOverZ {
83        let mut copy = PolyOverZ::default();
84        let entry = unsafe { fmpz_poly_mat_entry(&self.matrix, row, column) };
85        unsafe { fmpz_poly_set(&mut copy.poly, entry) };
86
87        copy
88    }
89}
90
91impl MatrixGetSubmatrix for MatPolyOverZ {
92    /// Returns a deep copy of the submatrix defined by the given parameters
93    /// and does not check the provided dimensions.
94    /// There is also a safe version of this function that checks the input.
95    ///
96    /// Parameters:
97    /// `row_1`: the starting row of the submatrix
98    /// `row_2`: the ending row of the submatrix
99    /// `col_1`: the starting column of the submatrix
100    /// `col_2`: the ending column of the submatrix
101    ///
102    /// Returns the submatrix from `(row_1, col_1)` to `(row_2, col_2)`(exclusively).
103    ///
104    /// # Examples
105    /// ```
106    /// use qfall_math::{integer::MatPolyOverZ, traits::MatrixGetSubmatrix};
107    /// use std::str::FromStr;
108    ///
109    /// let mat = MatPolyOverZ::identity(3, 3);
110    ///
111    /// let sub_mat_1 = mat.get_submatrix(0, 2, 1, 1).unwrap();
112    /// let sub_mat_2 = mat.get_submatrix(0, -1, 1, -2).unwrap();
113    /// let sub_mat_3 = unsafe{mat.get_submatrix_unchecked(0, 3, 1, 2)};
114    ///
115    /// let e_2 = MatPolyOverZ::from_str("[[0],[1  1],[0]]").unwrap();
116    /// assert_eq!(e_2, sub_mat_1);
117    /// assert_eq!(e_2, sub_mat_2);
118    /// assert_eq!(e_2, sub_mat_3);
119    /// ```
120    ///
121    /// # Safety
122    /// To use this function safely, make sure that the selected submatrix is part
123    /// of the matrix. If it is not, memory leaks, unexpected panics, etc. might
124    /// occur.
125    unsafe fn get_submatrix_unchecked(
126        &self,
127        row_1: i64,
128        row_2: i64,
129        col_1: i64,
130        col_2: i64,
131    ) -> Self {
132        let mut window = MaybeUninit::uninit();
133        // The memory for the elements of window is shared with self.
134        unsafe {
135            fmpz_poly_mat_window_init(
136                window.as_mut_ptr(),
137                &self.matrix,
138                row_1,
139                col_1,
140                row_2,
141                col_2,
142            )
143        };
144        let mut window_copy = MaybeUninit::uninit();
145        unsafe {
146            // Deep clone of the content of the window
147            fmpz_poly_mat_init_set(window_copy.as_mut_ptr(), window.as_ptr());
148            // Clears the matrix window and releases any memory that it uses. Note that
149            // the memory to the underlying matrix that window points to is not freed
150            fmpz_poly_mat_window_clear(window.as_mut_ptr());
151        }
152        MatPolyOverZ {
153            matrix: unsafe { window_copy.assume_init() },
154        }
155    }
156}
157
158impl MatPolyOverZ {
159    /// Efficiently collects all [`fmpz_poly_struct`]s in a [`MatPolyOverZ`] without cloning them.
160    ///
161    /// Hence, the values on the returned [`Vec`] are intended for short-term use
162    /// as the access to [`fmpz_poly_struct`] values could lead to memory leaks or
163    /// modified values once the [`MatPolyOverZ`] instance was modified or dropped.
164    ///
165    /// # Examples
166    /// ```compile_fail
167    /// use qfall_math::integer::MatPolyOverZ;
168    /// use std::str::FromStr;
169    ///
170    /// let mat = MatPolyOverZ::from_str("[[1  1, 0],[1  3, 1  4],[0, 1  6]]").unwrap();
171    ///
172    /// let fmpz_entries = mat.collect_entries();
173    /// ```
174    pub(crate) fn collect_entries(&self) -> Vec<fmpz_poly_struct> {
175        let mut entries: Vec<fmpz_poly_struct> =
176            Vec::with_capacity((self.get_num_rows() * self.get_num_columns()) as usize);
177
178        for row in 0..self.get_num_rows() {
179            for col in 0..self.get_num_columns() {
180                // efficiently get entry without cloning the entry itself
181                let entry = unsafe { *fmpz_poly_mat_entry(&self.matrix, row, col) };
182                entries.push(entry);
183            }
184        }
185
186        entries
187    }
188}
189
190#[cfg(test)]
191mod test_get_entry {
192    use crate::{
193        integer::{MatPolyOverZ, PolyOverZ},
194        traits::{MatrixGetEntry, MatrixSetEntry},
195    };
196    use std::str::FromStr;
197
198    /// Ensure that getting entries works with large polynomials.
199    #[test]
200    fn max_int_positive() {
201        let mut matrix = MatPolyOverZ::new(5, 10);
202        let value = PolyOverZ::from_str(&format!("2  {} 1", i64::MAX)).unwrap();
203        matrix.set_entry(1, 1, value).unwrap();
204
205        let entry = matrix.get_entry(1, 1).unwrap();
206
207        assert_eq!(format!("2  {} 1", i64::MAX), entry.to_string());
208    }
209
210    /// Ensure that getting entries works with large polynomials (larger than [`i64`]).
211    #[test]
212    fn large_positive() {
213        let mut matrix = MatPolyOverZ::new(5, 10);
214        let value = PolyOverZ::from_str(&format!("2  {} 1", u64::MAX)).unwrap();
215        matrix.set_entry(1, 1, value).unwrap();
216
217        let entry = matrix.get_entry(1, 1).unwrap();
218
219        assert_eq!(format!("2  {} 1", u64::MAX), entry.to_string());
220    }
221
222    /// Ensure that getting entries works with large negative polynomials.
223    #[test]
224    fn max_int_negative() {
225        let mut matrix = MatPolyOverZ::new(5, 10);
226        let value = PolyOverZ::from_str(&format!("2  {} 1", i64::MIN)).unwrap();
227        matrix.set_entry(1, 1, value).unwrap();
228
229        let entry = matrix.get_entry(1, 1).unwrap();
230
231        assert_eq!(format!("2  {} 1", i64::MIN), entry.to_string());
232    }
233
234    /// Ensure that getting entries works with large negative polynomials (larger than [`i64`]).
235    #[test]
236    fn large_negative() {
237        let mut matrix = MatPolyOverZ::new(5, 10);
238        let value = PolyOverZ::from_str(&format!("2  -{} 1", u64::MAX)).unwrap();
239        matrix.set_entry(1, 1, value).unwrap();
240
241        let entry = matrix.get_entry(1, 1).unwrap();
242
243        assert_eq!(format!("2  -{} 1", u64::MAX), entry.to_string());
244    }
245
246    /// Ensure that polynomials with many entries are correctly retrieved
247    #[test]
248    fn large_poly() {
249        let mut matrix = MatPolyOverZ::new(5, 10);
250        let value =
251            PolyOverZ::from_str(&format!("10000  -{} 1{}", u64::MAX, " 17".repeat(9998))).unwrap();
252        matrix.set_entry(1, 1, value).unwrap();
253
254        let entry = matrix.get_entry(1, 1).unwrap();
255
256        assert_eq!(
257            format!("10000  -{} 1{}", u64::MAX, " 17".repeat(9998)),
258            entry.to_string()
259        );
260    }
261
262    /// Ensure that getting entries at (0, 0) works.
263    #[test]
264    fn getting_at_zero() {
265        let mut matrix = MatPolyOverZ::new(5, 10);
266        let value = PolyOverZ::from_str(&format!("2  {} 1", i64::MAX)).unwrap();
267        matrix.set_entry(0, 0, value).unwrap();
268
269        let entry = matrix.get_entry(0, 0).unwrap();
270
271        assert_eq!(format!("2  {} 1", i64::MAX), entry.to_string());
272    }
273
274    /// Ensure that a wrong number of rows yields an Error.
275    #[test]
276    fn error_wrong_row() {
277        let matrix = MatPolyOverZ::new(5, 10);
278
279        assert!(matrix.get_entry(5, 1).is_err());
280        assert!(matrix.get_entry(-6, 1).is_err());
281    }
282
283    /// Ensure that a wrong number of columns yields an Error.
284    #[test]
285    fn error_wrong_column() {
286        let matrix = MatPolyOverZ::new(5, 10);
287
288        assert!(matrix.get_entry(1, 100).is_err());
289        assert!(matrix.get_entry(1, -11).is_err());
290    }
291
292    /// Ensure that negative indices return the correct values.
293    #[test]
294    fn negative_indexing() {
295        let matrix = MatPolyOverZ::from_str("[[1  1, 1  2],[1  3, 1  4],[1  5 , 1  6]]").unwrap();
296
297        assert_eq!(PolyOverZ::from(2), matrix.get_entry(0, -1).unwrap());
298        assert_eq!(PolyOverZ::from(4), matrix.get_entry(-2, 1).unwrap());
299        assert_eq!(PolyOverZ::from(4), matrix.get_entry(-2, -1).unwrap());
300        assert_eq!(PolyOverZ::from(6), matrix.get_entry(-1, -1).unwrap());
301    }
302
303    /// Ensure that the entry is a deep copy and not just a clone of the reference.
304    #[test]
305    fn memory_test() {
306        let mut matrix = MatPolyOverZ::new(5, 10);
307        let value = PolyOverZ::from_str(&format!("2  {} 1", u64::MAX)).unwrap();
308        matrix.set_entry(1, 1, value).unwrap();
309        let entry = matrix.get_entry(1, 1).unwrap();
310        matrix.set_entry(1, 1, PolyOverZ::default()).unwrap();
311
312        assert_eq!(format!("2  {} 1", u64::MAX), entry.to_string());
313    }
314}
315
316#[cfg(test)]
317mod test_get_num {
318    use crate::{integer::MatPolyOverZ, traits::MatrixDimensions};
319
320    /// Ensure that the getter for number of rows works correctly.
321    #[test]
322    fn num_rows() {
323        let matrix = MatPolyOverZ::new(5, 10);
324
325        assert_eq!(matrix.get_num_rows(), 5);
326    }
327
328    /// Ensure that the getter for number of columns works correctly.
329    #[test]
330    fn num_columns() {
331        let matrix = MatPolyOverZ::new(5, 10);
332
333        assert_eq!(matrix.get_num_columns(), 10);
334    }
335}
336
337#[cfg(test)]
338mod test_get_vec {
339    use crate::{integer::MatPolyOverZ, traits::MatrixGetSubmatrix};
340    use std::str::FromStr;
341
342    /// Ensure that getting a row works
343    #[test]
344    fn get_row_works() {
345        let matrix = MatPolyOverZ::from_str(&format!(
346            "[[0, 0, 0],[1  42, 1  {}, 1  {}]]",
347            i64::MAX,
348            i64::MIN
349        ))
350        .unwrap();
351        let row_1 = matrix.get_row(0).unwrap();
352        let row_2 = matrix.get_row(1).unwrap();
353
354        let cmp_1 = MatPolyOverZ::from_str("[[0, 0, 0]]").unwrap();
355        let cmp_2 = MatPolyOverZ::from_str(&format!("[[1  42, 1  {}, 1  {}]]", i64::MAX, i64::MIN))
356            .unwrap();
357
358        assert_eq!(cmp_1, row_1);
359        assert_eq!(cmp_2, row_2);
360    }
361
362    /// Ensure that getting a row with a negative index works
363    #[test]
364    fn get_row_negative_indexing_works() {
365        let matrix = MatPolyOverZ::from_str(&format!(
366            "[[0, 0, 0],[1  42, 1  {}, 1  {}]]",
367            i64::MAX,
368            i64::MIN
369        ))
370        .unwrap();
371        let row_1 = matrix.get_row(-2).unwrap();
372        let row_2 = matrix.get_row(-1).unwrap();
373
374        let cmp_1 = MatPolyOverZ::from_str("[[0, 0, 0]]").unwrap();
375        let cmp_2 = MatPolyOverZ::from_str(&format!("[[1  42, 1  {}, 1  {}]]", i64::MAX, i64::MIN))
376            .unwrap();
377
378        assert_eq!(cmp_1, row_1);
379        assert_eq!(cmp_2, row_2);
380    }
381
382    /// Ensure that getting a column works
383    #[test]
384    fn get_column_works() {
385        let matrix = MatPolyOverZ::from_str(&format!(
386            "[[1  42, 0, 2  17 42],[1  {}, 0, 2  17 42],[1  {}, 0, 2  17 42]]",
387            i64::MAX,
388            i64::MIN
389        ))
390        .unwrap();
391        let column_1 = matrix.get_column(0).unwrap();
392        let column_2 = matrix.get_column(1).unwrap();
393        let column_3 = matrix.get_column(2).unwrap();
394
395        let cmp_1 =
396            MatPolyOverZ::from_str(&format!("[[1  42],[1  {}],[1  {}]]", i64::MAX, i64::MIN))
397                .unwrap();
398        let cmp_2 = MatPolyOverZ::from_str("[[0],[0],[0]]").unwrap();
399        let cmp_3 = MatPolyOverZ::from_str("[[2  17 42],[2  17 42],[2  17 42]]").unwrap();
400
401        assert_eq!(cmp_1, column_1);
402        assert_eq!(cmp_2, column_2);
403        assert_eq!(cmp_3, column_3);
404    }
405
406    /// Ensure that getting a column with a negative index works
407    #[test]
408    fn get_column_negative_indexing_works() {
409        let matrix = MatPolyOverZ::from_str(&format!(
410            "[[1  42, 0, 2  17 42],[1  {}, 0, 2  17 42],[1  {}, 0, 2  17 42]]",
411            i64::MAX,
412            i64::MIN
413        ))
414        .unwrap();
415        let column_1 = matrix.get_column(-3).unwrap();
416        let column_2 = matrix.get_column(-2).unwrap();
417        let column_3 = matrix.get_column(-1).unwrap();
418
419        let cmp_1 =
420            MatPolyOverZ::from_str(&format!("[[1  42],[1  {}],[1  {}]]", i64::MAX, i64::MIN))
421                .unwrap();
422        let cmp_2 = MatPolyOverZ::from_str("[[0],[0],[0]]").unwrap();
423        let cmp_3 = MatPolyOverZ::from_str("[[2  17 42],[2  17 42],[2  17 42]]").unwrap();
424
425        assert_eq!(cmp_1, column_1);
426        assert_eq!(cmp_2, column_2);
427        assert_eq!(cmp_3, column_3);
428    }
429
430    /// Ensure that wrong row and column dimensions yields an error
431    #[test]
432    fn wrong_dim_error() {
433        let matrix = MatPolyOverZ::from_str(&format!(
434            "[[1  17, 2  17 42, 3  1 1 1],[1  {}, 1  1, 2  2 3],[1  {}, 1  142, 1  1]]",
435            i64::MAX,
436            i64::MIN
437        ))
438        .unwrap();
439        let row_1 = matrix.get_row(-4);
440        let row_2 = matrix.get_row(4);
441        let column_1 = matrix.get_column(-4);
442        let column_2 = matrix.get_column(4);
443
444        assert!(row_1.is_err());
445        assert!(row_2.is_err());
446        assert!(column_1.is_err());
447        assert!(column_2.is_err());
448    }
449}
450
451#[cfg(test)]
452mod test_get_submatrix {
453    use crate::{
454        integer::{MatPolyOverZ, Z},
455        traits::{MatrixDimensions, MatrixGetSubmatrix},
456    };
457    use std::str::FromStr;
458
459    /// Ensures that getting the entire matrix as a submatrix works.
460    #[test]
461    fn entire_matrix() {
462        let mat = MatPolyOverZ::identity(5, 5);
463
464        let sub_mat = mat.get_submatrix(0, 4, 0, 4).unwrap();
465
466        assert_eq!(mat, sub_mat);
467    }
468
469    /// Ensures that a single matrix entry can be retrieved.
470    #[test]
471    fn matrix_single_entry() {
472        let mat = MatPolyOverZ::identity(5, 5);
473
474        let sub_mat = mat.get_submatrix(0, 0, 0, 0).unwrap();
475
476        let cmp_mat = MatPolyOverZ::identity(1, 1);
477        assert_eq!(cmp_mat, sub_mat);
478    }
479
480    /// Ensures that the dimensions of the submatrix are correct.
481    #[test]
482    fn correct_dimensions() {
483        let mat = MatPolyOverZ::identity(100, 100);
484
485        let sub_mat = mat.get_submatrix(1, 37, 0, 29).unwrap();
486
487        assert_eq!(37, sub_mat.get_num_rows());
488        assert_eq!(30, sub_mat.get_num_columns());
489    }
490
491    /// Ensures that a submatrix can be correctly retrieved for a matrix with large
492    /// entries.
493    #[test]
494    fn large_entries() {
495        let mat = MatPolyOverZ::from_str(&format!(
496            "[[2  {} {}, 1  2, 1  3],[1  1, 1  {}, 1  3]]",
497            u64::MAX,
498            i64::MAX,
499            i64::MIN
500        ))
501        .unwrap();
502
503        let sub_mat = mat.get_submatrix(0, 1, 0, 1).unwrap();
504
505        let cmp_mat = MatPolyOverZ::from_str(&format!(
506            "[[2  {} {}, 1  2],[1  1, 1  {}]]",
507            u64::MAX,
508            i64::MAX,
509            i64::MIN
510        ))
511        .unwrap();
512        assert_eq!(cmp_mat, sub_mat);
513    }
514
515    /// Ensures that an error is returned if coordinates are addressed that are not
516    /// within the matrix.
517    #[test]
518    fn invalid_coordinates() {
519        let mat = MatPolyOverZ::identity(10, 10);
520
521        assert!(mat.get_submatrix(0, 0, 0, 10).is_err());
522        assert!(mat.get_submatrix(0, 10, 0, 0).is_err());
523        assert!(mat.get_submatrix(0, 0, -11, 0).is_err());
524        assert!(mat.get_submatrix(-11, 0, 0, 0).is_err());
525    }
526
527    /// Ensure that negative indices return the correct submatrix.
528    #[test]
529    fn negative_indexing() {
530        let matrix = MatPolyOverZ::identity(3, 3);
531
532        assert_eq!(matrix, matrix.get_submatrix(0, -1, 0, -1).unwrap());
533        assert_eq!(matrix, matrix.get_submatrix(-3, -1, -3, -1).unwrap());
534        assert_eq!(
535            matrix.get_row(0).unwrap(),
536            matrix.get_submatrix(0, -3, -3, -1).unwrap()
537        );
538    }
539
540    /// Ensures that the function panics if no columns of the matrix are addressed.
541    #[test]
542    #[should_panic]
543    fn no_columns() {
544        let mat = MatPolyOverZ::identity(10, 10);
545
546        let _ = mat.get_submatrix(0, 0, 6, 5);
547    }
548
549    /// Ensures that the function panics if no rows of the matrix are addressed.
550    #[test]
551    #[should_panic]
552    fn no_rows() {
553        let mat = MatPolyOverZ::identity(10, 10);
554
555        let _ = mat.get_submatrix(5, 4, 0, 0);
556    }
557
558    /// Ensure that the submatrix function can be called with several types.
559    #[test]
560    fn availability() {
561        let mat = MatPolyOverZ::identity(10, 10);
562
563        let _ = mat.get_submatrix(0_i8, 0_i8, 0_i8, 0_i8);
564        let _ = mat.get_submatrix(0_i16, 0_i16, 0_i16, 0_i16);
565        let _ = mat.get_submatrix(0_i32, 0_i32, 0_i32, 0_i32);
566        let _ = mat.get_submatrix(0_i64, 0_i64, 0_i64, 0_i64);
567        let _ = mat.get_submatrix(0_u8, 0_u8, 0_u8, 0_u8);
568        let _ = mat.get_submatrix(0_u16, 0_i16, 0_u16, 0_u16);
569        let _ = mat.get_submatrix(0_u32, 0_i32, 0_u32, 0_u32);
570        let _ = mat.get_submatrix(0_u64, 0_i64, 0_u64, 0_u64);
571        let _ = mat.get_submatrix(&Z::ZERO, &Z::ZERO, &Z::ZERO, &Z::ZERO);
572    }
573}
574
575#[cfg(test)]
576mod test_collect_entries {
577    use super::MatPolyOverZ;
578    use std::str::FromStr;
579
580    /// Ensures that all entries from the matrices are actually collected in the vector.
581    #[test]
582    fn all_entries_collected() {
583        let mat_1 = MatPolyOverZ::from_str(&format!(
584            "[[1  1, 0],[1  {}, 1  {}],[1  -3, 0]]",
585            i64::MAX,
586            i64::MIN
587        ))
588        .unwrap();
589        let mat_2 = MatPolyOverZ::from_str("[[1  -1, 2  1 2]]").unwrap();
590
591        let entries_1 = mat_1.collect_entries();
592        let entries_2 = mat_2.collect_entries();
593
594        assert_eq!(entries_1.len(), 6);
595        assert_eq!(unsafe { *entries_1[0].coeffs }.0, 1);
596        assert!(unsafe { *entries_1[2].coeffs }.0 >= 2_i64.pow(62));
597        assert!(unsafe { *entries_1[3].coeffs }.0 >= 2_i64.pow(62));
598        assert_eq!(unsafe { *entries_1[4].coeffs }.0, -3);
599
600        assert_eq!(entries_2.len(), 2);
601        assert_eq!(unsafe { *entries_2[0].coeffs.offset(0) }.0, -1);
602        assert_eq!(entries_2[0].length, 1);
603        assert_eq!(unsafe { *entries_2[1].coeffs.offset(0) }.0, 1);
604        assert_eq!(unsafe { *entries_2[1].coeffs.offset(1) }.0, 2);
605        assert_eq!(entries_2[1].length, 2);
606    }
607}