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
165
166
167
168
169
170
171
172
173
174
175
176
177
//! Mathematical constants and float wrapper types.
use OrderedFloat;
use fmt;
/// Wrapper type for f64 that provides proper equality and hashing semantics.
///
/// This type wraps `ordered_float::OrderedFloat<f64>` to enable `f64` values
/// to be used in `Expression` variants while implementing `PartialEq`, `Eq`, and `Hash`.
///
/// ## Semantics
///
/// - **NaN equality**: Unlike standard IEEE 754, `NaN == NaN` returns `true` for `MathFloat`.
/// This is necessary for use in hash-based collections like `HashSet` and `HashMap`.
/// - **Ordering**: Values are totally ordered, with NaN considered greater than infinity.
/// - **Hash stability**: Identical float values produce identical hashes, including special
/// values like NaN, Infinity, and -Infinity.
///
/// ## Parser Behavior
///
/// Parsers (`parse` and `parse_latex`) never produce NaN values. Only finite numbers and
/// infinities appear in parsed ASTs. NaN values can only arise through manual AST
/// construction via `MathFloat::new(f64::NAN)` or `MathFloat::from(f64::NAN)`.
///
/// ## Use Cases
///
/// Use this type when you need to store floating-point values in collections that require
/// `Eq` and `Hash`, or when building AST nodes that will be compared for equality.
///
/// ## Examples
///
/// ```
/// use mathlex::ast::MathFloat;
/// use std::collections::HashSet;
///
/// let f1 = MathFloat::from(3.14);
/// let f2 = MathFloat::from(3.14);
/// assert_eq!(f1, f2);
///
/// let value: f64 = f1.into();
/// assert_eq!(value, 3.14);
///
/// // NaN values are equal to themselves
/// let nan1 = MathFloat::from(f64::NAN);
/// let nan2 = MathFloat::from(f64::NAN);
/// assert_eq!(nan1, nan2);
///
/// // Can be used in HashSet
/// let mut set = HashSet::new();
/// set.insert(MathFloat::from(1.0));
/// set.insert(MathFloat::from(2.0));
/// assert_eq!(set.len(), 2);
/// ```
;
/// Mathematical constants used in expressions.
///
/// These represent well-known mathematical constants with precise mathematical meaning.
///
/// ## Parsing Notes
///
/// - **`Pi`**: Parsed from `π` (Unicode) or `\pi` (LaTeX)
/// - **`E`**: Parsed from `e` (plain text) or `e` (LaTeX)
/// - **`I`**: Parsed from `i` (plain text) or `i` (LaTeX), represents the imaginary unit
/// (also serves as quaternion basis vector i)
/// - **`J`**: Quaternion basis vector j, parsed from `\mathbf{j}` or in quaternion context
/// - **`K`**: Quaternion basis vector k, parsed from `\mathbf{k}` or in quaternion context
/// - **`Infinity`**: Parsed from `∞` (Unicode) or `\infty` (LaTeX)
/// - **`NegInfinity`**: Produced by parsers when unary minus is applied to infinity.
/// Both `-∞` / `-inf` (plain text) and `-\infty` (LaTeX) parse directly as
/// `Constant(NegInfinity)`.
/// - **`NaN`**: Not-a-Number. Parsed from `nan` or `NaN` (plain text) or
/// `\text{NaN}`, `\text{nan}`, `\mathrm{NaN}` (LaTeX). Represents an
/// indeterminate or undefined numeric result.
///
/// ## Quaternion Context
///
/// The presence of `J` or `K` constants in an expression implies quaternion context.
/// The existing `I` constant serves dual purpose: complex imaginary unit and quaternion
/// basis vector i. In quaternion expressions (a + bi + cj + dk), the multiplication
/// rules are: i² = j² = k² = ijk = -1.
///
/// ## Examples
///
/// ```
/// use mathlex::ast::MathConstant;
///
/// let pi = MathConstant::Pi;
/// let euler = MathConstant::E;
/// assert_ne!(pi, euler);
///
/// // Quaternion basis vectors
/// let i = MathConstant::I;
/// let j = MathConstant::J;
/// let k = MathConstant::K;
/// assert_ne!(i, j);
/// assert_ne!(j, k);
///
/// // Note: NegInfinity is for programmatic use
/// let neg_inf = MathConstant::NegInfinity;
/// assert_ne!(neg_inf, MathConstant::Infinity);
///
/// // NaN is distinct from all other constants
/// let nan = MathConstant::NaN;
/// assert_ne!(nan, MathConstant::Infinity);
/// assert_ne!(nan, MathConstant::NegInfinity);
/// ```