computable_real/lib.rs
1//! This crate provides an API to work with computable real numbers (or recursive
2//! real numbers). We represent real numbers as a function that accepts a
3//! desired precision level and returns an approximation of the real number.
4//! By providing an increasingly smaller precision level, we can approximate
5//! the real number to an arbitrary precision.
6//!
7//! The idea is from the paper [Towards an API for the Real Numbers] by H. Boehm,
8//! and the overall design and a lot of the functions are from the [CR.java] and
9//! [UnaryCRFunction.java] files in the Android ART repository.
10//!
11//! # Example
12//!
13//! ```
14//! use computable_real::Real;
15//!
16//! let pi = Real::pi();
17//! println!("π = {}", pi.render(10));
18//! assert_eq!(pi.render(10), "3.1415926536");
19//! let sin_pi = pi.clone().sin();
20//! println!("sin(π) = {}", sin_pi.render(10));
21//! assert_eq!(sin_pi.render(10), "0.0000000000");
22//!
23//! // We can evaluate and render pi past the limit of f64
24//! println!("π = {}", pi.render(30));
25//! assert_eq!(pi.render(30), "3.141592653589793238462643383280");
26//! ```
27//!
28//! [CR.java]: https://android-review.googlesource.com/c/platform/art/+/1012109/7/test/1972-math-prec/src/com/hp/creals/CR.java
29//! [UnaryCRFunction.java]: https://android-review.googlesource.com/c/platform/art/+/1012109/7/test/1972-math-prec/src/com/hp/creals/UnaryCRFunction.java
30//! [Towards an API for the Real Numbers]: https://dl.acm.org/doi/pdf/10.1145/3385412.3386037
31
32mod real;
33pub use real::Comparator;
34pub use real::Real;
35
36mod approx;
37pub use approx::Approx;
38
39mod prim;
40use prim::Primitive;
41
42mod traits;
43
44use num::BigInt;
45
46/// Scales a BigInt by 2^bits, and rounds towards the closest integer.
47fn scale(n: BigInt, bits: i32) -> BigInt {
48 if bits >= 0 {
49 n << bits
50 } else {
51 (n + (BigInt::from(1) << -(bits + 1))) >> -bits
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 #[test]
58 fn test_scale() {
59 use super::scale;
60 use num::BigInt;
61
62 // 7/4 = 1.75, so it should round to 2
63 // If we naively do 7 >> 2, we get 1
64 assert_eq!(scale(7.into(), -2), BigInt::from(2));
65 }
66}