EXPORT_C RInteger TInteger::TimesL(const TInteger& aOperand) const { RInteger product = PositiveMultiplyL(*this, aOperand); if (NotNegative() != aOperand.NotNegative()) { product.Negate(); } return product; }
EXPORT_C TInteger& TInteger::operator++() { if(NotNegative()) { if(Increment(Ptr(), Size())) { CleanGrowL(2*Size()); (Ptr())[Size()/2]=1; } } else { DecrementNoCarry(Ptr(), Size()); if(WordCount()==0) { this->CopyL(Zero()); } } return *this; }
EXPORT_C RInteger TInteger::MinusL(const TInteger& aOperand) const { RInteger diff; if (NotNegative()) { if (aOperand.NotNegative()) diff = PositiveSubtractL(*this, aOperand); else diff = PositiveAddL(*this, aOperand); } else { if (aOperand.NotNegative()) { diff = PositiveAddL(*this, aOperand); diff.SetSign(TInteger::ENegative); } else diff = PositiveSubtractL(aOperand, *this); } return diff; }
EXPORT_C RInteger TInteger::PlusL(const TInteger& aOperand) const { RInteger sum; if (NotNegative()) { if (aOperand.NotNegative()) sum = PositiveAddL(*this, aOperand); else sum = PositiveSubtractL(*this, aOperand); } else { if (aOperand.NotNegative()) sum = PositiveSubtractL(aOperand, *this); else { sum = PositiveAddL(*this, aOperand); sum.SetSign(TInteger::ENegative); } } return sum; }
bool IsPositive() const { return NotNegative() && NotZero(); }
void TInteger::PrimeRandomizeL(TUint aBits, TRandomAttribute aAttr) { assert(aBits > 1); //"this" is "empty" currently. Consists of Size() words of 0's. This is just //checking that sign flag is positive as we don't set it later. assert(NotNegative()); //Flag for the whole function saying if we've found a prime TBool foundProbablePrime = EFalse; //Find 2^aBits + 1 -- any prime we find must be less than this. RInteger max = RInteger::NewEmptyL(BitsToWords(aBits)+1); CleanupStack::PushL(max); max.SetBit(aBits); assert(max.BitCount()-1 == aBits); // aBits | approx number of odd numbers you must try to have a 50% // chance of finding a prime //--------------------------------------------------------- // 512 | 122 // 1024 | 245 // 2048 | 1023 //Therefore if we are generating larger than 1024 bit numbers we'll use a //bigger bit array to have a better chance of avoiding re-generating it. TUint sLength = aBits > 1024 ? 1024 : 512; RInteger S = RInteger::NewEmptyL(BitsToWords(sLength)); CleanupStack::PushL(S); while(!foundProbablePrime) { //Randomly choose aBits RandomizeL(aBits, aAttr); //If the random number chosen is less than KSmallPrimeSquared, we have a //special set of routines. if(SmallPrimeRandomizeL()) { foundProbablePrime = ETrue; } else { //if it was <= KLastSmallPrimeSquared then it would have been //handled by SmallPrimeRandomizeL() assert(*this > KLastSmallPrimeSquared); //Make sure any number we bother testing is at least odd SetBit(0); //Ensure that this + 2*sLength < max RInteger temp = max.MinusL(*this); CleanupStack::PushL(temp); ++temp; temp >>=1; if(temp < sLength) { //if this + 2*sLength >= max then we use a smaller sLength to //ensure we don't find a number that is outside of our bounds //(and bigger than our allocated memory for this) //temp must be less than KMaxTUint as sLength is a TUint sLength = temp.ConvertToUnsignedLong(); } CleanupStack::PopAndDestroy(&temp); //Start at 1 as no point in checking against 2 (all odd numbers) for(TUint i=1; i<KPrimeTableSize; i++) { //no need to call ModuloL as we know KPrimeTable[i] is not 0 TUint remainder = Modulo(*this, KPrimeTable[i]); TUint index = FindSmallestIndex(KPrimeTable[i], remainder); EliminateComposites(S.Ptr(), KPrimeTable[i], index, sLength); } TInt j = FindFirstPrimeCandidate(S.Ptr(), sLength); TInt prev = 0; for(; j>=0; j=FindFirstPrimeCandidate(S.Ptr(), sLength)) { ArraySetBit(S.Ptr(), j); //should never carry as we earlier made sure that 2*j + this < max //where max is 1 bit more than we asked for. IncrementNoCarry(Ptr(), Size(), 2*(j-prev)); assert(*this < max); assert(!HasSmallDivisorL(*this)); prev = j; if( IsStrongProbablePrimeL(*this) ) { foundProbablePrime = ETrue; break; } } //This clears the memory S.CopyL(0, EFalse); } } CleanupStack::PopAndDestroy(2, &max); }
EXPORT_C RInteger TInteger::GCDL(const TInteger& aOperand) const { //Binary GCD algorithm -- see HAC 14.4.1 //with a slight variation -- our g counts shifts rather than actually //shifting. We then do one shift at the end. assert(NotNegative()); assert(aOperand.NotNegative()); RInteger x = RInteger::NewL(*this); CleanupStack::PushL(x); RInteger y = RInteger::NewL(aOperand); CleanupStack::PushL(y); // 1 Ensure x >= y if( x < y ) { TClassSwap(x, y); } TUint g = 0; // 2 while x and y even x <- x/2, y <- y/2 while( x.IsEven() && y.IsEven() ) { x >>= 1; y >>= 1; ++g; } // 3 while x != 0 while( x.NotZero() ) { // 3.1 while x even x <- x/2 while( x.IsEven() ) { x >>= 1; } // 3.2 while y even y <- y/2 while( y.IsEven() ) { y >>= 1; } // 3.3 t <- abs(x-y)/2 RInteger t = x.MinusL(y); t >>= 1; t.SetSign(TInteger::EPositive); // 3.4 If x>=y then x <- t else y <- t if( x >= y ) { x.Set(t); } else { y.Set(t); } } // 4 Return (g*y) (equiv to y<<=g as our g was counting shifts not actually //shifting) y <<= g; CleanupStack::Pop(&y); CleanupStack::PopAndDestroy(&x); return y; }