1use crate::{subject::Subject::{self, *}, modular::ModularSubject, cont_frac::CfracSubject};
2use bigdecimal::ToPrimitive;
3use num_bigint::BigInt;
4use num_integer::Integer;
5use num_irrational::Quadratic64;
6use num_traits::{One, Pow, Zero};
7use std::fmt::{Debug, Display, Formatter};
8
9fn sprinti(f: &mut Formatter<'_>, i: &i64) -> std::fmt::Result {
11 if i.abs() >= 100000000 {
12 write!(f, "{:.7E}", i)
13 } else {
14 write!(f, "{}", i)
15 }
16}
17
18fn sprintbi(f: &mut Formatter<'_>, i: &BigInt) -> std::fmt::Result {
20 let decimal_digits = (i.bits() as f64) / 10f64.log2();
23 if decimal_digits > 7. {
24 let digits = decimal_digits.floor() as u32;
25 write!(
26 f,
27 "{}E{:+}",
28 (i / BigInt::from(10u8).pow(digits - 7)).to_f64().unwrap() / 10f64.pow(7),
29 digits
30 )
31 } else {
32 write!(f, "{}", i)
33 }
34}
35
36fn sprintf(f: &mut Formatter<'_>, v: &f64) -> std::fmt::Result {
38 if v.abs() >= 1e7 || v.abs() <= 1e-4 {
39 write!(f, "{:.7E}", v)
40 } else {
41 let s = v.to_string();
42 if s.len() > 9 {
43 f.write_str(&s[..9])
44 } else {
45 f.write_str(&s)
46 }
47 }
48}
49
50#[cfg(feature = "bigdecimal")]
52fn sprintbf(f: &mut Formatter<'_>, v: &bigdecimal::BigDecimal) -> std::fmt::Result {
53 let (mantissa, exp) = v.as_bigint_and_exponent();
55 let mantissa_digits = (mantissa.bits() as f64) / 10f64.log2();
56 let decimal_digits = mantissa_digits - exp as f64;
57 if decimal_digits >= 7. || decimal_digits < -4. {
58 let digits = decimal_digits.floor() as i32;
59 write!(
60 f,
61 "{}E{:+}",
62 (mantissa / BigInt::from(10u8).pow(mantissa_digits.floor() as u32 - 7))
63 .to_f64()
64 .unwrap()
65 / 10f64.pow(7),
66 digits
67 )
68 } else {
69 let s = v.to_string();
70 if s.len() > 9 {
71 f.write_str(&s[..9])
72 } else {
73 f.write_str(&s)
74 }
75 }
76}
77
78impl Debug for Subject {
79 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
80 match self {
81 Infinity(v) => {
82 if *v {
83 write!(f, "INF+")
84 } else {
85 write!(f, "INF-")
86 }
87 }
88 Int(v) => {
89 write!(f, "INT ")?;
90 sprinti(f, v)
91 }
92 BInt(v) => {
93 write!(f, "INT* ")?;
94 sprintbi(f, v)
95 }
96 Real(v) => {
97 write!(f, "REAL ")?;
98 sprintf(f, v)
99 }
100 #[cfg(feature = "bigdecimal")]
101 BReal(v) => {
102 write!(f, "REAL* ")?;
103 sprintbf(f, v)
104 }
105 Rational(v) => {
106 if v.denom().is_one() {
107 write!(f, "RATIONAL ")?;
108 sprinti(f, v.numer())
109 } else {
110 write!(f, "RATIONAL ")?;
111 sprinti(f, v.numer())?;
112 write!(f, " / ")?;
113 sprinti(f, v.denom())
114 }
115 }
116 Complex(v) => match (v.re == 0., v.im == 0.) {
117 (true, true) => write!(f, "COMPLEX 0"),
118 (true, false) => {
119 write!(f, "COMPLEX ")?;
120 sprintf(f, &v.im)?;
121 write!(f, "i")
122 }
123 (false, true) => {
124 write!(f, "COMPLEX ")?;
125 sprintf(f, &v.re)
126 }
127 (false, false) => {
128 write!(f, "COMPLEX ")?;
129 sprintf(f, &v.re)?;
130 if v.im > 0. {
131 write!(f, " + ")?;
132 if v.im != 1. {
133 sprintf(f, &v.im)?
134 }
135 } else {
136 write!(f, " - ")?;
137 if v.im != -1. {
138 sprintf(f, &-v.im)?
139 }
140 }
141 write!(f, "i")
142 }
143 },
144 Quad(v) => {
145 let (a, b, c, r) = v.parts();
146 write!(f, "QUAD ")?;
147
148 match (a.is_zero(), b.is_zero()) {
149 (true, true) => write!(f, "0"),
150 (false, false) => {
151 write!(f, "(")?;
153 sprinti(f, a)?;
154
155 if b > &0 {
156 write!(f, " + ")?;
157 sprinti(f, b)?;
158 } else {
159 write!(f, " - ")?;
160 sprinti(f, &-*b)?;
161 }
162 write!(f, "√")?;
163 sprinti(f, r)?;
164
165 if c.is_one() {
167 Ok(())
168 } else {
169 write!(f, " / ")?;
170 sprinti(f, c)
171 }
172 }
173 (az, _) => {
174 if az {
176 match b {
177 1 => {}
178 -1 => write!(f, "-")?,
179 b => sprinti(f, b)?,
180 }
181 write!(f, "√")?;
182 sprinti(f, r)?;
183 } else {
184 sprinti(f, a)?;
185 }
186
187 if c.is_one() {
189 Ok(())
190 } else {
191 write!(f, " / ")?;
192 sprinti(f, c)
193 }
194 }
195 }
196 }
197 _ => {
198 Display::fmt(self, f)
200 }
201 }
202 }
203}
204
205impl Display for Subject {
206 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
207 match self {
208 Infinity(v) => {
209 if *v {
210 write!(f, "+inf")
211 } else {
212 write!(f, "-inf")
213 }
214 }
215 Int(v) => Display::fmt(v, f),
216 BInt(v) => Display::fmt(v, f),
217 Real(v) => Display::fmt(v, f),
218 #[cfg(feature = "bigdecimal")]
219 BReal(v) => Display::fmt(v, f),
220 Rational(v) => Display::fmt(v, f),
221 BRational(v) => Display::fmt(v, f),
222 Quad(v) => Display::fmt(v, f),
223 BQuad(v) => Display::fmt(v, f),
224 Complex(v) => Display::fmt(v, f),
225 _ => write!(f, "..."),
226 }
227 }
228}
229
230impl Zero for Subject {
231 fn zero() -> Self {
232 Subject::Int(0)
233 }
234
235 fn is_zero(&self) -> bool {
236 match self {
237 Subject::Infinity(_) => false,
238 Subject::Int(v) => v.is_zero(),
239 Subject::BInt(v) => v.is_zero(),
240 Subject::Rational(v) => v.is_zero(),
241 Subject::BRational(v) => v.is_zero(),
242 Subject::Real(v) => v.is_zero(),
243 Subject::BReal(v) => v.is_zero(),
244 _ => unimplemented!()
245 }
246 }
247}
248
249impl One for Subject {
250 fn one() -> Self {
251 Subject::Int(1)
252 }
253
254 fn is_one(&self) -> bool {
255 match self {
256 Subject::Infinity(_) => false,
257 Subject::Int(v) => v.is_one(),
258 Subject::BInt(v) => v.is_one(),
259 Subject::Rational(v) => v.is_one(),
260 Subject::BRational(v) => v.is_one(),
261 Subject::Real(v) => v.is_one(),
262 Subject::BReal(v) => v.is_one(),
263 _ => unimplemented!()
264 }
265 }
266}
267
268pub enum Rounding {
269 Nearest,
270 Up,
271 Down,
272 ToZero,
273 AwayZero,
274}
275
276pub enum Precision {
277 Bits(usize),
279 Digits(usize),
281}
282
283impl Subject {
285 pub fn int(self, rounding: Option<Rounding>) -> Self {
287 use std::cmp::Ordering::*;
288 use Rounding::*;
289
290 match self {
291 Int(v) => Int(v),
292 BInt(v) => BInt(v),
293 Rational(v) => {
294 let (quo, rem) = v.numer().div_rem(v.denom());
295 match (rounding.unwrap_or(Nearest), rem.cmp(&0)) {
296 (_, Equal) | (ToZero, _) => Int(quo),
297 (Nearest, Greater) => Int(if rem * 2 > *v.denom() { quo + 1 } else { quo }),
298 (Nearest, Less) => Int(if rem * 2 + v.denom() > 0 { quo + 1 } else { quo }),
299 (Up, Greater) => Int(quo + 1),
300 (Up, Less) | (Down, Greater) => Int(quo),
301 (Down, Less) => Int(quo - 1),
302 (AwayZero, Greater) => Int(quo + 1),
303 (AwayZero, Less) => Int(quo - 1),
304 }
305 },
306 _ => unimplemented!()
307 }
308 }
309 pub fn real(self, precision: Option<Precision>, rounding: Option<Rounding>) -> Self {
310 unimplemented!() }
312 pub fn rational(self, precision: Option<Precision>, rounding: Option<Rounding>) -> Self {
313 unimplemented!() }
315 pub fn complex(self, precision: Option<Precision>, rounding: Option<Rounding>) -> Self {
316 unimplemented!() }
318 pub fn modulo(self, modulus: Self) -> ModularSubject { unimplemented!() }
319 pub fn quad(self, precision: Option<Precision>, rounding: Option<Rounding>) -> Self { unimplemented!() }
320 pub fn quadint(self, base: Self, rounding: Option<Rounding>) -> Self { unimplemented!() }
321 pub fn cfrac(self) -> CfracSubject { unimplemented!() }
322}
323
324impl Subject {
325 pub fn prec(&self) -> Precision {
327 unimplemented!()
328 }
329 pub fn trunc(&self) -> Subject {
331 unimplemented!()
332 }
333 pub fn frac(&self) -> Subject {
335 unimplemented!()
336 }
337}
338
339fn abs() {}
340fn conj() {}
341fn arg() {}