?? integer.cpp
字號:
// integer.cpp - written and placed in the public domain by Wei Dai
// contains public domain code contributed by Alister Lee and Leonard Janke
#include "pch.h"
#include "integer.h"
#include "modarith.h"
#include "nbtheory.h"
#include "asn.h"
#include "oids.h"
#include "words.h"
#include "algparam.h"
#include "pubkey.h" // for P1363_KDF2
#include "sha.h"
#include <iostream>
#ifdef SSE2_INTRINSICS_AVAILABLE
#include <emmintrin.h>
#endif
#include "algebra.cpp"
#include "eprecomp.cpp"
NAMESPACE_BEGIN(CryptoPP)
bool FunctionAssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt)
{
if (valueType != typeid(Integer))
return false;
*reinterpret_cast<Integer *>(pInteger) = *reinterpret_cast<const int *>(pInt);
return true;
}
static int DummyAssignIntToInteger = (AssignIntToInteger = FunctionAssignIntToInteger, 0);
#ifdef SSE2_INTRINSICS_AVAILABLE
template <class T>
AllocatorBase<T>::pointer AlignedAllocator<T>::allocate(size_type n, const void *)
{
if (n < 4)
return new T[n];
else
return (T *)_mm_malloc(sizeof(T)*n, 16);
}
template <class T>
void AlignedAllocator<T>::deallocate(void *p, size_type n)
{
memset(p, 0, n*sizeof(T));
if (n < 4)
delete [] p;
else
_mm_free(p);
}
template class AlignedAllocator<word>;
#endif
#define MAKE_DWORD(lowWord, highWord) ((dword(highWord)<<WORD_BITS) | (lowWord))
static int Compare(const word *A, const word *B, unsigned int N)
{
while (N--)
if (A[N] > B[N])
return 1;
else if (A[N] < B[N])
return -1;
return 0;
}
static word Increment(word *A, unsigned int N, word B=1)
{
assert(N);
word t = A[0];
A[0] = t+B;
if (A[0] >= t)
return 0;
for (unsigned i=1; i<N; i++)
if (++A[i])
return 0;
return 1;
}
static word Decrement(word *A, unsigned int N, word B=1)
{
assert(N);
word t = A[0];
A[0] = t-B;
if (A[0] <= t)
return 0;
for (unsigned i=1; i<N; i++)
if (A[i]--)
return 0;
return 1;
}
static void TwosComplement(word *A, unsigned int N)
{
Decrement(A, N);
for (unsigned i=0; i<N; i++)
A[i] = ~A[i];
}
static word LinearMultiply(word *C, const word *A, word B, unsigned int N)
{
word carry=0;
for(unsigned i=0; i<N; i++)
{
dword p = (dword)A[i] * B + carry;
C[i] = LOW_WORD(p);
carry = HIGH_WORD(p);
}
return carry;
}
static void AtomicInverseModPower2(word *C, word A0, word A1)
{
assert(A0%2==1);
dword A=MAKE_DWORD(A0, A1), R=A0%8;
for (unsigned i=3; i<2*WORD_BITS; i*=2)
R = R*(2-R*A);
assert(R*A==1);
C[0] = LOW_WORD(R);
C[1] = HIGH_WORD(R);
}
// ********************************************************
class Portable
{
public:
static word Add(word *C, const word *A, const word *B, unsigned int N);
static word Subtract(word *C, const word *A, const word *B, unsigned int N);
static inline void Multiply2(word *C, const word *A, const word *B);
static inline word Multiply2Add(word *C, const word *A, const word *B);
static void Multiply4(word *C, const word *A, const word *B);
static void Multiply8(word *C, const word *A, const word *B);
static inline unsigned int MultiplyRecursionLimit() {return 8;}
static inline void Multiply2Bottom(word *C, const word *A, const word *B);
static void Multiply4Bottom(word *C, const word *A, const word *B);
static void Multiply8Bottom(word *C, const word *A, const word *B);
static inline unsigned int MultiplyBottomRecursionLimit() {return 8;}
static void Square2(word *R, const word *A);
static void Square4(word *R, const word *A);
static void Square8(word *R, const word *A) {assert(false);}
static inline unsigned int SquareRecursionLimit() {return 4;}
};
word Portable::Add(word *C, const word *A, const word *B, unsigned int N)
{
assert (N%2 == 0);
#ifdef IS_LITTLE_ENDIAN
if (sizeof(dword) == sizeof(size_t)) // dword is only register size
{
dword carry = 0;
N >>= 1;
for (unsigned int i = 0; i < N; i++)
{
dword a = ((const dword *)A)[i] + carry;
dword c = a + ((const dword *)B)[i];
((dword *)C)[i] = c;
carry = (a < carry) | (c < a);
}
return (word)carry;
}
else
#endif
{
word carry = 0;
for (unsigned int i = 0; i < N; i+=2)
{
dword u = (dword) carry + A[i] + B[i];
C[i] = LOW_WORD(u);
u = (dword) HIGH_WORD(u) + A[i+1] + B[i+1];
C[i+1] = LOW_WORD(u);
carry = HIGH_WORD(u);
}
return carry;
}
}
word Portable::Subtract(word *C, const word *A, const word *B, unsigned int N)
{
assert (N%2 == 0);
#ifdef IS_LITTLE_ENDIAN
if (sizeof(dword) == sizeof(size_t)) // dword is only register size
{
dword borrow = 0;
N >>= 1;
for (unsigned int i = 0; i < N; i++)
{
dword a = ((const dword *)A)[i];
dword b = a - borrow;
dword c = b - ((const dword *)B)[i];
((dword *)C)[i] = c;
borrow = (b > a) | (c > b);
}
return (word)borrow;
}
else
#endif
{
word borrow=0;
for (unsigned i = 0; i < N; i+=2)
{
dword u = (dword) A[i] - B[i] - borrow;
C[i] = LOW_WORD(u);
u = (dword) A[i+1] - B[i+1] - (word)(0-HIGH_WORD(u));
C[i+1] = LOW_WORD(u);
borrow = 0-HIGH_WORD(u);
}
return borrow;
}
}
void Portable::Multiply2(word *C, const word *A, const word *B)
{
/*
word s;
dword d;
if (A1 >= A0)
if (B0 >= B1)
{
s = 0;
d = (dword)(A1-A0)*(B0-B1);
}
else
{
s = (A1-A0);
d = (dword)s*(word)(B0-B1);
}
else
if (B0 > B1)
{
s = (B0-B1);
d = (word)(A1-A0)*(dword)s;
}
else
{
s = 0;
d = (dword)(A0-A1)*(B1-B0);
}
*/
// this segment is the branchless equivalent of above
word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
unsigned int ai = A[1] < A[0];
unsigned int bi = B[0] < B[1];
unsigned int di = ai & bi;
dword d = (dword)D[di]*D[di+2];
D[1] = D[3] = 0;
unsigned int si = ai + !bi;
word s = D[si];
dword A0B0 = (dword)A[0]*B[0];
C[0] = LOW_WORD(A0B0);
dword A1B1 = (dword)A[1]*B[1];
dword t = (dword) HIGH_WORD(A0B0) + LOW_WORD(A0B0) + LOW_WORD(d) + LOW_WORD(A1B1);
C[1] = LOW_WORD(t);
t = A1B1 + HIGH_WORD(t) + HIGH_WORD(A0B0) + HIGH_WORD(d) + HIGH_WORD(A1B1) - s;
C[2] = LOW_WORD(t);
C[3] = HIGH_WORD(t);
}
inline void Portable::Multiply2Bottom(word *C, const word *A, const word *B)
{
#ifdef IS_LITTLE_ENDIAN
if (sizeof(dword) == sizeof(size_t))
{
dword a = *(const dword *)A, b = *(const dword *)B;
((dword *)C)[0] = a*b;
}
else
#endif
{
dword t = (dword)A[0]*B[0];
C[0] = LOW_WORD(t);
C[1] = HIGH_WORD(t) + A[0]*B[1] + A[1]*B[0];
}
}
word Portable::Multiply2Add(word *C, const word *A, const word *B)
{
word D[4] = {A[1]-A[0], A[0]-A[1], B[0]-B[1], B[1]-B[0]};
unsigned int ai = A[1] < A[0];
unsigned int bi = B[0] < B[1];
unsigned int di = ai & bi;
dword d = (dword)D[di]*D[di+2];
D[1] = D[3] = 0;
unsigned int si = ai + !bi;
word s = D[si];
dword A0B0 = (dword)A[0]*B[0];
dword t = A0B0 + C[0];
C[0] = LOW_WORD(t);
dword A1B1 = (dword)A[1]*B[1];
t = (dword) HIGH_WORD(t) + LOW_WORD(A0B0) + LOW_WORD(d) + LOW_WORD(A1B1) + C[1];
C[1] = LOW_WORD(t);
t = (dword) HIGH_WORD(t) + LOW_WORD(A1B1) + HIGH_WORD(A0B0) + HIGH_WORD(d) + HIGH_WORD(A1B1) - s + C[2];
C[2] = LOW_WORD(t);
t = (dword) HIGH_WORD(t) + HIGH_WORD(A1B1) + C[3];
C[3] = LOW_WORD(t);
return HIGH_WORD(t);
}
#define MulAcc(x, y) \
p = (dword)A[x] * B[y] + c; \
c = LOW_WORD(p); \
p = (dword)d + HIGH_WORD(p); \
d = LOW_WORD(p); \
e += HIGH_WORD(p);
#define SaveMulAcc(s, x, y) \
R[s] = c; \
p = (dword)A[x] * B[y] + d; \
c = LOW_WORD(p); \
p = (dword)e + HIGH_WORD(p); \
d = LOW_WORD(p); \
e = HIGH_WORD(p);
#define SquAcc(x, y) \
q = (dword)A[x] * A[y]; \
p = q + c; \
c = LOW_WORD(p); \
p = (dword)d + HIGH_WORD(p); \
d = LOW_WORD(p); \
e += HIGH_WORD(p); \
p = q + c; \
c = LOW_WORD(p); \
p = (dword)d + HIGH_WORD(p); \
d = LOW_WORD(p); \
e += HIGH_WORD(p);
#define SaveSquAcc(s, x, y) \
R[s] = c; \
q = (dword)A[x] * A[y]; \
p = q + d; \
c = LOW_WORD(p); \
p = (dword)e + HIGH_WORD(p); \
d = LOW_WORD(p); \
e = HIGH_WORD(p); \
p = q + c; \
c = LOW_WORD(p); \
p = (dword)d + HIGH_WORD(p); \
d = LOW_WORD(p); \
e += HIGH_WORD(p);
void Portable::Multiply4(word *R, const word *A, const word *B)
{
dword p;
word c, d, e;
p = (dword)A[0] * B[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
MulAcc(0, 1);
MulAcc(1, 0);
SaveMulAcc(1, 2, 0);
MulAcc(1, 1);
MulAcc(0, 2);
SaveMulAcc(2, 0, 3);
MulAcc(1, 2);
MulAcc(2, 1);
MulAcc(3, 0);
SaveMulAcc(3, 3, 1);
MulAcc(2, 2);
MulAcc(1, 3);
SaveMulAcc(4, 2, 3);
MulAcc(3, 2);
R[5] = c;
p = (dword)A[3] * B[3] + d;
R[6] = LOW_WORD(p);
R[7] = e + HIGH_WORD(p);
}
void Portable::Square2(word *R, const word *A)
{
dword p, q;
word c, d, e;
p = (dword)A[0] * A[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
SquAcc(0, 1);
R[1] = c;
p = (dword)A[1] * A[1] + d;
R[2] = LOW_WORD(p);
R[3] = e + HIGH_WORD(p);
}
void Portable::Square4(word *R, const word *A)
{
const word *B = A;
dword p, q;
word c, d, e;
p = (dword)A[0] * A[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
SquAcc(0, 1);
SaveSquAcc(1, 2, 0);
MulAcc(1, 1);
SaveSquAcc(2, 0, 3);
SquAcc(1, 2);
SaveSquAcc(3, 3, 1);
MulAcc(2, 2);
SaveSquAcc(4, 2, 3);
R[5] = c;
p = (dword)A[3] * A[3] + d;
R[6] = LOW_WORD(p);
R[7] = e + HIGH_WORD(p);
}
void Portable::Multiply8(word *R, const word *A, const word *B)
{
dword p;
word c, d, e;
p = (dword)A[0] * B[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
MulAcc(0, 1);
MulAcc(1, 0);
SaveMulAcc(1, 2, 0);
MulAcc(1, 1);
MulAcc(0, 2);
SaveMulAcc(2, 0, 3);
MulAcc(1, 2);
MulAcc(2, 1);
MulAcc(3, 0);
SaveMulAcc(3, 0, 4);
MulAcc(1, 3);
MulAcc(2, 2);
MulAcc(3, 1);
MulAcc(4, 0);
SaveMulAcc(4, 0, 5);
MulAcc(1, 4);
MulAcc(2, 3);
MulAcc(3, 2);
MulAcc(4, 1);
MulAcc(5, 0);
SaveMulAcc(5, 0, 6);
MulAcc(1, 5);
MulAcc(2, 4);
MulAcc(3, 3);
MulAcc(4, 2);
MulAcc(5, 1);
MulAcc(6, 0);
SaveMulAcc(6, 0, 7);
MulAcc(1, 6);
MulAcc(2, 5);
MulAcc(3, 4);
MulAcc(4, 3);
MulAcc(5, 2);
MulAcc(6, 1);
MulAcc(7, 0);
SaveMulAcc(7, 1, 7);
MulAcc(2, 6);
MulAcc(3, 5);
MulAcc(4, 4);
MulAcc(5, 3);
MulAcc(6, 2);
MulAcc(7, 1);
SaveMulAcc(8, 2, 7);
MulAcc(3, 6);
MulAcc(4, 5);
MulAcc(5, 4);
MulAcc(6, 3);
MulAcc(7, 2);
SaveMulAcc(9, 3, 7);
MulAcc(4, 6);
MulAcc(5, 5);
MulAcc(6, 4);
MulAcc(7, 3);
SaveMulAcc(10, 4, 7);
MulAcc(5, 6);
MulAcc(6, 5);
MulAcc(7, 4);
SaveMulAcc(11, 5, 7);
MulAcc(6, 6);
MulAcc(7, 5);
SaveMulAcc(12, 6, 7);
MulAcc(7, 6);
R[13] = c;
p = (dword)A[7] * B[7] + d;
R[14] = LOW_WORD(p);
R[15] = e + HIGH_WORD(p);
}
void Portable::Multiply4Bottom(word *R, const word *A, const word *B)
{
dword p;
word c, d, e;
p = (dword)A[0] * B[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
MulAcc(0, 1);
MulAcc(1, 0);
SaveMulAcc(1, 2, 0);
MulAcc(1, 1);
MulAcc(0, 2);
R[2] = c;
R[3] = d + A[0] * B[3] + A[1] * B[2] + A[2] * B[1] + A[3] * B[0];
}
void Portable::Multiply8Bottom(word *R, const word *A, const word *B)
{
dword p;
word c, d, e;
p = (dword)A[0] * B[0];
R[0] = LOW_WORD(p);
c = HIGH_WORD(p);
d = e = 0;
MulAcc(0, 1);
MulAcc(1, 0);
SaveMulAcc(1, 2, 0);
MulAcc(1, 1);
MulAcc(0, 2);
SaveMulAcc(2, 0, 3);
MulAcc(1, 2);
MulAcc(2, 1);
MulAcc(3, 0);
SaveMulAcc(3, 0, 4);
MulAcc(1, 3);
MulAcc(2, 2);
MulAcc(3, 1);
MulAcc(4, 0);
SaveMulAcc(4, 0, 5);
MulAcc(1, 4);
MulAcc(2, 3);
MulAcc(3, 2);
MulAcc(4, 1);
MulAcc(5, 0);
SaveMulAcc(5, 0, 6);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -