qfall_math/rational/q.rs
1// Copyright 2023 Marcel Luca Schmidt
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//! [`Q`] is a type for rationals of arbitrary length.
10//! This implementation uses the [FLINT](https://flintlib.org/) library.
11
12// For **DEVELOPERS**: Many functions assume that the [`Q`] instances are reduced.
13// To avoid unnecessary checks and reductions, always return canonical/reduced
14// values. The end-user should be unable to obtain a non-reduced value.
15
16use crate::integer::debug_fmpz;
17use flint3_sys::fmpq;
18use std::fmt;
19
20mod arithmetic;
21mod cmp;
22mod default;
23mod distance;
24mod from;
25mod get;
26mod ownership;
27mod properties;
28mod rounding;
29mod sample;
30mod serialize;
31mod to_string;
32mod unsafe_functions;
33
34/// [`Q`] is any rational value.
35///
36/// Attributes:
37/// - `value`: holds [FLINT](https://flintlib.org/)'s [struct](fmpq)
38/// for a rational value
39///
40/// # Implicit Typecasting
41/// Most of our functions take as input values of type [`Into<Q>`].
42/// These capture all types that can be turned into a [`Q`] value.
43/// The types are [`Q`],[`Z`](crate::integer::Z),
44/// [`Modulus`](crate::integer_mod_q::Modulus), [`i8`],[`i16`],[`i32`],
45/// [`i64`],[`u8`],[`u16`],[`u32`],[`u64`],[`f32`],[`f64`]
46/// and the references of all of these types.
47/// These types are then implicitly casted to a [`Q`] before the desired action is
48/// performed.
49///
50/// # Examples
51/// ```
52/// use qfall_math::rational::Q;
53/// use std::str::FromStr;
54///
55/// // instantiations
56/// let a = Q::from_str("-876543/235")?;
57/// let b = Q::from(21);
58/// let zero = Q::default();
59/// let _ = a.clone();
60///
61/// // arithmetics
62/// let _ = &a + &zero;
63/// let _ = &a * &b;
64///
65/// // to_string incl. (de-)serialization
66/// assert_eq!("-876543/235", &a.to_string());
67/// assert_eq!(
68/// "{\"value\":\"-876543/235\"}",
69/// serde_json::to_string(&a).unwrap()
70/// );
71///
72/// // comparison
73/// assert_ne!(a, b);
74/// # Ok::<(), qfall_math::error::MathError>(())
75/// ```
76pub struct Q {
77 pub(crate) value: fmpq,
78}
79
80impl fmt::Debug for Q {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 write!(
83 f,
84 "Q {{value_f64(may be rounded; 5 decimals): {}, value: {}, storage: {{value: {}}}}}",
85 self.to_string_decimal(5),
86 self,
87 debug_fmpq(&self.value)
88 )
89 }
90}
91
92fn debug_fmpq(value: &fmpq) -> String {
93 format!(
94 "fmpq {{ num: {}, den: {} }}",
95 debug_fmpz(&value.num),
96 debug_fmpz(&value.den)
97 )
98}