qfall_math/integer_mod_q/poly_over_zq/
to_string.rs

1// Copyright © 2023 Marcel Luca Schmidt, 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//! This module contains all options to convert a modulus of type
10//! [`PolyOverZq`] into a [`String`].
11//!
12//! This includes the [`Display`](std::fmt::Display) trait.
13
14use super::PolyOverZq;
15use crate::{integer::PolyOverZ, macros::for_others::implement_for_owned};
16use flint_sys::fmpz_mod_poly::fmpz_mod_poly_get_fmpz_poly;
17use std::fmt;
18
19impl From<&PolyOverZq> for String {
20    /// Converts a [`PolyOverZq`] into its [`String`] representation.
21    ///
22    /// Parameters:
23    /// - `value`: specifies the polynommial that will be represented as a [`String`]
24    ///
25    /// Returns a [`String`] of the form `"[#number of coefficients]⌴⌴[0th coefficient]⌴[1st coefficient]⌴...⌴mod⌴[q]"`.
26    ///
27    /// # Examples
28    /// ```
29    /// use qfall_math::integer_mod_q::PolyOverZq;
30    /// use std::str::FromStr;
31    /// let poly = PolyOverZq::from_str("2  2 1 mod 3").unwrap();
32    ///
33    /// let string: String = poly.into();
34    /// ```
35    fn from(value: &PolyOverZq) -> Self {
36        value.to_string()
37    }
38}
39
40implement_for_owned!(PolyOverZq, String, From);
41
42impl fmt::Display for PolyOverZq {
43    /// Allows to convert a [`PolyOverZq`] into a [`String`].
44    ///
45    /// # Examples
46    /// ```
47    /// use qfall_math::integer_mod_q::PolyOverZq;
48    /// use std::str::FromStr;
49    /// use core::fmt;
50    ///
51    /// let poly = PolyOverZq::from_str("4  0 1 2 3 mod 5").unwrap();
52    /// println!("{poly}");
53    /// ```
54    ///
55    /// ```
56    /// use qfall_math::integer_mod_q::PolyOverZq;
57    /// use std::str::FromStr;
58    ///
59    /// let poly = PolyOverZq::from_str("4  0 1 2 3 mod 5").unwrap();
60    /// let poly_string = poly.to_string();
61    /// ```
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        // there is no dedicated method to create a string from a fmpz_mod_poly
64        // hence we convert it to a fmpz_poly first to use the dedicated method
65
66        let mut poly_over_z = PolyOverZ::default();
67        unsafe {
68            fmpz_mod_poly_get_fmpz_poly(
69                &mut poly_over_z.poly,
70                &self.poly,
71                self.modulus.get_fmpz_mod_ctx_struct(),
72            )
73        };
74        write!(f, "{poly_over_z} mod {}", self.modulus)
75    }
76}
77
78#[cfg(test)]
79mod test_to_string {
80    use super::PolyOverZq;
81    use std::str::FromStr;
82
83    /// Tests whether a polynomial that is created using a string, returns the
84    /// same string, when it is converted back to a string
85    #[test]
86    fn working_keeps_same_string() {
87        let cmp_str = "3  1 2 2 mod 5";
88        let cmp = PolyOverZq::from_str(cmp_str).unwrap();
89
90        assert_eq!(cmp_str, cmp.to_string());
91    }
92
93    /// Tests whether a polynomial that is created using a string, returns a
94    /// string that can be used to create a polynomial
95    #[test]
96    fn working_use_result_of_to_string_as_input() {
97        let cmp_str = "3  1 2 2 mod 5";
98        let cmp = PolyOverZq::from_str(cmp_str).unwrap();
99
100        let cmp_str_2 = cmp.to_string();
101
102        assert!(PolyOverZq::from_str(&cmp_str_2).is_ok());
103    }
104
105    /// Test applied modulus if initialized with negative values
106    #[test]
107    fn initialized_neg() {
108        let cmp_str = "3  -1 -2 -3 mod 5";
109        let cmp = PolyOverZq::from_str(cmp_str).unwrap();
110
111        assert_eq!("3  4 3 2 mod 5", cmp.to_string());
112    }
113
114    /// Tests that large entries and large moduli work with to_string()
115    #[test]
116    fn large_entries_modulus() {
117        let cmp_str = format!("3  1 2 {} mod 1{}", u64::MAX, u64::MAX);
118        let cmp = PolyOverZq::from_str(&cmp_str).unwrap();
119
120        assert_eq!(cmp_str, cmp.to_string());
121    }
122
123    /// Ensures that the `Into<String>` trait works properly
124    #[test]
125    fn into_works_properly() {
126        let cmp = "2  2 1 mod 3";
127        let poly = PolyOverZq::from_str(cmp).unwrap();
128
129        let string: String = poly.clone().into();
130        let borrowed_string: String = (&poly).into();
131
132        assert_eq!(cmp, string);
133        assert_eq!(cmp, borrowed_string);
134    }
135}