1 use crate::error::{FendError, Interrupt}; 2 use crate::format::Format; 3 use crate::num::bigrat::{BigRat, FormattedBigRat}; 4 use crate::num::Exact; 5 use crate::num::{Base, FormattingStyle}; 6 use crate::result::FResult; 7 use crate::serialize::{Deserialize, Serialize}; 8 use std::cmp::Ordering; 9 use std::ops::Neg; 10 use std::{fmt, hash, io}; 11 12 use super::bigrat; 13 14 #[derive(Clone)] 15 pub(crate) struct Real { 16 pattern: Pattern, 17 } 18 19 impl fmt::Debug for Real { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 21 match &self.pattern { 22 Pattern::Simple(x) => write!(f, "{x:?}"), 23 Pattern::Pi(x) => { 24 if x.is_definitely_one() { 25 write!(f, "pi") 26 } else { 27 write!(f, "{x:?} * pi") 28 } 29 } 30 } 31 } 32 } 33 34 #[derive(Clone, Debug)] 35 pub(crate) enum Pattern { 36 /// a simple fraction 37 Simple(BigRat), 38 // n * pi 39 Pi(BigRat), 40 } 41 42 impl hash::Hash for Real { hash<H: hash::Hasher>(&self, state: &mut H)43 fn hash<H: hash::Hasher>(&self, state: &mut H) { 44 match &self.pattern { 45 Pattern::Simple(r) | Pattern::Pi(r) => r.hash(state), 46 } 47 } 48 } 49 50 impl Real { compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<Ordering>51 pub(crate) fn compare<I: Interrupt>(&self, other: &Self, int: &I) -> FResult<Ordering> { 52 Ok(match (&self.pattern, &other.pattern) { 53 (Pattern::Simple(a), Pattern::Simple(b)) | (Pattern::Pi(a), Pattern::Pi(b)) => a.cmp(b), 54 _ => { 55 let a = self.clone().approximate(int)?; 56 let b = other.clone().approximate(int)?; 57 a.cmp(&b) 58 } 59 }) 60 } 61 serialize(&self, write: &mut impl io::Write) -> FResult<()>62 pub(crate) fn serialize(&self, write: &mut impl io::Write) -> FResult<()> { 63 match &self.pattern { 64 Pattern::Simple(s) => { 65 1u8.serialize(write)?; 66 s.serialize(write)?; 67 } 68 Pattern::Pi(n) => { 69 2u8.serialize(write)?; 70 n.serialize(write)?; 71 } 72 } 73 Ok(()) 74 } 75 deserialize(read: &mut impl io::Read) -> FResult<Self>76 pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> { 77 Ok(Self { 78 pattern: match u8::deserialize(read)? { 79 1 => Pattern::Simple(BigRat::deserialize(read)?), 80 2 => Pattern::Pi(BigRat::deserialize(read)?), 81 _ => return Err(FendError::DeserializationError), 82 }, 83 }) 84 } 85 is_integer(&self) -> bool86 pub(crate) fn is_integer(&self) -> bool { 87 match &self.pattern { 88 Pattern::Simple(s) => s.is_integer(), 89 Pattern::Pi(_) => false, 90 } 91 } 92 approximate<I: Interrupt>(self, int: &I) -> FResult<BigRat>93 fn approximate<I: Interrupt>(self, int: &I) -> FResult<BigRat> { 94 match self.pattern { 95 Pattern::Simple(s) => Ok(s), 96 Pattern::Pi(n) => { 97 let num = BigRat::from(3_141_592_653_589_793_238); 98 let den = BigRat::from(1_000_000_000_000_000_000); 99 let pi = num.div(&den, int)?; 100 Ok(n.mul(&pi, int)?) 101 } 102 } 103 } 104 try_as_i64<I: Interrupt>(self, int: &I) -> FResult<i64>105 pub(crate) fn try_as_i64<I: Interrupt>(self, int: &I) -> FResult<i64> { 106 match self.pattern { 107 Pattern::Simple(s) => s.try_as_i64(int), 108 Pattern::Pi(n) => { 109 if n == 0.into() { 110 Ok(0) 111 } else { 112 Err(FendError::CannotConvertToInteger) 113 } 114 } 115 } 116 } 117 try_as_usize<I: Interrupt>(self, int: &I) -> FResult<usize>118 pub(crate) fn try_as_usize<I: Interrupt>(self, int: &I) -> FResult<usize> { 119 match self.pattern { 120 Pattern::Simple(s) => s.try_as_usize(int), 121 Pattern::Pi(n) => { 122 if n == 0.into() { 123 Ok(0) 124 } else { 125 Err(FendError::CannotConvertToInteger) 126 } 127 } 128 } 129 } 130 131 // sin works for all real numbers sin<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>>132 pub(crate) fn sin<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>> { 133 Ok(match self.pattern { 134 Pattern::Simple(s) => s.sin(int)?.apply(Self::from), 135 Pattern::Pi(n) => { 136 if n < 0.into() { 137 let s = Self { 138 pattern: Pattern::Pi(n), 139 }; 140 // sin(-x) == -sin(x) 141 return Ok(-Self::sin(-s, int)?); 142 } 143 if let Ok(integer) = n.clone().mul(&6.into(), int)?.try_as_usize(int) { 144 // values from https://en.wikipedia.org/wiki/Exact_trigonometric_values 145 if integer % 6 == 0 { 146 return Ok(Exact::new(Self::from(0), true)); 147 } else if integer % 12 == 3 { 148 return Ok(Exact::new(Self::from(1), true)); 149 } else if integer % 12 == 9 { 150 return Ok(Exact::new(-Self::from(1), true)); 151 } else if integer % 12 == 1 || integer % 12 == 5 { 152 return Exact::new(Self::from(1), true) 153 .div(&Exact::new(2.into(), true), int); 154 } else if integer % 12 == 7 || integer % 12 == 11 { 155 return Exact::new(-Self::from(1), true) 156 .div(&Exact::new(2.into(), true), int); 157 } 158 } 159 let s = Self { 160 pattern: Pattern::Pi(n), 161 }; 162 s.approximate(int)?.sin(int)?.apply(Self::from) 163 } 164 }) 165 } 166 cos<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>>167 pub(crate) fn cos<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>> { 168 // cos(x) = sin(x + pi/2) 169 let half_pi = Exact::new(Self::pi(), true).div(&Exact::new(Self::from(2), true), int)?; 170 Exact::new(self, true).add(half_pi, int)?.value.sin(int) 171 } 172 asin<I: Interrupt>(self, int: &I) -> FResult<Self>173 pub(crate) fn asin<I: Interrupt>(self, int: &I) -> FResult<Self> { 174 Ok(Self::from(self.approximate(int)?.asin(int)?)) 175 } 176 acos<I: Interrupt>(self, int: &I) -> FResult<Self>177 pub(crate) fn acos<I: Interrupt>(self, int: &I) -> FResult<Self> { 178 Ok(Self::from(self.approximate(int)?.acos(int)?)) 179 } 180 atan<I: Interrupt>(self, int: &I) -> FResult<Self>181 pub(crate) fn atan<I: Interrupt>(self, int: &I) -> FResult<Self> { 182 Ok(Self::from(self.approximate(int)?.atan(int)?)) 183 } 184 atan2<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self>185 pub(crate) fn atan2<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self> { 186 Ok(Self::from( 187 self.approximate(int)?.atan2(rhs.approximate(int)?, int)?, 188 )) 189 } 190 sinh<I: Interrupt>(self, int: &I) -> FResult<Self>191 pub(crate) fn sinh<I: Interrupt>(self, int: &I) -> FResult<Self> { 192 Ok(Self::from(self.approximate(int)?.sinh(int)?)) 193 } 194 cosh<I: Interrupt>(self, int: &I) -> FResult<Self>195 pub(crate) fn cosh<I: Interrupt>(self, int: &I) -> FResult<Self> { 196 Ok(Self::from(self.approximate(int)?.cosh(int)?)) 197 } 198 tanh<I: Interrupt>(self, int: &I) -> FResult<Self>199 pub(crate) fn tanh<I: Interrupt>(self, int: &I) -> FResult<Self> { 200 Ok(Self::from(self.approximate(int)?.tanh(int)?)) 201 } 202 asinh<I: Interrupt>(self, int: &I) -> FResult<Self>203 pub(crate) fn asinh<I: Interrupt>(self, int: &I) -> FResult<Self> { 204 Ok(Self::from(self.approximate(int)?.asinh(int)?)) 205 } 206 acosh<I: Interrupt>(self, int: &I) -> FResult<Self>207 pub(crate) fn acosh<I: Interrupt>(self, int: &I) -> FResult<Self> { 208 Ok(Self::from(self.approximate(int)?.acosh(int)?)) 209 } 210 atanh<I: Interrupt>(self, int: &I) -> FResult<Self>211 pub(crate) fn atanh<I: Interrupt>(self, int: &I) -> FResult<Self> { 212 Ok(Self::from(self.approximate(int)?.atanh(int)?)) 213 } 214 215 // For all logs: value must be greater than 0 ln<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>>216 pub(crate) fn ln<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>> { 217 Ok(self.approximate(int)?.ln(int)?.apply(Self::from)) 218 } 219 log2<I: Interrupt>(self, int: &I) -> FResult<Self>220 pub(crate) fn log2<I: Interrupt>(self, int: &I) -> FResult<Self> { 221 Ok(Self::from(self.approximate(int)?.log2(int)?)) 222 } 223 log10<I: Interrupt>(self, int: &I) -> FResult<Self>224 pub(crate) fn log10<I: Interrupt>(self, int: &I) -> FResult<Self> { 225 Ok(Self::from(self.approximate(int)?.log10(int)?)) 226 } 227 factorial<I: Interrupt>(self, int: &I) -> FResult<Self>228 pub(crate) fn factorial<I: Interrupt>(self, int: &I) -> FResult<Self> { 229 Ok(Self::from(self.approximate(int)?.factorial(int)?)) 230 } 231 floor<I: Interrupt>(self, int: &I) -> FResult<Self>232 pub(crate) fn floor<I: Interrupt>(self, int: &I) -> FResult<Self> { 233 Ok(Self::from(self.approximate(int)?.floor(int)?)) 234 } 235 ceil<I: Interrupt>(self, int: &I) -> FResult<Self>236 pub(crate) fn ceil<I: Interrupt>(self, int: &I) -> FResult<Self> { 237 Ok(Self::from(self.approximate(int)?.ceil(int)?)) 238 } 239 round<I: Interrupt>(self, int: &I) -> FResult<Self>240 pub(crate) fn round<I: Interrupt>(self, int: &I) -> FResult<Self> { 241 Ok(Self::from(self.approximate(int)?.round(int)?)) 242 } 243 format<I: Interrupt>( &self, base: Base, mut style: FormattingStyle, imag: bool, use_parens_if_fraction: bool, int: &I, ) -> FResult<Exact<Formatted>>244 pub(crate) fn format<I: Interrupt>( 245 &self, 246 base: Base, 247 mut style: FormattingStyle, 248 imag: bool, 249 use_parens_if_fraction: bool, 250 int: &I, 251 ) -> FResult<Exact<Formatted>> { 252 let mut pi = false; 253 if style == FormattingStyle::Exact && !self.is_zero() { 254 if let Pattern::Pi(_) = self.pattern { 255 pi = true; 256 } 257 } 258 259 let term = match (imag, pi) { 260 (false, false) => "", 261 (false, true) => "\u{3c0}", // pi symbol 262 (true, false) => "i", 263 (true, true) => "\u{3c0}i", 264 }; 265 266 let mut override_exact = true; 267 268 let rat = match &self.pattern { 269 Pattern::Simple(f) => f.clone(), 270 Pattern::Pi(f) => { 271 if pi { 272 f.clone() 273 } else { 274 override_exact = false; 275 if style == FormattingStyle::Auto { 276 style = FormattingStyle::DecimalPlaces(10); 277 } 278 self.clone().approximate(int)? 279 } 280 } 281 }; 282 283 let formatted = rat.format( 284 &bigrat::FormatOptions { 285 base, 286 style, 287 term, 288 use_parens_if_fraction, 289 }, 290 int, 291 )?; 292 let exact = formatted.exact && override_exact; 293 Ok(Exact::new( 294 Formatted { 295 num: formatted.value, 296 }, 297 exact, 298 )) 299 } 300 exp<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>>301 pub(crate) fn exp<I: Interrupt>(self, int: &I) -> FResult<Exact<Self>> { 302 Ok(self.approximate(int)?.exp(int)?.apply(Self::from)) 303 } 304 pow<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Exact<Self>>305 pub(crate) fn pow<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Exact<Self>> { 306 // x^1 == x 307 if let Pattern::Simple(n) = &rhs.pattern { 308 if n == &1.into() { 309 return Ok(Exact::new(self, true)); 310 } 311 } 312 313 // 1^x == 1 314 if let Pattern::Simple(n) = &self.pattern { 315 if n == &1.into() { 316 return Ok(Exact::new(1.into(), true)); 317 } 318 } 319 320 if let (Pattern::Simple(a), Pattern::Simple(b)) = 321 (self.clone().pattern, rhs.clone().pattern) 322 { 323 Ok(a.pow(b, int)?.apply(Self::from)) 324 } else { 325 Ok(self 326 .approximate(int)? 327 .pow(rhs.approximate(int)?, int)? 328 .combine(false) 329 .apply(Self::from)) 330 } 331 } 332 root_n<I: Interrupt>(self, n: &Self, int: &I) -> FResult<Exact<Self>>333 pub(crate) fn root_n<I: Interrupt>(self, n: &Self, int: &I) -> FResult<Exact<Self>> { 334 // TODO: Combining these match blocks is not currently possible because 335 // 'binding by-move and by-ref in the same pattern is unstable' 336 // https://github.com/rust-lang/rust/pull/76119 337 Ok(match self.pattern { 338 Pattern::Simple(a) => match &n.pattern { 339 Pattern::Simple(b) => a.root_n(b, int)?.apply(Self::from), 340 Pattern::Pi(_) => { 341 let b = n.clone().approximate(int)?; 342 a.root_n(&b, int)?.apply(Self::from).combine(false) 343 } 344 }, 345 Pattern::Pi(_) => { 346 let a = self.clone().approximate(int)?; 347 let b = n.clone().approximate(int)?; 348 a.root_n(&b, int)?.apply(Self::from).combine(false) 349 } 350 }) 351 } 352 pi() -> Self353 pub(crate) fn pi() -> Self { 354 Self { 355 pattern: Pattern::Pi(1.into()), 356 } 357 } 358 is_zero(&self) -> bool359 pub(crate) fn is_zero(&self) -> bool { 360 match &self.pattern { 361 Pattern::Simple(a) | Pattern::Pi(a) => a.is_definitely_zero() || a == &0.into(), 362 } 363 } 364 is_pos(&self) -> bool365 pub(crate) fn is_pos(&self) -> bool { 366 match &self.pattern { 367 Pattern::Simple(a) | Pattern::Pi(a) => !a.is_definitely_zero() && a > &0.into(), 368 } 369 } 370 is_neg(&self) -> bool371 pub(crate) fn is_neg(&self) -> bool { 372 match &self.pattern { 373 Pattern::Simple(a) | Pattern::Pi(a) => !a.is_definitely_zero() && a < &0.into(), 374 } 375 } 376 between_plus_minus_one_incl<I: Interrupt>(&self, int: &I) -> FResult<bool>377 pub(crate) fn between_plus_minus_one_incl<I: Interrupt>(&self, int: &I) -> FResult<bool> { 378 // -1 <= x <= 1 379 Ok(Self::from(1).neg().compare(self, int)? != Ordering::Greater 380 && self.compare(&1.into(), int)? != Ordering::Greater) 381 } 382 between_plus_minus_one_excl<I: Interrupt>(&self, int: &I) -> FResult<bool>383 pub(crate) fn between_plus_minus_one_excl<I: Interrupt>(&self, int: &I) -> FResult<bool> { 384 // -1 < x < 1 385 Ok(Self::from(1).neg().compare(self, int)? == Ordering::Less 386 && self.compare(&1.into(), int)? == Ordering::Less) 387 } 388 is_definitely_zero(&self) -> bool389 pub(crate) fn is_definitely_zero(&self) -> bool { 390 match &self.pattern { 391 Pattern::Simple(a) | Pattern::Pi(a) => a.is_definitely_zero(), 392 } 393 } 394 is_definitely_one(&self) -> bool395 pub(crate) fn is_definitely_one(&self) -> bool { 396 match &self.pattern { 397 Pattern::Simple(a) => a.is_definitely_one(), 398 Pattern::Pi(_) => false, 399 } 400 } 401 expect_rational(self) -> FResult<BigRat>402 pub(crate) fn expect_rational(self) -> FResult<BigRat> { 403 match self.pattern { 404 Pattern::Simple(a) => Ok(a), 405 Pattern::Pi(_) => Err(FendError::ExpectedARationalNumber), 406 } 407 } 408 modulo<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self>409 pub(crate) fn modulo<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self> { 410 Ok(Self::from( 411 self.expect_rational()? 412 .modulo(rhs.expect_rational()?, int)?, 413 )) 414 } 415 bitwise<I: Interrupt>( self, rhs: Self, op: crate::ast::BitwiseBop, int: &I, ) -> FResult<Self>416 pub(crate) fn bitwise<I: Interrupt>( 417 self, 418 rhs: Self, 419 op: crate::ast::BitwiseBop, 420 int: &I, 421 ) -> FResult<Self> { 422 Ok(Self::from(self.expect_rational()?.bitwise( 423 rhs.expect_rational()?, 424 op, 425 int, 426 )?)) 427 } 428 combination<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self>429 pub(crate) fn combination<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self> { 430 Ok(Self::from( 431 self.expect_rational()? 432 .combination(rhs.expect_rational()?, int)?, 433 )) 434 } 435 permutation<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self>436 pub(crate) fn permutation<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self> { 437 Ok(Self::from( 438 self.expect_rational()? 439 .permutation(rhs.expect_rational()?, int)?, 440 )) 441 } 442 } 443 444 impl Exact<Real> { add<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self>445 pub(crate) fn add<I: Interrupt>(self, rhs: Self, int: &I) -> FResult<Self> { 446 if self.exact && self.value.is_zero() { 447 return Ok(rhs); 448 } else if rhs.exact && rhs.value.is_zero() { 449 return Ok(self); 450 } 451 let args_exact = self.exact && rhs.exact; 452 Ok( 453 match (self.clone().value.pattern, rhs.clone().value.pattern) { 454 (Pattern::Simple(a), Pattern::Simple(b)) => { 455 Self::new(a.add(b, int)?.into(), args_exact) 456 } 457 (Pattern::Pi(a), Pattern::Pi(b)) => Self::new( 458 Real { 459 pattern: Pattern::Pi(a.add(b, int)?), 460 }, 461 args_exact, 462 ), 463 _ => { 464 let a = self.value.approximate(int)?; 465 let b = rhs.value.approximate(int)?; 466 Self::new(a.add(b, int)?.into(), false) 467 } 468 }, 469 ) 470 } 471 mul<I: Interrupt>(self, rhs: Exact<&Real>, int: &I) -> FResult<Self>472 pub(crate) fn mul<I: Interrupt>(self, rhs: Exact<&Real>, int: &I) -> FResult<Self> { 473 if self.exact && self.value.is_zero() { 474 return Ok(self); 475 } else if rhs.exact && rhs.value.is_zero() { 476 return Ok(Self::new(rhs.value.clone(), rhs.exact)); 477 } 478 let args_exact = self.exact && rhs.exact; 479 Ok(match self.value.pattern { 480 Pattern::Simple(a) => match &rhs.value.pattern { 481 Pattern::Simple(b) => Self::new(a.mul(b, int)?.into(), args_exact), 482 Pattern::Pi(b) => Self::new( 483 Real { 484 pattern: Pattern::Pi(a.mul(b, int)?), 485 }, 486 args_exact, 487 ), 488 }, 489 Pattern::Pi(a) => match &rhs.value.pattern { 490 Pattern::Simple(b) => Self::new( 491 Real { 492 pattern: Pattern::Pi(a.mul(b, int)?), 493 }, 494 args_exact, 495 ), 496 Pattern::Pi(_) => Self::new( 497 Real { 498 pattern: Pattern::Pi(a.mul(&rhs.value.clone().approximate(int)?, int)?), 499 }, 500 false, 501 ), 502 }, 503 }) 504 } 505 div<I: Interrupt>(self, rhs: &Self, int: &I) -> FResult<Self>506 pub(crate) fn div<I: Interrupt>(self, rhs: &Self, int: &I) -> FResult<Self> { 507 if rhs.value.is_zero() { 508 return Err(FendError::DivideByZero); 509 } 510 if self.exact && self.value.is_zero() { 511 return Ok(self); 512 } 513 Ok(match self.value.pattern { 514 Pattern::Simple(a) => match &rhs.value.pattern { 515 Pattern::Simple(b) => Self::new(a.div(b, int)?.into(), self.exact && rhs.exact), 516 Pattern::Pi(_) => Self::new( 517 a.div(&rhs.value.clone().approximate(int)?, int)?.into(), 518 false, 519 ), 520 }, 521 Pattern::Pi(a) => match &rhs.value.pattern { 522 Pattern::Simple(b) => Self::new( 523 Real { 524 pattern: Pattern::Pi(a.div(b, int)?), 525 }, 526 self.exact && rhs.exact, 527 ), 528 Pattern::Pi(b) => Self::new(a.div(b, int)?.into(), self.exact && rhs.exact), 529 }, 530 }) 531 } 532 } 533 534 impl Neg for Real { 535 type Output = Self; 536 neg(self) -> Self537 fn neg(self) -> Self { 538 match self.pattern { 539 Pattern::Simple(s) => Self::from(-s), 540 Pattern::Pi(n) => Self { 541 pattern: Pattern::Pi(-n), 542 }, 543 } 544 } 545 } 546 547 impl From<u64> for Real { from(i: u64) -> Self548 fn from(i: u64) -> Self { 549 Self { 550 pattern: Pattern::Simple(i.into()), 551 } 552 } 553 } 554 555 impl From<BigRat> for Real { from(n: BigRat) -> Self556 fn from(n: BigRat) -> Self { 557 Self { 558 pattern: Pattern::Simple(n), 559 } 560 } 561 } 562 563 #[derive(Debug)] 564 pub(crate) struct Formatted { 565 num: FormattedBigRat, 566 } 567 568 impl fmt::Display for Formatted { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result569 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 570 write!(f, "{}", self.num) 571 } 572 } 573