⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bignum.h

📁 windows的加密api源码
💻 H
📖 第 1 页 / 共 4 页
字号:
/*
        Compare a multiple-precision number to a scalar.
*/
{
    return compare_diff(a, lng, &ivalue, 1);
}
/****************************************************************************/
static inline int compare_same(digit_tc  a[],
                               digit_tc  b[],
                               DWORDC    lng)
/*
        Compare two multiple precision numbers a and b each of length lng.
        Function value is the sign of a - b, namely

                          +1 if a > b
                           0 if a = b
                          -1 if a < b
*/
#if USEASM_IX86
    #pragma warning(disable : 4035)      /* No return value */
{
                    /*
                            We could use REPE CMPSD,
                            but REPE is slow (4 cycles)
                            on the Pentium.  Plus we
                            would need std and cld
                            to adjust the direction flag.
                            We anticipate that most loops
                            will have either 1 or 2 iterations,
                            and use RISC instructions.
                    */

    _asm {
        mov  eax,lng
        mov  esi,a
        mov  edi,b
     label1:
        test eax,eax
        jz   label2              ; If nothing left, exit with eax = 0

        mov  ecx,[esi+4*eax-4]   ;
        mov  edx,[edi+4*eax-4]

        dec  eax                 ; Decrement remaining loop count
        cmp  ecx,edx             ; Test a[i] - b[i]

        je   label1

        sbb  eax,eax             ; eax = 0 if a > b,   -1 if a < b
        or   eax,1               ; eax = 1 if a > b,   -1 if a < b
     label2:
    }
}
    #pragma warning(default : 4035)
#else
{
    DWORD i;
    for (i = lng-1; i != -1; i--) {
        if (a[i] != b[i]) return (a[i] > b[i] ? +1 : -1);
    }
    return 0;
}  /* compare_same */
#endif
/****************************************************************************/
#if USEASM_ALPHA
    extern void mp_clear(MP_OUTPUT, DWORDC);
#elif 0
static inline void mp_clear(digit_t a[],
                            DWORDC  lnga)
/*
        Zero a multiple-precision number.
*/
{
    DWORD i;
    for (i = 0; i != lnga; i++) a[i] = 0;
}
#else
#define mp_clear(dest, lng) (void)memset((void *)(dest), 0, (lng)*sizeof(digit_t))
#endif
/****************************************************************************/
#if USEASM_ALPHA
    extern void mp_extend(MP_INPUT, DWORDC, MP_OUTPUT, DWORDC);
        // See alpha.s
#else
static inline void mp_extend(digit_tc  a[],
                             DWORDC    lnga,
                             digit_t   b[],
                             DWORDC    lngb)
/*
        Copy a to b, while changing its length from
        lnga to lngb (zero fill).  Require lngb >= lnga.
*/
{
    mp_copy(a, b, lnga);
    mp_clear(b + lnga, lngb - lnga);
}
#endif
/****************************************************************************/
static inline digit_t mp_getbit(digit_tc a[],
                                DWORDC ibit)
                /* Extract bit of multiple precision number */
{
    return digit_getbit(a[ibit/RADIX_BITS],  ibit % RADIX_BITS);
}

/******************************************************************************/
static inline int mp_jacobi_wrt_immediate(digit_tc  numer[],
                                          DWORD     lnumer,
                                          digit_tc  denom)
// Return jacobi(numer, denom), where denom is single precision
{
   digit_tc rem = divide_immediate(numer, denom,
                                   reciprocal_1_NULL,
                                   digit_NULL, lnumer);
   return digit_jacobi(rem, denom);
} /* mp_jacobi_wrt_immediate */
/***************************************************************************/
static inline DWORD mp_remove2(digit_t a[],
                               DWORDC lng)
/*
        mp_remove2 divides -a- by a power of 2 as large as possible
        (i.e., keep dividing by 2 until a is odd).
*/
{
    int nzero;
    digit_tc a0 = a[0];
    if (a0 == 0) {
        nzero = mp_trailing_zero_count(a, lng);
        mp_longshift(a, -nzero, a, lng);
    } else {
        nzero = trailing_zero_count(a0);
        if (nzero != 0) {
            DWORD i;
            digit_t carried_bits = DIGIT_ZERO;
            for (i = lng-1; i != -1; i--) {
                digit_tc anew = (a[i] >> nzero) | carried_bits;
                carried_bits = a[i] << (RADIX_BITS - nzero);
                a[i] = anew;
            }
        }
    }
    return (DWORD)nzero;
}  /* mp_remove2 */
/****************************************************************************/
static inline void mp_setbit(digit_t   a[],
                             DWORDC    ibit,
                             digit_tc  new_value)
/*
        Set a bit to 0 or 1,
        when the number is viewed as a bit array.
*/

{
    DWORDC j       = ibit / RADIX_BITS;
    DWORDC ishift  = ibit % RADIX_BITS;

    digit_tc mask1 = (DIGIT_ONE &  new_value) << ishift;
    digit_tc mask2 = (DIGIT_ONE & ~new_value) << ishift;

    a[j] = (a[j] & ~mask2) | mask1;
}
/****************************************************************************/
#if MEMORY_BANK_ALLOWANCE == 0
#define Preferred_Memory_Bank(new_array, old_array) new_array
#else
static inline digit_t* Preferred_Memory_Bank(digit_t  *new_array,
                                             digit_tc *old_array)
/*
        To avoid memory bank conflicts, it is desirable
        that (input) arguments to vmulxx assembly routines start
        on distinct memory banks, when not doing a squaring.
        If MEMORY_BANK_ALLOWANCE > 0,
        then new_array should have MEMORY_BANK_ALLOWANCE
        extra entries at the end.  We return either
        new_array or new_array + 1, whichever ensures the
        addresses are distinct.

        CAUTION -- This routine does non-portable pointer manipulations.
*/
{
    return new_array + (1 & ~(old_array - new_array));
}
#endif
/****************************************************************************/
static inline void set_immediate(digit_t  a[],
                                 digit_tc ivalue,
                                 DWORDC   lnga)
{
   a[0] = ivalue;
   mp_clear(a + 1, lnga - 1);
}
/****************************************************************************/
static inline DWORD set_immediate_signed(digit_t     a[],
                                         signed long ivalue)
{
    a[0] = labs(ivalue);
    return (ivalue > 0) - (ivalue < 0);     /* Sign of result  -- -1, 0, +1  */
}
/****************************************************************************/
static inline DWORD significant_digit_count(digit_tc  a[],
                                            DWORDC    lng)
/*
        Return the number of significant digits in a.
        Function value is zero precisely when a == 0.
*/
#if USEASM_IX86
    #pragma warning(disable : 4035)      /* No return value */
{
                /*
                   We could use REPE SCASD,
                   but the REPE overhead is
                   four cycles/compare on the Pentium.
                   We would also need sld and cld.
                   It is shorter to use RISC instructions.
                   We anticipate that the leading term a[lng-1]
                   will usually be nonzero.
                */

    _asm {
        mov  eax,lng
        mov  edx,a
     label1:
        test eax,eax
        jz   label2             ; If nothing left in number, return 0

        mov  ecx,[edx+4*eax-4]
        dec  eax

        test ecx,ecx            ; Test leading digit
        jz   label1

        inc  eax                ; Nonzero element found; return old eax
     label2:
    }
}
    #pragma warning(default : 4035)
#else
{
    DWORD i = lng;

    while (i != 0 && a[i-1] == 0) i--;
    return i;
}  /* significant_digit_count */
#endif
#define all_zero(a, lng) (significant_digit_count(a, lng) == 0)
/****************************************************************************/
static inline digit_t sub_immediate(digit_tc  a[],
                                    digit_tc  isub,
                                    digit_t   b[],
                                    DWORDC    lng)
/*
        Compute b = a - isub, where isub has length 1.
        Both a and b have length lng.
        Function value is borrow out of leftmost digit in b.
*/
{
    return (lng == 0 ? isub : sub_diff(a, lng, &isub, 1, b));
}
/****************************************************************************/
static inline int trailing_zero_count(digit_tc d)
/*
        Given a nonzero integer d, this routine computes
        the largest integer n such that 2^n divides d.

        If d = 2^n * (2k + 1), then

                        d =     k *2^(n+1) + 2^n
                       -d = (-1-k)*2^(n+1) + 2^n

        The integers k and -1 - k are one's complements of
        each other, so d & (-d) = 2^n.  Once we determine
        2^n from d, we can get n via significant_bit_count.
*/
#if USEASM_IX86
    #pragma warning(disable : 4035)      /* No return value */
{
    _asm {
            mov  eax,d
            bsf  eax,eax            ; eax = index of rightmost nonzero bit
                                    ; BSF is slow on Pentium,
                                    ; but fast on Pentium Pro.
         }

}
    #pragma warning(default : 4035)
#else
{
    return significant_bit_count(d & (-d)) - 1;
}  /* trailing_zero_count */
#endif
/****************************************************************************/
static inline void digits_to_dwords(digit_tc  pdigit[],
                                    DWORD     pdword[],
                                    DWORDC    lng_dwords)
{
#if DWORDS_PER_DIGIT == 1
    mp_copy(pdigit, (digit_t*)pdword, lng_dwords);
#elif DWORDS_PER_DIGIT == 2
    DWORDC lng_half = lng_dwords >> 1;
    DWORD i;

    if (IS_ODD(lng_dwords)) {
        pdword[lng_dwords-1] = (DWORD)pdigit[lng_half];
    }
    for (i = 0; i != lng_half; i++) {
        digit_tc dig = pdigit[i];
        pdword[2*i    ] = (DWORD)dig;
        pdword[2*i + 1] = (DWORD)(dig >> DWORD_BITS);
    }
#else
    #error "Unexpected DWORDS_PER_DIGIT"
#endif
}  /* digits_to_dwords */
/****************************************************************************/
static inline void dwords_to_digits(DWORDC  pdword[],
                                    digit_t pdigit[],
                                    DWORDC  lng_dwords)
{
#if DWORDS_PER_DIGIT == 1
    mp_copy((digit_t*)pdword, pdigit, lng_dwords);
#elif DWORDS_PER_DIGIT == 2
    DWORDC lng_half = lng_dwords >> 1;
    DWORD i;

    if (IS_ODD(lng_dwords)) {
        pdigit[lng_half] = (digit_t)pdword[lng_dwords - 1];  // Zero fill
    }
    for (i = 0; i != lng_half; i++) {
        pdigit[i] =    ((digit_t)pdword[2*i+1] << DWORD_BITS)
                     |  (digit_t)pdword[2*i];
    }
#else
    #error "Unexpected DWORDS_PER_DIGIT"
#endif
}  /* dwords_to_digits */

#endif // RADIX_BITS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -