1
1
2
2
import {
3
3
CharCode ,
4
- allocate ,
4
+ allocate as allocateString ,
5
5
HEADER_SIZE as STRING_HEADER_SIZE
6
6
} from "./string" ;
7
7
8
- import { loadUnsafe } from "./arraybuffer" ;
8
+ import {
9
+ loadUnsafe
10
+ } from "./arraybuffer" ;
9
11
10
12
@inline
11
- function getPowers10Table ( ) : u32 [ ] {
12
- return < u32 [ ] > [
13
+ function POWERS10 ( ) : u32 [ ] {
14
+ const table : u32 [ ] = [
13
15
1 ,
14
16
10 ,
15
17
100 ,
@@ -21,6 +23,7 @@ function getPowers10Table(): u32[] {
21
23
100000000 ,
22
24
1000000000
23
25
] ;
26
+ return table ; // inlines to a constant memory offset
24
27
}
25
28
26
29
/*
@@ -38,8 +41,8 @@ function getPowers10Table(): u32[] {
38
41
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99"
39
42
*/
40
43
@inline
41
- function getDigitsTable ( ) : u32 [ ] {
42
- return < u32 [ ] > [
44
+ function DIGITS ( ) : u32 [ ] {
45
+ const table : u32 [ ] = [
43
46
0x00300030 , 0x00310030 , 0x00320030 , 0x00330030 , 0x00340030 ,
44
47
0x00350030 , 0x00360030 , 0x00370030 , 0x00380030 , 0x00390030 ,
45
48
0x00300031 , 0x00310031 , 0x00320031 , 0x00330031 , 0x00340031 ,
@@ -61,42 +64,40 @@ function getDigitsTable(): u32[] {
61
64
0x00300039 , 0x00310039 , 0x00320039 , 0x00330039 , 0x00340039 ,
62
65
0x00350039 , 0x00360039 , 0x00370039 , 0x00380039 , 0x00390039
63
66
] ;
67
+ return table ; // inlines to a constant memory offset
64
68
}
65
69
66
70
// Count number of decimals in value
67
- function decimalCount < T > ( value : T ) : i32 {
68
- // make value abs
69
- var sign = value >> ( 8 * sizeof < T > ( ) - 1 ) ;
70
- var v = ( value ^ sign ) - sign ;
71
- var l = 8 * sizeof < T > ( ) - < i32 > clz < T > ( v | 10 ) ; // log2
72
- var t = l * 1233 >>> 12 ; // log10
73
-
74
- var lutbuf = changetype < ArrayBuffer > ( getPowers10Table ( ) . buffer_ ) ;
71
+ export function decimalCount < T > ( value : T ) : i32 {
72
+ var v = abs < T > ( value ) ; // NOP if value is unsigned anyway
73
+ var l : usize = 8 * sizeof < T > ( ) - < usize > clz < T > ( v | 10 ) ; // log2
74
+ var t = l * 1233 >>> 12 ; // log10
75
+
76
+ var lutbuf = < ArrayBuffer > POWERS10 ( ) . buffer_ ;
75
77
if ( sizeof < T > ( ) <= 4 ) {
76
78
let power = loadUnsafe < u32 , T > ( lutbuf , t ) ;
77
- t -= < i32 > ( v < power ) ;
79
+ t -= < usize > ( v < power ) ;
78
80
} else { // sizeof<T>() == 8
79
81
let le10 = t <= 10 ;
80
- let offset = select < i32 > ( 0 , 10 , le10 ) ; // offset = t <= 10 ? 0 : 10
82
+ let offset = select < usize > ( 0 , 10 , le10 ) ; // offset = t <= 10 ? 0 : 10
81
83
let factor = select < T > ( 1 , 10000000000 , le10 ) ; // factor = t <= 10 ? 1 : 10 ^ 10
82
84
let power = loadUnsafe < u32 , T > ( lutbuf , t - offset ) ;
83
- t -= < i32 > ( v < factor * power ) ;
85
+ t -= < usize > ( v < factor * power ) ;
84
86
}
85
87
return t + 1 ;
86
88
}
87
89
88
- function utoa32_lut ( buffer : usize , num : u32 , offset : u32 ) : void {
89
- var r : u32 , t : u32 , d1 : u32 , d2 : u32 ;
90
- var lutbuf = changetype < ArrayBuffer > ( getDigitsTable ( ) . buffer_ ) ;
90
+ function utoa32_lut ( buffer : usize , num : u32 , offset : usize ) : void {
91
+ var lutbuf = < ArrayBuffer > DIGITS ( ) . buffer_ ;
91
92
92
93
while ( num >= 10000 ) {
93
94
// in most VMs i32/u32 div and modulo by constant can be shared and simplificate
94
- t = num / 10000 ;
95
- r = num % 10000 ;
95
+ let t = num / 10000 ;
96
+ let r = num % 10000 ;
96
97
num = t ;
97
98
98
- d1 = r / 100 ;
99
- d2 = r % 100 ;
99
+ let d1 = r / 100 ;
100
+ let d2 = r % 100 ;
100
101
101
102
let digits1 = loadUnsafe < u32 , u64 > ( lutbuf , d1 ) ;
102
103
let digits2 = loadUnsafe < u32 , u64 > ( lutbuf , d2 ) ;
@@ -106,8 +107,8 @@ function utoa32_lut(buffer: usize, num: u32, offset: u32): void {
106
107
}
107
108
108
109
if ( num >= 100 ) {
109
- t = num / 100 ;
110
- d1 = num % 100 ;
110
+ let t = num / 100 ;
111
+ let d1 = num % 100 ;
111
112
num = t ;
112
113
offset -= 2 ;
113
114
let digits = loadUnsafe < u32 , u32 > ( lutbuf , d1 ) ;
@@ -125,24 +126,21 @@ function utoa32_lut(buffer: usize, num: u32, offset: u32): void {
125
126
}
126
127
}
127
128
128
- function utoa64_lut ( buffer : usize , num : u64 , offset : u32 ) : void {
129
- var t : u64 , r : u32 , b : u32 , c : u32 ;
130
- var b1 : u32 , b2 : u32 , c1 : u32 , c2 : u32 ;
131
-
132
- var lutbuf = changetype < ArrayBuffer > ( getDigitsTable ( ) . buffer_ ) ;
129
+ function utoa64_lut ( buffer : usize , num : u64 , offset : usize ) : void {
130
+ var lutbuf = < ArrayBuffer > DIGITS ( ) . buffer_ ;
133
131
134
132
while ( num >= 100000000 ) {
135
- t = num / 100000000 ;
136
- r = < u32 > ( num - t * 100000000 ) ;
133
+ let t = num / 100000000 ;
134
+ let r = < usize > ( num - t * 100000000 ) ;
137
135
num = t ;
138
136
139
- b = r / 10000 ;
140
- c = r % 10000 ;
137
+ let b = r / 10000 ;
138
+ let c = r % 10000 ;
141
139
142
- b1 = b / 100 ;
143
- b2 = b % 100 ;
144
- c1 = c / 100 ;
145
- c2 = c % 100 ;
140
+ let b1 = b / 100 ;
141
+ let b2 = b % 100 ;
142
+ let c1 = c / 100 ;
143
+ let c2 = c % 100 ;
146
144
147
145
let digits1 = loadUnsafe < u32 , u64 > ( lutbuf , c1 ) ;
148
146
let digits2 = loadUnsafe < u32 , u64 > ( lutbuf , c2 ) ;
@@ -157,15 +155,13 @@ function utoa64_lut(buffer: usize, num: u64, offset: u32): void {
157
155
store < u64 > ( buffer + ( offset << 1 ) , digits1 | ( digits2 << 32 ) , STRING_HEADER_SIZE ) ;
158
156
}
159
157
160
- r = < u32 > num ;
161
- if ( r ) utoa32_lut ( buffer , r , offset ) ;
158
+ utoa32_lut ( buffer , < u32 > num , offset ) ;
162
159
}
163
160
164
- function utoa_simple < T > ( buffer : usize , num : T , offset : u32 ) : void {
165
- var t : T , r : u32 ;
161
+ function utoa_simple < T > ( buffer : usize , num : T , offset : usize ) : void {
166
162
do {
167
- t = num / 10 ;
168
- r = < u32 > ( num % 10 ) ;
163
+ let t = num / 10 ;
164
+ let r = < u32 > ( num % 10 ) ;
169
165
num = t ;
170
166
offset -= 1 ;
171
167
store < u16 > ( buffer + ( offset << 1 ) , CharCode . _0 + r , STRING_HEADER_SIZE ) ;
@@ -175,26 +171,26 @@ function utoa_simple<T>(buffer: usize, num: T, offset: u32): void {
175
171
@inline
176
172
export function utoa32_core ( buffer : usize , num : u32 , offset : u32 ) : void {
177
173
if ( ASC_SHRINK_LEVEL >= 1 ) {
178
- utoa_simple ( buffer , num , offset ) ;
174
+ utoa_simple ( buffer , num , < usize > offset ) ;
179
175
} else {
180
- utoa32_lut ( buffer , num , offset ) ;
176
+ utoa32_lut ( buffer , num , < usize > offset ) ;
181
177
}
182
178
}
183
179
184
180
@inline
185
181
export function utoa64_core ( buffer : usize , num : u64 , offset : u32 ) : void {
186
182
if ( ASC_SHRINK_LEVEL >= 1 ) {
187
- utoa_simple ( buffer , num , offset ) ;
183
+ utoa_simple ( buffer , num , < usize > offset ) ;
188
184
} else {
189
- utoa64_lut ( buffer , num , offset ) ;
185
+ utoa64_lut ( buffer , num , < usize > offset ) ;
190
186
}
191
187
}
192
188
193
189
export function utoa32 ( value : u32 ) : string {
194
190
if ( ! value ) return "0" ;
195
191
196
192
var decimals = decimalCount < u32 > ( value ) ;
197
- var buffer = allocate ( decimals ) ;
193
+ var buffer = allocateString ( decimals ) ;
198
194
199
195
utoa32_core ( changetype < usize > ( buffer ) , value , decimals ) ;
200
196
return changetype < string > ( buffer ) ;
@@ -207,7 +203,7 @@ export function itoa32(value: i32): string {
207
203
if ( isneg ) value = - value ;
208
204
209
205
var decimals = decimalCount < u32 > ( value ) + < i32 > isneg ;
210
- var buffer = allocate ( decimals ) ;
206
+ var buffer = allocateString ( decimals ) ;
211
207
212
208
utoa32_core ( changetype < usize > ( buffer ) , value , decimals ) ;
213
209
if ( isneg ) store < u16 > ( changetype < usize > ( buffer ) , CharCode . MINUS , STRING_HEADER_SIZE ) ;
@@ -222,11 +218,11 @@ export function utoa64(value: u64): string {
222
218
if ( value <= u32 . MAX_VALUE ) {
223
219
let value32 = < u32 > value ;
224
220
let decimals = decimalCount < u32 > ( value32 ) ;
225
- buffer = allocate ( decimals ) ;
221
+ buffer = allocateString ( decimals ) ;
226
222
utoa32_core ( changetype < usize > ( buffer ) , value32 , decimals ) ;
227
223
} else {
228
224
let decimals = decimalCount < u64 > ( value ) ;
229
- buffer = allocate ( decimals ) ;
225
+ buffer = allocateString ( decimals ) ;
230
226
utoa64_core ( changetype < usize > ( buffer ) , value , decimals ) ;
231
227
}
232
228
@@ -243,11 +239,11 @@ export function itoa64(value: i64): string {
243
239
if ( < u64 > value <= < u64 > u32 . MAX_VALUE ) {
244
240
let value32 = < u32 > value ;
245
241
let decimals = decimalCount < u32 > ( value32 ) + < i32 > isneg ;
246
- buffer = allocate ( decimals ) ;
242
+ buffer = allocateString ( decimals ) ;
247
243
utoa32_core ( changetype < usize > ( buffer ) , value32 , decimals ) ;
248
244
} else {
249
245
let decimals = decimalCount < u64 > ( value ) + < i32 > isneg ;
250
- buffer = allocate ( decimals ) ;
246
+ buffer = allocateString ( decimals ) ;
251
247
utoa64_core ( changetype < usize > ( buffer ) , value , decimals ) ;
252
248
}
253
249
if ( isneg ) store < u16 > ( changetype < usize > ( buffer ) , CharCode . MINUS , STRING_HEADER_SIZE ) ;
0 commit comments