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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! A unified numeric type system for Rust with automatic overflow handling and
//! ergonomic primitive operations.
//!
//! This crate provides the `Number` enum which unifies all numeric types
//! and provides consistent behavior across operations with automatic type
//! promotion and overflow handling.
// Multiple versions of some transitive dev-dependencies (e.g., `syn`) are unavoidable
// until upstream crates align on editions. Restrict to allow to this lint only.
//! # Key Features
//!
//! - **Ergonomic operations**: `number + 5`, `5 + number`, `&number + 5` all
//! work naturally
//! - **Optimal string parsing**: Integers use the smallest fitting type, floats use
//! the highest precision
//! - **No undefined behavior**: All operations are mathematically well-defined
//! - **Automatic type promotion**: Overflow protection through intelligent type
//! promotion
//! - **Cross-type operations**: Mix different numeric types seamlessly
//! - **IEEE 754 semantics**: Special values (NaN, Infinity) are preserved
//! correctly
//!
//! # Float Construction
//!
//! Use the `num!` macro or direct construction with Float64 wrapper:
//!
//! ```rust
//! use uninum::{num, Float64, Number};
//!
//! // Using num! macro (recommended):
//! let a = num!(2.718);
//!
//! // Direct construction:
//! let b = Number::from(2.718_f64);
//! ```
//!
//! # Quick Start
//!
//! ```rust
//! use uninum::{num, Number};
//!
//! let a = Number::from(10u64);
//! let b = num!(3.14); // Using num! macro
//!
//! // Ergonomic operations with primitives
//! let result1 = &a + 5; // Number + i32
//! let result2 = 2.5 * &a; // f64 * Number
//! let result3 = &a + &b; // Number + Number
//!
//! // Comparison operations
//! assert!(&a > 5); // Number > i32
//! assert!(15 > &a); // i32 > Number
//! assert!(&a == 10); // Number == i32
//!
//! // String parsing with optimal type selection
//! let small = Number::try_from("42").unwrap(); // -> U64(42)
//! let large = Number::try_from("70_000").unwrap(); // -> U64(70_000)
//! let float = Number::try_from("3.14").unwrap(); // -> Decimal(3.14) or F64(3.14)
//! ```
//!
//! # Division by Zero Behavior
//!
//! Division operations follow IEEE 754 inspired semantics:
//! - `finite / 0` returns `+∞` or `-∞` (signed infinity)
//! - `0 / 0` returns `NaN` (Not a Number)
//! - Integer division by zero promotes to F64 and follows IEEE 754 rules
//!
//! Division operations never panic and always return a valid `Number`.
//!
//! # Special Float Values with Decimal Feature
//!
//! When the `decimal` feature is enabled, operations involving NaN or Infinity
//! always use F64 to preserve IEEE 754 semantics. Additionally, float division
//! with integer values promotes to Decimal for better precision:
//! - `NaN + Decimal` returns `F64(NaN)`, not `Decimal(0)`
//! - `Infinity * Decimal` returns `F64(Infinity)`, not overflow
//! - `num!(1.0) / num!(2.0)` returns `Decimal(0.5)` for exact representation
//! - Special values propagate correctly through all operations
use Arc;
use Decimal;
/// Internal modules
/// Public API exports
pub use ;
pub use Float64;
// The num! macro is exported via #[macro_export] in macros.rs
/// Internal macro imports
use impl_try_get_decimal_method;
use ;
pub use RoundingStrategy;
pub use BitwiseError;
pub use Number;
const I128_F64_MIN: f64 = -170_141_183_460_469_231_731_687_303_715_884_105_728.0; // -2^127
const I128_F64_EXCL_MAX: f64 = 170_141_183_460_469_231_731_687_303_715_884_105_728.0; // 2^127