@@ -7,8 +7,8 @@ import { trimNumber } from './util';
77
88export class BigFloat32 implements BigFloatBase < BigFloat32 > {
99
10- constructor ( value ?: number | BigFloat32 ) {
11- value ? this . setValue ( value ) : this . setZero ( ) ;
10+ constructor ( value ?: BigFloat32 | number | string , base ?: number ) {
11+ value ? this . setValue ( value , base ) : this . setZero ( ) ;
1212 }
1313
1414 clone ( ) {
@@ -23,12 +23,16 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
2323 return ( this ) ;
2424 }
2525
26- setValue ( other : number | BigFloat32 ) {
26+ setValue ( other : BigFloat32 | number | string , base ?: number ) {
2727 if ( typeof ( other ) == 'number' ) {
2828 return ( this . setNumber ( other ) ) ;
2929 }
3030
31- return ( this . setBig ( other ) ) ;
31+ if ( other instanceof BigFloat32 ) {
32+ return ( this . setBig ( other ) ) ;
33+ }
34+
35+ return ( this . setString ( other . toString ( ) , base || 10 ) ) ;
3236 }
3337
3438 private setBig ( other : BigFloat32 ) {
@@ -87,8 +91,10 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
8791 len += pos + 1 ;
8892
8993 // Handle integer part.
94+
9095 while ( iPart ) {
9196 // Extract limbs starting from the least significant.
97+
9298 limb = iPart % limbSize32 ; // Could also be iPart >>> 0
9399 iPart = ( iPart - limb ) / limbSize32 ;
94100
@@ -103,6 +109,112 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
103109 return ( this ) ;
104110 }
105111
112+ private parseFraction ( value : string , base : number , start : number , offset : number , limbBase : number , limbDigits : number ) {
113+ const limbList = this . limbList ;
114+ let pos = value . length ;
115+
116+ // Set limbs to zero, because divInt uses them as input.
117+
118+ let limbNum = offset - 1 ;
119+
120+ while ( limbNum ) {
121+ limbList [ -- limbNum ] = 0 ;
122+ }
123+
124+ // Read initial digits so their count becomes divisible by limbDigits.
125+
126+ let posNext = pos - ( ( pos - start + limbDigits - 1 ) % limbDigits + 1 ) ;
127+
128+ limbList [ offset - 1 ] = parseInt ( value . substr ( posNext , pos - posNext ) , base ) ;
129+ this . divInt ( Math . pow ( base , pos - posNext ) , offset ) ;
130+
131+ pos = posNext ;
132+
133+ // Read rest of the digits in limbDigits sized chunks.
134+
135+ while ( pos > start ) {
136+ pos -= limbDigits ;
137+
138+ limbList [ offset - 1 ] = parseInt ( value . substr ( pos , limbDigits ) , base ) ;
139+
140+ // Divide by maximum power of base that fits in a limb.
141+ this . divInt ( limbBase , offset ) ;
142+ }
143+ }
144+
145+ private setString ( value : string , base : number ) {
146+ const { limbBase, limbDigits, limbDigitsExact } = BaseInfo32 . init ( base ) ;
147+ const limbList = this . limbList ;
148+ let pos = - 1 ;
149+ let c : string ;
150+
151+ this . sign = 1 ;
152+
153+ // Handle leading signs and zeroes.
154+
155+ while ( 1 ) {
156+ c = value . charAt ( ++ pos ) ;
157+
158+ switch ( c ) {
159+ case '-' :
160+ this . sign = - 1 ;
161+ case '+' :
162+ case '0' :
163+ continue ;
164+ }
165+
166+ break ;
167+ }
168+
169+ const posDot = ( value . indexOf ( '.' , pos ) + 1 || value . length + 1 ) - 1 ;
170+
171+ // Handle fractional part.
172+
173+ if ( posDot < value . length - 1 ) {
174+ // Reserve enough limbs to contain digits in fractional part.
175+ const len = ~ ~ ( ( value . length - posDot - 1 ) / limbDigitsExact ) + 1 ;
176+
177+ this . parseFraction ( value , base , posDot + 1 , len + 1 , limbBase , limbDigits ) ;
178+
179+ this . fractionLen = len ;
180+ this . len = len ;
181+
182+ // Remove trailing zeroes.
183+ this . trimLeast ( ) ;
184+ } else {
185+ this . fractionLen = 0 ;
186+ this . len = 0 ;
187+ }
188+
189+ const offset = this . fractionLen ;
190+
191+ // Handle integer part.
192+
193+ if ( posDot > pos ) {
194+ // Read initial digits so their count becomes divisible by limbDigits.
195+
196+ let posNext = pos + ( posDot - pos + limbDigits - 1 ) % limbDigits + 1 ;
197+
198+ ++ this . len ;
199+ limbList [ offset ] = parseInt ( value . substr ( pos , posNext - pos ) , base ) ;
200+ pos = posNext ;
201+
202+ // Read rest of the digits in limbDigits sized chunks.
203+
204+ while ( pos < posDot ) {
205+ // Multiply by maximum power of base that fits in a limb.
206+ if ( this . mulInt ( limbBase , limbList , offset , offset , 0 ) ) ++ this . len ;
207+
208+ // Add latest limb.
209+ limbList [ offset ] += parseInt ( value . substr ( pos , limbDigits ) , base ) ;
210+
211+ pos += limbDigits ;
212+ }
213+ }
214+
215+ return ( this ) ;
216+ }
217+
106218 /** Trim zero limbs from most significant end. */
107219
108220 private trimMost ( ) {
@@ -481,21 +593,20 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
481593
482594 /** Divide by integer, replacing current value by quotient. Return integer remainder. */
483595
484- private divInt ( divisor : number ) {
596+ private divInt ( divisor : number , pos : number ) {
485597 let limbList = this . limbList ;
486- let limbNum = this . len ;
487598 let limb : number ;
488599 let hi : number , lo : number ;
489600 let carry = 0 ;
490601
491602 // If most significant limb is zero after dividing, decrement number of limbs remaining.
492- if ( limbList [ limbNum - 1 ] < divisor ) {
493- carry = limbList [ -- limbNum ] ;
494- this . len = limbNum ;
603+ if ( limbList [ pos - 1 ] < divisor ) {
604+ carry = limbList [ -- pos ] ;
605+ this . len = pos ;
495606 }
496607
497- while ( limbNum -- ) {
498- limb = limbList [ limbNum ] ;
608+ while ( pos -- ) {
609+ limb = limbList [ pos ] ;
499610
500611 carry = carry * 0x10000 + ( limb >>> 16 ) ;
501612 hi = ( carry / divisor ) >>> 0 ;
@@ -505,7 +616,7 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
505616 lo = ( carry / divisor ) >>> 0 ;
506617 carry = carry - lo * divisor ;
507618
508- limbList [ limbNum ] = ( ( hi << 16 ) | lo ) >>> 0 ;
619+ limbList [ pos ] = ( ( hi << 16 ) | lo ) >>> 0 ;
509620 }
510621
511622 return ( carry ) ;
@@ -545,11 +656,29 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
545656 }
546657 }
547658
659+ getExpansion ( output : number [ ] ) {
660+ const limbList = this . limbList ;
661+ const len = this . len ;
662+ let exp = this . sign ;
663+ let pos = this . fractionLen ;
664+
665+ while ( pos -- ) {
666+ exp *= limbInv32 ;
667+ }
668+
669+ while ( ++ pos < len ) {
670+ output [ pos ] = limbList [ pos ] * exp ;
671+ exp *= limbSize32 ;
672+ }
673+
674+ return ( len ) ;
675+ }
676+
548677 valueOf ( ) {
549678 const limbList = this . limbList ;
550- let len = this . fractionLen ;
551679 let result = 0 ;
552680 let exp = limbInv32 * this . sign ;
681+ let len = this . fractionLen ;
553682 let pos = 0 ;
554683
555684 while ( pos < len ) {
@@ -584,7 +713,7 @@ export class BigFloat32 implements BigFloatBase<BigFloat32> {
584713
585714 // Loop while 2 or more limbs remain, requiring arbitrary precision division to extract digits.
586715 while ( iPart . len > 1 ) {
587- limbStr = iPart . divInt ( limbBase ) . toString ( base ) ;
716+ limbStr = iPart . divInt ( limbBase , iPart . len ) . toString ( base ) ;
588717
589718 // Prepend digits into final result, padded with zeroes to 9 digits.
590719 // Since more limbs still remain, whole result will not have extra padding.
0 commit comments