Exemplo n.º 1
0
/*********************************************************************
 * Function:        void BIGINTMod(BIGINT_DATA *n, BIGINT_DATA *m)
 *
 * PreCondition:    None
 *
 * Input:           *n: a pointer to the number
 *                    *m: a pointer to the modulus
 *                    
 * Output:          *n contains the modded number
 *                     i.e: *n = *n % *m
 *
 * Side Effects:    None
 *
 * Overview:        Call BigIntMod() to calculate the modulus of two
 *                    really big numbers.
 *
 * Note:            Supports at least 2048 bits
 ********************************************************************/
BIGINT_RESULT BIGINT_Mod(BIGINT_DATA *result, BIGINT_DATA *a, BIGINT_DATA *b)
{
    BIGINT_DATA_TYPE    *_iB, *_xB, *_iR, _wC;
    BIGINT_DATA_TYPE    *ptrMSBa, MSBb;
    BIGINT_DATA_TYPE_2  qHatInt;
    BIGINT_DATA         temp1;
    uint32_t            tempLen;

    union
    {
        BIGINT_DATA_TYPE v[2];
        BIGINT_DATA_TYPE_2 Val;
    } topTwoWords;

    if (result == b)
    {
        // We can't store the result in m
        return BIGINT_RESULT_INVALID_PARAMETER;
    }
    else if (result != a)
    {
        // The result buffer is a separate buffer from n
        BIGINT_Copy (result, a);
    }


    // Set up assembly pointers for m
    // _iB and _xB are limiters in the _mas function
    _iB = b->startAddress;
    _xB = BigIntMSB(b);

    // Find the starting MSBs
    ptrMSBa = BigIntMSB(result);
    MSBb = *_xB;

    temp1.startAddress = result->startAddress;
    temp1.bLength = result->bLength;

    // Find out how many bytes we need to shift and move the LSB up
    _iR = result->startAddress + ((BigIntMagnitudeDifference(result, b) - 1) * BIGINT_DATA_SIZE);

    // This loops while the order of magnitude (in words) of n > m
    // Each iteration modulos off one word of magnitude from n
    while(_iR >= (BIGINT_DATA_TYPE *)result->startAddress)
    {
        // Find qHat = MSBn:MSBn-1/MSBb
        topTwoWords.Val = *((BIGINT_DATA_TYPE_2*)(ptrMSBa - 1));
        qHatInt = topTwoWords.Val / MSBb;
        if(qHatInt > BIGINT_DATA_MAX)  
            qHatInt = BIGINT_DATA_MAX;

        // Once qHat is determined, we multiply M by qHat, shift it up
        // as many bytes as possible, and subtract the result.
        // In essence, qHat is a rough estimation of the quotient, divided
        // by a power of 2^8 (PIC18) or 2^16 (PIC24/dsPIC)
        
        // This implementation multiplies and subtracts in the same step
        // using a _mas function which saves about 30% of clock cycles.

        // Save the old MSB and set up the ASM pointers
        _wC = (BIGINT_DATA_TYPE)qHatInt;

        // Do the multiply and subtract
        // Occassionally this results in underflow...this is solved below.
        _masBI(_xB, _iB, _wC, _iR);

        // qHat may have been 1 or 2 greater than possible.  If so,
        // the new MSB will be greater than the old one, so we *add*
        // M back to N in the shifted position until overflow occurs
        // and this case corrects itself.
        while(topTwoWords.v[1] < *ptrMSBa)
        {
            tempLen = result->bLength;
            result->bLength = (BigIntMSB(result) - _iR + 1) * BIGINT_DATA_SIZE;
            result->startAddress = _iR;

            _addBI(result,b);

            result->startAddress = temp1.startAddress;
            result->bLength = tempLen;
        }

        // We should have modulated off a word (or two if we were lucky),
        // so move our MSB and LSB pointers as applicable
        while(*ptrMSBa == 0x0u)
        {
            _iR--;
            result->bLength -= 2;
            ptrMSBa--;
        }
    }

    // Iteration of the _mas function can only handle full-byte orders
    // of magnitude.  The result may still be a little larger, so this
    // cleans up the last few multiples with simple subtraction.
    while(BIGINT_Compare(result, b) >= 0)
    {
//        _iA = result->startAddress;
//        _xA = result->startAddress + result->bLength - 1;

        _subBI(result,b);
    }

    result->startAddress = temp1.startAddress;
    result->bLength = temp1.bLength;

    return BIGINT_RESULT_OK;
}
Exemplo n.º 2
0
void BigIntMod(BIGINT *n, BIGINT* m)
{
	BIGINT_DATA_TYPE *ptrMSBn, MSBm;
	BIGINT_DATA_TYPE_2 qHatInt;
	union
	{
		BIGINT_DATA_TYPE v[2];
		BIGINT_DATA_TYPE_2 Val;
	} topTwoWords;

	// Find the starting MSBs
	ptrMSBn = BigIntMSB(n);
	MSBm = *BigIntMSB(m);

	// Set up assembly pointers for m
	// _iB and _xB are limiters in the _mas function
	_iB = m->ptrLSB;
	_xB = BigIntMSB(m);

	// Find out how many bytes we need to shift and move the LSB up
	_iR = n->ptrLSB + (BigIntMagnitudeDifference(n, m) - 1);

	// This loops while the order of magnitude (in words) of n > m
	// Each iteration modulos off one word of magnitude from n
	while(_iR >= n->ptrLSB)
	{
		// Find qHat = MSBn:MSBn-1/MSBm
		topTwoWords.Val = *((BIGINT_DATA_TYPE_2*)(ptrMSBn - 1));
		qHatInt = topTwoWords.Val / MSBm;
		if(qHatInt > BIGINT_DATA_MAX)  
			qHatInt = BIGINT_DATA_MAX;

#if BIGINT_DEBUG
		putrsUART("\r\n\r\n    n = ");
		BigIntPrint(n);
		putrsUART("\r\n    m = ");
		BigIntPrint(m);
		putrsUART("\r\n    qHat (");
		putulhexUART(qHatInt);
		putrsUART(") = topTwo(");
		putulhexUART(topTwoWords.Val);
		putrsUART(") / (");
		putulhexUART(MSBm);
		putrsUART(") ");
#endif

		// Once qHat is determined, we multiply M by qHat, shift it up
		// as many bytes as possible, and subtract the result.
		// In essence, qHat is a rough estimation of the quotient, divided
		// by a power of 2^8 (PIC18) or 2^16 (PIC24/dsPIC) or 2^32 (PIC32)
		
		// This implementation multiplies and subtracts in the same step
		// using a _mas function which saves about 30% of clock cycles.

		// Save the old MSB and set up the ASM pointers
		_wC = (BIGINT_DATA_TYPE)qHatInt;

		// Do the multiply and subtract
		// Occassionally this results in underflow...this is solved below.
		masBI();

		// qHat may have been 1 or 2 greater than possible.  If so,
		// the new MSB will be greater than the old one, so we *add*
		// M back to N in the shifted position until overflow occurs
		// and this case corrects itself.
		while(topTwoWords.v[1] < *BigIntMSB(n))
//		while(((BIGINT_DATA_TYPE*)&topTwoWords)[1] < *BigIntMSB(n))
		{
			_iA = _iR;
			_xA = BigIntMSB(n);
			addBI();
		}

		// We should have modulated off a word (or two if we were lucky),
		// so move our MSB and LSB pointers as applicable
		while(*ptrMSBn == 0x0u)
		{
			_iR--;
			n->ptrMSB--;
			ptrMSBn--;
		}
	}

	// Iteration of the _mas function can only handle full-byte orders
	// of magnitude.  The result may still be a little larger, so this
	// cleans up the last few multiples with simple subtraction.
	while(BigIntCompare(n, m) >= 0)
	{
		_iA = n->ptrLSB;
		_xA = n->ptrMSB;
		subBI();
	
		// Invalidate MSB pointer
		n->bMSBValid = 0;
	}
}