1use std::{
19 cmp::Ordering,
20 f64::consts,
21 fmt::{self, Display},
22 ops::*,
23 str::FromStr,
24};
25use thiserror::Error;
26
27#[cfg(feature = "serde")] mod serde;
28mod table;
29
30#[derive(Error, Debug, Eq, PartialEq, Clone)]
33pub enum ParseError {
34 #[error("{0}")]
35 Float(#[from] std::num::ParseFloatError),
36 #[error("{0}")]
37 Int(#[from] std::num::ParseIntError),
38}
39
40#[derive(Debug, Copy, Clone, PartialEq)]
52pub struct Float {
53 mantissa: f64,
54 exponent: i64,
55}
56
57const MAX_DIGITS: i64 = 17;
58const MAX_EXPONENT: i64 = 9_000_000_000_000_000;
59
60impl Float {
61 pub const MAX: Float = Float {
64 exponent: MAX_EXPONENT,
65 mantissa: 1.0,
66 };
67 pub const MIN: Float = Float {
69 exponent: MAX_EXPONENT,
70 mantissa: -1.0,
71 };
72 pub const NAN: Float = Float {
73 exponent: 0,
74 mantissa: std::f64::NAN,
75 };
76
77 pub fn mantissa(self) -> f64 {
78 self.mantissa
79 }
80
81 pub fn exponent(self) -> i64 {
82 self.exponent
83 }
84
85 #[doc(hidden)]
86 pub fn normalize(mut self) -> Self {
87 if !self.mantissa.is_finite() {
88 return self;
89 }
90 while self.mantissa.abs() < 1.0 && self.mantissa != 0.0 {
91 self.mantissa *= 10.0;
92 self.exponent -= 1;
93 }
94 while self.mantissa.abs() >= 10.0 {
95 self.mantissa /= 10.0;
96 self.exponent += 1;
97 }
98 self
99 }
100
101 pub fn sci(base: f64, exponent: i64) -> Self {
103 if !base.is_finite() {
104 Self::NAN
105 } else {
106 Float {
107 mantissa: base,
108 exponent,
109 }
110 .normalize()
111 }
112 }
113
114 pub fn float(value: f64) -> Self {
116 if value.is_nan() {
117 Self::NAN
118 } else if value.is_infinite() {
119 if value.is_sign_positive() {
120 Self::MAX
121 } else {
122 Self::MIN
123 }
124 } else if value == 0.0 || value == -0.0 {
125 Float {
126 mantissa: 0.0,
127 exponent: 0,
128 }
129 } else {
130 let exponent = value.abs().log10().floor() as i64;
131 let base = table::POWERS[(exponent + table::TABLE_CENTER as i64) as usize];
132 let mantissa = value / base;
133 Float { exponent, mantissa }.normalize()
134 }
135 }
136
137 pub fn int(value: i64) -> Self {
139 Self::float(value as f64)
140 }
141
142 pub fn try_float(self) -> Option<f64> {
145 let f = self.to_float();
146 if !f.is_finite() {
147 None
148 } else {
149 Some(f)
150 }
151 }
152
153 pub fn to_float(self) -> f64 {
162 dbg!(self.mantissa) * dbg!(10.0f64.powi(dbg!(self.exponent as i32)))
163 }
164
165 pub fn abs(mut self) -> Self {
166 self.mantissa = self.mantissa.abs();
167 self
168 }
169
170 pub fn signum(self) -> f64 {
171 self.mantissa.signum()
172 }
173
174 pub fn recip(self) -> Self {
175 Self::sci(1.0 / self.mantissa, -self.exponent)
176 }
177
178 pub fn round(self) -> Self {
179 if self.exponent.abs() < 308 {
180 Self::float(self.to_float().round())
181 } else {
182 self
183 }
184 }
185
186 pub fn floor(self) -> Self {
187 if self.exponent.abs() < 308 {
188 Self::float(self.to_float().floor())
189 } else {
190 self
191 }
192 }
193
194 pub fn ceil(self) -> Self {
195 if self.exponent.abs() < 308 {
196 Self::float(self.to_float().ceil())
197 } else {
198 self
199 }
200 }
201
202 pub fn trunc(self) -> Self {
203 if self.exponent.abs() < 308 {
204 Self::float(self.to_float().trunc())
205 } else {
206 self
207 }
208 }
209
210 pub fn log10(self) -> f64 {
211 (self.exponent as f64) + self.mantissa.log10()
212 }
213
214 pub fn log2(self) -> f64 {
215 self.log10() * consts::LOG2_10
216 }
217
218 pub fn ln(self) -> f64 {
219 self.log10() * consts::LN_10
220 }
221
222 pub fn log(self, base: f64) -> f64 {
224 assert!(
225 base >= 2.0,
226 "cannot call Float::log() with a base lower than 2"
227 );
228 (consts::LN_10 / base.ln()) * self.log10()
229 }
230
231 pub fn powf(self, n: f64) -> Self {
232 Self::float(n * self.ln()).exp()
233 }
234
235 pub fn powi(self, n: i32) -> Self {
236 Self::sci(self.mantissa.powi(n), self.exponent * (n as i64))
237 }
238
239 pub fn exp(self) -> Self {
240 let f = self.to_float();
241 if -706.0 < f && f < 709.0 {
242 Self::float(f.exp())
243 } else {
244 let mut x = self;
245 let mut exp = 0f64;
246 let expx = self.exponent;
247 let ln10 = Self::float(consts::LN_10);
248
249 if expx >= 0 {
250 exp = (x / ln10).to_float().trunc();
251 let tmp = Self::float(exp) * ln10;
252 x -= tmp;
253 if x >= ln10 {
254 exp += 1.0;
255 x -= ln10;
256 }
257 }
258 if x.signum() < 0.0 {
259 exp -= 1.0;
260 x += ln10;
261 }
262
263 let nextx = x.to_float().exp();
264
265 if exp != 0.0 {
266 x = Self::sci(nextx, exp.floor() as i64);
267 }
268
269 x
270 }
271 }
272
273 pub fn sqrt(self) -> Self {
274 self.powf(0.5)
275 }
276
277 pub fn cbrt(self) -> Self {
278 self.powf(1.0 / 3.0)
279 }
280}
281
282impl From<i64> for Float {
283 fn from(i: i64) -> Self {
284 Self::int(i)
285 }
286}
287
288impl From<f64> for Float {
289 fn from(f: f64) -> Self {
290 Self::float(f)
291 }
292}
293
294impl FromStr for Float {
295 type Err = ParseError;
296
297 fn from_str(input: &str) -> Result<Self, Self::Err> {
298 let mut sci_parts = input.splitn(2, 'e');
299 let first = sci_parts
300 .next()
301 .expect("split should never yield zero elements");
302 if let Some(second) = sci_parts.next() {
303 Ok(Self::sci(first.parse()?, second.parse()?))
304 } else {
305 Ok(Self::float(first.parse()?))
306 }
307 }
308}
309
310impl Display for Float {
311 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
312 let Float { mantissa, exponent } = *self;
313 if mantissa.is_nan() {
314 write!(f, "NaN")
315 } else if exponent >= MAX_EXPONENT {
316 if mantissa.is_sign_positive() {
317 write!(f, "Infinity")
318 } else {
319 write!(f, "-Infinity")
320 }
321 } else if exponent <= -MAX_EXPONENT || mantissa == 0.0 {
322 write!(f, "0")
323 } else if exponent >= MAX_DIGITS as i64 {
324 write!(
325 f,
326 "{value:0<prec$}",
327 value = mantissa.to_string().replace(".", ""),
328 prec = (exponent as usize) + 1
329 )
330 } else {
331 write!(
332 f,
333 "{value:.prec$}",
334 value = self.to_float(),
335 prec = f.precision().unwrap_or(0)
336 )
337 }
338 }
339}
340
341impl fmt::LowerExp for Float {
342 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
343 format_exp(*self, 'e', f)
344 }
345}
346
347impl fmt::UpperExp for Float {
348 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349 format_exp(*self, 'E', f)
350 }
351}
352
353fn format_exp(h: Float, chr: char, f: &mut fmt::Formatter) -> fmt::Result {
354 let Float { mantissa, exponent } = h;
355 if mantissa.is_nan() {
356 write!(f, "NaN")
357 } else if exponent >= MAX_EXPONENT {
358 if mantissa.is_sign_positive() {
359 write!(f, "Infinity")
360 } else {
361 write!(f, "-Infinity")
362 }
363 } else if exponent <= -MAX_EXPONENT || mantissa == 0.0 {
364 write!(f, "0")
365 } else {
366 write!(
367 f,
368 "{base:.prec$}{e}{exp}",
369 e = chr,
370 base = mantissa,
371 exp = exponent,
372 prec = f.precision().unwrap_or(0)
373 )
374 }
375}
376
377impl Neg for Float {
378 type Output = Self;
379
380 fn neg(self) -> Self::Output {
381 Self::sci(-self.mantissa, self.exponent)
382 }
383}
384
385impl Add<Float> for Float {
386 type Output = Self;
387
388 fn add(self, other: Self) -> Self::Output {
389 let (bigger, smaller) = if self.exponent >= other.exponent {
390 (self, other)
391 } else {
392 (other, self)
393 };
394 if bigger.exponent - smaller.exponent > MAX_DIGITS as i64 {
395 bigger
396 } else {
397 let factor =
398 table::POWERS[((smaller.exponent - bigger.exponent) + table::TABLE_CENTER as i64) as usize];
399 Self::sci(bigger.mantissa + smaller.mantissa * factor, bigger.exponent)
400 }
401 }
402}
403
404impl Add<i64> for Float {
405 type Output = Self;
406
407 fn add(self, other: i64) -> Self::Output {
408 self + Self::int(other)
409 }
410}
411
412impl Add<f64> for Float {
413 type Output = Self;
414
415 fn add(self, other: f64) -> Self::Output {
416 self + Self::float(other)
417 }
418}
419
420impl<T> AddAssign<T> for Float
421where
422 Float: Add<T, Output = Float>,
423{
424 fn add_assign(&mut self, other: T) {
425 *self = self.add(other)
426 }
427}
428
429impl Sub<Float> for Float {
430 type Output = Self;
431
432 fn sub(self, other: Float) -> Self::Output {
433 self + -other
434 }
435}
436
437impl Sub<i64> for Float {
438 type Output = Self;
439
440 fn sub(self, other: i64) -> Self::Output {
441 self + -other
442 }
443}
444
445impl Sub<f64> for Float {
446 type Output = Self;
447
448 fn sub(self, other: f64) -> Self::Output {
449 self + -other
450 }
451}
452
453impl<T> SubAssign<T> for Float
454where
455 Float: Sub<T, Output = Float>,
456{
457 fn sub_assign(&mut self, other: T) {
458 *self = self.sub(other)
459 }
460}
461
462impl Mul<Float> for Float {
463 type Output = Self;
464
465 #[allow(clippy::suspicious_arithmetic_impl)]
466 fn mul(self, other: Self) -> Self::Output {
467 Self::sci(
468 self.mantissa * other.mantissa,
469 self.exponent + other.exponent,
470 )
471 }
472}
473
474impl Mul<i64> for Float {
475 type Output = Self;
476
477 fn mul(self, other: i64) -> Self::Output {
478 self * Self::int(other)
479 }
480}
481
482impl Mul<f64> for Float {
483 type Output = Self;
484
485 fn mul(self, other: f64) -> Self::Output {
486 self * Self::float(other)
487 }
488}
489
490impl<T> MulAssign<T> for Float
491where
492 Float: Mul<T, Output = Float>,
493{
494 fn mul_assign(&mut self, other: T) {
495 *self = self.mul(other)
496 }
497}
498
499impl Div<Float> for Float {
500 type Output = Self;
501
502 #[allow(clippy::suspicious_arithmetic_impl)]
503 fn div(self, other: Self) -> Self::Output {
504 self * other.recip()
505 }
506}
507
508impl Div<i64> for Float {
509 type Output = Self;
510
511 fn div(self, other: i64) -> Self::Output {
512 self / Self::int(other)
513 }
514}
515
516impl Div<f64> for Float {
517 type Output = Self;
518
519 fn div(self, other: f64) -> Self::Output {
520 self / Self::float(other)
521 }
522}
523
524impl<T> DivAssign<T> for Float
525where
526 Float: Div<T, Output = Float>,
527{
528 fn div_assign(&mut self, other: T) {
529 *self = self.div(other)
530 }
531}
532
533impl PartialOrd for Float {
534 fn partial_cmp(&self, value: &Self) -> Option<Ordering> {
535 if !self.mantissa.is_finite() || !value.mantissa.is_finite() {
536 return None;
537 }
538 if self.mantissa == 0.0 || value.mantissa == 0.0 {
539 return self.mantissa.partial_cmp(&value.mantissa);
540 }
541 if self.mantissa > 0.0 {
542 if value.mantissa < 0.0 {
543 return Some(Ordering::Greater);
544 }
545 if self.exponent > value.exponent {
546 return Some(Ordering::Greater);
547 }
548 if self.exponent < value.exponent {
549 return Some(Ordering::Less);
550 }
551 if self.mantissa > value.mantissa {
552 return Some(Ordering::Greater);
553 }
554 if self.mantissa < value.mantissa {
555 return Some(Ordering::Less);
556 }
557 return Some(Ordering::Equal);
558 } else if self.mantissa < 0.0 {
559 if value.mantissa > 0.0 {
560 return Some(Ordering::Less);
561 }
562 if self.exponent > value.exponent {
563 return Some(Ordering::Less);
564 }
565 if self.exponent < value.exponent {
566 return Some(Ordering::Greater);
567 }
568 if self.mantissa > value.mantissa {
569 return Some(Ordering::Less);
570 }
571 if self.mantissa < value.mantissa {
572 return Some(Ordering::Greater);
573 }
574 return Some(Ordering::Equal);
575 }
576 None
577 }
578}
579
580#[test]
581fn test_format() {
582 let h = Float::sci(1.0, 10);
583 assert_eq!(format!("{}", h), "10000000000");
584 assert_eq!(format!("{:.3}", h), "10000000000.000");
585
586 let h = Float::sci(1.0, 10000);
587 assert_eq!(format!("{:e}", h), "1e10000");
588 assert_eq!(format!("{:.3e}", h), "1.000e10000");
589 assert_eq!(format!("{:.3e}", h.powi(2)), "1.000e20000");
590}
591
592#[test]
593fn test_math_ops() {
594 let h = Float::float(1.234);
595 assert_eq!(-h, Float::float(-1.234));
596
597 assert_eq!(Float::float(9.0).sqrt().round(), Float::float(3.0));
599 assert_eq!(Float::float(9.0).powf(2.0).round(), Float::float(81.0));
600
601 let mut bignum = Float::sci(1.2345, 347);
603
604 bignum = bignum.powf(2.0);
605 assert_eq!(bignum, Float::sci(1.523990249999763, 694));
606 bignum = bignum.powf(56.1);
607 assert_eq!(bignum, Float::sci(4.627013609064963, 38943));
608}