@@ -474,7 +474,7 @@ export function itoa64(value: i64, radix: i32): String {
474474@lazy let _frc_minus : u64 = 0 ;
475475
476476// @ts -ignore: decorator
477- @lazy let _frc_plus : u64 = 0 ;
477+ @lazy let _frc_plus : u64 = 0 ;
478478
479479// @ts -ignore: decorator
480480@lazy let _frc_pow : u64 = 0 ;
@@ -511,14 +511,14 @@ function umul64e(e1: i32, e2: i32): i32 {
511511
512512// @ts -ignore: decorator
513513@inline
514- function normalizedBoundaries ( f : u64 , e : i32 ) : void {
514+ function normalizedBoundaries ( f : u64 , e : i32 , isSinglePrecision : bool ) : void {
515515 let frc = ( f << 1 ) + 1 ;
516516 let exp = e - 1 ;
517517 let off = < i32 > clz < u64 > ( frc ) ;
518518 frc <<= off ;
519519 exp -= off ;
520520
521- let m = 1 + i32 ( f == 0x0010000000000000 ) ;
521+ let m = 1 + i32 ( f == ( isSinglePrecision ? 0x00800000 : 0x0010000000000000 ) ) ;
522522
523523 _frc_plus = frc ;
524524 _frc_minus = ( ( f << m ) - 1 ) << e - m - exp ;
@@ -559,16 +559,26 @@ function getCachedPower(minExp: i32): void {
559559
560560// @ts -ignore: decorator
561561@inline
562- function grisu2 ( value : f64 , buffer : usize , sign : i32 ) : i32 {
562+ function grisu2 ( value : f64 , buffer : usize , sign : i32 , isSinglePrecision : bool ) : i32 {
563+ let frc : u64 ;
564+ let exp : i32 ;
563565
564566 // frexp routine
565- let uv = reinterpret < u64 > ( value ) ;
566- let exp = i32 ( ( uv & 0x7FF0000000000000 ) >>> 52 ) ;
567- let sid = uv & 0x000FFFFFFFFFFFFF ;
568- let frc = ( u64 ( exp != 0 ) << 52 ) + sid ;
569- exp = select < i32 > ( exp , 1 , exp ) - ( 0x3FF + 52 ) ;
567+ if ( isSinglePrecision ) {
568+ let uv = reinterpret < u32 > ( < f32 > value ) ;
569+ exp = ( uv & 0x7F800000 ) >>> 23 ;
570+ let sid = uv & 0x007FFFFF ;
571+ frc = ( u64 ( exp != 0 ) << 23 ) + sid ;
572+ exp = select < i32 > ( exp , 1 , exp ) - ( 0x7F + 23 ) ;
573+ } else {
574+ let uv = reinterpret < u64 > ( value ) ;
575+ exp = i32 ( ( uv & 0x7FF0000000000000 ) >>> 52 ) ;
576+ let sid = uv & 0x000FFFFFFFFFFFFF ;
577+ frc = ( u64 ( exp != 0 ) << 52 ) + sid ;
578+ exp = select < i32 > ( exp , 1 , exp ) - ( 0x3FF + 52 ) ;
579+ }
570580
571- normalizedBoundaries ( frc , exp ) ;
581+ normalizedBoundaries ( frc , exp , isSinglePrecision ) ;
572582 getCachedPower ( _exp ) ;
573583
574584 // normalize
@@ -716,28 +726,47 @@ function prettify(buffer: usize, length: i32, k: i32): i32 {
716726 }
717727}
718728
719- function dtoa_core ( buffer : usize , value : f64 ) : i32 {
729+ function dtoa_core ( buffer : usize , value : f64 , isSinglePrecision : bool ) : i32 {
720730 let sign = i32 ( value < 0 ) ;
721731 if ( sign ) {
722732 value = - value ;
723733 store < u16 > ( buffer , CharCode . MINUS ) ;
724734 }
725- // assert(value > 0 && value <= 1.7976931348623157e308 );
726- let len = grisu2 ( value , buffer , sign ) ;
735+ // assert(value > 0 && value <= (isSinglePrecision ? f32.MAX_VALUE : f64.MAX_VALUE) );
736+ let len = grisu2 ( value , buffer , sign , isSinglePrecision ) ;
727737 len = prettify ( buffer + ( sign << 1 ) , len - sign , _K ) ;
728738 return len + sign ;
729739}
730740
731741// @ts -ignore: decorator
732742@lazy @inline const dtoa_buf = memory . data ( MAX_DOUBLE_LENGTH << 1 ) ;
733743
734- export function dtoa ( value : f64 ) : String {
744+ export function dtoa < T extends number > ( value : T ) : String {
745+ // assert(isFloat<T>());
746+ if ( sizeof < T > ( ) == 4 ) {
747+ return dtoa_impl ( < f32 > value , true ) ;
748+ } else {
749+ return dtoa_impl ( < f64 > value , false ) ;
750+ }
751+ }
752+
753+ export function dtoa32 ( value : f32 ) : String {
754+ return dtoa_impl ( value , true ) ;
755+ }
756+
757+ export function dtoa64 ( value : f64 ) : String {
758+ return dtoa_impl ( value , false ) ;
759+ }
760+
761+ // @ts -ignore: decorator
762+ @inline
763+ function dtoa_impl ( value : f64 , isSinglePrecision : bool ) : String {
735764 if ( value == 0 ) return "0.0" ;
736765 if ( ! isFinite ( value ) ) {
737766 if ( isNaN ( value ) ) return "NaN" ;
738767 return select < String > ( "-Infinity" , "Infinity" , value < 0 ) ;
739768 }
740- let size = dtoa_core ( dtoa_buf , value ) << 1 ;
769+ let size = dtoa_core ( dtoa_buf , value , isSinglePrecision ) << 1 ;
741770 let result = changetype < String > ( __new ( size , idof < String > ( ) ) ) ;
742771 memory . copy ( changetype < usize > ( result ) , dtoa_buf , size ) ;
743772 return result ;
@@ -821,7 +850,18 @@ export function itoa_buffered<T extends number>(buffer: usize, value: T): u32 {
821850 return sign + decimals ;
822851}
823852
824- export function dtoa_buffered ( buffer : usize , value : f64 ) : u32 {
853+ export function dtoa_buffered < T extends number > ( buffer : usize , value : T ) : u32 {
854+ // assert(isFloat<T>());
855+ if ( sizeof < T > ( ) == 4 ) {
856+ return dtoa_buffered_impl ( buffer , < f32 > value , true ) ;
857+ } else {
858+ return dtoa_buffered_impl ( buffer , < f64 > value , false ) ;
859+ }
860+ }
861+
862+ // @ts -ignore: decorator
863+ @inline
864+ function dtoa_buffered_impl ( buffer : usize , value : f64 , isSinglePrecision : bool ) : u32 {
825865 if ( value == 0 ) {
826866 store < u16 > ( buffer , CharCode . _0 ) ;
827867 store < u16 > ( buffer , CharCode . DOT , 2 ) ;
@@ -845,5 +885,5 @@ export function dtoa_buffered(buffer: usize, value: f64): u32 {
845885 return 8 + u32 ( sign ) ;
846886 }
847887 }
848- return dtoa_core ( buffer , value ) ;
888+ return dtoa_core ( buffer , value , isSinglePrecision ) ;
849889}
0 commit comments