52 #ifndef CRYPTOPP_IMPORTS 72 #if (_MSC_VER >= 1400) && !defined(_M_ARM) 81 #if (__SUNPRO_CC >= 0x5130) 83 # define MAYBE_UNCONST_CAST(x) const_cast<word*>(x) 85 # define MAYBE_CONST const 86 # define MAYBE_UNCONST_CAST(x) x 91 #if CRYPTOPP_BOOL_X32 || defined(CRYPTOPP_DISABLE_MIXED_ASM) 92 # undef CRYPTOPP_X86_ASM_AVAILABLE 93 # undef CRYPTOPP_X32_ASM_AVAILABLE 94 # undef CRYPTOPP_X64_ASM_AVAILABLE 95 # undef CRYPTOPP_SSE2_ASM_AVAILABLE 96 # undef CRYPTOPP_SSSE3_ASM_AVAILABLE 98 # define CRYPTOPP_INTEGER_SSE2 (CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86)) 106 static void SetFunctionPointers();
114 InitializeInteger::InitializeInteger()
120 SetFunctionPointers();
137 inline static int Compare(
const word *A,
const word *B,
size_t N)
142 else if (A[N] < B[N])
148 inline static int Increment(word *A,
size_t N, word B=1)
155 for (
unsigned i=1; i<N; i++)
161 inline static int Decrement(word *A,
size_t N, word B=1)
168 for (
unsigned i=1; i<N; i++)
174 static void TwosComplement(word *A,
size_t N)
177 for (
unsigned i=0; i<N; i++)
181 static word AtomicInverseModPower2(word A)
187 for (
unsigned i=3; i<WORD_BITS; i*=2)
196 #if !defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) || (defined(__x86_64__) && defined(CRYPTOPP_WORD128_AVAILABLE)) 197 #define TWO_64_BIT_WORDS 1 198 #define Declare2Words(x) word x##0, x##1; 199 #define AssignWord(a, b) a##0 = b; a##1 = 0; 200 #define Add2WordsBy1(a, b, c) a##0 = b##0 + c; a##1 = b##1 + (a##0 < c); 201 #define LowWord(a) a##0 202 #define HighWord(a) a##1 204 #define MultiplyWordsLoHi(p0, p1, a, b) p0 = _umul128(a, b, &p1); 205 #ifndef __INTEL_COMPILER 206 #define Double3Words(c, d) d##1 = __shiftleft128(d##0, d##1, 1); d##0 = __shiftleft128(c, d##0, 1); c *= 2; 208 #elif defined(__DECCXX) 209 #define MultiplyWordsLoHi(p0, p1, a, b) p0 = a*b; p1 = asm("umulh %a0, %a1, %v0", a, b); 210 #elif defined(__x86_64__) 211 #if defined(__SUNPRO_CC) && __SUNPRO_CC < 0x5100 213 #define MultiplyWordsLoHi(p0, p1, a, b) asm ("mulq %3" : "=a"(p0), "=d"(p1) : "a"(a), "r"(b) : "cc"); 215 #define MultiplyWordsLoHi(p0, p1, a, b) asm ("mulq %3" : "=a"(p0), "=d"(p1) : "a"(a), "g"(b) : "cc"); 216 #define MulAcc(c, d, a, b) asm ("mulq %6; addq %3, %0; adcq %4, %1; adcq $0, %2;" : "+r"(c), "+r"(d##0), "+r"(d##1), "=a"(p0), "=d"(p1) : "a"(a), "g"(b) : "cc"); 217 #define Double3Words(c, d) asm ("addq %0, %0; adcq %1, %1; adcq %2, %2;" : "+r"(c), "+r"(d##0), "+r"(d##1) : : "cc"); 218 #define Acc2WordsBy1(a, b) asm ("addq %2, %0; adcq $0, %1;" : "+r"(a##0), "+r"(a##1) : "r"(b) : "cc"); 219 #define Acc2WordsBy2(a, b) asm ("addq %2, %0; adcq %3, %1;" : "+r"(a##0), "+r"(a##1) : "r"(b##0), "r"(b##1) : "cc"); 220 #define Acc3WordsBy2(c, d, e) asm ("addq %5, %0; adcq %6, %1; adcq $0, %2;" : "+r"(c), "=r"(e##0), "=r"(e##1) : "1"(d##0), "2"(d##1), "r"(e##0), "r"(e##1) : "cc"); 223 #define MultiplyWords(p, a, b) MultiplyWordsLoHi(p##0, p##1, a, b) 225 #define Double3Words(c, d) d##1 = 2*d##1 + (d##0>>(WORD_BITS-1)); d##0 = 2*d##0 + (c>>(WORD_BITS-1)); c *= 2; 228 #define Acc2WordsBy2(a, b) a##0 += b##0; a##1 += a##0 < b##0; a##1 += b##1; 230 #define AddWithCarry(u, a, b) {word t = a+b; u##0 = t + u##1; u##1 = (t<a) + (u##0<t);} 231 #define SubtractWithBorrow(u, a, b) {word t = a-b; u##0 = t - u##1; u##1 = (t>a) + (u##0>t);} 232 #define GetCarry(u) u##1 233 #define GetBorrow(u) u##1 235 #define Declare2Words(x) dword x; 236 #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER) && !defined(_M_ARM) 237 #define MultiplyWords(p, a, b) p = __emulu(a, b); 239 #define MultiplyWords(p, a, b) p = (dword)a*b; 241 #define AssignWord(a, b) a = b; 242 #define Add2WordsBy1(a, b, c) a = b + c; 243 #define Acc2WordsBy2(a, b) a += b; 244 #define LowWord(a) word(a) 245 #define HighWord(a) word(a>>WORD_BITS) 246 #define Double3Words(c, d) d = 2*d + (c>>(WORD_BITS-1)); c *= 2; 247 #define AddWithCarry(u, a, b) u = dword(a) + b + GetCarry(u); 248 #define SubtractWithBorrow(u, a, b) u = dword(a) - b - GetBorrow(u); 249 #define GetCarry(u) HighWord(u) 250 #define GetBorrow(u) word(u>>(WORD_BITS*2-1)) 253 #define MulAcc(c, d, a, b) MultiplyWords(p, a, b); Acc2WordsBy1(p, c); c = LowWord(p); Acc2WordsBy1(d, HighWord(p)); 256 #define Acc2WordsBy1(a, b) Add2WordsBy1(a, a, b) 259 #define Acc3WordsBy2(c, d, e) Acc2WordsBy1(e, c); c = LowWord(e); Add2WordsBy1(e, d, HighWord(e)); 265 #if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) 266 DWord() {std::memset(&m_whole, 0x00,
sizeof(m_whole));}
268 DWord() {std::memset(&m_halfs, 0x00,
sizeof(m_halfs));}
271 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 272 explicit DWord(word low) : m_whole(low) { }
274 explicit DWord(word low)
281 #if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) 282 DWord(word low, word high) : m_whole()
284 DWord(word low, word high) : m_halfs()
287 #if defined(CRYPTOPP_NATIVE_DWORD_AVAILABLE) 288 # if (CRYPTOPP_LITTLE_ENDIAN) 289 const word t[2] = {low,high};
290 memcpy(&m_whole, t,
sizeof(m_whole));
292 const word t[2] = {high,low};
293 memcpy(&m_whole, t,
sizeof(m_whole));
301 static DWord Multiply(word a, word b)
304 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 305 r.m_whole = (dword)a * b;
306 #elif defined(MultiplyWordsLoHi) 307 MultiplyWordsLoHi(r.m_halfs.low, r.m_halfs.high, a, b);
314 static DWord MultiplyAndAdd(word a, word b, word c)
316 DWord r = Multiply(a, b);
320 DWord & operator+=(word a)
322 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 323 m_whole = m_whole + a;
326 m_halfs.high += (m_halfs.low < a);
331 DWord operator+(word a)
334 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 335 r.m_whole = m_whole + a;
337 r.m_halfs.low = m_halfs.low + a;
338 r.m_halfs.high = m_halfs.high + (r.m_halfs.low < a);
346 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 347 r.m_whole = m_whole - a.m_whole;
349 r.m_halfs.low = m_halfs.low - a.m_halfs.low;
350 r.m_halfs.high = m_halfs.high - a.m_halfs.high - (r.m_halfs.low > m_halfs.low);
355 DWord operator-(word a)
358 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 359 r.m_whole = m_whole - a;
361 r.m_halfs.low = m_halfs.low - a;
362 r.m_halfs.high = m_halfs.high - (r.m_halfs.low > m_halfs.low);
368 word operator/(word divisor);
370 word operator%(word a);
372 bool operator!()
const 374 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 377 return !m_halfs.high && !m_halfs.low;
383 word GetLowHalf()
const {
return m_halfs.low;}
384 word GetHighHalf()
const {
return m_halfs.high;}
385 word GetHighHalfAsBorrow()
const {
return 0-m_halfs.high;}
393 #if (CRYPTOPP_LITTLE_ENDIAN) 403 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 413 Word() : m_whole(0) {}
414 Word(word value) : m_whole(value) {}
415 Word(hword low, hword high) : m_whole(low | (word(high) << (WORD_BITS/2))) {}
417 static Word Multiply(hword a, hword b)
420 r.m_whole = (word)a * b;
427 r.m_whole = m_whole - a.m_whole;
431 Word operator-(hword a)
434 r.m_whole = m_whole - a;
439 hword operator/(hword divisor)
441 return hword(m_whole / divisor);
444 bool operator!()
const 449 word GetWhole()
const {
return m_whole;}
450 hword GetLowHalf()
const {
return hword(m_whole);}
451 hword GetHighHalf()
const {
return hword(m_whole>>(WORD_BITS/2));}
452 hword GetHighHalfAsBorrow()
const {
return 0-hword(m_whole>>(WORD_BITS/2));}
459 template <
class S,
class D>
460 S DivideThreeWordsByTwo(S *A, S B0, S B1, D *dummy=NULLPTR)
462 CRYPTOPP_UNUSED(dummy);
471 S Q;
bool pre = (S(B1+1) == 0);
473 Q = D(A[1], A[2]) / S(B1+1);
477 Q = D(A[0], A[1]) / B0;
480 D p = D::Multiply(B0, Q);
481 D u = (D) A[0] - p.GetLowHalf();
482 A[0] = u.GetLowHalf();
483 u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q);
484 A[1] = u.GetLowHalf();
485 A[2] += u.GetHighHalf();
488 while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0))
491 A[0] = u.GetLowHalf();
492 u = (D) A[1] - B1 - u.GetHighHalfAsBorrow();
493 A[1] = u.GetLowHalf();
494 A[2] += u.GetHighHalf();
503 template <
class S,
class D>
504 inline D DivideFourWordsByTwo(S *T,
const D &Al,
const D &Ah,
const D &B)
512 T[0] = Al.GetLowHalf();
513 T[1] = Al.GetHighHalf();
514 T[2] = Ah.GetLowHalf();
515 T[3] = Ah.GetHighHalf();
516 Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(), B.GetHighHalf());
517 Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf());
518 return D(Q[0], Q[1]);
522 return D(Ah.GetLowHalf(), Ah.GetHighHalf());
527 inline word DWord::operator/(word a)
529 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 530 return word(m_whole / a);
533 return DivideFourWordsByTwo<hword, Word>(r, m_halfs.low, m_halfs.high, a).GetWhole();
537 inline word DWord::operator%(word a)
539 #ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE 540 return word(m_whole % a);
542 if (a < (word(1) << (WORD_BITS/2)))
545 word r = m_halfs.high % h;
546 r = ((m_halfs.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h;
547 return hword((hword(m_halfs.low) + (r << (WORD_BITS/2))) % h);
552 DivideFourWordsByTwo<hword, Word>(r, m_halfs.low, m_halfs.high, a);
553 return Word(r[0], r[1]).GetWhole();
561 #if defined(__GNUC__) 562 #define AddPrologue \ 564 __asm__ __volatile__ \ 567 #define AddEpilogue \ 570 : "d" (C), "a" (A), "D" (B), "c" (N) \ 571 : "%esi", "memory", "cc" \ 574 #define MulPrologue \ 575 __asm__ __volatile__ \ 580 #define MulEpilogue \ 584 : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B) \ 585 : "%esi", "memory", "cc" \ 587 #define SquPrologue MulPrologue 588 #define SquEpilogue \ 592 : "d" (s_maskLow16), "c" (C), "a" (A) \ 593 : "%esi", "%edi", "memory", "cc" \ 595 #define TopPrologue MulPrologue 596 #define TopEpilogue \ 600 : "d" (s_maskLow16), "c" (C), "a" (A), "D" (B), "S" (L) \ 604 #define AddPrologue \ 607 __asm mov eax, [esp+12] \ 608 __asm mov edi, [esp+16] 609 #define AddEpilogue \ 615 #define SquPrologue \ 619 AS2( lea ebx, s_maskLow16) 620 #define MulPrologue \ 625 AS2( lea ebx, s_maskLow16) 626 #define TopPrologue \ 632 AS2( lea ebx, s_maskLow16) 633 #define SquEpilogue RestoreEBX 634 #define MulEpilogue RestoreEBX 635 #define TopEpilogue RestoreEBX 638 #ifdef CRYPTOPP_X64_MASM_AVAILABLE 640 int Baseline_Add(
size_t N, word *C,
const word *A,
const word *B);
641 int Baseline_Sub(
size_t N, word *C,
const word *A,
const word *B);
643 #elif defined(CRYPTOPP_X64_ASM_AVAILABLE) && defined(__GNUC__) && defined(CRYPTOPP_WORD128_AVAILABLE) 644 int Baseline_Add(
size_t N, word *C,
const word *A,
const word *B)
652 AS2( mov %0,[%3+8*%1])
653 AS2( add %0,[%4+8*%1])
654 AS2( mov [%2+8*%1],%0)
656 AS2( mov %0,[%3+8*%1+8])
657 AS2( adc %0,[%4+8*%1+8])
658 AS2( mov [%2+8*%1+8],%0)
661 AS2( mov %0,[%3+8*%1])
662 AS2( adc %0,[%4+8*%1])
663 AS2( mov [%2+8*%1],%0)
669 :
"=&r" (result),
"+c" (N)
670 :
"r" (C+N),
"r" (A+N),
"r" (B+N)
676 int Baseline_Sub(
size_t N, word *C,
const word *A,
const word *B)
684 AS2( mov %0,[%3+8*%1])
685 AS2( sub %0,[%4+8*%1])
686 AS2( mov [%2+8*%1],%0)
688 AS2( mov %0,[%3+8*%1+8])
689 AS2( sbb %0,[%4+8*%1+8])
690 AS2( mov [%2+8*%1+8],%0)
693 AS2( mov %0,[%3+8*%1])
694 AS2( sbb %0,[%4+8*%1])
695 AS2( mov [%2+8*%1],%0)
701 :
"=&r" (result),
"+c" (N)
702 :
"r" (C+N),
"r" (A+N),
"r" (B+N)
707 #elif defined(CRYPTOPP_X86_ASM_AVAILABLE) && CRYPTOPP_BOOL_X86 708 CRYPTOPP_NAKED
int CRYPTOPP_FASTCALL Baseline_Add(
size_t N, word *C,
const word *A,
const word *B)
713 AS2( lea eax, [eax+4*ecx])
714 AS2( lea edi, [edi+4*ecx])
715 AS2( lea edx, [edx+4*ecx])
725 AS2( mov esi,[eax+4*ecx])
726 AS2( adc esi,[edi+4*ecx])
727 AS2( mov [edx+4*ecx],esi)
728 AS2( mov esi,[eax+4*ecx+4])
729 AS2( adc esi,[edi+4*ecx+4])
730 AS2( mov [edx+4*ecx+4],esi)
732 AS2( mov esi,[eax+4*ecx+8])
733 AS2( adc esi,[edi+4*ecx+8])
734 AS2( mov [edx+4*ecx+8],esi)
735 AS2( mov esi,[eax+4*ecx+12])
736 AS2( adc esi,[edi+4*ecx+12])
737 AS2( mov [edx+4*ecx+12],esi)
739 AS2( lea ecx,[ecx+4])
749 CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B);
750 CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N);
753 CRYPTOPP_NAKED
int CRYPTOPP_FASTCALL Baseline_Sub(
size_t N, word *C, const word *A, const word *B)
758 AS2( lea eax, [eax+4*ecx])
759 AS2( lea edi, [edi+4*ecx])
760 AS2( lea edx, [edx+4*ecx])
770 AS2( mov esi,[eax+4*ecx])
771 AS2( sbb esi,[edi+4*ecx])
772 AS2( mov [edx+4*ecx],esi)
773 AS2( mov esi,[eax+4*ecx+4])
774 AS2( sbb esi,[edi+4*ecx+4])
775 AS2( mov [edx+4*ecx+4],esi)
777 AS2( mov esi,[eax+4*ecx+8])
778 AS2( sbb esi,[edi+4*ecx+8])
779 AS2( mov [edx+4*ecx+8],esi)
780 AS2( mov esi,[eax+4*ecx+12])
781 AS2( sbb esi,[edi+4*ecx+12])
782 AS2( mov [edx+4*ecx+12],esi)
784 AS2( lea ecx,[ecx+4])
794 CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B);
795 CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N);
798 #if CRYPTOPP_INTEGER_SSE2 799 CRYPTOPP_NAKED
int CRYPTOPP_FASTCALL SSE2_Add(
size_t N, word *C,
const word *A,
const word *B)
804 AS2( lea eax, [eax+4*ecx])
805 AS2( lea edi, [edi+4*ecx])
806 AS2( lea edx, [edx+4*ecx])
817 AS2( movd mm0, DWORD PTR [eax+4*ecx])
818 AS2( movd mm1, DWORD PTR [edi+4*ecx])
821 AS2( movd DWORD PTR [edx+4*ecx], mm2)
824 AS2( movd mm0, DWORD PTR [eax+4*ecx+4])
825 AS2( movd mm1, DWORD PTR [edi+4*ecx+4])
828 AS2( movd DWORD PTR [edx+4*ecx+4], mm2)
832 AS2( movd mm0, DWORD PTR [eax+4*ecx+8])
833 AS2( movd mm1, DWORD PTR [edi+4*ecx+8])
836 AS2( movd DWORD PTR [edx+4*ecx+8], mm2)
839 AS2( movd mm0, DWORD PTR [eax+4*ecx+12])
840 AS2( movd mm1, DWORD PTR [edi+4*ecx+12])
843 AS2( movd DWORD PTR [edx+4*ecx+12], mm2)
856 CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B);
857 CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N);
859 CRYPTOPP_NAKED
int CRYPTOPP_FASTCALL SSE2_Sub(
size_t N, word *C, const word *A, const word *B)
864 AS2( lea eax, [eax+4*ecx])
865 AS2( lea edi, [edi+4*ecx])
866 AS2( lea edx, [edx+4*ecx])
877 AS2( movd mm0, DWORD PTR [eax+4*ecx])
878 AS2( movd mm1, DWORD PTR [edi+4*ecx])
881 AS2( movd DWORD PTR [edx+4*ecx], mm0)
884 AS2( movd mm2, DWORD PTR [eax+4*ecx+4])
885 AS2( movd mm1, DWORD PTR [edi+4*ecx+4])
888 AS2( movd DWORD PTR [edx+4*ecx+4], mm2)
892 AS2( movd mm0, DWORD PTR [eax+4*ecx+8])
893 AS2( movd mm1, DWORD PTR [edi+4*ecx+8])
896 AS2( movd DWORD PTR [edx+4*ecx+8], mm0)
899 AS2( movd mm2, DWORD PTR [eax+4*ecx+12])
900 AS2( movd mm1, DWORD PTR [edi+4*ecx+12])
903 AS2( movd DWORD PTR [edx+4*ecx+12], mm2)
916 CRYPTOPP_UNUSED(A); CRYPTOPP_UNUSED(B);
917 CRYPTOPP_UNUSED(C); CRYPTOPP_UNUSED(N);
919 #endif // CRYPTOPP_INTEGER_SSE2 920 #else // CRYPTOPP_SSE2_ASM_AVAILABLE 921 int CRYPTOPP_FASTCALL Baseline_Add(
size_t N, word *C,
const word *A,
const word *B)
927 for (
size_t i=0; i<N; i+=2)
929 AddWithCarry(u, A[i], B[i]);
931 AddWithCarry(u, A[i+1], B[i+1]);
934 return int(GetCarry(u));
937 int CRYPTOPP_FASTCALL Baseline_Sub(
size_t N, word *C,
const word *A,
const word *B)
943 for (
size_t i=0; i<N; i+=2)
945 SubtractWithBorrow(u, A[i], B[i]);
947 SubtractWithBorrow(u, A[i+1], B[i+1]);
950 return int(GetBorrow(u));
954 static word LinearMultiply(word *C,
const word *AA, word B,
size_t N)
957 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
960 for(
unsigned i=0; i<N; i++)
963 MultiplyWords(p, A[i], B);
964 Acc2WordsBy1(p, carry);
971 #ifndef CRYPTOPP_DOXYGEN_PROCESSING 975 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 980 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 981 Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \ 982 Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \ 983 Mul_SaveAcc(3, 1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) \ 984 Mul_SaveAcc(4, 2, 3) Mul_Acc(3, 2) \ 989 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 990 Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \ 991 Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \ 992 Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \ 993 Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \ 994 Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \ 995 Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \ 996 Mul_SaveAcc(7, 1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) \ 997 Mul_SaveAcc(8, 2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) \ 998 Mul_SaveAcc(9, 3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) \ 999 Mul_SaveAcc(10, 4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) \ 1000 Mul_SaveAcc(11, 5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) \ 1001 Mul_SaveAcc(12, 6, 7) Mul_Acc(7, 6) \ 1006 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 1007 Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \ 1008 Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \ 1009 Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \ 1010 Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \ 1011 Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \ 1012 Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \ 1013 Mul_SaveAcc(7, 0, 8) Mul_Acc(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) Mul_Acc(8, 0) \ 1014 Mul_SaveAcc(8, 0, 9) Mul_Acc(1, 8) Mul_Acc(2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) Mul_Acc(8, 1) Mul_Acc(9, 0) \ 1015 Mul_SaveAcc(9, 0, 10) Mul_Acc(1, 9) Mul_Acc(2, 8) Mul_Acc(3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) Mul_Acc(8, 2) Mul_Acc(9, 1) Mul_Acc(10, 0) \ 1016 Mul_SaveAcc(10, 0, 11) Mul_Acc(1, 10) Mul_Acc(2, 9) Mul_Acc(3, 8) Mul_Acc(4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) Mul_Acc(8, 3) Mul_Acc(9, 2) Mul_Acc(10, 1) Mul_Acc(11, 0) \ 1017 Mul_SaveAcc(11, 0, 12) Mul_Acc(1, 11) Mul_Acc(2, 10) Mul_Acc(3, 9) Mul_Acc(4, 8) Mul_Acc(5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) Mul_Acc(8, 4) Mul_Acc(9, 3) Mul_Acc(10, 2) Mul_Acc(11, 1) Mul_Acc(12, 0) \ 1018 Mul_SaveAcc(12, 0, 13) Mul_Acc(1, 12) Mul_Acc(2, 11) Mul_Acc(3, 10) Mul_Acc(4, 9) Mul_Acc(5, 8) Mul_Acc(6, 7) Mul_Acc(7, 6) Mul_Acc(8, 5) Mul_Acc(9, 4) Mul_Acc(10, 3) Mul_Acc(11, 2) Mul_Acc(12, 1) Mul_Acc(13, 0) \ 1019 Mul_SaveAcc(13, 0, 14) Mul_Acc(1, 13) Mul_Acc(2, 12) Mul_Acc(3, 11) Mul_Acc(4, 10) Mul_Acc(5, 9) Mul_Acc(6, 8) Mul_Acc(7, 7) Mul_Acc(8, 6) Mul_Acc(9, 5) Mul_Acc(10, 4) Mul_Acc(11, 3) Mul_Acc(12, 2) Mul_Acc(13, 1) Mul_Acc(14, 0) \ 1020 Mul_SaveAcc(14, 0, 15) Mul_Acc(1, 14) Mul_Acc(2, 13) Mul_Acc(3, 12) Mul_Acc(4, 11) Mul_Acc(5, 10) Mul_Acc(6, 9) Mul_Acc(7, 8) Mul_Acc(8, 7) Mul_Acc(9, 6) Mul_Acc(10, 5) Mul_Acc(11, 4) Mul_Acc(12, 3) Mul_Acc(13, 2) Mul_Acc(14, 1) Mul_Acc(15, 0) \ 1021 Mul_SaveAcc(15, 1, 15) Mul_Acc(2, 14) Mul_Acc(3, 13) Mul_Acc(4, 12) Mul_Acc(5, 11) Mul_Acc(6, 10) Mul_Acc(7, 9) Mul_Acc(8, 8) Mul_Acc(9, 7) Mul_Acc(10, 6) Mul_Acc(11, 5) Mul_Acc(12, 4) Mul_Acc(13, 3) Mul_Acc(14, 2) Mul_Acc(15, 1) \ 1022 Mul_SaveAcc(16, 2, 15) Mul_Acc(3, 14) Mul_Acc(4, 13) Mul_Acc(5, 12) Mul_Acc(6, 11) Mul_Acc(7, 10) Mul_Acc(8, 9) Mul_Acc(9, 8) Mul_Acc(10, 7) Mul_Acc(11, 6) Mul_Acc(12, 5) Mul_Acc(13, 4) Mul_Acc(14, 3) Mul_Acc(15, 2) \ 1023 Mul_SaveAcc(17, 3, 15) Mul_Acc(4, 14) Mul_Acc(5, 13) Mul_Acc(6, 12) Mul_Acc(7, 11) Mul_Acc(8, 10) Mul_Acc(9, 9) Mul_Acc(10, 8) Mul_Acc(11, 7) Mul_Acc(12, 6) Mul_Acc(13, 5) Mul_Acc(14, 4) Mul_Acc(15, 3) \ 1024 Mul_SaveAcc(18, 4, 15) Mul_Acc(5, 14) Mul_Acc(6, 13) Mul_Acc(7, 12) Mul_Acc(8, 11) Mul_Acc(9, 10) Mul_Acc(10, 9) Mul_Acc(11, 8) Mul_Acc(12, 7) Mul_Acc(13, 6) Mul_Acc(14, 5) Mul_Acc(15, 4) \ 1025 Mul_SaveAcc(19, 5, 15) Mul_Acc(6, 14) Mul_Acc(7, 13) Mul_Acc(8, 12) Mul_Acc(9, 11) Mul_Acc(10, 10) Mul_Acc(11, 9) Mul_Acc(12, 8) Mul_Acc(13, 7) Mul_Acc(14, 6) Mul_Acc(15, 5) \ 1026 Mul_SaveAcc(20, 6, 15) Mul_Acc(7, 14) Mul_Acc(8, 13) Mul_Acc(9, 12) Mul_Acc(10, 11) Mul_Acc(11, 10) Mul_Acc(12, 9) Mul_Acc(13, 8) Mul_Acc(14, 7) Mul_Acc(15, 6) \ 1027 Mul_SaveAcc(21, 7, 15) Mul_Acc(8, 14) Mul_Acc(9, 13) Mul_Acc(10, 12) Mul_Acc(11, 11) Mul_Acc(12, 10) Mul_Acc(13, 9) Mul_Acc(14, 8) Mul_Acc(15, 7) \ 1028 Mul_SaveAcc(22, 8, 15) Mul_Acc(9, 14) Mul_Acc(10, 13) Mul_Acc(11, 12) Mul_Acc(12, 11) Mul_Acc(13, 10) Mul_Acc(14, 9) Mul_Acc(15, 8) \ 1029 Mul_SaveAcc(23, 9, 15) Mul_Acc(10, 14) Mul_Acc(11, 13) Mul_Acc(12, 12) Mul_Acc(13, 11) Mul_Acc(14, 10) Mul_Acc(15, 9) \ 1030 Mul_SaveAcc(24, 10, 15) Mul_Acc(11, 14) Mul_Acc(12, 13) Mul_Acc(13, 12) Mul_Acc(14, 11) Mul_Acc(15, 10) \ 1031 Mul_SaveAcc(25, 11, 15) Mul_Acc(12, 14) Mul_Acc(13, 13) Mul_Acc(14, 12) Mul_Acc(15, 11) \ 1032 Mul_SaveAcc(26, 12, 15) Mul_Acc(13, 14) Mul_Acc(14, 13) Mul_Acc(15, 12) \ 1033 Mul_SaveAcc(27, 13, 15) Mul_Acc(14, 14) Mul_Acc(15, 13) \ 1034 Mul_SaveAcc(28, 14, 15) Mul_Acc(15, 14) \ 1043 Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \ 1044 Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \ 1045 Squ_SaveAcc(3, 1, 3) Squ_Diag(2) \ 1046 Squ_SaveAcc(4, 2, 3) Squ_NonDiag \ 1051 Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \ 1052 Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \ 1053 Squ_SaveAcc(3, 0, 4) Squ_Acc(1, 3) Squ_Diag(2) \ 1054 Squ_SaveAcc(4, 0, 5) Squ_Acc(1, 4) Squ_Acc(2, 3) Squ_NonDiag \ 1055 Squ_SaveAcc(5, 0, 6) Squ_Acc(1, 5) Squ_Acc(2, 4) Squ_Diag(3) \ 1056 Squ_SaveAcc(6, 0, 7) Squ_Acc(1, 6) Squ_Acc(2, 5) Squ_Acc(3, 4) Squ_NonDiag \ 1057 Squ_SaveAcc(7, 1, 7) Squ_Acc(2, 6) Squ_Acc(3, 5) Squ_Diag(4) \ 1058 Squ_SaveAcc(8, 2, 7) Squ_Acc(3, 6) Squ_Acc(4, 5) Squ_NonDiag \ 1059 Squ_SaveAcc(9, 3, 7) Squ_Acc(4, 6) Squ_Diag(5) \ 1060 Squ_SaveAcc(10, 4, 7) Squ_Acc(5, 6) Squ_NonDiag \ 1061 Squ_SaveAcc(11, 5, 7) Squ_Diag(6) \ 1062 Squ_SaveAcc(12, 6, 7) Squ_NonDiag \ 1067 Squ_SaveAcc(1, 0, 2) Squ_Diag(1) \ 1068 Squ_SaveAcc(2, 0, 3) Squ_Acc(1, 2) Squ_NonDiag \ 1069 Squ_SaveAcc(3, 0, 4) Squ_Acc(1, 3) Squ_Diag(2) \ 1070 Squ_SaveAcc(4, 0, 5) Squ_Acc(1, 4) Squ_Acc(2, 3) Squ_NonDiag \ 1071 Squ_SaveAcc(5, 0, 6) Squ_Acc(1, 5) Squ_Acc(2, 4) Squ_Diag(3) \ 1072 Squ_SaveAcc(6, 0, 7) Squ_Acc(1, 6) Squ_Acc(2, 5) Squ_Acc(3, 4) Squ_NonDiag \ 1073 Squ_SaveAcc(7, 0, 8) Squ_Acc(1, 7) Squ_Acc(2, 6) Squ_Acc(3, 5) Squ_Diag(4) \ 1074 Squ_SaveAcc(8, 0, 9) Squ_Acc(1, 8) Squ_Acc(2, 7) Squ_Acc(3, 6) Squ_Acc(4, 5) Squ_NonDiag \ 1075 Squ_SaveAcc(9, 0, 10) Squ_Acc(1, 9) Squ_Acc(2, 8) Squ_Acc(3, 7) Squ_Acc(4, 6) Squ_Diag(5) \ 1076 Squ_SaveAcc(10, 0, 11) Squ_Acc(1, 10) Squ_Acc(2, 9) Squ_Acc(3, 8) Squ_Acc(4, 7) Squ_Acc(5, 6) Squ_NonDiag \ 1077 Squ_SaveAcc(11, 0, 12) Squ_Acc(1, 11) Squ_Acc(2, 10) Squ_Acc(3, 9) Squ_Acc(4, 8) Squ_Acc(5, 7) Squ_Diag(6) \ 1078 Squ_SaveAcc(12, 0, 13) Squ_Acc(1, 12) Squ_Acc(2, 11) Squ_Acc(3, 10) Squ_Acc(4, 9) Squ_Acc(5, 8) Squ_Acc(6, 7) Squ_NonDiag \ 1079 Squ_SaveAcc(13, 0, 14) Squ_Acc(1, 13) Squ_Acc(2, 12) Squ_Acc(3, 11) Squ_Acc(4, 10) Squ_Acc(5, 9) Squ_Acc(6, 8) Squ_Diag(7) \ 1080 Squ_SaveAcc(14, 0, 15) Squ_Acc(1, 14) Squ_Acc(2, 13) Squ_Acc(3, 12) Squ_Acc(4, 11) Squ_Acc(5, 10) Squ_Acc(6, 9) Squ_Acc(7, 8) Squ_NonDiag \ 1081 Squ_SaveAcc(15, 1, 15) Squ_Acc(2, 14) Squ_Acc(3, 13) Squ_Acc(4, 12) Squ_Acc(5, 11) Squ_Acc(6, 10) Squ_Acc(7, 9) Squ_Diag(8) \ 1082 Squ_SaveAcc(16, 2, 15) Squ_Acc(3, 14) Squ_Acc(4, 13) Squ_Acc(5, 12) Squ_Acc(6, 11) Squ_Acc(7, 10) Squ_Acc(8, 9) Squ_NonDiag \ 1083 Squ_SaveAcc(17, 3, 15) Squ_Acc(4, 14) Squ_Acc(5, 13) Squ_Acc(6, 12) Squ_Acc(7, 11) Squ_Acc(8, 10) Squ_Diag(9) \ 1084 Squ_SaveAcc(18, 4, 15) Squ_Acc(5, 14) Squ_Acc(6, 13) Squ_Acc(7, 12) Squ_Acc(8, 11) Squ_Acc(9, 10) Squ_NonDiag \ 1085 Squ_SaveAcc(19, 5, 15) Squ_Acc(6, 14) Squ_Acc(7, 13) Squ_Acc(8, 12) Squ_Acc(9, 11) Squ_Diag(10) \ 1086 Squ_SaveAcc(20, 6, 15) Squ_Acc(7, 14) Squ_Acc(8, 13) Squ_Acc(9, 12) Squ_Acc(10, 11) Squ_NonDiag \ 1087 Squ_SaveAcc(21, 7, 15) Squ_Acc(8, 14) Squ_Acc(9, 13) Squ_Acc(10, 12) Squ_Diag(11) \ 1088 Squ_SaveAcc(22, 8, 15) Squ_Acc(9, 14) Squ_Acc(10, 13) Squ_Acc(11, 12) Squ_NonDiag \ 1089 Squ_SaveAcc(23, 9, 15) Squ_Acc(10, 14) Squ_Acc(11, 13) Squ_Diag(12) \ 1090 Squ_SaveAcc(24, 10, 15) Squ_Acc(11, 14) Squ_Acc(12, 13) Squ_NonDiag \ 1091 Squ_SaveAcc(25, 11, 15) Squ_Acc(12, 14) Squ_Diag(13) \ 1092 Squ_SaveAcc(26, 12, 15) Squ_Acc(13, 14) Squ_NonDiag \ 1093 Squ_SaveAcc(27, 13, 15) Squ_Diag(14) \ 1094 Squ_SaveAcc(28, 14, 15) Squ_NonDiag \ 1099 Bot_SaveAcc(0, 0, 1) Bot_Acc(1, 0) \ 1104 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 1105 Mul_SaveAcc(1, 2, 0) Mul_Acc(1, 1) Mul_Acc(0, 2) \ 1106 Bot_SaveAcc(2, 0, 3) Bot_Acc(1, 2) Bot_Acc(2, 1) Bot_Acc(3, 0) \ 1111 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 1112 Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \ 1113 Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \ 1114 Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \ 1115 Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \ 1116 Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \ 1117 Bot_SaveAcc(6, 0, 7) Bot_Acc(1, 6) Bot_Acc(2, 5) Bot_Acc(3, 4) Bot_Acc(4, 3) Bot_Acc(5, 2) Bot_Acc(6, 1) Bot_Acc(7, 0) \ 1122 Mul_SaveAcc(0, 0, 1) Mul_Acc(1, 0) \ 1123 Mul_SaveAcc(1, 0, 2) Mul_Acc(1, 1) Mul_Acc(2, 0) \ 1124 Mul_SaveAcc(2, 0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \ 1125 Mul_SaveAcc(3, 0, 4) Mul_Acc(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) Mul_Acc(4, 0) \ 1126 Mul_SaveAcc(4, 0, 5) Mul_Acc(1, 4) Mul_Acc(2, 3) Mul_Acc(3, 2) Mul_Acc(4, 1) Mul_Acc(5, 0) \ 1127 Mul_SaveAcc(5, 0, 6) Mul_Acc(1, 5) Mul_Acc(2, 4) Mul_Acc(3, 3) Mul_Acc(4, 2) Mul_Acc(5, 1) Mul_Acc(6, 0) \ 1128 Mul_SaveAcc(6, 0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \ 1129 Mul_SaveAcc(7, 0, 8) Mul_Acc(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) Mul_Acc(8, 0) \ 1130 Mul_SaveAcc(8, 0, 9) Mul_Acc(1, 8) Mul_Acc(2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) Mul_Acc(8, 1) Mul_Acc(9, 0) \ 1131 Mul_SaveAcc(9, 0, 10) Mul_Acc(1, 9) Mul_Acc(2, 8) Mul_Acc(3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) Mul_Acc(8, 2) Mul_Acc(9, 1) Mul_Acc(10, 0) \ 1132 Mul_SaveAcc(10, 0, 11) Mul_Acc(1, 10) Mul_Acc(2, 9) Mul_Acc(3, 8) Mul_Acc(4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) Mul_Acc(8, 3) Mul_Acc(9, 2) Mul_Acc(10, 1) Mul_Acc(11, 0) \ 1133 Mul_SaveAcc(11, 0, 12) Mul_Acc(1, 11) Mul_Acc(2, 10) Mul_Acc(3, 9) Mul_Acc(4, 8) Mul_Acc(5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) Mul_Acc(8, 4) Mul_Acc(9, 3) Mul_Acc(10, 2) Mul_Acc(11, 1) Mul_Acc(12, 0) \ 1134 Mul_SaveAcc(12, 0, 13) Mul_Acc(1, 12) Mul_Acc(2, 11) Mul_Acc(3, 10) Mul_Acc(4, 9) Mul_Acc(5, 8) Mul_Acc(6, 7) Mul_Acc(7, 6) Mul_Acc(8, 5) Mul_Acc(9, 4) Mul_Acc(10, 3) Mul_Acc(11, 2) Mul_Acc(12, 1) Mul_Acc(13, 0) \ 1135 Mul_SaveAcc(13, 0, 14) Mul_Acc(1, 13) Mul_Acc(2, 12) Mul_Acc(3, 11) Mul_Acc(4, 10) Mul_Acc(5, 9) Mul_Acc(6, 8) Mul_Acc(7, 7) Mul_Acc(8, 6) Mul_Acc(9, 5) Mul_Acc(10, 4) Mul_Acc(11, 3) Mul_Acc(12, 2) Mul_Acc(13, 1) Mul_Acc(14, 0) \ 1136 Bot_SaveAcc(14, 0, 15) Bot_Acc(1, 14) Bot_Acc(2, 13) Bot_Acc(3, 12) Bot_Acc(4, 11) Bot_Acc(5, 10) Bot_Acc(6, 9) Bot_Acc(7, 8) Bot_Acc(8, 7) Bot_Acc(9, 6) Bot_Acc(10, 5) Bot_Acc(11, 4) Bot_Acc(12, 3) Bot_Acc(13, 2) Bot_Acc(14, 1) Bot_Acc(15, 0) \ 1142 #define Mul_Begin(n) \ 1146 MultiplyWords(p, A[0], B[0]) \ 1147 AssignWord(c, LowWord(p)) \ 1148 AssignWord(d, HighWord(p)) 1150 #define Mul_Acc(i, j) \ 1151 MultiplyWords(p, A[i], B[j]) \ 1152 Acc2WordsBy1(c, LowWord(p)) \ 1153 Acc2WordsBy1(d, HighWord(p)) 1155 #define Mul_SaveAcc(k, i, j) \ 1156 R[k] = LowWord(c); \ 1157 Add2WordsBy1(c, d, HighWord(c)) \ 1158 MultiplyWords(p, A[i], B[j]) \ 1159 AssignWord(d, HighWord(p)) \ 1160 Acc2WordsBy1(c, LowWord(p)) 1162 #define Mul_End(n) \ 1163 R[2*n-3] = LowWord(c); \ 1164 Acc2WordsBy1(d, HighWord(c)) \ 1165 MultiplyWords(p, A[n-1], B[n-1])\ 1166 Acc2WordsBy2(d, p) \ 1167 R[2*n-2] = LowWord(d); \ 1168 R[2*n-1] = HighWord(d); 1170 #define Bot_SaveAcc(k, i, j) \ 1171 R[k] = LowWord(c); \ 1172 word e = LowWord(d) + HighWord(c); \ 1175 #define Bot_Acc(i, j) \ 1178 #define Bot_End(n) \ 1181 #define Mul_Begin(n) \ 1185 MultiplyWords(p, A[0], B[0]) \ 1187 AssignWord(d, HighWord(p)) 1189 #define Mul_Acc(i, j) \ 1190 MulAcc(c, d, A[i], B[j]) 1192 #define Mul_SaveAcc(k, i, j) \ 1195 AssignWord(d, HighWord(d)) \ 1196 MulAcc(c, d, A[i], B[j]) 1198 #define Mul_End(k, i) \ 1200 MultiplyWords(p, A[i], B[i]) \ 1201 Acc2WordsBy2(p, d) \ 1202 R[k+1] = LowWord(p); \ 1203 R[k+2] = HighWord(p); 1205 #define Bot_SaveAcc(k, i, j) \ 1210 #define Bot_Acc(i, j) \ 1213 #define Bot_End(n) \ 1217 #define Squ_Begin(n) \ 1222 MultiplyWords(p, A[0], A[0]) \ 1223 R[0] = LowWord(p); \ 1224 AssignWord(e, HighWord(p)) \ 1225 MultiplyWords(p, A[0], A[1]) \ 1227 AssignWord(d, HighWord(p)) \ 1230 #define Squ_NonDiag \ 1233 #define Squ_SaveAcc(k, i, j) \ 1234 Acc3WordsBy2(c, d, e) \ 1236 MultiplyWords(p, A[i], A[j]) \ 1238 AssignWord(d, HighWord(p)) \ 1240 #define Squ_Acc(i, j) \ 1241 MulAcc(c, d, A[i], A[j]) 1243 #define Squ_Diag(i) \ 1245 MulAcc(c, d, A[i], A[i]) 1247 #define Squ_End(n) \ 1248 Acc3WordsBy2(c, d, e) \ 1250 MultiplyWords(p, A[n-1], A[n-1])\ 1251 Acc2WordsBy2(p, e) \ 1252 R[2*n-2] = LowWord(p); \ 1253 R[2*n-1] = HighWord(p); 1256 void Baseline_Multiply2(word *R,
const word *AA,
const word *BB)
1259 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1260 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1265 void Baseline_Multiply4(word *R,
const word *AA,
const word *BB)
1268 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1269 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1274 void Baseline_Multiply8(word *R,
const word *AA,
const word *BB)
1277 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1278 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1283 void Baseline_Square2(word *R,
const word *AA)
1286 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1291 void Baseline_Square4(word *R,
const word *AA)
1294 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1299 void Baseline_Square8(word *R,
const word *AA)
1302 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1307 void Baseline_MultiplyBottom2(word *R,
const word *AA,
const word *BB)
1310 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1311 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1316 #if defined(TWO_64_BIT_WORDS) 1317 CRYPTOPP_UNUSED(d0); CRYPTOPP_UNUSED(d1);
1321 void Baseline_MultiplyBottom4(word *R,
const word *AA,
const word *BB)
1324 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1325 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1330 void Baseline_MultiplyBottom8(word *R,
const word *AA,
const word *BB)
1333 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1334 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1339 #define Top_Begin(n) \ 1343 MultiplyWords(p, A[0], B[n-2]);\ 1344 AssignWord(d, HighWord(p)); 1346 #define Top_Acc(i, j) \ 1347 MultiplyWords(p, A[i], B[j]);\ 1348 Acc2WordsBy1(d, HighWord(p)); 1350 #define Top_SaveAcc0(i, j) \ 1352 AssignWord(d, HighWord(d)) \ 1353 MulAcc(c, d, A[i], B[j]) 1355 #define Top_SaveAcc1(i, j) \ 1357 Acc2WordsBy1(d, c); \ 1359 AssignWord(d, HighWord(d)) \ 1360 MulAcc(c, d, A[i], B[j]) 1362 void Baseline_MultiplyTop2(word *R,
const word *A,
const word *B, word L)
1366 Baseline_Multiply2(T, A, B);
1371 void Baseline_MultiplyTop4(word *R,
const word *AA,
const word *BB, word L)
1374 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1375 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1378 Top_Acc(1, 1) Top_Acc(2, 0) \
1379 Top_SaveAcc0(0, 3) Mul_Acc(1, 2) Mul_Acc(2, 1) Mul_Acc(3, 0) \
1380 Top_SaveAcc1(1, 3) Mul_Acc(2, 2) Mul_Acc(3, 1) \
1381 Mul_SaveAcc(0, 2, 3) Mul_Acc(3, 2) \
1385 void Baseline_MultiplyTop8(word *R, const word *AA, const word *BB, word L)
1388 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1389 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1392 Top_Acc(1, 5) Top_Acc(2, 4) Top_Acc(3, 3) Top_Acc(4, 2) Top_Acc(5, 1) Top_Acc(6, 0) \
1393 Top_SaveAcc0(0, 7) Mul_Acc(1, 6) Mul_Acc(2, 5) Mul_Acc(3, 4) Mul_Acc(4, 3) Mul_Acc(5, 2) Mul_Acc(6, 1) Mul_Acc(7, 0) \
1394 Top_SaveAcc1(1, 7) Mul_Acc(2, 6) Mul_Acc(3, 5) Mul_Acc(4, 4) Mul_Acc(5, 3) Mul_Acc(6, 2) Mul_Acc(7, 1) \
1395 Mul_SaveAcc(0, 2, 7) Mul_Acc(3, 6) Mul_Acc(4, 5) Mul_Acc(5, 4) Mul_Acc(6, 3) Mul_Acc(7, 2) \
1396 Mul_SaveAcc(1, 3, 7) Mul_Acc(4, 6) Mul_Acc(5, 5) Mul_Acc(6, 4) Mul_Acc(7, 3) \
1397 Mul_SaveAcc(2, 4, 7) Mul_Acc(5, 6) Mul_Acc(6, 5) Mul_Acc(7, 4) \
1398 Mul_SaveAcc(3, 5, 7) Mul_Acc(6, 6) Mul_Acc(7, 5) \
1399 Mul_SaveAcc(4, 6, 7) Mul_Acc(7, 6) \
1403 #if !CRYPTOPP_INTEGER_SSE2 // save memory by not compiling these functions when SSE2 is available 1404 void Baseline_Multiply16(word *R,
const word *AA,
const word *BB)
1407 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1408 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1413 void Baseline_Square16(word *R,
const word *AA)
1416 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1421 void Baseline_MultiplyBottom16(word *R,
const word *AA,
const word *BB)
1424 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1425 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1430 void Baseline_MultiplyTop16(word *R,
const word *AA,
const word *BB, word L)
1433 MAYBE_CONST word* A = MAYBE_UNCONST_CAST(AA);
1434 MAYBE_CONST word* B = MAYBE_UNCONST_CAST(BB);
1437 Top_Acc(1, 13) Top_Acc(2, 12) Top_Acc(3, 11) Top_Acc(4, 10) Top_Acc(5, 9) Top_Acc(6, 8) Top_Acc(7, 7) Top_Acc(8, 6) Top_Acc(9, 5) Top_Acc(10, 4) Top_Acc(11, 3) Top_Acc(12, 2) Top_Acc(13, 1) Top_Acc(14, 0) \
1438 Top_SaveAcc0(0, 15) Mul_Acc(1, 14) Mul_Acc(2, 13) Mul_Acc(3, 12) Mul_Acc(4, 11) Mul_Acc(5, 10) Mul_Acc(6, 9) Mul_Acc(7, 8) Mul_Acc(8, 7) Mul_Acc(9, 6) Mul_Acc(10, 5) Mul_Acc(11, 4) Mul_Acc(12, 3) Mul_Acc(13, 2) Mul_Acc(14, 1) Mul_Acc(15, 0) \
1439 Top_SaveAcc1(1, 15) Mul_Acc(2, 14) Mul_Acc(3, 13) Mul_Acc(4, 12) Mul_Acc(5, 11) Mul_Acc(6, 10) Mul_Acc(7, 9) Mul_Acc(8, 8) Mul_Acc(9, 7) Mul_Acc(10, 6) Mul_Acc(11, 5) Mul_Acc(12, 4) Mul_Acc(13, 3) Mul_Acc(14, 2) Mul_Acc(15, 1) \
1440 Mul_SaveAcc(0, 2, 15) Mul_Acc(3, 14) Mul_Acc(4, 13) Mul_Acc(5, 12) Mul_Acc(6, 11) Mul_Acc(7, 10) Mul_Acc(8, 9) Mul_Acc(9, 8) Mul_Acc(10, 7) Mul_Acc(11, 6) Mul_Acc(12, 5) Mul_Acc(13, 4) Mul_Acc(14, 3) Mul_Acc(15, 2) \
1441 Mul_SaveAcc(1, 3, 15) Mul_Acc(4, 14) Mul_Acc(5, 13) Mul_Acc(6, 12) Mul_Acc(7, 11) Mul_Acc(8, 10) Mul_Acc(9, 9) Mul_Acc(10, 8) Mul_Acc(11, 7) Mul_Acc(12, 6) Mul_Acc(13, 5) Mul_Acc(14, 4) Mul_Acc(15, 3) \
1442 Mul_SaveAcc(2, 4, 15) Mul_Acc(5, 14) Mul_Acc(6, 13) Mul_Acc(7, 12) Mul_Acc(8, 11) Mul_Acc(9, 10) Mul_Acc(10, 9) Mul_Acc(11, 8) Mul_Acc(12, 7) Mul_Acc(13, 6) Mul_Acc(14, 5) Mul_Acc(15, 4) \
1443 Mul_SaveAcc(3, 5, 15) Mul_Acc(6, 14) Mul_Acc(7, 13) Mul_Acc(8, 12) Mul_Acc(9, 11) Mul_Acc(10, 10) Mul_Acc(11, 9) Mul_Acc(12, 8) Mul_Acc(13, 7) Mul_Acc(14, 6) Mul_Acc(15, 5) \
1444 Mul_SaveAcc(4, 6, 15) Mul_Acc(7, 14) Mul_Acc(8, 13) Mul_Acc(9, 12) Mul_Acc(10, 11) Mul_Acc(11, 10) Mul_Acc(12, 9) Mul_Acc(13, 8) Mul_Acc(14, 7) Mul_Acc(15, 6) \
1445 Mul_SaveAcc(5, 7, 15) Mul_Acc(8, 14) Mul_Acc(9, 13) Mul_Acc(10, 12) Mul_Acc(11, 11) Mul_Acc(12, 10) Mul_Acc(13, 9) Mul_Acc(14, 8) Mul_Acc(15, 7) \
1446 Mul_SaveAcc(6, 8, 15) Mul_Acc(9, 14) Mul_Acc(10, 13) Mul_Acc(11, 12) Mul_Acc(12, 11) Mul_Acc(13, 10) Mul_Acc(14, 9) Mul_Acc(15, 8) \
1447 Mul_SaveAcc(7, 9, 15) Mul_Acc(10, 14) Mul_Acc(11, 13) Mul_Acc(12, 12) Mul_Acc(13, 11) Mul_Acc(14, 10) Mul_Acc(15, 9) \
1448 Mul_SaveAcc(8, 10, 15) Mul_Acc(11, 14) Mul_Acc(12, 13) Mul_Acc(13, 12) Mul_Acc(14, 11) Mul_Acc(15, 10) \
1449 Mul_SaveAcc(9, 11, 15) Mul_Acc(12, 14) Mul_Acc(13, 13) Mul_Acc(14, 12) Mul_Acc(15, 11) \
1450 Mul_SaveAcc(10, 12, 15) Mul_Acc(13, 14) Mul_Acc(14, 13) Mul_Acc(15, 12) \
1451 Mul_SaveAcc(11, 13, 15) Mul_Acc(14, 14) Mul_Acc(15, 13) \
1452 Mul_SaveAcc(12, 14, 15) Mul_Acc(15, 14) \
1459 #if CRYPTOPP_INTEGER_SSE2 1461 CRYPTOPP_ALIGN_DATA(16)
1463 const word32 s_maskLow16[4] = {
1464 0xffff,0xffff,0xffff,0xffff
1483 #define SSE2_FinalSave(k) \ 1484 AS2( psllq xmm5, 16) \ 1485 AS2( paddq xmm4, xmm5) \ 1486 AS2( movq QWORD PTR [ecx+8*(k)], xmm4) 1488 #define SSE2_SaveShift(k) \ 1489 AS2( movq xmm0, xmm6) \ 1490 AS2( punpckhqdq xmm6, xmm0) \ 1491 AS2( movq xmm1, xmm7) \ 1492 AS2( punpckhqdq xmm7, xmm1) \ 1493 AS2( paddd xmm6, xmm0) \ 1494 AS2( pslldq xmm6, 4) \ 1495 AS2( paddd xmm7, xmm1) \ 1496 AS2( paddd xmm4, xmm6) \ 1497 AS2( pslldq xmm7, 4) \ 1498 AS2( movq xmm6, xmm4) \ 1499 AS2( paddd xmm5, xmm7) \ 1500 AS2( movq xmm7, xmm5) \ 1501 AS2( movd DWORD PTR [ecx+8*(k)], xmm4) \ 1502 AS2( psrlq xmm6, 16) \ 1503 AS2( paddq xmm6, xmm7) \ 1504 AS2( punpckhqdq xmm4, xmm0) \ 1505 AS2( punpckhqdq xmm5, xmm0) \ 1506 AS2( movq QWORD PTR [ecx+8*(k)+2], xmm6) \ 1507 AS2( psrlq xmm6, 3*16) \ 1508 AS2( paddd xmm4, xmm6) \ 1510 #define Squ_SSE2_SaveShift(k) \ 1511 AS2( movq xmm0, xmm6) \ 1512 AS2( punpckhqdq xmm6, xmm0) \ 1513 AS2( movq xmm1, xmm7) \ 1514 AS2( punpckhqdq xmm7, xmm1) \ 1515 AS2( paddd xmm6, xmm0) \ 1516 AS2( pslldq xmm6, 4) \ 1517 AS2( paddd xmm7, xmm1) \ 1518 AS2( paddd xmm4, xmm6) \ 1519 AS2( pslldq xmm7, 4) \ 1520 AS2( movhlps xmm6, xmm4) \ 1521 AS2( movd DWORD PTR [ecx+8*(k)], xmm4) \ 1522 AS2( paddd xmm5, xmm7) \ 1523 AS2( movhps QWORD PTR [esp+12], xmm5)\ 1524 AS2( psrlq xmm4, 16) \ 1525 AS2( paddq xmm4, xmm5) \ 1526 AS2( movq QWORD PTR [ecx+8*(k)+2], xmm4) \ 1527 AS2( psrlq xmm4, 3*16) \ 1528 AS2( paddd xmm4, xmm6) \ 1529 AS2( movq QWORD PTR [esp+4], xmm4)\ 1531 #define SSE2_FirstMultiply(i) \ 1532 AS2( movdqa xmm7, [esi+(i)*16])\ 1533 AS2( movdqa xmm5, [edi-(i)*16])\ 1534 AS2( pmuludq xmm5, xmm7) \ 1535 AS2( movdqa xmm4, [ebx])\ 1536 AS2( movdqa xmm6, xmm4) \ 1537 AS2( pand xmm4, xmm5) \ 1538 AS2( psrld xmm5, 16) \ 1539 AS2( pmuludq xmm7, [edx-(i)*16])\ 1540 AS2( pand xmm6, xmm7) \ 1541 AS2( psrld xmm7, 16) 1543 #define Squ_Begin(n) \ 1546 AS2( and esp, 0xfffffff0)\ 1547 AS2( lea edi, [esp-32*n])\ 1548 AS2( sub esp, 32*n+16)\ 1550 AS2( mov esi, edi) \ 1551 AS2( xor edx, edx) \ 1553 ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \ 1554 ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \ 1555 AS2( movdqa [edi+2*edx], xmm0) \ 1556 AS2( psrlq xmm0, 32) \ 1557 AS2( movdqa [edi+2*edx+16], xmm0) \ 1558 AS2( movdqa [edi+16*n+2*edx], xmm1) \ 1559 AS2( psrlq xmm1, 32) \ 1560 AS2( movdqa [edi+16*n+2*edx+16], xmm1) \ 1562 AS2( cmp edx, 8*(n)) \ 1564 AS2( lea edx, [edi+16*n])\ 1565 SSE2_FirstMultiply(0) \ 1567 #define Squ_Acc(i) \ 1569 AS2( movdqa xmm1, [esi+(i)*16]) \ 1570 AS2( movdqa xmm0, [edi-(i)*16]) \ 1571 AS2( movdqa xmm2, [ebx]) \ 1572 AS2( pmuludq xmm0, xmm1) \ 1573 AS2( pmuludq xmm1, [edx-(i)*16]) \ 1574 AS2( movdqa xmm3, xmm2) \ 1575 AS2( pand xmm2, xmm0) \ 1576 AS2( psrld xmm0, 16) \ 1577 AS2( paddd xmm4, xmm2) \ 1578 AS2( paddd xmm5, xmm0) \ 1579 AS2( pand xmm3, xmm1) \ 1580 AS2( psrld xmm1, 16) \ 1581 AS2( paddd xmm6, xmm3) \ 1582 AS2( paddd xmm7, xmm1) \ 1585 #define Squ_Acc2(i) ASC(call, LSqu##i) 1586 #define Squ_Acc3(i) Squ_Acc2(i) 1587 #define Squ_Acc4(i) Squ_Acc2(i) 1588 #define Squ_Acc5(i) Squ_Acc2(i) 1589 #define Squ_Acc6(i) Squ_Acc2(i) 1590 #define Squ_Acc7(i) Squ_Acc2(i) 1591 #define Squ_Acc8(i) Squ_Acc2(i) 1593 #define SSE2_End(E, n) \ 1594 SSE2_SaveShift(2*(n)-3) \ 1595 AS2( movdqa xmm7, [esi+16]) \ 1596 AS2( movdqa xmm0, [edi]) \ 1597 AS2( pmuludq xmm0, xmm7) \ 1598 AS2( movdqa xmm2, [ebx]) \ 1599 AS2( pmuludq xmm7, [edx]) \ 1600 AS2( movdqa xmm6, xmm2) \ 1601 AS2( pand xmm2, xmm0) \ 1602 AS2( psrld xmm0, 16) \ 1603 AS2( paddd xmm4, xmm2) \ 1604 AS2( paddd xmm5, xmm0) \ 1605 AS2( pand xmm6, xmm7) \ 1606 AS2( psrld xmm7, 16) \ 1607 SSE2_SaveShift(2*(n)-2) \ 1608 SSE2_FinalSave(2*(n)-1) \ 1612 #define Squ_End(n) SSE2_End(SquEpilogue, n) 1613 #define Mul_End(n) SSE2_End(MulEpilogue, n) 1614 #define Top_End(n) SSE2_End(TopEpilogue, n) 1616 #define Squ_Column1(k, i) \ 1617 Squ_SSE2_SaveShift(k) \ 1619 SSE2_FirstMultiply(1)\ 1621 AS2( paddd xmm4, xmm4) \ 1622 AS2( paddd xmm5, xmm5) \ 1623 AS2( movdqa xmm3, [esi]) \ 1624 AS2( movq xmm1, QWORD PTR [esi+8]) \ 1625 AS2( pmuludq xmm1, xmm3) \ 1626 AS2( pmuludq xmm3, xmm3) \ 1627 AS2( movdqa xmm0, [ebx])\ 1628 AS2( movdqa xmm2, xmm0) \ 1629 AS2( pand xmm0, xmm1) \ 1630 AS2( psrld xmm1, 16) \ 1631 AS2( paddd xmm6, xmm0) \ 1632 AS2( paddd xmm7, xmm1) \ 1633 AS2( pand xmm2, xmm3) \ 1634 AS2( psrld xmm3, 16) \ 1635 AS2( paddd xmm6, xmm6) \ 1636 AS2( paddd xmm7, xmm7) \ 1637 AS2( paddd xmm4, xmm2) \ 1638 AS2( paddd xmm5, xmm3) \ 1639 AS2( movq xmm0, QWORD PTR [esp+4])\ 1640 AS2( movq xmm1, QWORD PTR [esp+12])\ 1641 AS2( paddd xmm4, xmm0)\ 1642 AS2( paddd xmm5, xmm1)\ 1644 #define Squ_Column0(k, i) \ 1645 Squ_SSE2_SaveShift(k) \ 1648 SSE2_FirstMultiply(1)\ 1650 AS2( paddd xmm6, xmm6) \ 1651 AS2( paddd xmm7, xmm7) \ 1652 AS2( paddd xmm4, xmm4) \ 1653 AS2( paddd xmm5, xmm5) \ 1654 AS2( movq xmm0, QWORD PTR [esp+4])\ 1655 AS2( movq xmm1, QWORD PTR [esp+12])\ 1656 AS2( paddd xmm4, xmm0)\ 1657 AS2( paddd xmm5, xmm1)\ 1659 #define SSE2_MulAdd45 \ 1660 AS2( movdqa xmm7, [esi]) \ 1661 AS2( movdqa xmm0, [edi]) \ 1662 AS2( pmuludq xmm0, xmm7) \ 1663 AS2( movdqa xmm2, [ebx]) \ 1664 AS2( pmuludq xmm7, [edx]) \ 1665 AS2( movdqa xmm6, xmm2) \ 1666 AS2( pand xmm2, xmm0) \ 1667 AS2( psrld xmm0, 16) \ 1668 AS2( paddd xmm4, xmm2) \ 1669 AS2( paddd xmm5, xmm0) \ 1670 AS2( pand xmm6, xmm7) \ 1671 AS2( psrld xmm7, 16) 1673 #define Mul_Begin(n) \ 1676 AS2( and esp, 0xfffffff0)\ 1677 AS2( sub esp, 48*n+16)\ 1679 AS2( xor edx, edx) \ 1681 ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \ 1682 ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \ 1683 ASS( pshufd xmm2, [edi+edx], 3,1,2,0) \ 1684 AS2( movdqa [esp+20+2*edx], xmm0) \ 1685 AS2( psrlq xmm0, 32) \ 1686 AS2( movdqa [esp+20+2*edx+16], xmm0) \ 1687 AS2( movdqa [esp+20+16*n+2*edx], xmm1) \ 1688 AS2( psrlq xmm1, 32) \ 1689 AS2( movdqa [esp+20+16*n+2*edx+16], xmm1) \ 1690 AS2( movdqa [esp+20+32*n+2*edx], xmm2) \ 1691 AS2( psrlq xmm2, 32) \ 1692 AS2( movdqa [esp+20+32*n+2*edx+16], xmm2) \ 1694 AS2( cmp edx, 8*(n)) \ 1696 AS2( lea edi, [esp+20])\ 1697 AS2( lea edx, [esp+20+16*n])\ 1698 AS2( lea esi, [esp+20+32*n])\ 1699 SSE2_FirstMultiply(0) \ 1701 #define Mul_Acc(i) \ 1703 AS2( movdqa xmm1, [esi+i/2*(1-(i-2*(i/2))*2)*16]) \ 1704 AS2( movdqa xmm0, [edi-i/2*(1-(i-2*(i/2))*2)*16]) \ 1705 AS2( movdqa xmm2, [ebx]) \ 1706 AS2( pmuludq xmm0, xmm1) \ 1707 AS2( pmuludq xmm1, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \ 1708 AS2( movdqa xmm3, xmm2) \ 1709 AS2( pand xmm2, xmm0) \ 1710 AS2( psrld xmm0, 16) \ 1711 AS2( paddd xmm4, xmm2) \ 1712 AS2( paddd xmm5, xmm0) \ 1713 AS2( pand xmm3, xmm1) \ 1714 AS2( psrld xmm1, 16) \ 1715 AS2( paddd xmm6, xmm3) \ 1716 AS2( paddd xmm7, xmm1) \ 1719 #define Mul_Acc2(i) ASC(call, LMul##i) 1720 #define Mul_Acc3(i) Mul_Acc2(i) 1721 #define Mul_Acc4(i) Mul_Acc2(i) 1722 #define Mul_Acc5(i) Mul_Acc2(i) 1723 #define Mul_Acc6(i) Mul_Acc2(i) 1724 #define Mul_Acc7(i) Mul_Acc2(i) 1725 #define Mul_Acc8(i) Mul_Acc2(i) 1726 #define Mul_Acc9(i) Mul_Acc2(i) 1727 #define Mul_Acc10(i) Mul_Acc2(i) 1728 #define Mul_Acc11(i) Mul_Acc2(i) 1729 #define Mul_Acc12(i) Mul_Acc2(i) 1730 #define Mul_Acc13(i) Mul_Acc2(i) 1731 #define Mul_Acc14(i) Mul_Acc2(i) 1732 #define Mul_Acc15(i) Mul_Acc2(i) 1733 #define Mul_Acc16(i) Mul_Acc2(i) 1735 #define Mul_Column1(k, i) \ 1741 #define Mul_Column0(k, i) \ 1748 #define Bot_Acc(i) \ 1749 AS2( movdqa xmm1, [esi+i/2*(1-(i-2*(i/2))*2)*16]) \ 1750 AS2( movdqa xmm0, [edi-i/2*(1-(i-2*(i/2))*2)*16]) \ 1751 AS2( pmuludq xmm0, xmm1) \ 1752 AS2( pmuludq xmm1, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \ 1753 AS2( paddq xmm4, xmm0) \ 1754 AS2( paddd xmm6, xmm1) 1756 #define Bot_SaveAcc(k) \ 1760 AS2( movdqa xmm6, [esi]) \ 1761 AS2( movdqa xmm0, [edi]) \ 1762 AS2( pmuludq xmm0, xmm6) \ 1763 AS2( paddq xmm4, xmm0) \ 1764 AS2( psllq xmm5, 16) \ 1765 AS2( paddq xmm4, xmm5) \ 1766 AS2( pmuludq xmm6, [edx]) 1768 #define Bot_End(n) \ 1769 AS2( movhlps xmm7, xmm6) \ 1770 AS2( paddd xmm6, xmm7) \ 1771 AS2( psllq xmm6, 32) \ 1772 AS2( paddd xmm4, xmm6) \ 1773 AS2( movq QWORD PTR [ecx+8*((n)-1)], xmm4) \ 1777 #define Top_Begin(n) \ 1780 AS2( and esp, 0xfffffff0)\ 1781 AS2( sub esp, 48*n+16)\ 1783 AS2( xor edx, edx) \ 1785 ASS( pshufd xmm0, [eax+edx], 3,1,2,0) \ 1786 ASS( pshufd xmm1, [eax+edx], 2,0,3,1) \ 1787 ASS( pshufd xmm2, [edi+edx], 3,1,2,0) \ 1788 AS2( movdqa [esp+20+2*edx], xmm0) \ 1789 AS2( psrlq xmm0, 32) \ 1790 AS2( movdqa [esp+20+2*edx+16], xmm0) \ 1791 AS2( movdqa [esp+20+16*n+2*edx], xmm1) \ 1792 AS2( psrlq xmm1, 32) \ 1793 AS2( movdqa [esp+20+16*n+2*edx+16], xmm1) \ 1794 AS2( movdqa [esp+20+32*n+2*edx], xmm2) \ 1795 AS2( psrlq xmm2, 32) \ 1796 AS2( movdqa [esp+20+32*n+2*edx+16], xmm2) \ 1798 AS2( cmp edx, 8*(n)) \ 1800 AS2( mov eax, esi) \ 1801 AS2( lea edi, [esp+20+00*n+16*(n/2-1)])\ 1802 AS2( lea edx, [esp+20+16*n+16*(n/2-1)])\ 1803 AS2( lea esi, [esp+20+32*n+16*(n/2-1)])\ 1804 AS2( pxor xmm4, xmm4)\ 1805 AS2( pxor xmm5, xmm5) 1807 #define Top_Acc(i) \ 1808 AS2( movq xmm0, QWORD PTR [esi+i/2*(1-(i-2*(i/2))*2)*16+8]) \ 1809 AS2( pmuludq xmm0, [edx-i/2*(1-(i-2*(i/2))*2)*16]) \ 1810 AS2( psrlq xmm0, 48) \ 1811 AS2( paddd xmm5, xmm0)\ 1813 #define Top_Column0(i) \ 1814 AS2( psllq xmm5, 32) \ 1820 #define Top_Column1(i) \ 1826 AS2( movd xmm0, eax)\ 1827 AS2( movd xmm1, [ecx+4])\ 1828 AS2( psrld xmm1, 16)\ 1829 AS2( pcmpgtd xmm1, xmm0)\ 1830 AS2( psrld xmm1, 31)\ 1831 AS2( paddd xmm4, xmm1)\ 1833 void SSE2_Square4(word *C,
const word *A)
1840 void SSE2_Square8(word *C, const word *A)
1856 void SSE2_Square16(word *C, const word *A)
1861 Squ_Acc(4) Squ_Acc(3) Squ_Acc(2)
1880 void SSE2_Square32(word *C, const word *A)
1884 Squ_Acc(8) Squ_Acc(7) Squ_Acc(6) Squ_Acc(5) Squ_Acc(4) Squ_Acc(3) Squ_Acc(2)
1918 void SSE2_Multiply4(word *C, const word *A, const word *B)
1930 void SSE2_Multiply8(word *C, const word *A, const word *B)
1935 Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
1946 void SSE2_Multiply16(word *C, const word *A, const word *B)
1951 Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
1970 void SSE2_Multiply32(word *C, const word *A, const word *B)
1974 Mul_Acc(16) Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2008 void SSE2_MultiplyBottom4(word *C, const word *A, const word *B)
2011 Bot_SaveAcc(0) Bot_Acc(2)
2015 void SSE2_MultiplyBottom8(word *C, const word *A, const word *B)
2020 Mul_Acc(3) Mul_Acc(2)
2025 Bot_SaveAcc(2) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
2029 void SSE2_MultiplyBottom16(word *C, const word *A, const word *B)
2034 Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2043 Bot_SaveAcc(6) Bot_Acc(8) Bot_Acc(7) Bot_Acc(6) Bot_Acc(5) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
2047 void SSE2_MultiplyBottom32(word *C, const word *A, const word *B)
2052 Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2069 Bot_SaveAcc(14) Bot_Acc(16) Bot_Acc(15) Bot_Acc(14) Bot_Acc(13) Bot_Acc(12) Bot_Acc(11) Bot_Acc(10) Bot_Acc(9) Bot_Acc(8) Bot_Acc(7) Bot_Acc(6) Bot_Acc(5) Bot_Acc(4) Bot_Acc(3) Bot_Acc(2)
2073 void SSE2_MultiplyTop8(word *C, const word *A, const word *B, word L)
2076 Top_Acc(3) Top_Acc(2) Top_Acc(1)
2079 Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2088 void SSE2_MultiplyTop16(word *C, const word *A, const word *B, word L)
2091 Top_Acc(7) Top_Acc(6) Top_Acc(5) Top_Acc(4) Top_Acc(3) Top_Acc(2) Top_Acc(1)
2094 Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2107 void SSE2_MultiplyTop32(word *C, const word *A, const word *B, word L)
2110 Top_Acc(15) Top_Acc(14) Top_Acc(13) Top_Acc(12) Top_Acc(11) Top_Acc(10) Top_Acc(9) Top_Acc(8) Top_Acc(7) Top_Acc(6) Top_Acc(5) Top_Acc(4) Top_Acc(3) Top_Acc(2) Top_Acc(1)
2113 Mul_Acc(16) Mul_Acc(15) Mul_Acc(14) Mul_Acc(13) Mul_Acc(12) Mul_Acc(11) Mul_Acc(10) Mul_Acc(9) Mul_Acc(8) Mul_Acc(7) Mul_Acc(6) Mul_Acc(5) Mul_Acc(4) Mul_Acc(3) Mul_Acc(2)
2134 #endif // #if CRYPTOPP_INTEGER_SSE2 2138 typedef int (CRYPTOPP_FASTCALL * PAdd)(
size_t N, word *C,
const word *A,
const word *B);
2139 typedef void (* PMul)(word *C,
const word *A,
const word *B);
2140 typedef void (* PSqu)(word *C,
const word *A);
2141 typedef void (* PMulTop)(word *C,
const word *A,
const word *B, word L);
2143 #if CRYPTOPP_INTEGER_SSE2 2144 static PAdd s_pAdd = &Baseline_Add, s_pSub = &Baseline_Sub;
2145 static size_t s_recursionLimit = 8;
2147 static const size_t s_recursionLimit = 16;
2148 #endif // CRYPTOPP_INTEGER_SSE2 2150 static PMul s_pMul[9], s_pBot[9];
2151 static PSqu s_pSqu[9];
2152 static PMulTop s_pTop[9];
2154 void SetFunctionPointers()
2156 s_pMul[0] = &Baseline_Multiply2;
2157 s_pBot[0] = &Baseline_MultiplyBottom2;
2158 s_pSqu[0] = &Baseline_Square2;
2159 s_pTop[0] = &Baseline_MultiplyTop2;
2160 s_pTop[1] = &Baseline_MultiplyTop4;
2162 #if CRYPTOPP_INTEGER_SSE2 2171 s_recursionLimit = 32;
2173 s_pMul[1] = &SSE2_Multiply4;
2174 s_pMul[2] = &SSE2_Multiply8;
2175 s_pMul[4] = &SSE2_Multiply16;
2176 s_pMul[8] = &SSE2_Multiply32;
2178 s_pBot[1] = &SSE2_MultiplyBottom4;
2179 s_pBot[2] = &SSE2_MultiplyBottom8;
2180 s_pBot[4] = &SSE2_MultiplyBottom16;
2181 s_pBot[8] = &SSE2_MultiplyBottom32;
2183 s_pSqu[1] = &SSE2_Square4;
2184 s_pSqu[2] = &SSE2_Square8;
2185 s_pSqu[4] = &SSE2_Square16;
2186 s_pSqu[8] = &SSE2_Square32;
2188 s_pTop[2] = &SSE2_MultiplyTop8;
2189 s_pTop[4] = &SSE2_MultiplyTop16;
2190 s_pTop[8] = &SSE2_MultiplyTop32;
2193 #endif // CRYPTOPP_INTEGER_SSE2 2195 s_pMul[1] = &Baseline_Multiply4;
2196 s_pMul[2] = &Baseline_Multiply8;
2198 s_pBot[1] = &Baseline_MultiplyBottom4;
2199 s_pBot[2] = &Baseline_MultiplyBottom8;
2201 s_pSqu[1] = &Baseline_Square4;
2202 s_pSqu[2] = &Baseline_Square8;
2204 s_pTop[2] = &Baseline_MultiplyTop8;
2206 #if !CRYPTOPP_INTEGER_SSE2 2207 s_pMul[4] = &Baseline_Multiply16;
2208 s_pBot[4] = &Baseline_MultiplyBottom16;
2209 s_pSqu[4] = &Baseline_Square16;
2210 s_pTop[4] = &Baseline_MultiplyTop16;
2211 #endif // !CRYPTOPP_INTEGER_SSE2 2215 inline int Add(word *C,
const word *A,
const word *B,
size_t N)
2217 #if CRYPTOPP_INTEGER_SSE2 2218 return s_pAdd(N, C, A, B);
2220 return Baseline_Add(N, C, A, B);
2221 #endif // CRYPTOPP_INTEGER_SSE2 2224 inline int Subtract(word *C,
const word *A,
const word *B,
size_t N)
2226 #if CRYPTOPP_INTEGER_SSE2 2227 return s_pSub(N, C, A, B);
2229 return Baseline_Sub(N, C, A, B);
2230 #endif // CRYPTOPP_INTEGER_SSE2 2256 void RecursiveMultiply(word *R, word *T,
const word *A,
const word *B,
size_t N)
2260 if (N <= s_recursionLimit)
2261 s_pMul[N/4](R, A, B);
2264 const size_t N2 = N/2;
2266 size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2;
2267 Subtract(R0, A + AN2, A + (N2 ^ AN2), N2);
2269 size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2;
2270 Subtract(R1, B + BN2, B + (N2 ^ BN2), N2);
2272 RecursiveMultiply(R2, T2, A1, B1, N2);
2273 RecursiveMultiply(T0, T2, R0, R1, N2);
2274 RecursiveMultiply(R0, T2, A0, B0, N2);
2278 int c2 = Add(R2, R2, R1, N2);
2280 c2 += Add(R1, R2, R0, N2);
2281 c3 += Add(R2, R2, R3, N2);
2284 c3 -= Subtract(R1, R1, T0, N);
2286 c3 += Add(R1, R1, T0, N);
2288 c3 += Increment(R2, N2, c2);
2290 Increment(R3, N2, c3);
2298 void RecursiveSquare(word *R, word *T,
const word *A,
size_t N)
2302 if (N <= s_recursionLimit)
2306 const size_t N2 = N/2;
2308 RecursiveSquare(R0, T2, A0, N2);
2309 RecursiveSquare(R2, T2, A1, N2);
2310 RecursiveMultiply(T0, T2, A0, A1, N2);
2312 int carry = Add(R1, R1, T0, N);
2313 carry += Add(R1, R1, T0, N);
2314 Increment(R3, N2, carry);
2323 void RecursiveMultiplyBottom(word *R, word *T,
const word *A,
const word *B,
size_t N)
2327 if (N <= s_recursionLimit)
2328 s_pBot[N/4](R, A, B);
2331 const size_t N2 = N/2;
2333 RecursiveMultiply(R, T, A0, B0, N2);
2334 RecursiveMultiplyBottom(T0, T1, A1, B0, N2);
2335 Add(R1, R1, T0, N2);
2336 RecursiveMultiplyBottom(T0, T1, A0, B1, N2);
2337 Add(R1, R1, T0, N2);
2347 void MultiplyTop(word *R, word *T,
const word *L,
const word *A,
const word *B,
size_t N)
2351 if (N <= s_recursionLimit)
2352 s_pTop[N/4](R, A, B, L[N-1]);
2355 const size_t N2 = N/2;
2357 size_t AN2 = Compare(A0, A1, N2) > 0 ? 0 : N2;
2358 Subtract(R0, A + AN2, A + (N2 ^ AN2), N2);
2360 size_t BN2 = Compare(B0, B1, N2) > 0 ? 0 : N2;
2361 Subtract(R1, B + BN2, B + (N2 ^ BN2), N2);
2363 RecursiveMultiply(T0, T2, R0, R1, N2);
2364 RecursiveMultiply(R0, T2, A1, B1, N2);
2369 int c2 = Subtract(T2, L+N2, L, N2);
2373 c2 -= Add(T2, T2, T0, N2);
2374 t = (Compare(T2, R0, N2) == -1);
2375 c3 = t - Subtract(T2, T2, T1, N2);
2379 c2 += Subtract(T2, T2, T0, N2);
2380 t = (Compare(T2, R0, N2) == -1);
2381 c3 = t + Add(T2, T2, T1, N2);
2386 c3 += Increment(T2, N2, c2);
2388 c3 -= Decrement(T2, N2, -c2);
2389 c3 += Add(R0, T2, R1, N2);
2392 Increment(R1, N2, c3);
2396 inline void Multiply(word *R, word *T,
const word *A,
const word *B,
size_t N)
2398 RecursiveMultiply(R, T, A, B, N);
2401 inline void Square(word *R, word *T,
const word *A,
size_t N)
2403 RecursiveSquare(R, T, A, N);
2406 inline void MultiplyBottom(word *R, word *T,
const word *A,
const word *B,
size_t N)
2408 RecursiveMultiplyBottom(R, T, A, B, N);
2416 void AsymmetricMultiply(word *R, word *T,
const word *A,
size_t NA,
const word *B,
size_t NB)
2423 Multiply(R, T, A, B, NA);
2445 R[NB] = LinearMultiply(R, B, A[0], NB);
2449 SetWords(R, 0, NB+2);
2452 CopyWords(R, B, NB);
2453 R[NB] = R[NB+1] = 0;
2461 Multiply(R, T, A, B, NA);
2462 CopyWords(T+2*NA, R+NA, NA);
2464 for (i=2*NA; i<NB; i+=2*NA)
2465 Multiply(T+NA+i, T, A, B+i, NA);
2466 for (i=NA; i<NB; i+=2*NA)
2467 Multiply(R+i, T, A, B+i, NA);
2471 for (i=0; i<NB; i+=2*NA)
2472 Multiply(R+i, T, A, B+i, NA);
2473 for (i=NA; i<NB; i+=2*NA)
2474 Multiply(T+NA+i, T, A, B+i, NA);
2477 if (Add(R+NA, R+NA, T+2*NA, NB-NA))
2478 Increment(R+NB, NA);
2485 void RecursiveInverseModPower2(word *R, word *T,
const word *A,
size_t N)
2491 const size_t N2 = N/2;
2492 RecursiveInverseModPower2(R0, T0, A0, N2);
2494 SetWords(T0+1, 0, N2-1);
2495 MultiplyTop(R1, T1, T0, R0, A0, N2);
2496 MultiplyBottom(T0, T1, R0, A1, N2);
2497 Add(T0, R1, T0, N2);
2498 TwosComplement(T0, N2);
2499 MultiplyBottom(R1, T1, R0, T0, N2);
2503 T[0] = AtomicInverseModPower2(A[0]);
2505 s_pBot[0](T+2, T, A);
2506 TwosComplement(T+2, 2);
2507 Increment(T+2, 2, 2);
2508 s_pBot[0](R, T, T+2);
2518 void MontgomeryReduce(word *R, word *T, word *X,
const word *M,
const word *U,
size_t N)
2521 MultiplyBottom(R, T, X, U, N);
2522 MultiplyTop(T, T+N, X, R, M, N);
2523 word borrow = Subtract(T, X+N, T, N);
2525 word carry = Add(T+N, T, M, N);
2527 CRYPTOPP_UNUSED(carry), CRYPTOPP_UNUSED(borrow);
2528 CopyWords(R, T + ((0-borrow) & N), N);
2530 const word u = 0-U[0];
2532 for (
size_t i=0; i<N; i++)
2534 const word t = u * X[i];
2536 for (
size_t j=0; j<N; j+=2)
2538 MultiplyWords(p, t, M[j]);
2539 Acc2WordsBy1(p, X[i+j]);
2541 X[i+j] = LowWord(p);
2543 MultiplyWords(p, t, M[j+1]);
2544 Acc2WordsBy1(p, X[i+j+1]);
2546 X[i+j+1] = LowWord(p);
2550 if (Increment(X+N+i, N-i, c))
2551 while (!Subtract(X+N, X+N, M, N)) {}
2554 memcpy(R, X+N, N*WORD_SIZE);
2556 __m64 u = _mm_cvtsi32_si64(0-U[0]), p;
2557 for (
size_t i=0; i<N; i++)
2559 __m64 t = _mm_cvtsi32_si64(X[i]);
2560 t = _mm_mul_su32(t, u);
2561 __m64 c = _mm_setzero_si64();
2562 for (
size_t j=0; j<N; j+=2)
2564 p = _mm_mul_su32(t, _mm_cvtsi32_si64(M[j]));
2565 p = _mm_add_si64(p, _mm_cvtsi32_si64(X[i+j]));
2566 c = _mm_add_si64(c, p);
2567 X[i+j] = _mm_cvtsi64_si32(c);
2568 c = _mm_srli_si64(c, 32);
2569 p = _mm_mul_su32(t, _mm_cvtsi32_si64(M[j+1]));
2570 p = _mm_add_si64(p, _mm_cvtsi32_si64(X[i+j+1]));
2571 c = _mm_add_si64(c, p);
2572 X[i+j+1] = _mm_cvtsi64_si32(c);
2573 c = _mm_srli_si64(c, 32);
2576 if (Increment(X+N+i, N-i, _mm_cvtsi64_si32(c)))
2577 while (!Subtract(X+N, X+N, M, N)) {}
2580 memcpy(R, X+N, N*WORD_SIZE);
2592 void HalfMontgomeryReduce(word *R, word *T,
const word *X,
const word *M,
const word *U,
const word *V,
size_t N)
2606 const size_t N2 = N/2;
2607 Multiply(T0, T2, V0, X3, N2);
2608 int c2 = Add(T0, T0, X0, N);
2609 MultiplyBottom(T3, T2, T0, U, N2);
2610 MultiplyTop(T2, R, T0, T3, M0, N2);
2611 c2 -= Subtract(T2, T1, T2, N2);
2612 Multiply(T0, R, T3, M1, N2);
2613 c2 -= Subtract(T0, T2, T0, N2);
2614 int c3 = -(int)Subtract(T1, X2, T1, N2);
2615 Multiply(R0, T2, V1, X3, N2);
2616 c3 += Add(R, R, T, N);
2619 c3 += Increment(R1, N2);
2621 c3 -= Decrement(R1, N2, -c2);
2625 Subtract(R, R, M, N);
2719 static inline void AtomicDivide(word *Q,
const word *A,
const word *B)
2722 DWord q = DivideFourWordsByTwo<word, DWord>(T,
DWord(A[0], A[1]),
DWord(A[2], A[3]),
DWord(B[0], B[1]));
2723 Q[0] = q.GetLowHalf();
2724 Q[1] = q.GetHighHalf();
2726 #if defined(CRYPTOPP_DEBUG) 2730 CRYPTOPP_ASSERT(!T[2] && !T[3] && (T[1] < B[1] || (T[1]==B[1] && T[0]<B[0])));
2740 static void CorrectQuotientEstimate(word *R, word *T, word *Q,
const word *B,
size_t N)
2744 AsymmetricMultiply(T, T+N+2, Q, 2, B, N);
2746 word borrow = Subtract(R, R, T, N+2);
2748 CRYPTOPP_UNUSED(borrow);
2750 while (R[N] || Compare(R, B, N) >= 0)
2752 R[N] -= Subtract(R, R, B, N);
2753 Q[1] += (++Q[0]==0);
2764 void Divide(word *R, word *Q, word *T,
const word *A,
size_t NA,
const word *B,
size_t NB)
2772 word *
const TB=T+NA+2;
2773 word *
const TP=T+NA+2+NB;
2776 unsigned shiftWords = (B[NB-1]==0);
2777 TB[0] = TB[NB-1] = 0;
2778 CopyWords(TB+shiftWords, B, NB-shiftWords);
2779 unsigned shiftBits = WORD_BITS -
BitPrecision(TB[NB-1]);
2781 ShiftWordsLeftByBits(TB, NB, shiftBits);
2784 TA[0] = TA[NA] = TA[NA+1] = 0;
2785 CopyWords(TA+shiftWords, A, NA);
2786 ShiftWordsLeftByBits(TA, NA+2, shiftBits);
2788 if (TA[NA+1]==0 && TA[NA] <= 1)
2790 Q[NA-NB+1] = Q[NA-NB] = 0;
2791 while (TA[NA] || Compare(TA+NA-NB, TB, NB) >= 0)
2793 TA[NA] -= Subtract(TA+NA-NB, TA+NA-NB, TB, NB);
2804 BT[0] = TB[NB-2] + 1;
2805 BT[1] = TB[NB-1] + (BT[0]==0);
2808 for (
size_t i=NA-2; i>=NB; i-=2)
2810 AtomicDivide(Q+i-NB, TA+i-2, BT);
2811 CorrectQuotientEstimate(TA+i-NB, TP, Q+i-NB, TB, NB);
2815 CopyWords(R, TA+shiftWords, NB);
2816 ShiftWordsRightByBits(R, NB, shiftBits);
2819 static inline size_t EvenWordCount(
const word *X,
size_t N)
2821 while (N && X[N-2]==0 && X[N-1]==0)
2832 unsigned int AlmostInverse(word *R, word *T,
const word *A,
size_t NA,
const word *M,
size_t N)
2840 size_t bcLen=2, fgLen=EvenWordCount(M, N);
2844 SetWords(T, 0, 3*N);
2846 CopyWords(f, A, NA);
2854 if (EvenWordCount(f, fgLen)==0)
2860 ShiftWordsRightByWords(f, fgLen, 1);
2861 bcLen += 2 * (c[bcLen-1] != 0);
2863 ShiftWordsLeftByWords(c, bcLen, 1);
2873 if (t==1 && f[1]==0 && EvenWordCount(f+2, fgLen-2)==0)
2876 Subtract(R, M, b, N);
2882 ShiftWordsRightByBits(f, fgLen, i);
2883 t = ShiftWordsLeftByBits(c, bcLen, i);
2885 bcLen += 2 * (t!=0);
2888 bool swap = Compare(f, g, fgLen)==-1;
2893 fgLen -= 2 * !(f[fgLen-2] | f[fgLen-1]);
2895 Subtract(f, f, g, fgLen);
2896 t = Add(b, b, c, bcLen);
2907 void DivideByPower2Mod(word *R,
const word *A,
size_t k,
const word *M,
size_t N)
2914 ShiftWordsRightByBits(R, N, 1);
2917 word carry = Add(R, R, M, N);
2918 ShiftWordsRightByBits(R, N, 1);
2919 R[N-1] += carry<<(WORD_BITS-1);
2928 void MultiplyByPower2Mod(word *R,
const word *A,
size_t k,
const word *M,
size_t N)
2933 if (ShiftWordsLeftByBits(R, N, 1) || Compare(R, M, N)>=0)
2934 Subtract(R, R, M, N);
2939 static const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};
2941 static inline size_t RoundupSize(
size_t n)
2944 return RoundupSizeTable[n];
2956 : reg(2), sign(POSITIVE)
2958 reg[0] = reg[1] = 0;
2962 : reg(RoundupSize(t.WordCount())), sign(t.sign)
2964 CopyWords(reg, t.reg, reg.
size());
2970 reg[0] = word(value);
2971 reg[1] = word(SafeRightShift<WORD_BITS>(value));
2984 reg[0] = word(value);
2985 reg[1] = word(SafeRightShift<WORD_BITS>((
unsigned long)value));
3000 unsigned long value = (
unsigned long)reg[0];
3001 value += SafeLeftShift<WORD_BITS, unsigned long>((
unsigned long)reg[1]);
3004 return (
signed long)value >= 0;
3006 return -(
signed long)value < 0;
3013 unsigned long value = (
unsigned long)reg[0];
3014 value += SafeLeftShift<WORD_BITS, unsigned long>((
unsigned long)reg[1]);
3015 return sign==
POSITIVE ? value : -(
signed long)value;
3024 Decode(encodedInteger, byteCount, s);
3029 encodedInteger.
Get(block, block.
size());
3043 Decode(encodedInteger, byteCount, s);
3048 #if (_MSC_VER >= 1500) 3049 std::reverse_copy(encodedInteger, encodedInteger+byteCount,
3050 stdext::make_checked_array_iterator(block.
begin(), block.
size()));
3052 std::reverse_copy(encodedInteger, encodedInteger+byteCount, block.
begin());
3072 if (!
Randomize(rng, min, max, rnType, equiv, mod))
3092 if (reg.
size() != t.reg.
size() || t.reg[t.reg.
size()/2] == 0)
3094 CopyWords(reg, t.reg, reg.
size());
3104 if (n/WORD_BITS < reg.
size())
3105 return bool((reg[n/WORD_BITS] >> (n % WORD_BITS)) & 1);
3115 reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
3119 if (n/WORD_BITS < reg.
size())
3120 reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
3128 if (n/WORD_SIZE < reg.
size())
3129 return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
3137 reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
3138 reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
3145 for (
unsigned int j=0; j<n; j++)
3146 v |= lword(
GetBit(i+j)) << j;
3167 std::swap(sign, a.sign);
3171 : reg(RoundupSize(length)), sign(POSITIVE)
3174 SetWords(reg+1, 0, reg.
size()-1);
3182 int radix, sign = 1;
3185 unsigned int length;
3186 for (length = 0; str[length] != 0; length++) {}
3193 switch (str[length-1])
3215 str += 1, length -= 1;
3218 if (length > 2 && str[0] ==
'0' && (str[1] ==
'x' || str[1] ==
'X'))
3221 str += 2, length -= 2;
3226 for (
unsigned int i=0; i<length; i++)
3228 int digit, ch =
static_cast<int>(str[i]);
3232 if (ch >=
'0' && ch <=
'9')
3234 else if (ch >=
'a' && ch <=
'f')
3235 digit = ch -
'a' + 10;
3236 else if (ch >=
'A' && ch <=
'F')
3237 digit = ch -
'A' + 10;
3251 unsigned int nh = 0, nl = 0, nc = 0;
3254 for (
unsigned int i=0; i<length; i++)
3256 int digit, ch =
static_cast<int>(str[i]);
3258 if (ch >=
'0' && ch <=
'9')
3260 else if (ch >=
'a' && ch <=
'f')
3261 digit = ch -
'a' + 10;
3262 else if (ch >=
'A' && ch <=
'F')
3263 digit = ch -
'A' + 10;
3276 v += position * (nh << 4 | nl);
3277 nc = 0, position <<= 8;
3287 for (
int i=static_cast<int>(length)-1; i>=0; i--)
3289 int digit, ch =
static_cast<int>(str[i]);
3291 if (ch >=
'0' && ch <=
'9')
3293 else if (ch >=
'a' && ch <=
'f')
3294 digit = ch -
'a' + 10;
3295 else if (ch >=
'A' && ch <=
'F')
3296 digit = ch -
'A' + 10;
3315 : reg(2), sign(POSITIVE)
3317 *
this = StringToInteger(str,order);
3321 : reg(2), sign(POSITIVE)
3323 *
this = StringToInteger(str,order);
3328 return (
unsigned int)CountWords(reg, reg.
size());
3335 return (wordCount-1)*WORD_SIZE +
BytePrecision(reg[wordCount-1]);
3344 return (wordCount-1)*WORD_BITS +
BitPrecision(reg[wordCount-1]);
3353 Decode(store, inputLen, s);
3366 while (inputLen>0 && (sign==
POSITIVE ? b==0 : b==0xff))
3374 for (
size_t i=inputLen; i > 0; i--)
3377 reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
3382 for (
size_t i=inputLen; i<reg.
size()*WORD_SIZE; i++)
3383 reg[i/WORD_SIZE] |= word(0xff) << (i%WORD_SIZE)*8;
3384 TwosComplement(reg, reg.
size());
3393 const bool pre = (signedness ==
UNSIGNED);
3408 Encode(sink, outputLen, signedness);
3415 for (
size_t i=outputLen; i > 0; i--)
3443 if (!dec.IsDefiniteLength() || dec.
MaxRetrievable() < dec.RemainingLength())
3459 if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
3475 word16 bitCount = word16(
BitCount());
3479 return 2 + byteCount;
3499 const size_t nbytes = nbits/8 + 1;
3503 buf[0] = (byte)
Crop(buf[0], nbits % 8);
3513 const unsigned int nbits = range.
BitCount();
3519 while (*
this > range);
3532 KDF2_RNG(
const byte *seed,
size_t seedSize)
3533 : m_counter(0), m_counterAndSeed(seedSize + 4)
3535 memcpy(m_counterAndSeed + 4, seed, seedSize);
3570 throw InvalidArgument(
"Integer: invalid EquivalentTo and/or Mod argument");
3589 bq.
Get(finalSeed, finalSeed.size());
3590 kdf2Rng.reset(
new KDF2_RNG(finalSeed.begin(), finalSeed.size()));
3601 Integer min1 = min + (equiv-min)%mod;
3622 if (
FirstPrime(first, max, equiv, mod, pSelector))
3626 if (!
FirstPrime(first, max, equiv, mod, pSelector))
3634 if (
FirstPrime(*
this,
STDMIN(*
this+mod*PrimeSearchInterval(max), max), equiv, mod, pSelector))
3644 std::istream& operator>>(std::istream& in,
Integer &a)
3647 unsigned int length = 0;
3656 if (length >= str.
size())
3657 str.
Grow(length + 16);
3659 while (in && (c==
'-' || c==
'x' || (c>=
'0' && c<=
'9') || (c>=
'a' && c<=
'f') || (c>=
'A' && c<=
'F') || c==
'h' || c==
'H' || c==
'o' || c==
'O' || c==
',' || c==
'.'));
3663 str[length-1] =
'\0';
3670 inline int FlagToBase(
long f) {
3671 return f == std::ios::hex ? 16 : (f == std::ios::oct ? 8 : 10);
3674 inline char FlagToSuffix(
long f) {
3675 return f == std::ios::hex ?
'h' : (f == std::ios::oct ?
'o' :
'.');
3679 std::ostream& operator<<(std::ostream& out,
const Integer &a)
3682 const long f = out.flags() & std::ios::basefield;
3683 const int base = FlagToBase(f);
3684 const char suffix = FlagToSuffix(f);
3696 static const char upper[]=
"0123456789ABCDEF";
3697 static const char lower[]=
"0123456789abcdef";
3699 const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
3716 #ifdef CRYPTOPP_USE_STD_SHOWBASE 3717 if (out.flags() & std::ios_base::showbase)
3722 return out << suffix;
3730 if (Increment(reg, reg.
size()))
3733 reg[reg.
size()/2]=1;
3738 word borrow = Decrement(reg, reg.
size());
3751 if (Increment(reg, reg.
size()))
3754 reg[reg.
size()/2]=1;
3759 if (Decrement(reg, reg.
size()))
3773 else if (reg.
size() >= t.reg.
size())
3776 AndWords(result.reg, reg, t.reg.
size());
3784 AndWords(result.reg, t.reg, reg.
size());
3799 else if (reg.
size() >= t.reg.
size())
3802 OrWords(result.reg, t.reg, t.reg.
size());
3810 OrWords(result.reg, reg, reg.
size());
3825 else if (reg.
size() >= t.reg.
size())
3828 XorWords(result.reg, t.reg, t.reg.
size());
3836 XorWords(result.reg, reg, reg.
size());
3847 int carry;
const bool pre = (a.reg.size() == b.reg.size());
3848 if (!pre && a.reg.size() > b.reg.size())
3850 carry = Add(sum.reg, a.reg, b.reg, b.reg.size());
3851 CopyWords(sum.reg+b.reg.size(), a.reg+b.reg.size(), a.reg.size()-b.reg.size());
3852 carry = Increment(sum.reg+b.reg.size(), a.reg.size()-b.reg.size(), carry);
3856 carry = Add(sum.reg, a.reg, b.reg, a.reg.size());
3860 carry = Add(sum.reg, a.reg, b.reg, a.reg.size());
3861 CopyWords(sum.reg+a.reg.size(), b.reg+a.reg.size(), b.reg.size()-a.reg.size());
3862 carry = Increment(sum.reg+a.reg.size(), b.reg.size()-a.reg.size(), carry);
3868 sum.reg[sum.reg.
size()/2] = 1;
3875 unsigned aSize = a.WordCount();
3877 unsigned bSize = b.WordCount();
3884 word borrow = Subtract(diff.reg, a.reg, b.reg, bSize);
3885 CopyWords(diff.reg+bSize, a.reg+bSize, aSize-bSize);
3886 borrow = Decrement(diff.reg+bSize, aSize-bSize, borrow);
3890 else if (aSize == bSize)
3892 if (Compare(a.reg, b.reg, aSize) >= 0)
3894 Subtract(diff.reg, a.reg, b.reg, aSize);
3899 Subtract(diff.reg, b.reg, a.reg, aSize);
3905 word borrow = Subtract(diff.reg, b.reg, a.reg, aSize);
3906 CopyWords(diff.reg+aSize, b.reg+aSize, bSize-aSize);
3907 borrow = Decrement(diff.reg+aSize, bSize-aSize, borrow);
3914 template <
class T>
inline const T& STDMAX2(
const T& a,
const T& b)
3916 return a < b ? b : a;
3921 Integer sum((word)0, STDMAX2(reg.
size(), b.reg.size()));
3924 if (b.NotNegative())
3925 PositiveAdd(sum, *
this, b);
3927 PositiveSubtract(sum, *
this, b);
3931 if (b.NotNegative())
3932 PositiveSubtract(sum, b, *
this);
3935 PositiveAdd(sum, *
this, b);
3948 PositiveAdd(*
this, *
this, t);
3950 PositiveSubtract(*
this, *
this, t);
3955 PositiveSubtract(*
this, t, *
this);
3958 PositiveAdd(*
this, *
this, t);
3967 Integer diff((word)0, STDMAX2(reg.
size(), b.reg.size()));
3970 if (b.NotNegative())
3971 PositiveSubtract(diff, *
this, b);
3973 PositiveAdd(diff, *
this, b);
3977 if (b.NotNegative())
3979 PositiveAdd(diff, *
this, b);
3983 PositiveSubtract(diff, b, *
this);
3994 PositiveSubtract(*
this, *
this, t);
3996 PositiveAdd(*
this, *
this, t);
4002 PositiveAdd(*
this, *
this, t);
4006 PositiveSubtract(*
this, t, *
this);
4014 const size_t shiftWords = n / WORD_BITS;
4015 const unsigned int shiftBits = (
unsigned int)(n % WORD_BITS);
4018 ShiftWordsLeftByWords(reg, wordCount + shiftWords, shiftWords);
4019 ShiftWordsLeftByBits(reg+shiftWords, wordCount+
BitsToWords(shiftBits), shiftBits);
4026 const size_t shiftWords = n / WORD_BITS;
4027 const unsigned int shiftBits = (
unsigned int)(n % WORD_BITS);
4029 ShiftWordsRightByWords(reg, wordCount, shiftWords);
4030 if (wordCount > shiftWords)
4031 ShiftWordsRightByBits(reg, wordCount-shiftWords, shiftBits);
4043 AndWords(reg, t.reg, size);
4055 OrWords(reg, t.reg, t.reg.
size());
4059 const size_t head = reg.
size();
4060 const size_t tail = t.reg.
size() - reg.
size();
4062 OrWords(reg, t.reg, head);
4063 CopyWords(reg+head,t.reg+head,tail);
4080 XorWords(reg, t.reg, t.reg.
size());
4084 const size_t head = reg.
size();
4085 const size_t tail = t.reg.
size() - reg.
size();
4087 XorWords(reg, t.reg, head);
4088 CopyWords(reg+head,t.reg+head,tail);
4097 size_t aSize = RoundupSize(a.WordCount());
4098 size_t bSize = RoundupSize(b.WordCount());
4100 product.reg.
CleanNew(RoundupSize(aSize+bSize));
4104 AsymmetricMultiply(product.reg, workspace, a.reg, aSize, b.reg, bSize);
4109 PositiveMultiply(product, a, b);
4111 if (a.NotNegative() != b.NotNegative())
4118 Multiply(product, *
this, b);
4147 unsigned aSize = a.WordCount();
4148 unsigned bSize = b.WordCount();
4164 remainder.reg.
CleanNew(RoundupSize(bSize));
4166 quotient.reg.
CleanNew(RoundupSize(aSize-bSize+2));
4170 Divide(remainder.reg, quotient.reg, T, a.reg, aSize, b.reg, bSize);
4175 PositiveDivide(remainder, quotient, dividend, divisor);
4197 if (wordCount <= a.WordCount())
4199 r.reg.
resize(RoundupSize(wordCount));
4200 CopyWords(r.reg, a.reg, wordCount);
4201 SetWords(r.reg+wordCount, 0, r.reg.
size()-wordCount);
4202 if (n % WORD_BITS != 0)
4203 r.reg[wordCount-1] %= (word(1) << (n % WORD_BITS));
4207 r.reg.
resize(RoundupSize(a.WordCount()));
4208 CopyWords(r.reg, a.reg, r.reg.
size());
4212 if (a.IsNegative() && r.
NotZero())
4238 if ((divisor & (divisor-1)) == 0)
4241 remainder = dividend.reg[0] & (divisor-1);
4246 quotient.reg.
CleanNew(RoundupSize(i));
4250 quotient.reg[i] =
DWord(dividend.reg[i], remainder) / divisor;
4251 remainder =
DWord(dividend.reg[i], remainder) % divisor;
4262 remainder = divisor - remainder;
4284 if ((divisor & (divisor-1)) != 0)
4293 remainder =
DWord(reg[i], remainder) % divisor;
4300 remainder = sum % divisor;
4305 remainder = reg[0] & (divisor-1);
4309 remainder = divisor - remainder;
4317 sign =
Sign(1-sign);
4320 int Integer::PositiveCompare(
const Integer& t)
const 4326 return size > tSize ? 1 : -1;
4328 return CryptoPP::Compare(reg, t.reg, size);
4336 return PositiveCompare(t);
4345 return -PositiveCompare(t);
4361 y = (x + *
this/x) >> 1;
4375 return (
WordCount() == 1) && (reg[0] == 1);
4413 return Modulo(m).InverseModNext(m);
4417 return Modulo(m).InverseModNext(m);
4419 return InverseModNext(m);
4435 return !u ?
Zero() : (m*(*this-u)+1)/(*this);
4441 unsigned k = AlmostInverse(r.reg, T, reg, reg.
size(), m.reg, m.reg.
size());
4442 DivideByPower2Mod(r.reg, r.reg, k, m.reg, m.reg.
size());
4450 word g0 = mod, g1 = *
this % mod;
4451 word v0 = 0, v1 = 1;
4479 if (oid != ASN1::prime_field())
4489 ASN1::prime_field().DEREncode(seq);
4506 if (a.reg.size()==m_modulus.reg.
size())
4508 CryptoPP::DivideByPower2Mod(m_result.reg.
begin(), a.reg, 1, m_modulus.reg, a.reg.size());
4512 return m_result1 = (a.IsEven() ? (a >> 1) : ((a+m_modulus) >> 1));
4517 if (a.reg.size()==m_modulus.reg.
size() && b.reg.size()==m_modulus.reg.
size())
4519 if (CryptoPP::Add(m_result.reg.
begin(), a.reg, b.reg, a.reg.size())
4520 || Compare(m_result.reg, m_modulus.reg, a.reg.size()) >= 0)
4522 CryptoPP::Subtract(m_result.reg.
begin(), m_result.reg, m_modulus.reg, a.reg.size());
4529 if (m_result1 >= m_modulus)
4530 m_result1 -= m_modulus;
4537 if (a.reg.size()==m_modulus.reg.
size() && b.reg.size()==m_modulus.reg.
size())
4539 if (CryptoPP::Add(a.reg, a.reg, b.reg, a.reg.size())
4540 || Compare(a.reg, m_modulus.reg, a.reg.size()) >= 0)
4542 CryptoPP::Subtract(a.reg, a.reg, m_modulus.reg, a.reg.size());
4557 if (a.reg.size()==m_modulus.reg.
size() && b.reg.size()==m_modulus.reg.
size())
4559 if (CryptoPP::Subtract(m_result.reg.
begin(), a.reg, b.reg, a.reg.size()))
4560 CryptoPP::Add(m_result.reg.
begin(), m_result.reg, m_modulus.reg, a.reg.size());
4567 m_result1 += m_modulus;
4574 if (a.reg.size()==m_modulus.reg.
size() && b.reg.size()==m_modulus.reg.
size())
4576 if (CryptoPP::Subtract(a.reg, a.reg, b.reg, a.reg.size()))
4577 CryptoPP::Add(a.reg, a.reg, m_modulus.reg, a.reg.size());
4594 CopyWords(m_result.reg.
begin(), m_modulus.reg, m_modulus.reg.
size());
4595 if (CryptoPP::Subtract(m_result.reg.
begin(), m_result.reg, a.reg, a.reg.size()))
4596 Decrement(m_result.reg.
begin()+a.reg.size(), m_modulus.reg.
size()-a.reg.size());
4603 if (m_modulus.
IsOdd())
4614 if (m_modulus.
IsOdd())
4618 for (
unsigned int i=0; i<exponentsCount; i++)
4627 m_u((word)0, m_modulus.reg.size()),
4628 m_workspace(5*m_modulus.reg.size())
4630 if (!m_modulus.IsOdd())
4631 throw InvalidArgument(
"MontgomeryRepresentation: Montgomery representation requires an odd modulus");
4633 RecursiveInverseModPower2(m_u.reg, m_workspace, m_modulus.reg, m_modulus.reg.
size());
4638 word *
const T = m_workspace.
begin();
4639 word *
const R = m_result.reg.begin();
4640 const size_t N = m_modulus.reg.size();
4643 AsymmetricMultiply(T, T+2*N, a.reg, a.reg.size(), b.reg, b.reg.size());
4644 SetWords(T+a.reg.size()+b.reg.size(), 0, 2*N-a.reg.size()-b.reg.size());
4645 MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
4651 word *
const T = m_workspace.
begin();
4652 word *
const R = m_result.reg.begin();
4653 const size_t N = m_modulus.reg.size();
4656 CryptoPP::Square(T, T+2*N, a.reg, a.reg.size());
4657 SetWords(T+2*a.reg.size(), 0, 2*N-2*a.reg.size());
4658 MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
4664 word *
const T = m_workspace.
begin();
4665 word *
const R = m_result.reg.begin();
4666 const size_t N = m_modulus.reg.size();
4669 CopyWords(T, a.reg, a.reg.size());
4670 SetWords(T+a.reg.size(), 0, 2*N-a.reg.size());
4671 MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
4678 word *
const T = m_workspace.
begin();
4679 word *
const R = m_result.reg.begin();
4680 const size_t N = m_modulus.reg.size();
4683 CopyWords(T, a.reg, a.reg.size());
4684 SetWords(T+a.reg.size(), 0, 2*N-a.reg.size());
4685 MontgomeryReduce(R, T+2*N, T, m_modulus.reg, m_u.reg, N);
4686 unsigned k = AlmostInverse(R, T, R, N, m_modulus.reg, N);
4691 DivideByPower2Mod(R, R, k-N*WORD_BITS, m_modulus.reg, N);
4693 MultiplyByPower2Mod(R, R, N*WORD_BITS-k, m_modulus.reg, N);
4700 template <> CRYPTOPP_DLL
4704 static const unsigned int BIT_32 = (1U << 31);
4705 const bool UPPER = !!(base & BIT_32);
4706 static const unsigned int BIT_31 = (1U << 30);
4707 const bool BASE = !!(base & BIT_31);
4709 const char CH = UPPER ?
'A' :
'a';
4710 base &= ~(BIT_32|BIT_31);
4716 bool negative =
false, zero =
false;
4717 if (value.IsNegative())
4734 s[i++]=char((digit < 10 ?
'0' : (CH - 10)) + digit);
4739 result.reserve(i+2);
4754 else if (base == 16)
4766 template <> CRYPTOPP_DLL
4770 static const unsigned int HIGH_BIT = (1U << 31);
4771 const char CH = !!(base & HIGH_BIT) ?
'A' :
'a';
4781 word64 digit = value % base;
4782 result = char((digit < 10 ?
'0' : (CH - 10)) + digit) + result;
4788 #ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER 4791 bool AssignIntToInteger(
const std::type_info &valueType,
void *pInteger,
const void *pInt)
4793 if (valueType !=
typeid(
Integer))
4795 *
reinterpret_cast<Integer *
>(pInteger) = *reinterpret_cast<const int *>(pInt);
4798 #endif // CRYPTOPP_NO_ASSIGN_TO_INTEGER 4807 SetFunctionPointers();
4816 #if defined(HAVE_GCC_INIT_PRIORITY) 4818 const Integer g_zero __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 11))) =
Integer(0L);
4819 const Integer g_one __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 12))) =
Integer(1L);
4820 const Integer g_two __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 13))) =
Integer(2L);
4821 #elif defined(HAVE_MSC_INIT_PRIORITY) 4822 #pragma warning(disable: 4075) 4823 #pragma init_seg(".CRT$XCU") 4828 #pragma warning(default: 4075) 4829 #elif HAVE_XLC_INIT_PRIORITY 4831 #pragma priority(280) 4844 #if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) 4846 #elif defined(CRYPTOPP_CXX11_DYNAMIC_INIT) 4847 static const Integer s_zero(0L);
4849 #else // Potential memory leak. Avoid if possible. 4856 #if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) 4858 #elif defined(CRYPTOPP_CXX11_DYNAMIC_INIT) 4859 static const Integer s_one(1L);
4861 #else // Potential memory leak. Avoid if possible. 4868 #if defined(HAVE_GCC_INIT_PRIORITY) || defined(HAVE_MSC_INIT_PRIORITY) || defined(HAVE_XLC_INIT_PRIORITY) 4870 #elif defined(CRYPTOPP_CXX11_DYNAMIC_INIT) 4871 static const Integer s_two(2L);
4873 #else // Potential memory leak. Avoid if possible. 4880 #endif // CRYPTOPP_IMPORTS Used to pass byte array input as part of a NameValuePairs object.
An invalid argument was detected.
unsigned int WordCount() const
Determines the number of words required to represent the Integer.
Integer MultiplicativeInverse() const
Calculate multiplicative inverse.
Integer & Reduce(Integer &a, const Integer &b) const
TODO.
bool NotZero() const
Determines if the Integer is non-0.
Classes for working with NameValuePairs.
Integer Or(const Integer &t) const
Bitwise OR.
Integer & operator|=(const Integer &t)
Bitwise OR Assignment.
void swap(SecBlock< T, A > &b)
Swap contents with another SecBlock.
Integer And(const Integer &t) const
Bitwise AND.
a number which is probabilistically prime
Utility functions for the Crypto++ library.
Integer Plus(const Integer &b) const
Addition.
ByteOrder
Provides the byte ordering.
Restricts the instantiation of a class to one static object without locks.
void CleanNew(size_type newSize)
Change size without preserving contents.
T GetValueWithDefault(const char *name, T defaultValue) const
Get a named value.
bool IsSquare() const
Determine whether this integer is a perfect square.
void DEREncode(BufferedTransformation &bt) const
Encode in DER format.
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag=INTEGER)
DER Encode unsigned value.
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
size_t size() const
Length of the memory block.
size_t BitsToBytes(size_t bitCount)
Returns the number of 8-bit bytes or octets required for the specified number of bits.
This file contains helper classes/functions for implementing public key algorithms.
void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
Encode absolute value as big-endian octet string.
Integer & operator=(const Integer &t)
Assignment.
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector)
Finds a random prime of special form.
static Integer Gcd(const Integer &a, const Integer &n)
Calculate greatest common divisor.
void resize(size_type newSize)
Change size and preserve contents.
Integer & operator+=(const Integer &t)
Addition Assignment.
size_t BitsToWords(size_t bitCount)
Returns the number of words required for the specified number of bits.
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
void CleanGrow(size_type newSize)
Change size and preserve contents.
Integer & operator--()
Pre-decrement.
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
TODO.
Secure memory block with allocator and cleanup.
const Integer & Inverse(const Integer &a) const
Inverts the element in the ring.
signed long ConvertToLong() const
Convert the Integer to Long.
const Integer & Subtract(const Integer &a, const Integer &b) const
Subtracts elements in the ring.
void OpenPGPDecode(const byte *input, size_t inputLen)
Decode from OpenPGP format.
Signedness
Used when importing and exporting integers.
unsigned int MaxElementByteLength() const
Provides the maximum byte size of an element in the ring.
ASN.1 object identifiers for algorthms and schemes.
Classes for automatic resource management.
bool IsP4()
Determines if the CPU is an Intel P4.
bool IsNegative() const
Determines if the Integer is negative.
lword MaxRetrievable() const
Provides the number of bytes ready for retrieval.
Library configuration file.
MontgomeryRepresentation(const Integer &modulus)
Construct a MontgomeryRepresentation.
static void DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n)
Extended Division.
Ring of congruence classes modulo n.
Interface for random number generators.
size_t BytesToWords(size_t byteCount)
Returns the number of words required for the specified number of bytes.
void Randomize(RandomNumberGenerator &rng, size_t bitCount)
Set this Integer to random integer.
std::string IntToString< word64 >(word64 value, unsigned int base)
Converts an unsigned value to a string.
void New(size_type newSize)
Change size without preserving contents.
void SetByte(size_t n, byte value)
Set the n-th byte to value.
Integer InverseMod(const Integer &n) const
Calculate multiplicative inverse.
bool IsPositive() const
Determines if the Integer is positive.
bool NotNegative() const
Determines if the Integer is non-negative.
const Integer & Add(const Integer &a, const Integer &b) const
Adds elements in the ring.
static const Integer & One()
Integer representing 1.
Integer & Accumulate(Integer &a, const Integer &b) const
TODO.
P1363 key derivation function.
byte order is little-endian
Sign
Used internally to represent the integer.
Integer ConvertIn(const Integer &a) const
Reduces an element in the congruence class.
bool operator!() const
Negation.
Pointer that overloads operator ->
bool IsUnit() const
Determine if 1 or -1.
unsigned int ByteCount() const
Determines the number of bytes required to represent the Integer.
Classes and functions for secure memory allocations.
void DEREncodeElement(BufferedTransformation &out, const Element &a) const
Encodes element in DER format.
Integer Modulo(const Integer &b) const
Remainder.
Copy input to a memory buffer.
void BERDecodeElement(BufferedTransformation &in, Element &a) const
Decodes element in DER format.
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
Minimum number of bytes to encode this integer.
Integer DividedBy(const Integer &b) const
Division.
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
TODO.
Integer Times(const Integer &b) const
Multiplication.
a number with no special properties
const byte * begin() const
Pointer to the first byte in the memory block.
Integer & operator++()
Pre-increment.
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
void swap(Integer &a)
Swaps this Integer with another Integer.
Integer()
Creates the zero integer.
unsigned int TrailingZeros(word32 v)
Determines the number of trailing 0-bits in a value.
Integer & operator<<=(size_t n)
Left-shift Assignment.
bool IsZero() const
Determines if the Integer is 0.
Exception thrown when an error is encountered decoding an OpenPGP integer.
void Negate()
Reverse the Sign of the Integer.
int Compare(const Integer &a) const
Perform signed comparison.
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
Decode nonnegative value from big-endian octet string.
Application callback to signal suitability of a cabdidate prime.
void ConditionalSwapPointers(bool c, T &a, T &b)
Performs a branchless swap of pointers a and b if condition c is true.
static Integer Power2(size_t e)
Exponentiates to a power of 2.
Multiple precision integer with arithmetic operations.
virtual Element Exponentiate(const Element &a, const Integer &e) const
Raises a base to an exponent in the group.
const Integer & Multiply(const Integer &a, const Integer &b) const
Multiplies elements in the ring.
size_t OpenPGPEncode(byte *output, size_t bufferSize) const
Encode absolute value in OpenPGP format.
const Integer & Half(const Integer &a) const
Divides an element by 2.
static const Integer & Two()
Integer representing 2.
const Integer & Square(const Integer &a) const
Square an element in the ring.
Integer & operator^=(const Integer &t)
Bitwise XOR Assignment.
#define MEMORY_BARRIER
A memory barrier.
RandomNumberType
Properties of a random integer.
const char * Seed()
ConstByteArrayParameter.
bool IsEven() const
Determines if the Integer is even parity.
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
String-based implementation of Store interface.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d)
Extended Division.
ModularArithmetic(const Integer &modulus=Integer::One())
Construct a ModularArithmetic.
void BERDecodeError()
Raises a BERDecodeErr.
Data structure used to store byte strings.
Functions for CPU features and intrinsics.
Classes and functions for working with ANS.1 objects.
Classes for SHA-1 and SHA-2 family of message digests.
void SetBit(size_t n, bool value=1)
Set the n-th bit to value.
iterator begin()
Provides an iterator pointing to the first element in the memory block.
unsigned int BitCount() const
Determines the number of bits required to represent the Integer.
const char * PointerToPrimeSelector()
const PrimeSelector *
Implementation of BufferedTransformation's attachment interface.
Classes and functions for number theoretic operations.
byte GetByte(size_t i) const
Provides the i-th byte of the Integer.
Exception thrown when division by 0 is encountered.
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Integer Squared() const
Multiply this integer by itself.
T1 SaturatingSubtract1(const T1 &a, const T2 &b)
Performs a saturating subtract clamped at 1.
Exception thrown when a random number cannot be found that satisfies the condition.
bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms=g_nullNameValuePairs)
Generate a random number.
Performs modular arithmetic in Montgomery representation for increased speed.
bool HasSSE2()
Determines SSE2 availability.
Integer Minus(const Integer &b) const
Subtraction.
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
void Decode(const byte *input, size_t inputLen, Signedness sign=UNSIGNED)
Decode from big-endian byte array.
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
TODO.
size_t DEREncodeOctetString(BufferedTransformation &bt, const byte *str, size_t strLen)
DER encode octet string.
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
Exponentiates a base to multiple exponents in the ring.
Multiple precision integer with arithmetic operations.
Integer Xor(const Integer &t) const
Bitwise XOR.
static const Integer & Zero()
Integer representing 0.
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
void Grow(size_type newSize)
Change size and preserve contents.
void BERDecode(const byte *input, size_t inputLen)
Decode from BER format.
std::string IntToString< Integer >(Integer value, unsigned int base)
Converts an Integer to a string.
Class file for performing modular arithmetic.
Crypto++ library namespace.
bool GetValue(const char *name, T &value) const
Get a named value.
Integer & operator>>=(size_t n)
Right-shift Assignment.
bool GetBit(size_t i) const
Provides the i-th bit of the Integer.
Integer SquareRoot() const
Extract square root.
bool GetIntValue(const char *name, int &value) const
Get a named value with type int.
bool IsConvertableToLong() const
Determines if the Integer is convertable to Long.
size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Integer AbsoluteValue() const
Retrieve the absolute value of this integer.
Integer & operator-=(const Integer &t)
Subtraction Assignment.
unsigned int BitPrecision(const T &value)
Returns the number of bits required for a value.
size_type size() const
Provides the count of elements in the SecBlock.
Integer & operator &=(const Integer &t)
Bitwise AND Assignment.
void DEREncode(BufferedTransformation &bt) const
Encodes in DER format.
lword GetBits(size_t i, size_t n) const
Provides the low order bits of the Integer.
Integer operator-() const
Subtraction.
the value is positive or 0
const Integer & MultiplicativeInverse(const Integer &a) const
Calculate the multiplicative inverse of an element in the ring.
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
Exponentiates a base to multiple exponents in the ring.
bool IsOdd() const
Determines if the Integer is odd parity.
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
Exponentiates a base to multiple exponents in the Ring.
Interface for retrieving values given their names.
Integer ConvertOut(const Integer &a) const
Reduces an element in the congruence class.