sl@0: /* sl@0: * Copyright (c) 2003-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "words.h" sl@0: #include "algorithms.h" sl@0: #include "windowslider.h" sl@0: #include "stackinteger.h" sl@0: #include "mont.h" sl@0: sl@0: sl@0: /** sl@0: * Creates a new buffer containing the big-endian binary representation of this sl@0: * integer. sl@0: * sl@0: * Note that it does not support the exporting of negative integers. sl@0: * sl@0: * @return The new buffer. sl@0: * sl@0: * @leave KErrNegativeExportNotSupported If this instance is a negative integer. sl@0: * sl@0: */ sl@0: EXPORT_C HBufC8* TInteger::BufferLC() const sl@0: { sl@0: if(IsNegative()) sl@0: { sl@0: User::Leave(KErrNegativeExportNotSupported); sl@0: } sl@0: TUint bytes = ByteCount(); sl@0: HBufC8* buf = HBufC8::NewMaxLC(bytes); sl@0: TUint8* bufPtr = (TUint8*)(buf->Ptr()); sl@0: TUint8* regPtr = (TUint8*)Ptr(); sl@0: sl@0: // we internally store the number little endian, as a string we want it big sl@0: // endian sl@0: for(TUint i=0,j=bytes-1; iPtr()); sl@0: TUint8* regPtr = (TUint8*)Ptr(); sl@0: for(TUint i=0,j=bytes-1; i(KBigintZero); sl@0: } sl@0: sl@0: /** sl@0: * Gets the TInteger that represents one sl@0: * sl@0: * @return The TInteger representing one sl@0: */ sl@0: EXPORT_C const TInteger& TInteger::One(void) sl@0: { sl@0: return *reinterpret_cast(KBigintOne); sl@0: } sl@0: sl@0: /** sl@0: * Gets the TInteger that represents two sl@0: * sl@0: * @return The TInteger representing two sl@0: */ sl@0: EXPORT_C const TInteger& TInteger::Two(void) sl@0: { sl@0: return *reinterpret_cast(KBigintTwo); sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::PlusL(const TInteger& aOperand) const sl@0: { sl@0: RInteger sum; sl@0: if (NotNegative()) sl@0: { sl@0: if (aOperand.NotNegative()) sl@0: sum = PositiveAddL(*this, aOperand); sl@0: else sl@0: sum = PositiveSubtractL(*this, aOperand); sl@0: } sl@0: else sl@0: { sl@0: if (aOperand.NotNegative()) sl@0: sum = PositiveSubtractL(aOperand, *this); sl@0: else sl@0: { sl@0: sum = PositiveAddL(*this, aOperand); sl@0: sum.SetSign(TInteger::ENegative); sl@0: } sl@0: } sl@0: return sum; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::MinusL(const TInteger& aOperand) const sl@0: { sl@0: RInteger diff; sl@0: if (NotNegative()) sl@0: { sl@0: if (aOperand.NotNegative()) sl@0: diff = PositiveSubtractL(*this, aOperand); sl@0: else sl@0: diff = PositiveAddL(*this, aOperand); sl@0: } sl@0: else sl@0: { sl@0: if (aOperand.NotNegative()) sl@0: { sl@0: diff = PositiveAddL(*this, aOperand); sl@0: diff.SetSign(TInteger::ENegative); sl@0: } sl@0: else sl@0: diff = PositiveSubtractL(aOperand, *this); sl@0: } sl@0: return diff; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::TimesL(const TInteger& aOperand) const sl@0: { sl@0: RInteger product = PositiveMultiplyL(*this, aOperand); sl@0: sl@0: if (NotNegative() != aOperand.NotNegative()) sl@0: { sl@0: product.Negate(); sl@0: } sl@0: return product; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::DividedByL(const TInteger& aOperand) const sl@0: { sl@0: RInteger quotient; sl@0: RInteger remainder; sl@0: DivideL(remainder, quotient, *this, aOperand); sl@0: remainder.Close(); sl@0: return quotient; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::ModuloL(const TInteger& aOperand) const sl@0: { sl@0: RInteger remainder; sl@0: RInteger quotient; sl@0: DivideL(remainder, quotient, *this, aOperand); sl@0: quotient.Close(); sl@0: return remainder; sl@0: } sl@0: sl@0: EXPORT_C TUint TInteger::ModuloL(TUint aOperand) const sl@0: { sl@0: if(!aOperand) sl@0: { sl@0: User::Leave(KErrDivideByZero); sl@0: } sl@0: return Modulo(*this, aOperand); sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::ModularMultiplyL(const TInteger& aA, const TInteger& aB, sl@0: const TInteger& aMod) sl@0: { sl@0: RInteger product = aA.TimesL(aB); sl@0: CleanupStack::PushL(product); sl@0: RInteger reduced = product.ModuloL(aMod); sl@0: CleanupStack::PopAndDestroy(&product); sl@0: return reduced; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::ModularExponentiateL(const TInteger& aBase, sl@0: const TInteger& aExp, const TInteger& aMod) sl@0: { sl@0: CMontgomeryStructure* mont = CMontgomeryStructure::NewLC(aMod); sl@0: RInteger result = RInteger::NewL(mont->ExponentiateL(aBase, aExp)); sl@0: CleanupStack::PopAndDestroy(mont); sl@0: return result; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::GCDL(const TInteger& aOperand) const sl@0: { sl@0: //Binary GCD algorithm -- see HAC 14.4.1 sl@0: //with a slight variation -- our g counts shifts rather than actually sl@0: //shifting. We then do one shift at the end. sl@0: assert(NotNegative()); sl@0: assert(aOperand.NotNegative()); sl@0: sl@0: RInteger x = RInteger::NewL(*this); sl@0: CleanupStack::PushL(x); sl@0: RInteger y = RInteger::NewL(aOperand); sl@0: CleanupStack::PushL(y); sl@0: sl@0: // 1 Ensure x >= y sl@0: if( x < y ) sl@0: { sl@0: TClassSwap(x, y); sl@0: } sl@0: sl@0: TUint g = 0; sl@0: // 2 while x and y even x <- x/2, y <- y/2 sl@0: while( x.IsEven() && y.IsEven() ) sl@0: { sl@0: x >>= 1; sl@0: y >>= 1; sl@0: ++g; sl@0: } sl@0: // 3 while x != 0 sl@0: while( x.NotZero() ) sl@0: { sl@0: // 3.1 while x even x <- x/2 sl@0: while( x.IsEven() ) sl@0: { sl@0: x >>= 1; sl@0: } sl@0: // 3.2 while y even y <- y/2 sl@0: while( y.IsEven() ) sl@0: { sl@0: y >>= 1; sl@0: } sl@0: // 3.3 t <- abs(x-y)/2 sl@0: RInteger t = x.MinusL(y); sl@0: t >>= 1; sl@0: t.SetSign(TInteger::EPositive); sl@0: sl@0: // 3.4 If x>=y then x <- t else y <- t sl@0: if( x >= y ) sl@0: { sl@0: x.Set(t); sl@0: } sl@0: else sl@0: { sl@0: y.Set(t); sl@0: } sl@0: } sl@0: sl@0: // 4 Return (g*y) (equiv to y<<=g as our g was counting shifts not actually sl@0: //shifting) sl@0: y <<= g; sl@0: CleanupStack::Pop(&y); sl@0: CleanupStack::PopAndDestroy(&x); sl@0: return y; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::InverseModL(const TInteger& aMod) const sl@0: { sl@0: assert(aMod.NotNegative()); sl@0: sl@0: RInteger result; sl@0: if(IsNegative() || *this>=aMod) sl@0: { sl@0: RInteger temp = ModuloL(aMod); sl@0: CleanupClosePushL(temp); sl@0: result = temp.InverseModL(aMod); sl@0: CleanupStack::PopAndDestroy(&temp); sl@0: return result; sl@0: } sl@0: sl@0: if(aMod.IsEven()) sl@0: { sl@0: if( !aMod || IsEven() ) sl@0: { sl@0: return RInteger::NewL(Zero()); sl@0: } sl@0: if( *this == One() ) sl@0: { sl@0: return RInteger::NewL(One()); sl@0: } sl@0: RInteger u = aMod.InverseModL(*this); sl@0: CleanupClosePushL(u); sl@0: if(!u) sl@0: { sl@0: result = RInteger::NewL(Zero()); sl@0: } sl@0: else sl@0: { sl@0: //calculates (aMod*(*this-u)+1)/(*this) sl@0: result = MinusL(u); sl@0: CleanupClosePushL(result); sl@0: result *= aMod; sl@0: ++result; sl@0: result /= *this; sl@0: CleanupStack::Pop(&result); sl@0: } sl@0: CleanupStack::PopAndDestroy(&u); sl@0: return result; sl@0: } sl@0: sl@0: result = RInteger::NewEmptyL(aMod.Size()); sl@0: CleanupClosePushL(result); sl@0: RInteger workspace = RInteger::NewEmptyL(aMod.Size() * 4); sl@0: TUint k = AlmostInverse(result.Ptr(), workspace.Ptr(), Ptr(), Size(), sl@0: aMod.Ptr(), aMod.Size()); sl@0: DivideByPower2Mod(result.Ptr(), result.Ptr(), k, aMod.Ptr(), aMod.Size()); sl@0: workspace.Close(); sl@0: CleanupStack::Pop(&result); sl@0: sl@0: return result; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator+=(const TInteger& aOperand) sl@0: { sl@0: this->Set(PlusL(aOperand)); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator-=(const TInteger& aOperand) sl@0: { sl@0: this->Set(MinusL(aOperand)); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator*=(const TInteger& aOperand) sl@0: { sl@0: this->Set(TimesL(aOperand)); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator/=(const TInteger& aOperand) sl@0: { sl@0: this->Set(DividedByL(aOperand)); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator%=(const TInteger& aOperand) sl@0: { sl@0: this->Set(ModuloL(aOperand)); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator+=(TInt aOperand) sl@0: { sl@0: TStackInteger64 operand(aOperand); sl@0: *this += operand; sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator-=(TInt aOperand) sl@0: { sl@0: TStackInteger64 operand(aOperand); sl@0: *this -= operand; sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator*=(TInt aOperand) sl@0: { sl@0: TStackInteger64 operand(aOperand); sl@0: *this *= operand; sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator--() sl@0: { sl@0: if (IsNegative()) sl@0: { sl@0: if (Increment(Ptr(), Size())) sl@0: { sl@0: CleanGrowL(2*Size()); sl@0: (Ptr())[Size()/2]=1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (Decrement(Ptr(), Size())) sl@0: { sl@0: this->CopyL(-1); sl@0: } sl@0: } sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator++() sl@0: { sl@0: if(NotNegative()) sl@0: { sl@0: if(Increment(Ptr(), Size())) sl@0: { sl@0: CleanGrowL(2*Size()); sl@0: (Ptr())[Size()/2]=1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: DecrementNoCarry(Ptr(), Size()); sl@0: if(WordCount()==0) sl@0: { sl@0: this->CopyL(Zero()); sl@0: } sl@0: } sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator <<=(TUint aBits) sl@0: { sl@0: const TUint wordCount = WordCount(); sl@0: const TUint shiftWords = aBits / WORD_BITS; sl@0: const TUint shiftBits = aBits % WORD_BITS; sl@0: sl@0: CleanGrowL(wordCount+BitsToWords(aBits)); sl@0: ShiftWordsLeftByWords(Ptr(), wordCount + shiftWords, shiftWords); sl@0: ShiftWordsLeftByBits(Ptr()+shiftWords, wordCount + BitsToWords(shiftBits), sl@0: shiftBits); sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator >>=(TUint aBits) sl@0: { sl@0: const TUint wordCount = WordCount(); sl@0: const TUint shiftWords = aBits / WORD_BITS; sl@0: const TUint shiftBits = aBits % WORD_BITS; sl@0: sl@0: ShiftWordsRightByWords(Ptr(), wordCount, shiftWords); sl@0: if(wordCount > shiftWords) sl@0: { sl@0: ShiftWordsRightByBits(Ptr(), wordCount - shiftWords, shiftBits); sl@0: } sl@0: if(IsNegative() && WordCount()==0) // avoid negative 0 sl@0: { sl@0: SetSign(EPositive); sl@0: } sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInt TInteger::UnsignedCompare(const TInteger& aThat) const sl@0: { sl@0: TUint size = WordCount(); sl@0: TUint thatSize = aThat.WordCount(); sl@0: sl@0: if( size == thatSize ) sl@0: return Compare(Ptr(), aThat.Ptr(), size); sl@0: else sl@0: return size > thatSize ? 1 : -1; sl@0: } sl@0: sl@0: EXPORT_C TInt TInteger::SignedCompare(const TInteger& aThat) const sl@0: { sl@0: if (NotNegative()) sl@0: { sl@0: if (aThat.NotNegative()) sl@0: return UnsignedCompare(aThat); sl@0: else sl@0: return 1; sl@0: } sl@0: else sl@0: { sl@0: if (aThat.NotNegative()) sl@0: return -1; sl@0: else sl@0: return -UnsignedCompare(aThat); sl@0: } sl@0: } sl@0: sl@0: EXPORT_C TBool TInteger::operator!() const sl@0: { sl@0: //Ptr()[0] is just a quick way of weeding out non-zero numbers without sl@0: //doing a full WordCount() == 0. Very good odds that a non-zero number sl@0: //will have a bit set in the least significant word sl@0: return IsNegative() ? EFalse : (Ptr()[0]==0 && WordCount()==0); sl@0: } sl@0: sl@0: EXPORT_C TInt TInteger::SignedCompare(TInt aInteger) const sl@0: { sl@0: TStackInteger64 temp(aInteger); sl@0: return SignedCompare(temp); sl@0: } sl@0: sl@0: /* TBool IsPrimeL(void) const sl@0: * and all primality related functions are implemented in primes.cpp */ sl@0: sl@0: EXPORT_C TBool TInteger::Bit(TUint aBitPos) const sl@0: { sl@0: if( aBitPos/WORD_BITS >= Size() ) sl@0: { sl@0: return 0; sl@0: } sl@0: else sl@0: { sl@0: return (((Ptr())[aBitPos/WORD_BITS] >> (aBitPos % WORD_BITS)) & 1); sl@0: } sl@0: } sl@0: sl@0: EXPORT_C void TInteger::SetBit(TUint aBitPos) sl@0: { sl@0: if( aBitPos/WORD_BITS < Size() ) sl@0: { sl@0: ArraySetBit(Ptr(), aBitPos); sl@0: } sl@0: } sl@0: sl@0: EXPORT_C void TInteger::Negate() sl@0: { sl@0: if(!!(*this)) //don't flip sign if *this==0 sl@0: { sl@0: SetSign(TSign((~Sign())&KSignMask)); sl@0: } sl@0: } sl@0: sl@0: EXPORT_C void TInteger::CopyL(const TInteger& aInteger, TBool aAllowShrink) sl@0: { sl@0: if(aAllowShrink) sl@0: { sl@0: CleanResizeL(aInteger.Size()); sl@0: } sl@0: else sl@0: { sl@0: CleanGrowL(aInteger.Size()); sl@0: } sl@0: Construct(aInteger); sl@0: } sl@0: sl@0: EXPORT_C void TInteger::CopyL(TInt aInteger, TBool aAllowShrink) sl@0: { sl@0: if(aAllowShrink) sl@0: { sl@0: CleanResizeL(2); sl@0: } sl@0: else sl@0: { sl@0: CleanGrowL(2); sl@0: } sl@0: Construct(aInteger); sl@0: } sl@0: sl@0: EXPORT_C void TInteger::Set(const RInteger& aInteger) sl@0: { sl@0: assert(IsHeapBased()); sl@0: Mem::FillZ(Ptr(), WordsToBytes(Size())); sl@0: User::Free(Ptr()); sl@0: iPtr = aInteger.iPtr; sl@0: iSize = aInteger.iSize; sl@0: } sl@0: sl@0: RInteger TInteger::PositiveAddL(const TInteger &aA, const TInteger& aB) const sl@0: { sl@0: RInteger sum = RInteger::NewEmptyL(CryptoMax(aA.Size(), aB.Size())); sl@0: const word aSize = aA.Size(); sl@0: const word bSize = aB.Size(); sl@0: const word* const aReg = aA.Ptr(); sl@0: const word* const bReg = aB.Ptr(); sl@0: word* const sumReg = sum.Ptr(); sl@0: sl@0: word carry; sl@0: if (aSize == bSize) sl@0: carry = Add(sumReg, aReg, bReg, aSize); sl@0: else if (aSize > bSize) sl@0: { sl@0: carry = Add(sumReg, aReg, bReg, bSize); sl@0: CopyWords(sumReg+bSize, aReg+bSize, aSize-bSize); sl@0: carry = Increment(sumReg+bSize, aSize-bSize, carry); sl@0: } sl@0: else sl@0: { sl@0: carry = Add(sumReg, aReg, bReg, aSize); sl@0: CopyWords(sumReg+aSize, bReg+aSize, bSize-aSize); sl@0: carry = Increment(sumReg+aSize, bSize-aSize, carry); sl@0: } sl@0: sl@0: if (carry) sl@0: { sl@0: CleanupStack::PushL(sum); sl@0: sum.CleanGrowL(2*sum.Size()); sl@0: CleanupStack::Pop(&sum); sl@0: sum.Ptr()[sum.Size()/2] = 1; sl@0: } sl@0: sum.SetSign(TInteger::EPositive); sl@0: return sum; sl@0: } sl@0: sl@0: RInteger TInteger::PositiveSubtractL(const TInteger &aA, const TInteger& aB) const sl@0: { sl@0: RInteger diff = RInteger::NewEmptyL(CryptoMax(aA.Size(), aB.Size())); sl@0: unsigned aSize = aA.WordCount(); sl@0: aSize += aSize%2; sl@0: unsigned bSize = aB.WordCount(); sl@0: bSize += bSize%2; sl@0: const word* const aReg = aA.Ptr(); sl@0: const word* const bReg = aB.Ptr(); sl@0: word* const diffReg = diff.Ptr(); sl@0: sl@0: if (aSize == bSize) sl@0: { sl@0: if (Compare(aReg, bReg, aSize) >= 0) sl@0: { sl@0: Subtract(diffReg, aReg, bReg, aSize); sl@0: diff.SetSign(TInteger::EPositive); sl@0: } sl@0: else sl@0: { sl@0: Subtract(diffReg, bReg, aReg, aSize); sl@0: diff.SetSign(TInteger::ENegative); sl@0: } sl@0: } sl@0: else if (aSize > bSize) sl@0: { sl@0: word borrow = Subtract(diffReg, aReg, bReg, bSize); sl@0: CopyWords(diffReg+bSize, aReg+bSize, aSize-bSize); sl@0: borrow = Decrement(diffReg+bSize, aSize-bSize, borrow); sl@0: assert(!borrow); sl@0: diff.SetSign(TInteger::EPositive); sl@0: } sl@0: else sl@0: { sl@0: word borrow = Subtract(diffReg, bReg, aReg, aSize); sl@0: CopyWords(diffReg+aSize, bReg+aSize, bSize-aSize); sl@0: borrow = Decrement(diffReg+aSize, bSize-aSize, borrow); sl@0: assert(!borrow); sl@0: diff.SetSign(TInteger::ENegative); sl@0: } sl@0: return diff; sl@0: } sl@0: sl@0: RInteger TInteger::PositiveMultiplyL(const TInteger &aA, const TInteger &aB) const sl@0: { sl@0: unsigned aSize = RoundupSize(aA.WordCount()); sl@0: unsigned bSize = RoundupSize(aB.WordCount()); sl@0: sl@0: RInteger product = RInteger::NewEmptyL(aSize+bSize); sl@0: CleanupClosePushL(product); sl@0: sl@0: RInteger workspace = RInteger::NewEmptyL(aSize + bSize); sl@0: AsymmetricMultiply(product.Ptr(), workspace.Ptr(), aA.Ptr(), aSize, aB.Ptr(), sl@0: bSize); sl@0: workspace.Close(); sl@0: CleanupStack::Pop(&product); sl@0: return product; sl@0: } sl@0: sl@0: TUint TInteger::Modulo(const TInteger& aDividend, TUint aDivisor) const sl@0: { sl@0: assert(aDivisor); sl@0: TUint i = aDividend.WordCount(); sl@0: TUint remainder = 0; sl@0: while(i--) sl@0: { sl@0: remainder = TUint(MAKE_DWORD(aDividend.Ptr()[i], remainder) % aDivisor); sl@0: } sl@0: return remainder; sl@0: } sl@0: sl@0: void TInteger::PositiveDivideL(RInteger &aRemainder, RInteger &aQuotient, sl@0: const TInteger &aDividend, const TInteger &aDivisor) const sl@0: { sl@0: unsigned dividendSize = aDividend.WordCount(); sl@0: unsigned divisorSize = aDivisor.WordCount(); sl@0: sl@0: if (!divisorSize) sl@0: { sl@0: User::Leave(KErrDivideByZero); sl@0: } sl@0: sl@0: if (aDividend.UnsignedCompare(aDivisor) == -1) sl@0: { sl@0: aRemainder.CreateNewL(aDividend.Size()); sl@0: CleanupStack::PushL(aRemainder); sl@0: aRemainder.CopyL(aDividend); //set remainder to a sl@0: aRemainder.SetSign(TInteger::EPositive); sl@0: aQuotient.CleanNewL(2); //Set quotient to zero sl@0: CleanupStack::Pop(&aRemainder); sl@0: return; sl@0: } sl@0: sl@0: dividendSize += dividendSize%2; // round up to next even number sl@0: divisorSize += divisorSize%2; sl@0: sl@0: aRemainder.CleanNewL(divisorSize); sl@0: CleanupStack::PushL(aRemainder); sl@0: aQuotient.CleanNewL(dividendSize-divisorSize+2); sl@0: CleanupStack::PushL(aQuotient); sl@0: sl@0: RInteger T = RInteger::NewEmptyL(dividendSize+2*divisorSize+4); sl@0: Divide(aRemainder.Ptr(), aQuotient.Ptr(), T.Ptr(), aDividend.Ptr(), sl@0: dividendSize, aDivisor.Ptr(), divisorSize); sl@0: T.Close(); sl@0: CleanupStack::Pop(2, &aRemainder); //aQuotient, aRemainder sl@0: } sl@0: sl@0: void TInteger::DivideL(RInteger& aRemainder, RInteger& aQuotient, sl@0: const TInteger& aDividend, const TInteger& aDivisor) const sl@0: { sl@0: PositiveDivideL(aRemainder, aQuotient, aDividend, aDivisor); sl@0: sl@0: if (aDividend.IsNegative()) sl@0: { sl@0: aQuotient.Negate(); sl@0: if (aRemainder.NotZero()) sl@0: { sl@0: --aQuotient; sl@0: assert(aRemainder.Size() <= aDivisor.Size()); sl@0: Subtract(aRemainder.Ptr(), aDivisor.Ptr(), aRemainder.Ptr(), sl@0: aRemainder.Size()); sl@0: } sl@0: } sl@0: sl@0: if (aDivisor.IsNegative()) sl@0: aQuotient.Negate(); sl@0: } sl@0: sl@0: void TInteger::RandomizeL(TUint aBits, TRandomAttribute aAttr) sl@0: { sl@0: if(!aBits) sl@0: { sl@0: return; sl@0: } sl@0: const TUint bytes = BitsToBytes(aBits); sl@0: const TUint words = BitsToWords(aBits); sl@0: CleanGrowL(words); sl@0: TPtr8 buf((TUint8*)(Ptr()), bytes, WordsToBytes(Size())); sl@0: TUint bitpos = aBits % BYTE_BITS; sl@0: TRAPD(err, GenerateRandomBytesL(buf)); sl@0: if((err != KErrNone) && (err != KErrNotSecure)) sl@0: User::Leave(err); sl@0: //mask with 0 all bits above the num requested in the most significant byte sl@0: if(bitpos) sl@0: { sl@0: buf[bytes-1] = TUint8( buf[bytes-1] & ((1L << bitpos) - 1) ); sl@0: } sl@0: //set most significant (top) bit sl@0: if(aAttr == ETopBitSet || aAttr == ETop2BitsSet) sl@0: { sl@0: SetBit(aBits-1); //Set bit counts from 0 sl@0: assert(BitCount() == aBits); sl@0: assert(Bit(aBits-1)); sl@0: } sl@0: //set 2nd bit from top sl@0: if(aAttr == ETop2BitsSet) sl@0: { sl@0: SetBit(aBits-2); //Set bit counts from 0 sl@0: assert(BitCount() == aBits); sl@0: assert(Bit(aBits-1)); sl@0: assert(Bit(aBits-2)); sl@0: } sl@0: } sl@0: sl@0: void TInteger::RandomizeL(const TInteger& aMin, const TInteger& aMax) sl@0: { sl@0: assert(aMax > aMin); sl@0: assert(aMin.NotNegative()); sl@0: RInteger range = RInteger::NewL(aMax); sl@0: CleanupStack::PushL(range); sl@0: range -= aMin; sl@0: const TUint bits = range.BitCount(); sl@0: sl@0: //if we find a number < range then aMin+range < aMax sl@0: do sl@0: { sl@0: RandomizeL(bits, EAllBitsRandom); sl@0: } sl@0: while(*this > range); sl@0: sl@0: *this += aMin; sl@0: CleanupStack::PopAndDestroy(&range); sl@0: } sl@0: sl@0: /* void PrimeRandomizeL(TUint aBits, TRandomAttribute aAttr) sl@0: * and all primality related functions are implemented in primes.cpp */ sl@0: sl@0: void TInteger::CreateNewL(TUint aNewSize) sl@0: { sl@0: //should only be called on construction sl@0: assert(!iPtr); sl@0: sl@0: TUint newSize = RoundupSize(aNewSize); sl@0: SetPtr((TUint*)User::AllocL(WordsToBytes(newSize))); sl@0: SetSize(newSize); sl@0: SetHeapBased(); sl@0: } sl@0: sl@0: void TInteger::CleanNewL(TUint aNewSize) sl@0: { sl@0: CreateNewL(aNewSize); sl@0: Mem::FillZ(Ptr(), WordsToBytes(Size())); //clear integer storage sl@0: } sl@0: sl@0: void TInteger::CleanGrowL(TUint aNewSize) sl@0: { sl@0: assert(IsHeapBased()); sl@0: TUint newSize = RoundupSize(aNewSize); sl@0: TUint oldSize = Size(); sl@0: if(newSize > oldSize) sl@0: { sl@0: TUint* oldPtr = Ptr(); sl@0: //1) allocate new memory and set ptr and size sl@0: SetPtr((TUint*)User::AllocL(WordsToBytes(newSize))); sl@0: SetSize(newSize); sl@0: //2) copy old mem to new mem sl@0: Mem::Copy(Ptr(), oldPtr, WordsToBytes(oldSize)); sl@0: //3) zero all old memory sl@0: Mem::FillZ(oldPtr, WordsToBytes(oldSize)); sl@0: //4) give back old memory sl@0: User::Free(oldPtr); sl@0: //5) zero new memory from end of copy to end of growth sl@0: Mem::FillZ(Ptr() + oldSize, WordsToBytes(newSize-oldSize)); sl@0: } sl@0: } sl@0: sl@0: void TInteger::CleanResizeL(TUint aNewSize) sl@0: { sl@0: assert(IsHeapBased()); sl@0: TUint newSize = RoundupSize(aNewSize); sl@0: TUint oldSize = Size(); sl@0: if(newSize > oldSize) sl@0: { sl@0: CleanGrowL(aNewSize); sl@0: } sl@0: else if(newSize < oldSize) sl@0: { sl@0: TUint* oldPtr = Ptr(); sl@0: //1) zero memory above newsize sl@0: Mem::FillZ(oldPtr+WordsToBytes(aNewSize),WordsToBytes(oldSize-newSize)); sl@0: //2) ReAlloc cell. Since our newsize is less than oldsize, it is sl@0: //guarenteed not to move. Thus this is just freeing part of our old sl@0: //cell to the heap for other uses. sl@0: SetPtr((TUint*)User::ReAllocL(Ptr(), WordsToBytes(newSize))); sl@0: SetSize(newSize); sl@0: } sl@0: } sl@0: sl@0: EXPORT_C TInteger::TInteger() : iSize(0), iPtr(0) sl@0: { sl@0: } sl@0: sl@0: void TInteger::Construct(const TDesC8& aValue) sl@0: { sl@0: assert(Size() >= BytesToWords(aValue.Size())); sl@0: if(aValue.Size() > 0) sl@0: { sl@0: //People write numbers with the most significant digits first (big sl@0: //endian) but we store our numbers in little endian. Hence we need to sl@0: //reverse the string by bytes. sl@0: sl@0: TUint bytes = aValue.Size(); sl@0: TUint8* i = (TUint8*)Ptr(); sl@0: TUint8* j = (TUint8*)aValue.Ptr() + bytes; sl@0: sl@0: //Swap the endianess of the number itself sl@0: // (msb) 01 02 03 04 05 06 (lsb) becomes -> sl@0: // (lsb) 06 05 04 03 02 01 (msb) sl@0: while( j != (TUint8*)aValue.Ptr() ) sl@0: { sl@0: *i++ = *--j; sl@0: } sl@0: Mem::FillZ((TUint8*)Ptr() + bytes, WordsToBytes(Size()) - bytes); sl@0: } sl@0: else sl@0: { sl@0: //if size is zero, we zero the whole register sl@0: Mem::FillZ((TUint8*)Ptr(), WordsToBytes(Size())); sl@0: } sl@0: SetSign(EPositive); sl@0: } sl@0: sl@0: void TInteger::Construct(const TInteger& aInteger) sl@0: { sl@0: assert(Size() >= aInteger.Size()); sl@0: CopyWords(Ptr(), aInteger.Ptr(), aInteger.Size()); sl@0: if(Size() > aInteger.Size()) sl@0: { sl@0: Mem::FillZ(Ptr()+aInteger.Size(), WordsToBytes(Size()-aInteger.Size())); sl@0: } sl@0: SetSign(aInteger.Sign()); sl@0: } sl@0: sl@0: void TInteger::Construct(TInt aInteger) sl@0: { sl@0: Construct((TUint)aInteger); sl@0: if(aInteger < 0) sl@0: { sl@0: SetSign(ENegative); sl@0: Ptr()[0] = -aInteger; sl@0: } sl@0: } sl@0: sl@0: void TInteger::Construct(TUint aInteger) sl@0: { sl@0: assert(Size() >= 2); sl@0: SetSign(EPositive); sl@0: Ptr()[0] = aInteger; sl@0: Mem::FillZ(Ptr()+1, WordsToBytes(Size()-1)); sl@0: } sl@0: sl@0: void TInteger::ConstructStack(TUint aWords, TUint aInteger) sl@0: { sl@0: SetPtr((TUint*)(this)+2); sl@0: //SetStackBased(); //Not strictly needed as stackbased is a 0 at bit 1 sl@0: SetSize(aWords); sl@0: assert(Size() >= 2); sl@0: Ptr()[0] = aInteger; sl@0: Mem::FillZ(&(Ptr()[1]), WordsToBytes(Size()-1)); sl@0: } sl@0: sl@0: void TInteger::ConstructStack(TUint aWords, const TInteger& aInteger) sl@0: { sl@0: SetPtr((TUint*)(this)+2); sl@0: //SetStackBased(); //Not strictly needed as stackbased is a 0 at bit 1 sl@0: SetSize(aWords); sl@0: assert( Size() >= RoundupSize(aInteger.WordCount()) ); sl@0: CopyWords(Ptr(), aInteger.Ptr(), aInteger.Size()); sl@0: Mem::FillZ(Ptr()+aInteger.Size(), WordsToBytes(Size()-aInteger.Size())); sl@0: } sl@0: sl@0: // Methods are excluded from coverage due to the problem with BullsEye on ONB. sl@0: // Manually verified that these methods are functionally covered. sl@0: #ifdef _BullseyeCoverage sl@0: #pragma suppress_warnings on sl@0: #pragma BullseyeCoverage off sl@0: #pragma suppress_warnings off sl@0: #endif sl@0: sl@0: EXPORT_C TInteger& TInteger::operator/=(TInt aOperand) sl@0: { sl@0: TStackInteger64 operand(aOperand); sl@0: *this /= operand; sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInteger& TInteger::operator%=(TInt aOperand) sl@0: { sl@0: TStackInteger64 operand(aOperand); sl@0: assert(operand.NotNegative()); sl@0: *this %= operand; sl@0: return *this; sl@0: } sl@0: sl@0: EXPORT_C TInt TInteger::ConvertToLongL(void) const sl@0: { sl@0: if(!IsConvertableToLong()) sl@0: { sl@0: User::Leave(KErrTotalLossOfPrecision); sl@0: } sl@0: return ConvertToLong(); sl@0: } sl@0: sl@0: TInt TInteger::ConvertToLong(void) const sl@0: { sl@0: TUint value = ConvertToUnsignedLong(); sl@0: return Sign() == EPositive ? value : -(static_cast(value)); sl@0: } sl@0: sl@0: TBool TInteger::IsConvertableToLong(void) const sl@0: { sl@0: if(WordCount() > 1) sl@0: { sl@0: return EFalse; sl@0: } sl@0: TUint value = (Ptr())[0]; sl@0: if(Sign() == EPositive) sl@0: { sl@0: return static_cast(value) >= 0; sl@0: } sl@0: else sl@0: { sl@0: return -(static_cast(value)) < 0; sl@0: } sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::SquaredL() const sl@0: { sl@0: //PositiveMultiplyL optimises for the squaring case already sl@0: //Any number squared is positive, no need for negative handling in TimesL sl@0: return PositiveMultiplyL(*this, *this); sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::DividedByL(TUint aOperand) const sl@0: { sl@0: TUint remainder; sl@0: RInteger quotient; sl@0: DivideL(remainder, quotient, *this, aOperand); sl@0: return quotient; sl@0: } sl@0: sl@0: EXPORT_C RInteger TInteger::ExponentiateL(const TInteger& aExponent) const sl@0: { sl@0: //See HAC 14.85 sl@0: sl@0: // 1.1 Precomputation sl@0: // g1 <- g sl@0: // g2 <- g^2 sl@0: RInteger g2 = SquaredL(); sl@0: CleanupStack::PushL(g2); sl@0: RInteger g1 = RInteger::NewL(*this); sl@0: CleanupStack::PushL(g1); sl@0: TWindowSlider slider(aExponent); sl@0: sl@0: // 1.2 sl@0: // For i from 1 to (2^(k-1) -1) do g2i+1 <- g2i-1 * g2 sl@0: TUint count = (1 << (slider.WindowSize()-1)) - 1; //2^(k-1) -1 sl@0: RRArray powerArray(count+1); //+1 because we append g1 sl@0: powerArray.AppendL(g1); sl@0: CleanupStack::Pop(); //g1 sl@0: CleanupClosePushL(powerArray); sl@0: for(TUint k=1; k <= count; k++) sl@0: { sl@0: RInteger g2iplus1 = g2.TimesL(powerArray[k-1]); sl@0: powerArray.AppendL(g2iplus1); sl@0: } sl@0: sl@0: // 2 A <- 1, i <- t sl@0: RInteger A = RInteger::NewL(One()); sl@0: CleanupStack::PushL(A); sl@0: TInt i = aExponent.BitCount() - 1; sl@0: sl@0: // 3 While i>=0 do: sl@0: while( i>=0 ) sl@0: { sl@0: // 3.1 If ei == 0 then A <- A^2 sl@0: if(!aExponent.Bit(i)) sl@0: { sl@0: A *= A; sl@0: i--; sl@0: } sl@0: // 3.2 Find longest bitstring ei,ei-1,...,el s.t. i-l+1<=k and el==1 sl@0: // and do: sl@0: // A <- (A^2^(i-l+1)) * g[the index indicated by the bitstring value] sl@0: else sl@0: { sl@0: slider.FindNextWindow(i); sl@0: assert(slider.Length() >= 1); sl@0: for(TUint j=0; j>1]; sl@0: i -= slider.Length(); sl@0: } sl@0: } sl@0: CleanupStack::Pop(&A); sl@0: CleanupStack::PopAndDestroy(2, &g2); //powerArray, g2 sl@0: return A; sl@0: } sl@0: sl@0: void TInteger::DivideL(TUint& aRemainder, RInteger& aQuotient, sl@0: const TInteger& aDividend, TUint aDivisor) const sl@0: { sl@0: if(!aDivisor) sl@0: { sl@0: User::Leave(KErrDivideByZero); sl@0: } sl@0: sl@0: TUint i = aDividend.WordCount(); sl@0: aQuotient.CleanNewL(RoundupSize(i)); sl@0: PositiveDivide(aRemainder, aQuotient, aDividend, aDivisor); sl@0: sl@0: if(aDividend.NotNegative()) sl@0: { sl@0: aQuotient.SetSign(TInteger::EPositive); sl@0: } sl@0: else sl@0: { sl@0: aQuotient.SetSign(TInteger::ENegative); sl@0: if(aRemainder) sl@0: { sl@0: --aQuotient; sl@0: aRemainder = aDivisor = aRemainder; sl@0: } sl@0: } sl@0: } sl@0: sl@0: void TInteger::PositiveDivide(TUint& aRemainder, TInteger& aQuotient, sl@0: const TInteger& aDividend, TUint aDivisor) const sl@0: { sl@0: assert(aDivisor); sl@0: sl@0: TUint i = aDividend.WordCount(); sl@0: assert(aQuotient.Size() >= RoundupSize(i)); sl@0: assert(aQuotient.Sign() == TInteger::EPositive); sl@0: aRemainder = 0; sl@0: while(i--) sl@0: { sl@0: aQuotient.Ptr()[i] = sl@0: TUint(MAKE_DWORD(aDividend.Ptr()[i], aRemainder) / aDivisor); sl@0: aRemainder = sl@0: TUint(MAKE_DWORD(aDividend.Ptr()[i], aRemainder) % aDivisor); sl@0: } sl@0: }