@@ -76,57 +76,59 @@ export const __Porffor_bigint_fromString = (n: string|bytestring): bigint => {
76
76
const len : i32 = n . length ;
77
77
78
78
let negative : boolean = false ;
79
- let end : i32 = 0 ;
79
+ let offset : i32 = 0 ;
80
80
if ( n [ 0 ] === '-' ) {
81
81
negative = true ;
82
- end = 1 ;
82
+ offset = 1 ;
83
83
} else if ( n [ 0 ] === '+' ) {
84
- end = 1 ;
84
+ offset = 1 ;
85
85
}
86
86
87
87
// n -> digits (base 2^32) (most to least significant)
88
88
// 4294967294 -> [ 4294967294 ]
89
89
// 4294967295 -> [ 4294967295 ]
90
90
// 4294967296 -> [ 1, 0 ]
91
91
// 4294967297 -> [ 1, 1 ]
92
- // 4294967298 -> [ 1, 2 ]
93
- // 9007199254740992 -> [ 2097152 ]
92
+ // 9007199254740992 -> [ 2097152, 0 ]
94
93
// 9007199254740993 -> [ 2097152, 1 ]
95
94
// 9007199254740994 -> [ 2097152, 2 ]
96
- // 9007199254740995 -> [ 2097152, 3 ]
97
95
98
- let acc : number = 0 ;
99
- let digits : i32 [ ] ;
100
96
const BASE : i32 = 0x100000000 ; // 2^32
97
+ const digits : i32 [ ] = Porffor . allocate ( ) ; // todo: free later
98
+ digits . length = len - offset ;
101
99
102
- for ( let i : i32 = end ; i < len ; i ++ ) {
103
- const char : i32 = n . charCodeAt ( i ) ;
100
+ let i : i32 = 0 ;
101
+ let acc : number = 0 ;
102
+ while ( i < len ) {
103
+ const char : i32 = n . charCodeAt ( offset + i ) ;
104
104
const digit : i32 = char - 48 ;
105
- if ( digit < 0 || digit > 9 ) throw new SyntaxError ( 'Invalid character in BigInt string' ) ;
106
-
107
- if ( acc == - 1 ) {
108
- let carry : i32 = digit ;
109
- for ( let j : i32 = 0 ; j < digits . length ; j ++ ) {
110
- const value : i32 = digits [ j ] * BASE + carry ;
111
- digits [ j ] = value % BASE ;
112
- carry = Math . trunc ( value / BASE ) ;
113
- }
105
+ if ( Porffor . fastOr ( digit < 0 , digit > 9 ) ) throw new SyntaxError ( 'Invalid character in BigInt string' ) ;
114
106
115
- if ( carry > 0 ) digits . push ( carry ) ;
116
- } else {
117
- acc = acc * 10 + digit ;
118
- if ( acc >= BASE ) {
119
- digits = Porffor . allocate ( ) ;
120
- digits . length = 2 ;
121
- digits [ 0 ] = Math . floor ( acc / BASE ) ;
122
- digits [ 1 ] = acc % BASE ;
123
- acc = - 1 ;
124
- }
107
+ digits [ i ++ ] = digit ;
108
+ acc = acc * 10 + digit ;
109
+ }
110
+
111
+ if ( acc < 0x8000000000000 ) {
112
+ // inline if small enough
113
+ return acc as bigint ;
114
+ }
115
+
116
+ const result : i32 [ ] = Porffor . allocate ( ) ;
117
+ while ( digits . length > 0 ) {
118
+ let carry : i32 = 0 ;
119
+ for ( let j : i32 = 0 ; j < digits . length ; j ++ ) {
120
+ let value : i32 = carry * 10 + digits [ j ] ;
121
+ let quotient : i32 = Math . floor ( value / BASE ) ;
122
+ carry = value % BASE ;
123
+
124
+ digits [ j ] = quotient ;
125
125
}
126
+
127
+ while ( digits . length > 0 && digits [ 0 ] === 0 ) digits . shift ( ) ;
128
+ if ( carry !== 0 || digits . length > 0 ) result . unshift ( carry ) ;
126
129
}
127
130
128
- if ( acc == - 1 ) return __Porffor_bigint_fromDigits ( negative , digits ) ;
129
- return ( negative ? - acc : acc ) as bigint ;
131
+ return __Porffor_bigint_fromDigits ( negative , result ) ;
130
132
} ;
131
133
132
134
export const __Porffor_bigint_toString = ( x : number , radix : any ) : string => {
0 commit comments