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
//! Precision-control helpers for the `DBig` wrapper.
//!
//! These free functions wrap `dashu-float` precision primitives in an
//! ergonomic, allocation-friendly API:
//!
//! * [`with_precision`] — rebind a value to a different working precision.
//! * [`epsilon`] — the smallest positive *unit* representable at a given
//! decimal precision, i.e. `10^(1 - precision)` at the requested
//! precision.
//! * [`ulp`] — the unit in the last place of a specific value at the
//! precision currently carried by its context.
//!
//! All three operate on the decimal big-float (`DBig = FBig<HalfAway, 10>`)
//! so callers do not have to spell out the underlying generic parameters.
//!
//! # `precision == 0` (unlimited)
//!
//! `dashu-float` reserves a `precision` of `0` to mean *unlimited*.
//! `ulp` is not meaningful in that regime and the underlying
//! `dashu_float::FBig::ulp` panics in that case. We surface that as an
//! [`OxiNumError::Precision`] instead — see [`ulp`] for details.
use FromStr;
use crate::;
/// Return `x` rebound to the requested *decimal* precision.
///
/// This delegates to [`dashu_float::FBig::with_precision`], which returns
/// an [`dashu_base::Approximation`] indicating whether the rebind was
/// exact (the new precision was at least the old digit count) or
/// inexact (digits were rounded off). This helper discards that
/// distinction and returns the rounded value directly. Use the raw
/// `dashu-float` API if you need the inexact-flag.
///
/// `precision == 0` is *unlimited* precision in `dashu-float`'s
/// vocabulary, which is also passed through unchanged.
///
/// # Examples
///
/// ```
/// use std::str::FromStr;
/// use oxinum_float::{precision::with_precision, DBig};
///
/// let a = DBig::from_str("1.234").expect("parse 1.234");
/// let a100 = with_precision(&a, 100);
/// assert_eq!(a100.precision(), 100);
/// ```
/// Return the smallest positive "unit" representable at the requested
/// decimal precision, i.e. `10^(1 - precision)` rounded to `precision`
/// significant digits.
///
/// In decimal base, a value with precision `p` has its least significant
/// digit at position `10^(1 - p)` when the leading digit is `1` —
/// this is the "epsilon" in the floating-point sense.
///
/// `precision == 0` is *unlimited* precision in `dashu-float`'s
/// vocabulary; in that case there is no meaningful machine epsilon, so
/// this helper returns an error.
///
/// # Errors
///
/// Returns [`OxiNumError::Precision`] if `precision == 0`.
///
/// # Examples
///
/// ```
/// use std::str::FromStr;
/// use oxinum_float::{precision::epsilon, DBig};
///
/// let eps10 = epsilon(10).expect("precision 10");
/// // 10^(1 - 10) = 10^-9, at precision 10.
/// assert_eq!(eps10.precision(), 10);
///
/// let expected = DBig::from_str("1e-9")
/// .expect("parse 1e-9")
/// .with_precision(10)
/// .value();
/// assert_eq!(eps10, expected);
/// ```
/// Return the unit in the last place of `x` at its current precision.
///
/// This is `dashu_float::FBig::ulp` re-exported as a free function for
/// API symmetry with [`epsilon`] and [`with_precision`]. The result is
/// a positive value whose least significant decimal position matches
/// `x` (i.e. `ulp(x)` is the smallest positive `d` such that `x + d`
/// is the next representable neighbour of `x`).
///
/// # Errors
///
/// Returns [`OxiNumError::Precision`] if `x` carries unlimited
/// precision (`x.precision() == 0`). In that case `ulp` is
/// undefined — `dashu_float::FBig::ulp` would itself panic, which we
/// surface as a recoverable error here.
///
/// # Examples
///
/// ```
/// use std::str::FromStr;
/// use oxinum_float::{precision::ulp, DBig};
///
/// let x = DBig::from_str("1.23").expect("parse 1.23");
/// let u = ulp(&x).expect("finite precision");
/// assert_eq!(u, DBig::from_str("0.01").expect("parse 0.01"));
/// // ulp does not change the carried precision.
/// assert_eq!(u.precision(), x.precision());
/// ```