📄 integer.cpp
字号:
/* integer.cpp * * Copyright (C) 2003 Sawtooth Consulting Ltd. * * This file is part of yaSSL. * * yaSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * yaSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA *//* based on Wei Dai's integer.cpp from CryptoPP */#include "runtime.hpp"#include "integer.hpp"#include "modarith.hpp"#include "asn.hpp"#ifdef __DECCXX #include <c_asm.h> // for asm overflow assembly#endif// 64bit multiply overflow intrinsic#if defined(_MSC_VER) && defined(_WIN64) && !defined(__INTEL_COMPILER) && \ !defined(TAOCRYPT_NATIVE_DWORD_AVAILABLE) #ifdef __ia64__ #define myUMULH __UMULH #elif __x86_64__ #define myUMULH __umulh #else #error unknown 64bit windows #endifextern "C" word myUMULH(word, word); #pragma intrinsic (myUMULH)#endif#ifdef SSE2_INTRINSICS_AVAILABLE #ifdef __GNUC__ #include <xmmintrin.h> #include <signal.h> #include <setjmp.h> #ifdef TAOCRYPT_MEMALIGN_AVAILABLE #include <malloc.h> #else #include <stdlib.h> #endif #else #include <emmintrin.h> #endif#elif defined(_MSC_VER) && defined(_M_IX86) #pragma message("You do not seem to have the Visual C++ Processor Pack ") #pragma message("installed, so use of SSE2 intrinsics will be disabled.")#elif defined(__GNUC__) && defined(__i386__)/* #warning You do not have GCC 3.3 or later, or did not specify the -msse2 \ compiler option. Use of SSE2 intrinsics will be disabled.*/#endifnamespace TaoCrypt {#ifdef SSE2_INTRINSICS_AVAILABLEtemplate <class T>CPP_TYPENAME AllocatorBase<T>::pointer AlignedAllocator<T>::allocate( size_type n, const void *){ CheckSize(n); if (n == 0) return 0; if (n >= 4) { void* p; #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE p = _mm_malloc(sizeof(T)*n, 16); #elif defined(TAOCRYPT_MEMALIGN_AVAILABLE) p = memalign(16, sizeof(T)*n); #elif defined(TAOCRYPT_MALLOC_ALIGNMENT_IS_16) p = malloc(sizeof(T)*n); #else p = (byte *)malloc(sizeof(T)*n + 8); // assume malloc alignment is at least 8 #endif #ifdef TAOCRYPT_NO_ALIGNED_ALLOC assert(m_pBlock == 0); m_pBlock = p; if (!IsAlignedOn(p, 16)) { assert(IsAlignedOn(p, 8)); p = (byte *)p + 8; } #endif assert(IsAlignedOn(p, 16)); return (T*)p; } return new (tc) T[n];}template <class T>void AlignedAllocator<T>::deallocate(void* p, size_type n){ memset(p, 0, n*sizeof(T)); if (n >= 4) { #ifdef TAOCRYPT_MM_MALLOC_AVAILABLE _mm_free(p); #elif defined(TAOCRYPT_NO_ALIGNED_ALLOC) assert(m_pBlock == p || (byte*)m_pBlock+8 == p); free(m_pBlock); m_pBlock = 0; #else free(p); #endif } else tcArrayDelete((T *)p);}#endif // SSE2// ******** start of integer needs// start 5.2.1 adds DWord and Word ********// ********************************************************class DWord {public:DWord() {}#ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE explicit DWord(word low) { whole_ = low; }#else explicit DWord(word low) { halfs_.low = low; halfs_.high = 0; }#endif DWord(word low, word high) { halfs_.low = low; halfs_.high = high; } static DWord Multiply(word a, word b) { DWord r; #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE r.whole_ = (dword)a * b; #elif defined(_MSC_VER) r.halfs_.low = a*b; r.halfs_.high = myUMULH(a,b); #elif defined(__alpha__) r.halfs_.low = a*b; #ifdef __GNUC__ __asm__("umulh %1,%2,%0" : "=r" (r.halfs_.high) : "r" (a), "r" (b)); #elif defined(__DECCXX) r.halfs_.high = asm("umulh %a0, %a1, %v0", a, b); #else #error unknown alpha compiler #endif #elif defined(__ia64__) r.halfs_.low = a*b; __asm__("xmpy.hu %0=%1,%2" : "=f" (r.halfs_.high) : "f" (a), "f" (b)); #elif defined(_ARCH_PPC64) r.halfs_.low = a*b; __asm__("mulhdu %0,%1,%2" : "=r" (r.halfs_.high) : "r" (a), "r" (b) : "cc"); #elif defined(__x86_64__) __asm__("mulq %3" : "=d" (r.halfs_.high), "=a" (r.halfs_.low) : "a" (a), "rm" (b) : "cc"); #elif defined(__mips64) __asm__("dmultu %2,%3" : "=h" (r.halfs_.high), "=l" (r.halfs_.low) : "r" (a), "r" (b)); #elif defined(_M_IX86) // for testing word64 t = (word64)a * b; r.halfs_.high = ((word32 *)(&t))[1]; r.halfs_.low = (word32)t; #else #error can not implement DWord #endif return r; } static DWord MultiplyAndAdd(word a, word b, word c) { DWord r = Multiply(a, b); return r += c; } DWord & operator+=(word a) { #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE whole_ = whole_ + a; #else halfs_.low += a; halfs_.high += (halfs_.low < a); #endif return *this; } DWord operator+(word a) { DWord r; #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE r.whole_ = whole_ + a; #else r.halfs_.low = halfs_.low + a; r.halfs_.high = halfs_.high + (r.halfs_.low < a); #endif return r; } DWord operator-(DWord a) { DWord r; #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE r.whole_ = whole_ - a.whole_; #else r.halfs_.low = halfs_.low - a.halfs_.low; r.halfs_.high = halfs_.high - a.halfs_.high - (r.halfs_.low > halfs_.low); #endif return r; } DWord operator-(word a) { DWord r; #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE r.whole_ = whole_ - a; #else r.halfs_.low = halfs_.low - a; r.halfs_.high = halfs_.high - (r.halfs_.low > halfs_.low); #endif return r; } // returns quotient, which must fit in a word word operator/(word divisor); word operator%(word a); bool operator!() const { #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE return !whole_; #else return !halfs_.high && !halfs_.low; #endif } word GetLowHalf() const {return halfs_.low;} word GetHighHalf() const {return halfs_.high;} word GetHighHalfAsBorrow() const {return 0-halfs_.high;}private: union { #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE dword whole_; #endif struct { #ifdef LITTLE_ENDIAN_ORDER word low; word high; #else word high; word low; #endif } halfs_; };};class Word {public: Word() {} Word(word value) { whole_ = value; } Word(hword low, hword high) { whole_ = low | (word(high) << (WORD_BITS/2)); } static Word Multiply(hword a, hword b) { Word r; r.whole_ = (word)a * b; return r; } Word operator-(Word a) { Word r; r.whole_ = whole_ - a.whole_; return r; } Word operator-(hword a) { Word r; r.whole_ = whole_ - a; return r; } // returns quotient, which must fit in a word hword operator/(hword divisor) { return hword(whole_ / divisor); } bool operator!() const { return !whole_; } word GetWhole() const {return whole_;} hword GetLowHalf() const {return hword(whole_);} hword GetHighHalf() const {return hword(whole_>>(WORD_BITS/2));} hword GetHighHalfAsBorrow() const {return 0-hword(whole_>>(WORD_BITS/2));}private: word whole_;};// dummy is VC60 compiler bug workaround// do a 3 word by 2 word divide, returns quotient and leaves remainder in Atemplate <class S, class D>S DivideThreeWordsByTwo(S* A, S B0, S B1, D* dummy_VC6_WorkAround = 0){ // assert {A[2],A[1]} < {B1,B0}, so quotient can fit in a S assert(A[2] < B1 || (A[2]==B1 && A[1] < B0)); // estimate the quotient: do a 2 S by 1 S divide S Q; if (S(B1+1) == 0) Q = A[2]; else Q = D(A[1], A[2]) / S(B1+1); // now subtract Q*B from A D p = D::Multiply(B0, Q); D u = (D) A[0] - p.GetLowHalf(); A[0] = u.GetLowHalf(); u = (D) A[1] - p.GetHighHalf() - u.GetHighHalfAsBorrow() - D::Multiply(B1, Q); A[1] = u.GetLowHalf(); A[2] += u.GetHighHalf(); // Q <= actual quotient, so fix it while (A[2] || A[1] > B1 || (A[1]==B1 && A[0]>=B0)) { u = (D) A[0] - B0; A[0] = u.GetLowHalf(); u = (D) A[1] - B1 - u.GetHighHalfAsBorrow(); A[1] = u.GetLowHalf(); A[2] += u.GetHighHalf(); Q++; assert(Q); // shouldn't overflow } return Q;}// do a 4 word by 2 word divide, returns 2 word quotient in Q0 and Q1template <class S, class D>inline D DivideFourWordsByTwo(S *T, const D &Al, const D &Ah, const D &B){ if (!B) // if divisor is 0, we assume divisor==2**(2*WORD_BITS) return D(Ah.GetLowHalf(), Ah.GetHighHalf()); else { S Q[2]; T[0] = Al.GetLowHalf(); T[1] = Al.GetHighHalf(); T[2] = Ah.GetLowHalf(); T[3] = Ah.GetHighHalf(); Q[1] = DivideThreeWordsByTwo<S, D>(T+1, B.GetLowHalf(), B.GetHighHalf()); Q[0] = DivideThreeWordsByTwo<S, D>(T, B.GetLowHalf(), B.GetHighHalf()); return D(Q[0], Q[1]); }}// returns quotient, which must fit in a wordinline word DWord::operator/(word a){ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE return word(whole_ / a); #else hword r[4]; return DivideFourWordsByTwo<hword, Word>(r, halfs_.low, halfs_.high, a).GetWhole(); #endif}inline word DWord::operator%(word a){ #ifdef TAOCRYPT_NATIVE_DWORD_AVAILABLE return word(whole_ % a); #else if (a < (word(1) << (WORD_BITS/2))) { hword h = hword(a); word r = halfs_.high % h; r = ((halfs_.low >> (WORD_BITS/2)) + (r << (WORD_BITS/2))) % h; return hword((hword(halfs_.low) + (r << (WORD_BITS/2))) % h); } else { hword r[4]; DivideFourWordsByTwo<hword, Word>(r, halfs_.low, halfs_.high, a); return Word(r[0], r[1]).GetWhole(); } #endif}// end 5.2.1 DWord and Word addsstatic const unsigned int RoundupSizeTable[] = {2, 2, 2, 4, 4, 8, 8, 8, 8};static inline unsigned int RoundupSize(unsigned int n){ if (n<=8) return RoundupSizeTable[n]; else if (n<=16) return 16; else if (n<=32) return 32; else if (n<=64) return 64; else return 1U << BitPrecision(n-1);}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]--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -