1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright © 2026 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
use crateRational;
use String;
use ;
use ;
/// Formats a [`Rational`] according to a GMP-style `printf` format string, for strict compatibility
/// with GMP's `gmp_printf` family.
///
/// The format string should contain a single conversion consuming the [`Rational`], written
/// `%[flags][width][.precision]Q[conv]`, with any surrounding literal text (a literal `%` is
/// written `%%`). The value is written as the numerator's digits, and, unless the denominator is 1,
/// a slash and the denominator's digits, as with `mpq_get_str`. The pieces are:
/// - **flags**: any of `-` (left-justify within the field), `+` (always show a sign), space (show a
/// space before a nonnegative value), `#` (alternate form: prefix hexadecimal output with `0x` or
/// `0X` and octal output with `0`, on the numerator and on the denominator, unless the respective
/// digits already begin with a zero), and `0` (pad the field with leading zeros). The `'` flag is
/// accepted but, as in GMP, has no effect on GMP types.
/// - **width**: the minimum field width, as a decimal integer; the numerator, slash, and
/// denominator are justified as a unit.
/// - **precision**: following a `.`, a minimum digit count; GMP documents the influence of the
/// precision on a rational as undefined, and this function reproduces what its code does, padding
/// the numerator with leading zeros until the whole string, slash and denominator included,
/// reaches the precision.
/// - **`Q`**: marks the argument as a multiple-precision rational (GMP's type character).
/// - **conv**: the conversion — `d`, `i`, or `u` (decimal; all three are the same, and a negative
/// value keeps its sign under every conversion), `o` (octal), or `x`/`X` (lowercase/uppercase
/// hexadecimal).
///
/// A negative value is written as a `-` followed by the absolute value, and with the `#` flag the
/// sign precedes the numerator's base prefix, as in `-0xff/0x10`.
///
/// Returns [`None`] when the format string is not a single well-formed `%Q` conversion: for
/// instance if it uses `*` for the width or precision (which would need an integer argument that
/// this single-value entry point does not supply), contains no `%Q` conversion or more than one,
/// contains a conversion of any other type, or requests a width or precision beyond `i32::MAX` (the
/// range of the C `int` GMP itself stores them in).
///
/// # Worst-case complexity
/// $T(n) = O(n (\log n)^2 \log\log n)$
///
/// $M(n) = O(n \log n)$
///
/// where $T$ is time, $M$ is additional memory, and $n$ is `max(x.significant_bits(), p, w)`, with
/// `p` and `w` the precision and field width requested by the format string.
///
/// # Examples
/// ```
/// use malachite_q::Rational;
/// use malachite_q::rational::conversion::string::format_rational::format_rational_str;
///
/// let x = Rational::from_signeds(255, 16);
/// assert_eq!(format_rational_str(&x, "%Qd"), Some("255/16".to_string()));
/// assert_eq!(
/// format_rational_str(&x, "%#Qx"),
/// Some("0xff/0x10".to_string())
/// );
/// assert_eq!(
/// format_rational_str(&x, "%10Qd"),
/// Some(" 255/16".to_string())
/// );
/// assert_eq!(format_rational_str(&-x, "%Qd"), Some("-255/16".to_string()));
///
/// // a denominator of 1 is omitted, as with `mpq_get_str`
/// assert_eq!(
/// format_rational_str(&Rational::from(255), "%Qd"),
/// Some("255".to_string())
/// );
///
/// // invalid or unsupported format strings
/// let x = Rational::from_signeds(255, 16);
/// assert_eq!(format_rational_str(&x, "%Zd"), None);
/// assert_eq!(format_rational_str(&x, "%*Qd"), None);
/// assert_eq!(format_rational_str(&x, "%Qd %Qd"), None);
/// ```
///
/// This is `gmp_snprintf` from `printf/snprintf.c`, GMP 6.3.0, where the format string contains a
/// single `%Q` conversion and the buffer is always large enough.