@@ -241,6 +241,24 @@ macro_rules! impl_common_fixed_ops {
241241 Self ( self . 0 >> rhs)
242242 }
243243 }
244+
245+ impl <const B : u32 > core:: fmt:: Debug for Fixed <$t, B > {
246+ fn fmt( & self , f: & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
247+ let raw: $t = self . to_bits( ) ;
248+ write!(
249+ f,
250+ concat!(
251+ "Fixed::<" ,
252+ stringify!( $t) ,
253+ ",{}>::from_bits({:#x}_u32 as " ,
254+ stringify!( $t) ,
255+ ")"
256+ ) ,
257+ B , raw
258+ )
259+ }
260+ }
261+
244262 impl_trait_op_unit!( $t, Not , not) ;
245263 impl_trait_op_self_rhs!( $t, Add , add) ;
246264 impl_trait_op_self_rhs!( $t, Sub , sub) ;
@@ -335,18 +353,11 @@ macro_rules! impl_signed_fixed_ops {
335353 }
336354 }
337355 impl_trait_op_unit!( $t, Neg , neg) ;
338- impl < const B : u32 > core :: fmt :: Debug for Fixed <$t , B > {
339- # [ inline ]
356+
357+ impl < const B : u32 > core :: fmt :: Display for Fixed <$t , B > {
340358 fn fmt( & self , f: & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
341- let whole: $t = self . trunc( ) . to_bits( ) >> B ;
342- let fract: $t = self . fract( ) . to_bits( ) ;
343- let divisor: $t = 1 << B ;
344- if self . is_negative( ) {
345- let whole = whole. unsigned_abs( ) ;
346- write!( f, "-({whole}+{fract}/{divisor})" )
347- } else {
348- write!( f, "{whole}+{fract}/{divisor}" )
349- }
359+ let neg = self . to_bits( ) < 0 ;
360+ fixed_fmt_abs:: <B >( f, self . to_bits( ) . abs( ) as u32 , neg)
350361 }
351362 }
352363 } ;
@@ -393,17 +404,105 @@ macro_rules! impl_unsigned_fixed_ops {
393404 Self ( self . 0 & ( <$t>:: MAX << B ) )
394405 }
395406 }
396- impl < const B : u32 > core :: fmt :: Debug for Fixed <$t , B > {
397- # [ inline ]
407+
408+ impl < const B : u32 > core :: fmt :: Display for Fixed <$t , B > {
398409 fn fmt( & self , f: & mut core:: fmt:: Formatter ) -> core:: fmt:: Result {
399- let whole: $t = self . trunc( ) . to_bits( ) >> B ;
400- let fract: $t = self . fract( ) . to_bits( ) ;
401- let divisor: $t = 1 << B ;
402- write!( f, "{whole}+{fract}/{divisor}" )
410+ fixed_fmt_abs:: <B >( f, self . to_bits( ) as u32 , false )
403411 }
404412 }
405413 } ;
406414}
407415impl_unsigned_fixed_ops ! ( u8 ) ;
408416impl_unsigned_fixed_ops ! ( u16 ) ;
409417impl_unsigned_fixed_ops ! ( u32 ) ;
418+
419+ fn fixed_fmt_abs < const B : u32 > (
420+ f : & mut core:: fmt:: Formatter , abs : u32 , neg : bool ,
421+ ) -> core:: fmt:: Result {
422+ let precision = f. precision ( ) . unwrap_or ( const { ( ( B as usize ) + 1 ) / 3 } ) ;
423+ let width = f. width ( ) . unwrap_or ( 0 ) . saturating_sub ( precision + 1 ) ;
424+ let fract = abs & ( ( 1 << B ) - 1 ) ;
425+ let fract_dec = 10u32
426+ . checked_pow ( precision as u32 )
427+ . and_then ( |digits| fract. checked_mul ( digits) )
428+ . map ( |x| ( x >> B ) as u64 )
429+ . unwrap_or_else ( || ( fract as u64 * 10u64 . pow ( precision as u32 ) >> B ) ) ;
430+ let mut ones = ( abs >> B ) as i32 ;
431+ if neg {
432+ if ones != 0 {
433+ ones = ones. neg ( )
434+ } else {
435+ let width = width. saturating_sub ( 2 ) ;
436+ return write ! ( f, "{:width$}-0.{fract_dec:0precision$}" , "" ) ;
437+ }
438+ }
439+ write ! ( f, "{ones:width$}.{fract_dec:0precision$}" )
440+ }
441+
442+ #[ cfg( test) ]
443+ mod test {
444+ use crate :: fixed:: { i16fx14, i32fx8} ;
445+ use core:: { fmt:: Write , str} ;
446+
447+ struct WriteBuf < const N : usize > ( [ u8 ; N ] , usize ) ;
448+ impl < ' a , const N : usize > Default for WriteBuf < N > {
449+ fn default ( ) -> Self {
450+ Self ( [ 0u8 ; N ] , 0 )
451+ }
452+ }
453+ impl < const N : usize > Write for WriteBuf < N > {
454+ fn write_str ( & mut self , s : & str ) -> core:: fmt:: Result {
455+ let src = s. as_bytes ( ) ;
456+ let len = ( self . 0 . len ( ) - self . 1 ) . min ( src. len ( ) ) ;
457+ self . 0 [ self . 1 ..self . 1 + len] . copy_from_slice ( & src[ ..len] ) ;
458+ self . 1 += len;
459+ if len < src. len ( ) {
460+ Err ( core:: fmt:: Error )
461+ } else {
462+ Ok ( ( ) )
463+ }
464+ }
465+ }
466+ impl < const N : usize > WriteBuf < N > {
467+ fn take ( & mut self ) -> & str {
468+ let len = self . 1 ;
469+ self . 1 = 0 ;
470+ str:: from_utf8 ( & self . 0 [ ..len] ) . unwrap ( )
471+ }
472+ }
473+
474+ #[ test_case]
475+ fn decimal_display ( ) {
476+ let mut wbuf = WriteBuf :: < 16 > :: default ( ) ;
477+
478+ let x = i32fx8:: from_bits ( 0x12345678 ) ;
479+
480+ write ! ( & mut wbuf, "{x}" ) . unwrap ( ) ;
481+ assert_eq ! ( wbuf. take( ) , "1193046.468" ) ;
482+
483+ write ! ( & mut wbuf, "{x:11.1}" ) . unwrap ( ) ;
484+ assert_eq ! ( wbuf. take( ) , " 1193046.4" ) ;
485+
486+ write ! ( & mut wbuf, "{x:1.6}" ) . unwrap ( ) ;
487+ assert_eq ! ( wbuf. take( ) , "1193046.468750" ) ;
488+
489+ let x = x. neg ( ) ;
490+ write ! ( & mut wbuf, "{x}" ) . unwrap ( ) ;
491+ assert_eq ! ( wbuf. take( ) , "-1193046.468" ) ;
492+
493+ let x = i16fx14:: from_bits ( 0x6544 as i16 ) ;
494+ write ! ( & mut wbuf, "{x}" ) . unwrap ( ) ;
495+ assert_eq ! ( wbuf. take( ) , "1.58227" ) ;
496+
497+ let x = x. neg ( ) ;
498+ write ! ( & mut wbuf, "{x:.10}" ) . unwrap ( ) ;
499+ assert_eq ! ( wbuf. take( ) , "-1.5822753906" ) ;
500+
501+ write ! ( & mut wbuf, "{x:9.1}" ) . unwrap ( ) ;
502+ assert_eq ! ( wbuf. take( ) , " -1.5" ) ;
503+
504+ let x = x. add ( i16fx14:: wrapping_from ( 1 ) ) ;
505+ write ! ( & mut wbuf, "{x:9.2}" ) . unwrap ( ) ;
506+ assert_eq ! ( wbuf. take( ) , " -0.58" ) ;
507+ }
508+ }
0 commit comments