1use super::{
2 Decimal, Integer, NewVal, Parse, ParseU, Prec, SinhCosh, Special, SpecialValues,
3 SpecialValuesDeci, Type, WithVal, WithValDeci,
4};
5use crate::macros::impls::{
6 float_impl, impl_neg, impl_new_val, impl_partial_ord, impl_rem, impl_self_ops,
7};
8use rug::ops::CompleteRound;
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11use std::ops::{Div, Mul};
12use std::{
13 cmp::{Ordering, PartialOrd},
14 fmt::{Display, Formatter},
15};
16#[derive(Clone, PartialEq)]
17#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18pub enum Float {
19 Rug(rug::Float),
20 Fastnum(Decimal),
21 F64(f64),
22 F32(f32),
23}
24
25impl Prec for Float {
26 fn prec(&self) -> u32 {
27 match self {
28 Self::Rug(a) => a.prec(),
29 Self::Fastnum(a) => a.prec(),
30 Self::F64(_) => 64,
31 Self::F32(_) => 32,
32 }
33 }
34 fn set_prec(&mut self, new_prec: u32) {
35 match self {
36 Self::Rug(a) => a.set_prec(new_prec),
37 Self::Fastnum(a) => a.set_prec(new_prec),
38 Self::F64(_) => {}
39 Self::F32(_) => {}
40 }
41 }
42}
43impl Float {
44 pub fn cmp0(&self) -> Option<Ordering> {
45 self.partial_cmp(&Float::new(self.ftype(), self.prec()))
46 }
47 pub fn is_zero(&self) -> bool {
48 match self {
49 Self::Rug(a) => a.is_zero(),
50 Self::Fastnum(a) => a.is_zero(),
51 Self::F64(a) => a == &0.0,
52 Self::F32(a) => a == &0.0,
53 }
54 }
55 pub fn ftype(&self) -> Type {
56 match self {
57 Self::Rug(_) => Type::Rug,
58 Self::Fastnum(_) => Type::Fastnum,
59 Self::F64(_) => Type::F64,
60 Self::F32(_) => Type::F32,
61 }
62 }
63 pub fn to_f64(&self) -> f64 {
64 match self {
65 Float::Rug(a) => a.to_f64(),
66 Float::Fastnum(a) => a.to_f64(),
67 Float::F64(a) => *a,
68 Float::F32(a) => *a as f64,
69 }
70 }
71 pub fn to_string_radix(self, base: i32, num_digits: Option<usize>) -> String {
72 match self {
73 Self::Rug(a) => a.to_string_radix(base, num_digits),
74 Self::Fastnum(a) => a.to_string_radix(base, num_digits),
75 Self::F64(a) => a.to_string(),
76 Self::F32(a) => a.to_string(),
77 }
78 }
79}
80impl ParseU<&str> for Float {
81 fn parse(t: Type, prec: u32, s: &str) -> Option<Self> {
82 match t {
83 Type::Rug => rug::Float::parse(s)
84 .ok()
85 .map(|a| Float::Rug(a.complete(prec))),
86 Type::Fastnum => Decimal::parse(prec, s).map(Float::Fastnum),
87 Type::F64 => s.parse().ok().map(Float::F64),
88 Type::F32 => s.parse().ok().map(Float::F32),
89 }
90 }
91 fn parse_radix(t: Type, prec: u32, s: &str, base: i32) -> Option<Self> {
92 match t {
93 Type::Rug => rug::Float::parse_radix(s, base)
94 .ok()
95 .map(|a| Float::Rug(a.complete(prec))),
96 Type::Fastnum => Decimal::parse_radix(prec, s, base).map(Float::Fastnum),
97 Type::F64 => s.parse().ok().map(Float::F64),
98 Type::F32 => s.parse().ok().map(Float::F32),
99 }
100 }
101}
102impl Mul<Integer> for Float {
103 type Output = Self;
104 fn mul(self, rhs: Integer) -> Self::Output {
105 match (self, rhs) {
106 (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a * b),
107 (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a * b),
108 (Float::F64(a), Integer::F64(b)) => Float::F64(a * b as f64),
109 (Float::F32(a), Integer::F32(b)) => Float::F32(a * b as f32),
110 _ => unreachable!(),
111 }
112 }
113}
114impl Div<Integer> for Float {
115 type Output = Self;
116 fn div(self, rhs: Integer) -> Self::Output {
117 match (self, rhs) {
118 (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a / b),
119 (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a / b),
120 (Float::F64(a), Integer::F64(b)) => Float::F64(a / b as f64),
121 (Float::F32(a), Integer::F32(b)) => Float::F32(a / b as f32),
122 _ => unreachable!(),
123 }
124 }
125}
126impl Mul<Float> for Integer {
127 type Output = Float;
128 fn mul(self, rhs: Float) -> Self::Output {
129 match (rhs, self) {
130 (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a * b),
131 (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a * b),
132 (Float::F64(a), Integer::F64(b)) => Float::F64(a * b as f64),
133 (Float::F32(a), Integer::F32(b)) => Float::F32(a * b as f32),
134 _ => unreachable!(),
135 }
136 }
137}
138impl Div<Float> for Integer {
139 type Output = Float;
140 fn div(self, rhs: Float) -> Self::Output {
141 match (rhs, self) {
142 (Float::Rug(a), Integer::Rug(b)) => Float::Rug(a / b),
143 (Float::Fastnum(a), Integer::Fastnum(b)) => Float::Fastnum(a / b),
144 (Float::F64(a), Integer::F64(b)) => Float::F64(a / b as f64),
145 (Float::F32(a), Integer::F32(b)) => Float::F32(a / b as f32),
146 _ => unreachable!(),
147 }
148 }
149}
150impl SpecialValues for Float {
151 fn pi(t: Type, prec: u32) -> Self {
152 match t {
153 Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Constant::Pi)),
154 Type::Fastnum => Self::Fastnum(Decimal::pi(prec)),
155 Type::F64 => Self::F64(f64::pi(prec)),
156 Type::F32 => Self::F32(f32::pi(prec)),
157 }
158 }
159 fn nan(t: Type, prec: u32) -> Self {
160 match t {
161 Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Special::Nan)),
162 Type::Fastnum => Self::Fastnum(Decimal::nan(prec)),
163 Type::F64 => Self::F64(f64::nan(prec)),
164 Type::F32 => Self::F32(f32::nan(prec)),
165 }
166 }
167 fn inf(t: Type, prec: u32) -> Self {
168 match t {
169 Type::Rug => Self::Rug(rug::Float::with_val(prec, rug::float::Special::Infinity)),
170 Type::Fastnum => Self::Fastnum(Decimal::inf(prec)),
171 Type::F64 => Self::F64(f64::inf(prec)),
172 Type::F32 => Self::F32(f32::inf(prec)),
173 }
174 }
175}
176
177impl WithVal<Special> for Float {
178 fn with_val(obj: Type, prec: u32, val: Special) -> Self {
179 match val {
180 Special::Pi => Float::pi(obj, prec),
181 Special::Nan => Float::nan(obj, prec),
182 Special::Infinity => Float::inf(obj, prec),
183 }
184 }
185}
186
187impl Display for Float {
188 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
189 match self {
190 Self::Rug(a) => a.fmt(f),
191 Self::Fastnum(a) => a.fmt(f),
192 Self::F32(a) => a.fmt(f),
193 Self::F64(a) => a.fmt(f),
194 }
195 }
196}
197
198impl Float {
199 pub fn sin_cos(self) -> (Self, Self) {
200 match self {
201 Self::Rug(a) => {
202 let p = a.prec();
203 let (s, c) = a.sin_cos(rug::Float::new(p));
204 (Self::Rug(s), Self::Rug(c))
205 }
206 Self::Fastnum(a) => {
207 let (s, c) = a.sin_cos();
208 (Self::Fastnum(s), Self::Fastnum(c))
209 }
210 Self::F64(a) => {
211 let (s, c) = a.sin_cos();
212 (Self::F64(s), Self::F64(c))
213 }
214 Self::F32(a) => {
215 let (s, c) = a.sin_cos();
216 (Self::F32(s), Self::F32(c))
217 }
218 }
219 }
220 pub fn sinh_cosh(self) -> (Self, Self) {
221 match self {
222 Self::Rug(a) => {
223 let p = a.prec();
224 let (s, c) = a.sinh_cosh(rug::Float::new(p));
225 (Self::Rug(s), Self::Rug(c))
226 }
227 Self::Fastnum(a) => {
228 let (s, c) = a.sinh_cosh();
229 (Self::Fastnum(s), Self::Fastnum(c))
230 }
231 Self::F64(a) => {
232 let (s, c) = a.sinh_cosh();
233 (Self::F64(s), Self::F64(c))
234 }
235 Self::F32(a) => {
236 let (s, c) = a.sinh_cosh();
237 (Self::F32(s), Self::F32(c))
238 }
239 }
240 }
241 pub fn atan2(self, other: Self) -> Self {
242 match (self, other) {
243 (Self::Rug(a), Self::Rug(b)) => Self::Rug(a.atan2(&b)),
244 (Self::Fastnum(a), Self::Fastnum(b)) => Self::Fastnum(a.atan2(b)),
245 (Self::F64(a), Self::F64(b)) => Self::F64(a.atan2(b)),
246 (Self::F32(a), Self::F32(b)) => Self::F32(a.atan2(b)),
247 _ => unreachable!(),
248 }
249 }
250 pub fn hypot(self, other: Self) -> Self {
251 match (self, other) {
252 (Self::Rug(a), Self::Rug(b)) => Self::Rug(a.hypot(&b)),
253 (Self::Fastnum(a), Self::Fastnum(b)) => Self::Fastnum(a.hypot(b)),
254 (Self::F64(a), Self::F64(b)) => Self::F64(a.hypot(b)),
255 (Self::F32(a), Self::F32(b)) => Self::F32(a.hypot(b)),
256 _ => unreachable!(),
257 }
258 }
259 pub fn to_integer(self) -> Integer {
260 match self {
261 Float::Rug(a) => Integer::Rug(a.to_integer().unwrap()),
262 Float::Fastnum(a) => Integer::Fastnum(a.to_integer()),
263 Float::F64(a) => Integer::F64(a as i128),
264 Float::F32(a) => Integer::F32(a as i128),
265 }
266 }
267 pub fn gamma(self) -> Self {
268 match self {
269 Float::Rug(a) => Self::Rug(a.gamma()),
270 Float::Fastnum(a) => Self::Fastnum(a),
271 Float::F64(a) => Self::F64(a),
272 Float::F32(a) => Self::F32(a),
273 }
274 }
275}
276
277impl PartialEq<f64> for Float {
278 fn eq(&self, other: &f64) -> bool {
279 match self {
280 Float::Rug(a) => a == other,
281 Float::Fastnum(a) => a == other,
282 Float::F64(a) => a == other,
283 Float::F32(a) => *a == *other as f32,
284 }
285 }
286}
287impl PartialEq<i32> for Float {
288 fn eq(&self, other: &i32) -> bool {
289 match self {
290 Float::Rug(a) => a == other,
291 Float::Fastnum(a) => a == other,
292 Float::F64(a) => *a == *other as f64,
293 Float::F32(a) => *a == *other as f32,
294 }
295 }
296}
297impl PartialOrd<i32> for Float {
298 fn partial_cmp(&self, other: &i32) -> Option<Ordering> {
299 match self {
300 Float::Rug(a) => a.partial_cmp(other),
301 Float::Fastnum(a) => a.to_integer().partial_cmp(&fastnum::I512::from(*other)),
302 Float::F64(a) => a.partial_cmp(&(*other as f64)),
303 Float::F32(a) => a.partial_cmp(&(*other as f32)),
304 }
305 }
306}
307
308impl_new_val!(
309 Float,
310 (Rug, rug::Float::with_val),
311 (Fastnum, Decimal::with_val),
312 (F64, |_, x| x),
313 (F32, |_, x| x as f32)
314);
315impl_rem!(
316 Float,
317 (Rug, |x| x),
318 (Fastnum, |x| x),
319 (F64, |x| x as f64),
320 (F32, |x| x as f32)
321);
322float_impl!(Float, Rug, Fastnum, F64, F32);
323impl_partial_ord!(
324 Float,
325 (Rug, |x: &rug::Float| x.to_f64()),
326 (Fastnum, |x: &Decimal| x.to_f64()),
327 (F64, |x: &f64| *x),
328 (F32, |x: &f32| *x as f64)
329);
330impl_neg!(Float, Rug, Fastnum, F64, F32);
331impl_self_ops!(
332 Float,
333 (Rug, |x| x),
334 (Fastnum, |x| x),
335 (F64, |x| x),
336 (F32, |x| x)
337);