@@ -2,55 +2,146 @@ use super::*;
22
33pub trait FloatExt {
44 fn to_f64 ( & self , rounding_mode : astro_float:: RoundingMode ) -> Option < f64 > ;
5+ fn display ( & self ) -> String ;
56}
67
78impl FloatExt for BigFloat {
9+ fn display ( & self ) -> String {
10+ if let Some ( parts) = self . as_raw_parts ( ) {
11+ let number =
12+ BigFloat :: from_raw_parts ( parts. 0 , parts. 1 , parts. 2 , parts. 3 , parts. 4 ) ;
13+
14+ if number. is_nan ( ) {
15+ return "NaN" . into ( ) ;
16+ }
17+
18+ if number. is_inf_pos ( ) {
19+ return "Inf" . into ( ) ;
20+ }
21+
22+ if number. is_inf_neg ( ) {
23+ return "-Inf" . into ( ) ;
24+ }
25+
26+ if number. is_zero ( ) {
27+ return "0" . into ( ) ;
28+ }
29+
30+ let formatted = number
31+ . format (
32+ Radix :: Dec ,
33+ astro_float:: RoundingMode :: None ,
34+ & mut Consts :: new ( ) . expect ( "BigFloat constants cache" ) ,
35+ )
36+ . unwrap ( ) ;
37+
38+ if !formatted. contains ( 'e' ) {
39+ return formatted;
40+ }
41+
42+ let ( mant, exp) = {
43+ let mut parts = formatted. split ( 'e' ) ;
44+ ( parts. next ( ) . unwrap ( ) , parts. next ( ) . unwrap ( ) )
45+ } ;
46+
47+ let exp: i32 = exp. parse ( ) . unwrap ( ) ;
48+
49+ let ( sign, mant) =
50+ mant. split_at ( if mant. starts_with ( '-' ) { 1 } else { 0 } ) ;
51+
52+ let digits = mant. replace ( '.' , "" ) ;
53+
54+ let new_int_len = mant. find ( '.' ) . unwrap_or ( mant. len ( ) ) as i32 + exp;
55+
56+ let result = if new_int_len <= 0 {
57+ format ! (
58+ "{}0.{}{}" ,
59+ sign,
60+ "0" . repeat( ( -new_int_len) as usize ) ,
61+ digits
62+ )
63+ } else if new_int_len as usize >= digits. len ( ) {
64+ format ! (
65+ "{}{}{}" ,
66+ sign,
67+ digits,
68+ "0" . repeat( new_int_len as usize - digits. len( ) )
69+ )
70+ } else {
71+ let ( left, right) = digits. split_at ( new_int_len as usize ) ;
72+ format ! ( "{}{}.{}" , sign, left, right)
73+ } ;
74+
75+ if result. find ( '.' ) . is_some ( ) {
76+ result
77+ . trim_end_matches ( '0' )
78+ . trim_end_matches ( '.' )
79+ . to_string ( )
80+ } else {
81+ result
82+ }
83+ } else {
84+ self . to_string ( )
85+ }
86+ }
87+
888 fn to_f64 ( & self , rounding_mode : astro_float:: RoundingMode ) -> Option < f64 > {
989 let mut big_float = self . clone ( ) ;
1090 big_float. set_precision ( 64 , rounding_mode) . ok ( ) ?;
1191
1292 let sign = big_float. sign ( ) ?;
93+
1394 let exponent = big_float. exponent ( ) ? as isize ;
95+
1496 let mantissa_digits = big_float. mantissa_digits ( ) ?;
1597
1698 if mantissa_digits. is_empty ( ) {
1799 return Some ( 0.0 ) ;
18100 }
19101
20102 let mantissa = mantissa_digits[ 0 ] ;
103+
21104 if mantissa == 0 {
22105 return Some ( 0.0 ) ;
23106 }
24107
25108 let mut exponent = exponent + 0b1111111111 ;
109+
26110 let mut ret = 0u64 ;
27111
28112 if exponent >= 0b11111111111 {
29- return Some ( match sign {
113+ Some ( match sign {
30114 Sign :: Pos => f64:: INFINITY ,
31115 Sign :: Neg => f64:: NEG_INFINITY ,
32- } ) ;
116+ } )
33117 } else if exponent <= 0 {
34118 let shift = -exponent;
119+
35120 if shift < 52 {
36121 ret |= mantissa >> ( shift + 12 ) ;
122+
37123 if sign == Sign :: Neg {
38124 ret |= 0x8000000000000000u64 ;
39125 }
126+
40127 return Some ( f64:: from_bits ( ret) ) ;
41128 } else {
42129 return Some ( 0.0 ) ;
43130 }
44131 } else {
45132 let mantissa = mantissa << 1 ;
133+
46134 exponent -= 1 ;
135+
47136 if sign == Sign :: Neg {
48137 ret |= 1 ;
49138 }
139+
50140 ret <<= 11 ;
51141 ret |= exponent as u64 ;
52142 ret <<= 52 ;
53143 ret |= mantissa >> 12 ;
144+
54145 return Some ( f64:: from_bits ( ret) ) ;
55146 }
56147 }
0 commit comments