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 135 136 137
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
// enable pedantic group but not all
#![warn(clippy::pedantic)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_possible_wrap)]
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::explicit_iter_loop)]
#![allow(clippy::if_not_else)]
#![allow(clippy::inline_always)]
#![allow(clippy::match_same_arms)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::single_match_else)]
//! Arbitrary precision scientific number
//!
//! # Constants
//!
//! Use `Scientific!` in the crate [`scientific-macro`](https://docs.rs/scientific-macro) to create constant numbers.
//!
//! ```ignore
//! use scientific_macro::Scientific;
//! let n1 = Scientific!(1e100);
//! let n2 = Scientific!(1e80);
//! assert_eq!(&n1 + &n2, Scientific!(1.00000000000000000001e100));
//! // An f64 has only a precision of about 15.9 digits, this are already 21.
//! ```
//!
//! # Invocation
//!
//! All functions expect a reference to the [`Scientific`](crate::Scientific) number. (See example above.)
//!
//! # Conversion
//!
//! There are `From` and `TryFrom` traits for conversion between [`Scientific`](crate::Scientific) and integers, floats and strings.
//!
//! Converting a scientific number with decimals to an integer will fail.
//!
//! There is a `FromStr` instance (which clones the `str` and calls [`Scientific::from_string`](crate::Scientific::from_string)).
//!
//! The functions [`Scientific::to_bytes`](crate::Scientific::to_bytes) and [`Scientific::from_bytes`](crate::Scientific::from_bytes) use a compressed representation and not ASCII
//! (this format will also be used when using serde with non human-readable formats).
//!
//! # Precision
//!
//! Most functions work in truly arbitrary precision, please be aware of this.
//!
//! For example: adding 1e1000 and 1e-1000, which both have only one byte of mantissa, results in 2001 bytes of mantissa.
//!
//! Functions for division and square root (which depends on div) as also all rounding functions require
//! a precision to be specified, the result is only calculated to that precision.
//!
//! It can be specified as [`Decimals`](crate::Decimals) or [`Digits`](crate::Digits). When using decimals specify the number of decimal places to
//! calculate (`2` for `0.01` as the smallest number, `0` for `1` and `-2` for `100`). When using digits specify
//! the number of digits in the mantissa (using <= 0 digits will always result in zero).
//!
//! Shortcuts: [`Precision::INTEGER`](crate::Precision::INTEGER) for integer calculations (aka `Decimals(0)`) and [`Precision::F64`](crate::Precision::F64) for
//! calculations with a slightly better precision as an f64 (aka `Digits(16)`).
//!
//! # Shifting
//!
//! The shifting operators do shift by one digit (and not one bit as you may expected).
//!
//! # Rounding
//!
//! The functions [`round`](crate::Scientific::round)/[`round_assign`](crate::Scientific::round_assign) support several rounding options. See [`Rounding`](crate::Rounding).
//!
//! The functions above should be only used for the final rounding. If rounding in between is required (e.g. to keep the mantissa manageable) use
//! [`round_rpsp`](crate::Scientific::round_rpsp)/[`round_assign`](crate::Scientific::round_rpsp_assign) with at least the same precision than the final one.
//! The rounding will create one more digit than you required, to easily use it.
//! RPSP stands for Rounding to prepare for shorter precision, see [Wikipedia](https://en.wikipedia.org/wiki/Rounding#Rounding_to_prepare_for_shorter_precision) for more information.
//!
//! In any case it's preferred to use the `*_assign` version since it can save reallocation of the mantissa (though not everytime relocation is required or can be avoided).
//!
//! ## Example
//!
//! ```
//! # use scientific::{Precision, RoundHalfUp, Scientific};
//! # let mut value = Scientific::ZERO;
//! let precision = Precision::Digits(30); // precision for intermediate roundings and the final one
//! // do calculations
//! value.round_rpsp_assign(precision); // round to 31 digits with 'Rounding to prepare for shorter precision'
//! // do more calculations
//! value.round_assign(precision, RoundHalfUp); // round to 30 digits with the method 'RoundHalfUp'
//! ```
//!
//! # Truncating
//!
//! The functions [`truncate`](crate::Scientific::truncate)/[`truncate_assign`](crate::Scientific::truncate_assign) are identical to rounding with [`RoundTowardsZero`](crate::Rounding::RoundTowardsZero) but faster.
//!
//! Also [`truncate_assign`](crate::Scientific::truncate_assign) is faster than [`truncate`](crate::Scientific::truncate) because it does not need to clone.
//! Either way it does never require relocation of the mantissa (since it's not changed, just maybe referenced to a prefix of it).
//!
//! # Features
//!
//! - `serde`: Enable De-/Serialization with serde.
//!
//! - `std`: If activated the library requires `std` and the [`Error`](::std::error::Error]) trait is implemented for all error types.
//! Without it the library is `no_std`.
//!
//! - `arc`: Use of [`Arc`](::alloc::sync::Arc) instead of [`Rc`](::alloc::rc::Rc), which enables [`Send`](::core::marker::Send) and [`Sync`](::core::marker::Sync) for [`Scientific`](crate::Scientific).
//! Though [`Arc`](::alloc::sync::Arc) is more expensive, but since it's only used during create/clone/drop of
//! the [`Scientific`](crate::Scientific) number it's probably not that much.
//!
//! - `debug`: Enables several checks. Very helpful during development of this lib.
//!
//! # Exponent
//!
//! The exponent is represented as an [`isize`](::core::isize). It is expected that it will never under-/overflow,
//! even when smaller numbers are added/subtracted, like e.g. the length of the mantissa.
//!
//! This is not checked!
#[macro_use]
extern crate alloc;
#[cfg(not(no_re_export))]
pub use crate::types::conversion_error::ConversionError;
#[cfg(not(no_re_export))]
pub use crate::types::error::Error;
#[cfg(not(no_re_export))]
pub use crate::types::precision::Precision::{self, Decimals, Digits};
#[cfg(not(no_re_export))]
pub use crate::types::rounding::Rounding::{
self, RoundAwayFromZero, RoundDown, RoundHalfAwayFromZero, RoundHalfDown, RoundHalfToEven,
RoundHalfToOdd, RoundHalfTowardsZero, RoundHalfUp, RoundUp,
};
#[cfg(not(no_re_export))]
pub use crate::types::scientific::Scientific;
#[doc(hidden)]
#[cfg(not(no_re_export))]
pub mod __private;
pub(crate) mod conversion;
pub(crate) mod math;
pub(crate) mod types;