@@ -12,14 +12,17 @@ namespace Js
12
12
}
13
13
14
14
JavascriptBigInt * JavascriptBigInt::CreateZero (ScriptContext * scriptContext)
15
+ {
16
+ return JavascriptBigInt::CreateZeroWithLength (1 , scriptContext);
17
+ }
18
+
19
+ JavascriptBigInt * JavascriptBigInt::CreateZeroWithLength (digit_t length, ScriptContext * scriptContext)
15
20
{
16
21
JavascriptBigInt * bigintNew = RecyclerNew (scriptContext->GetRecycler (), JavascriptBigInt, scriptContext->GetLibrary ()->GetBigIntTypeStatic ());
17
- bigintNew->m_length = 1 ;
22
+ bigintNew->m_length = length ;
18
23
bigintNew->m_isNegative = false ;
19
- bigintNew->m_maxLength = 1 ;
20
- bigintNew->m_digits = RecyclerNewArrayLeaf (scriptContext->GetRecycler (), digit_t , bigintNew->m_length );
21
- bigintNew->m_digits [0 ] = 0 ;
22
-
24
+ bigintNew->m_maxLength = length;
25
+ bigintNew->m_digits = RecyclerNewArrayLeafZ (scriptContext->GetRecycler (), digit_t , bigintNew->m_length );
23
26
return bigintNew;
24
27
}
25
28
@@ -32,11 +35,12 @@ namespace Js
32
35
33
36
JavascriptBigInt * JavascriptBigInt::New (JavascriptBigInt * pbi, ScriptContext * scriptContext)
34
37
{
38
+ Assert (pbi->m_maxLength >= pbi->m_length );
35
39
JavascriptBigInt * bigintNew = RecyclerNew (scriptContext->GetRecycler (), JavascriptBigInt, scriptContext->GetLibrary ()->GetBigIntTypeStatic ());
36
40
bigintNew->m_length = pbi->m_length ;
37
41
bigintNew->m_maxLength = pbi->m_maxLength ;
38
42
bigintNew->m_isNegative = pbi->m_isNegative ;
39
- bigintNew->m_digits = RecyclerNewArrayLeaf (scriptContext->GetRecycler (), digit_t , pbi->m_length );
43
+ bigintNew->m_digits = RecyclerNewArrayLeaf (scriptContext->GetRecycler (), digit_t , pbi->m_maxLength );
40
44
js_memcpy_s (bigintNew->m_digits , bigintNew->m_length * sizeof (digit_t ), pbi->m_digits , bigintNew->m_length * sizeof (digit_t ));
41
45
42
46
return bigintNew;
@@ -151,23 +155,20 @@ namespace Js
151
155
152
156
digit_t digitMul = 1 ;
153
157
digit_t digitAdd = 0 ;
154
- bool check = true ;
155
158
for (; pChar < pCharLimit; pChar++)
156
159
{
157
160
Assert (NumberUtilities::IsDigit (*pChar));
158
161
if (digitMul == 1e9 )
159
162
{
160
- check = MulThenAdd (digitMul, digitAdd);
161
- Assert (check);
163
+ MulThenAdd (digitMul, digitAdd);
162
164
digitMul = 1 ;
163
165
digitAdd = 0 ;
164
166
}
165
167
digitMul *= 10 ;
166
168
digitAdd = digitAdd * 10 + *pChar - ' 0' ;
167
169
}
168
170
Assert (1 < digitMul);
169
- check = MulThenAdd (digitMul, digitAdd);
170
- Assert (check);
171
+ MulThenAdd (digitMul, digitAdd);
171
172
172
173
// make sure this is no negative zero
173
174
if (m_length == 0 )
@@ -352,7 +353,7 @@ namespace Js
352
353
return resultLow;
353
354
}
354
355
355
- bool JavascriptBigInt::MulThenAdd (digit_t digitMul, digit_t digitAdd)
356
+ void JavascriptBigInt::MulThenAdd (digit_t digitMul, digit_t digitAdd)
356
357
{
357
358
Assert (digitMul != 0 );
358
359
@@ -377,7 +378,6 @@ namespace Js
377
378
}
378
379
m_digits[m_length++] = digitAdd;
379
380
}
380
- return true ;
381
381
}
382
382
383
383
int JavascriptBigInt::Compare (JavascriptBigInt *pbi)
@@ -419,7 +419,9 @@ namespace Js
419
419
for (index = m_length - 1 ; m_digits[index] == pbi->m_digits [index]; index--)
420
420
{
421
421
if (0 == index)
422
+ {
422
423
return 0 ;
424
+ }
423
425
}
424
426
Assert (m_digits[index] != pbi->m_digits [index]);
425
427
@@ -554,6 +556,72 @@ namespace Js
554
556
}
555
557
}
556
558
559
+ // return |pbi1| * |pbi2|
560
+ JavascriptBigInt * JavascriptBigInt::MulAbsolute (JavascriptBigInt * pbi1, JavascriptBigInt * pbi2)
561
+ {
562
+ // Start with maximum length possible in pbi3
563
+ digit_t length = pbi1->m_length + pbi2->m_length ;
564
+ if (SIZE_MAX / sizeof (digit_t ) < length) // overflow
565
+ {
566
+ JavascriptError::ThrowRangeError (pbi1->GetScriptContext (), VBSERR_TypeMismatch, _u (" Multiply BigInt" ));
567
+ }
568
+ JavascriptBigInt * pbi3 = JavascriptBigInt::CreateZeroWithLength (length, pbi1->GetScriptContext ());
569
+
570
+ // Compute pbi3 = pbi1 * pbi2 as follow:
571
+ // e.g. A1 A0 * B1 B0 = C3 C2 C1 C0
572
+ // C0 = A0 * B0 (take the digit and carry)
573
+ // C1 = carry + A0 * B1 + A1 * B0 (take the digit and carry)
574
+ // C2 = carry + A1 * B1 (take the digit and carry)
575
+ // C3 = carry
576
+ digit_t carryDigit = 0 ;
577
+ digit_t i3 = 0 ;
578
+
579
+ for (digit_t i1 = 0 ; i1 < pbi1->m_length ; i1++)
580
+ {
581
+ carryDigit = 0 ;
582
+ for (digit_t i2 = 0 ; i2 < pbi2->m_length ; i2++)
583
+ {
584
+ i3 = i1 + i2;
585
+ digit_t tempCarryDigit1 = 0 ;
586
+ digit_t tempCarryDigit2 = 0 ;
587
+ pbi3->m_digits [i3] = JavascriptBigInt::AddDigit (pbi3->m_digits [i3], carryDigit, &tempCarryDigit1);
588
+ digit_t mulDigitResult = JavascriptBigInt::MulDigit (pbi1->m_digits [i1], pbi2->m_digits [i2], &carryDigit);
589
+ pbi3->m_digits [i3] = JavascriptBigInt::AddDigit (pbi3->m_digits [i3], mulDigitResult, &tempCarryDigit2);
590
+ digit_t overflow = 0 ;
591
+ carryDigit = JavascriptBigInt::AddDigit (carryDigit, tempCarryDigit1, &overflow);
592
+ Assert (overflow == 0 ); // [i1] * [i2] can not carry through [i1+i2+2]
593
+ carryDigit = JavascriptBigInt::AddDigit (carryDigit, tempCarryDigit2, &overflow);
594
+ Assert (overflow == 0 ); // [i1] * [i2] can not carry through [i1+i2+2]
595
+ }
596
+ if (carryDigit > 0 )
597
+ {
598
+ pbi3->m_digits [i3 + 1 ] = carryDigit;
599
+ }
600
+ }
601
+
602
+ // adjust length
603
+ while ((pbi3->m_length > 0 ) && (pbi3->m_digits [pbi3->m_length - 1 ] == 0 ))
604
+ {
605
+ pbi3->m_length --;
606
+ }
607
+ Assert (pbi3->m_length > 0 );
608
+ return pbi3;
609
+ }
610
+
611
+ JavascriptBigInt * JavascriptBigInt::Mul (JavascriptBigInt * pbi1, JavascriptBigInt * pbi2)
612
+ {
613
+ if (JavascriptBigInt::IsZero (pbi1) || JavascriptBigInt::IsZero (pbi2))
614
+ {
615
+ return JavascriptBigInt::CreateZero (pbi1->GetScriptContext ());
616
+ }
617
+ JavascriptBigInt * result = JavascriptBigInt::MulAbsolute (pbi1, pbi2);
618
+ if (pbi1->m_isNegative != pbi2->m_isNegative )
619
+ {
620
+ result->m_isNegative = true ;
621
+ }
622
+ return result;
623
+ }
624
+
557
625
JavascriptBigInt * JavascriptBigInt::Add (JavascriptBigInt * pbi1, JavascriptBigInt * pbi2)
558
626
{
559
627
if (JavascriptBigInt::IsZero (pbi1))
@@ -607,4 +675,11 @@ namespace Js
607
675
// TODO: Consider deferring creation of new instances until we need them
608
676
}
609
677
678
+ Var JavascriptBigInt::Mul (Var aLeft, Var aRight)
679
+ {
680
+ JavascriptBigInt *leftBigInt = VarTo<JavascriptBigInt>(aLeft);
681
+ JavascriptBigInt *rightBigInt = VarTo<JavascriptBigInt>(aRight);
682
+ return JavascriptBigInt::Mul (leftBigInt, rightBigInt);
683
+ }
684
+
610
685
} // namespace Js
0 commit comments