Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit be1d94a

Browse files
fix: use single precision for dtoa with f32 (#2908)
1 parent 6e151f8 commit be1d94a

18 files changed

+13604
-3232
lines changed

‎std/assembly/util/number.ts

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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,isSingle: 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 == (isSingle ? 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, isSingle: 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 (isSingle) {
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 = (exp || 1) - (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 = (exp || 1) - (0x3FF + 52);
579+
}
570580

571-
normalizedBoundaries(frc, exp);
581+
normalizedBoundaries(frc, exp,isSingle);
572582
getCachedPower(_exp);
573583

574584
// normalize
@@ -716,28 +726,35 @@ 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,isSingle: 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 <= (isSingle ? f32.MAX_VALUE : f64.MAX_VALUE));
736+
let len = grisu2(value, buffer, sign,isSingle);
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+
const isSingle = isFloat<T>() && sizeof<T>() == 4;
746+
return dtoa_impl(value, isSingle);
747+
}
748+
749+
// @ts-ignore: decorator
750+
@inline
751+
function dtoa_impl(value: f64, isSingle: bool): String {
735752
if (value == 0) return "0.0";
736753
if (!isFinite(value)) {
737754
if (isNaN(value)) return "NaN";
738755
return select<String>("-Infinity", "Infinity", value < 0);
739756
}
740-
let size = dtoa_core(dtoa_buf, value) << 1;
757+
let size = dtoa_core(dtoa_buf, value,isSingle) << 1;
741758
let result = changetype<String>(__new(size, idof<String>()));
742759
memory.copy(changetype<usize>(result), dtoa_buf, size);
743760
return result;
@@ -821,7 +838,14 @@ export function itoa_buffered<T extends number>(buffer: usize, value: T): u32 {
821838
return sign + decimals;
822839
}
823840

824-
export function dtoa_buffered(buffer: usize, value: f64): u32 {
841+
export function dtoa_buffered<T extends number>(buffer: usize, value: T): u32 {
842+
const isSingle = isFloat<T>() && sizeof<T>() == 4;
843+
return dtoa_buffered_impl(buffer, value, isSingle);
844+
}
845+
846+
// @ts-ignore: decorator
847+
@inline
848+
function dtoa_buffered_impl(buffer: usize, value: f64, isSingle: bool): u32 {
825849
if (value == 0) {
826850
store<u16>(buffer, CharCode._0);
827851
store<u16>(buffer, CharCode.DOT, 2);
@@ -845,5 +869,5 @@ export function dtoa_buffered(buffer: usize, value: f64): u32 {
845869
return 8 + u32(sign);
846870
}
847871
}
848-
return dtoa_core(buffer, value);
872+
return dtoa_core(buffer, value,isSingle);
849873
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /