@@ -201,6 +201,235 @@ export class BigFloat {
201201 return ( this . mulBig ( factor as BigFloat ) ) ;
202202 }
203203
204+ absDeltaFrom ( other : BigFloat ) {
205+ let limbList = this . limbList ;
206+ let otherList = other . limbList ;
207+ let limbCount = limbList . length ;
208+ let otherCount = otherList . length ;
209+
210+ // Compare lengths.
211+ let d = ( limbCount - this . fractionLen ) - ( otherCount - other . fractionLen ) ;
212+ // If lengths are equal, compare each limb from most to least significant.
213+ while ( ! d && limbCount && otherCount ) d = limbList [ -- limbCount ] - otherList [ -- otherCount ] ;
214+
215+ if ( d ) return ( d ) ;
216+
217+ if ( limbCount ) {
218+ do d = limbList [ -- limbCount ] ; while ( ! d && limbCount ) ;
219+ } else if ( otherCount ) {
220+ do d = - otherList [ -- otherCount ] ; while ( ! d && otherCount ) ;
221+ }
222+
223+ return ( d ) ;
224+ }
225+
226+ isZero ( ) {
227+ let limbList = this . limbList ;
228+ let limbCount = limbList . length ;
229+ let d : number ;
230+
231+ if ( ! limbCount ) return ( true ) ;
232+
233+ do d = limbList [ -- limbCount ] ; while ( ! d && limbCount ) ;
234+
235+ return ( ! d ) ;
236+ }
237+
238+ /** Return an arbitrary number with sign matching the result of this - other. */
239+
240+ deltaFrom ( other : BigFloat ) {
241+ let isNegative = this . isNegative ;
242+ let d = other . isNegative - isNegative ;
243+
244+ // Check if signs are different.
245+ if ( d ) {
246+ // Make sure positive and negative zero have no difference.
247+ if ( this . isZero ( ) && other . isZero ( ) ) return ( 0 ) ;
248+
249+ // Return difference of signs.
250+ return ( d ) ;
251+ }
252+
253+ if ( isNegative ) {
254+ return ( - this . absDeltaFrom ( other ) ) ;
255+ } else {
256+ return ( this . absDeltaFrom ( other ) ) ;
257+ }
258+ }
259+
260+ addBig ( addend : BigFloat ) {
261+ let augend = this as BigFloat ;
262+ let sum = new BigFloat ( ) ;
263+
264+ let fractionLen = augend . fractionLen ;
265+ let len = fractionLen - addend . fractionLen ;
266+
267+ if ( len < 0 ) {
268+ len = - len ;
269+ fractionLen += len ;
270+ augend = addend ;
271+ addend = this ;
272+ }
273+
274+ sum . isNegative = this . isNegative ;
275+ sum . fractionLen = fractionLen ;
276+
277+ let sumLimbs = sum . limbList ;
278+ let augendLimbs = augend . limbList ;
279+ let addendLimbs = addend . limbList ;
280+ let posAugend = 0 ;
281+ let posAddend = 0 ;
282+ let carry = 0 ;
283+ let limbSum : number ;
284+
285+ // If one input has more fractional limbs, just copy the leftovers to output.
286+
287+ while ( posAugend < len ) {
288+ sumLimbs [ posAugend ] = augendLimbs [ posAugend ] ;
289+ ++ posAugend ;
290+ }
291+
292+ let lenAddend = addendLimbs . length ;
293+
294+ len = augendLimbs . length - posAugend ;
295+ if ( len > lenAddend ) len = lenAddend ;
296+
297+ // Calculate sum where input numbers overlap.
298+
299+ while ( posAddend < len ) {
300+ carry += augendLimbs [ posAugend ] + addendLimbs [ posAddend ++ ] ;
301+ limbSum = carry >>> 0 ;
302+ carry = carry - limbSum && 1 ;
303+
304+ sumLimbs [ posAugend ++ ] = limbSum ;
305+ }
306+
307+ let posSum = posAugend ;
308+
309+ if ( len < lenAddend ) {
310+ len = lenAddend ;
311+ augend = addend ;
312+ posAugend = posAddend ;
313+ augendLimbs = addendLimbs ;
314+ } else len = augendLimbs . length ;
315+
316+ // Copy leftover most significant limbs to output, propagating carry.
317+
318+ while ( posAugend < len ) {
319+ carry += augendLimbs [ posAugend ++ ] ;
320+ limbSum = carry >>> 0 ;
321+ carry = carry - limbSum && 1 ;
322+
323+ sumLimbs [ posSum ++ ] = limbSum ;
324+ }
325+
326+ if ( carry ) sumLimbs [ posSum ] = carry ;
327+
328+ return ( sum ) ;
329+ }
330+
331+ subBig ( subtrahend : BigFloat ) {
332+ let minuend = this as BigFloat ;
333+ let difference = new BigFloat ( ) ;
334+
335+ difference . isNegative = this . isNegative ;
336+
337+ // Make sure the subtrahend is the smaller number.
338+ if ( minuend . absDeltaFrom ( subtrahend ) < 0 ) {
339+ minuend = subtrahend ;
340+ subtrahend = this ;
341+ difference . isNegative ^= 1 ;
342+ }
343+
344+ let fractionLen = minuend . fractionLen ;
345+ let len = fractionLen - subtrahend . fractionLen ;
346+
347+ let differenceLimbs = difference . limbList ;
348+ let minuendLimbs = minuend . limbList ;
349+ let subtrahendLimbs = subtrahend . limbList ;
350+ let lenMinuend = minuendLimbs . length ;
351+ let lenSubtrahend = subtrahendLimbs . length ;
352+ let lenFinal = lenMinuend ;
353+ let posMinuend = 0 ;
354+ let posSubtrahend = 0 ;
355+ let posDifference = 0 ;
356+ let carry = 0 ;
357+ let limbDiff : number ;
358+
359+ if ( len >= 0 ) {
360+ while ( posMinuend < len ) {
361+ differenceLimbs [ posMinuend ] = minuendLimbs [ posMinuend ] ;
362+ ++ posMinuend ;
363+ }
364+
365+ len += lenSubtrahend ;
366+ if ( len > lenMinuend ) len = lenMinuend ;
367+
368+ posDifference = posMinuend ;
369+ } else {
370+ len = - len ;
371+ fractionLen += len ;
372+ lenFinal += len ;
373+
374+ while ( posSubtrahend < len ) {
375+ carry -= subtrahendLimbs [ posSubtrahend ] ;
376+ limbDiff = carry >>> 0 ;
377+ carry = - ( carry < 0 ) ;
378+
379+ differenceLimbs [ posSubtrahend ++ ] = limbDiff ;
380+ }
381+
382+ len += lenMinuend ;
383+ if ( len > lenSubtrahend ) len = lenSubtrahend ;
384+
385+ posDifference = posSubtrahend ;
386+ }
387+
388+ difference . fractionLen = fractionLen ;
389+
390+ // Calculate difference where input numbers overlap.
391+
392+ while ( posDifference < len ) {
393+ carry += minuendLimbs [ posMinuend ++ ] - subtrahendLimbs [ posSubtrahend ++ ] ;
394+ limbDiff = carry >>> 0 ;
395+ carry = - ( carry < 0 ) ;
396+
397+ differenceLimbs [ posDifference ++ ] = limbDiff ;
398+ }
399+
400+ // Copy leftover most significant limbs to output, propagating carry.
401+
402+ while ( posDifference < lenFinal ) {
403+ carry += minuendLimbs [ posMinuend ++ ] ;
404+ limbDiff = carry >>> 0 ;
405+ carry = - ( carry < 0 ) ;
406+
407+ differenceLimbs [ posDifference ++ ] = limbDiff ;
408+ }
409+
410+ return ( difference ) ;
411+ }
412+
413+ private addSub ( addend : number | BigFloat , flip : number ) {
414+ if ( typeof ( addend ) == 'number' ) {
415+ addend = BigFloat . tempFloat . setDouble ( addend as number ) ;
416+ }
417+
418+ if ( this . isNegative ^ ( addend as BigFloat ) . isNegative ^ flip ) {
419+ return ( this . subBig ( addend as BigFloat ) ) ;
420+ } else {
421+ return ( this . addBig ( addend as BigFloat ) ) ;
422+ }
423+ }
424+
425+ add ( addend : number | BigFloat ) {
426+ return ( this . addSub ( addend , 0 ) ) ;
427+ }
428+
429+ sub ( subtrahend : number | BigFloat ) {
430+ return ( this . addSub ( subtrahend , 1 ) ) ;
431+ }
432+
204433 /** Divide by integer, replacing current value by quotient. Return integer remainder. */
205434
206435 private divInt ( divisor : number ) {
0 commit comments