qfall_math/integer_mod_q/modulus.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//! [`Modulus`] is a type of a positive integer larger than `1` that is used in
10//! order to do modulus operations. The modulus type itself is also used for
11//! optimizations.
12//! A [`Modulus`] of `1` is not allowed, since operations would always just
13//! return `0`. This way, checks later in the code can be avoided.
14//!
15//! This implementation uses the [FLINT](https://flintlib.org/) library.
16
17use crate::integer::debug_fmpz;
18use flint3_sys::{fmpz_mod_ctx, nmod_t};
19use std::{fmt, rc::Rc};
20
21mod cmp;
22mod distance;
23mod fmpz_helpers;
24mod from;
25mod get;
26mod ownership;
27mod properties;
28mod serialize;
29mod to_string;
30mod unsafe_functions;
31
32/// [`Modulus`] is a type of a positive integer larger than `1` that is used
33/// to do modulus operations.
34///
35/// Attributes:
36/// - `modulus`: holds the value of the modulus
37///
38/// # Examples
39/// Create [`Modulus`] from [`str`]:
40/// ```
41/// use qfall_math::integer_mod_q::Modulus;
42/// use std::str::FromStr;
43/// use qfall_math::integer::Z;
44/// let value = Z::from(10);
45///
46/// // instantiations
47/// let _ = Modulus::from(10);
48/// let a = Modulus::from_str("42").unwrap();
49/// let b: Modulus = (&value).try_into().unwrap();
50///
51/// // clone
52/// let clone = a.clone();
53///
54/// // properties
55/// let is_prime: bool = a.is_prime();
56///
57/// // to_string incl. (de-)serialization
58/// assert_eq!("42", &a.to_string());
59/// assert_eq!(
60/// "{\"modulus\":\"42\"}",
61/// serde_json::to_string(&a).unwrap()
62/// );
63///
64/// // comparison
65/// assert_eq!(a, clone);
66/// ```
67pub struct Modulus {
68 pub(crate) modulus: Rc<fmpz_mod_ctx>,
69}
70
71impl fmt::Debug for Modulus {
72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73 write!(
74 f,
75 "Modulus {{ modulus: {}, storage: {{ modulus: {}}}}}",
76 self,
77 debug_fmpz_mod_ctx(&self.modulus)
78 )
79 }
80}
81
82macro_rules! debug_fn_ptr {
83 ($opt_fn:expr) => {
84 match $opt_fn {
85 Some(f) => format!("Some({:#x})", f as usize),
86 None => "None".to_string(),
87 }
88 };
89}
90
91fn debug_fmpz_mod_ctx(value: &fmpz_mod_ctx) -> String {
92 format!(
93 "fmpz_mod_ctx {{ n: [{}], add_fxn: {}, sub_fxn: {}, mul_fxn: {}, mod_: {}, n_limbs: {:?}, ninv_limbs: {:?}}}",
94 debug_fmpz(&value.n[0]),
95 debug_fn_ptr!(value.add_fxn),
96 debug_fn_ptr!(value.sub_fxn),
97 debug_fn_ptr!(value.mul_fxn),
98 debug_nmod_t(&value.mod_),
99 value.n_limbs,
100 value.ninv_limbs
101 )
102}
103
104fn debug_nmod_t(value: &nmod_t) -> String {
105 format!(
106 "nmod_t {{ n: {}, ninv: {}, norm: {} }}",
107 value.n, value.ninv, value.norm
108 )
109}