Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / BigInt.cs / 1 / BigInt.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- // // Copied from System.security.Cryptography.BigInt as the class was internal // using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; using System.Text; using System; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; using Microsoft.InfoCards.Diagnostics; namespace Microsoft.InfoCards { // // This is a pretty "crude" implementation of BigInt arithmetic operations. // This class is used in particular to convert certificate serial numbers from // hexadecimal representation to decimal format and vice versa. // // We are not very concerned about the perf characterestics of this implementation // for now. We perform all operations up to 128 bytes (which is enough for the current // purposes although this constant can be increased). Any overflow bytes are going to be lost. // // A BigInt is represented as a little endian byte array of size 128 bytes. All // arithmetic operations are performed in base 0x100 (256). The algorithms used // are simply the common primary school techniques for doing operations in base 10. // internal sealed class BigInt { private byte[ ] m_elements; private const int m_maxbytes = 128; // 128 bytes is the maximum we can handle. // This means any overflow bits beyond 128 bytes // will be lost when doing arithmetic operations. private const int m_base = 0x100; private int m_size = 0; internal BigInt() { m_elements = new byte[ m_maxbytes ]; } internal BigInt( byte[ ] b ) { m_elements = new byte[ m_maxbytes ]; Array.Copy( b, m_elements, b.Length ); m_size = b.Length; } internal BigInt( byte b ) { m_elements = new byte[ m_maxbytes ]; SetDigit( 0, b ); } // // Gets or sets the size of a BigInt. // internal int Size { get { return m_size; } set { m_size = value; if( value > m_maxbytes ) { m_size = m_maxbytes; } if( value < 0 ) { m_size = 0; } } } // // Gets the digit at the specified index. // internal byte GetDigit( int index ) { if( index < 0 || index >= m_size ) return 0; return m_elements[ index ]; } // // Sets the digit at the specified index. // internal void SetDigit( int index, byte digit ) { if( index >= 0 && index < m_maxbytes ) { m_elements[ index ] = digit; if( index >= m_size && digit != 0 ) m_size = ( index + 1 ); if( index == m_size - 1 && digit == 0 ) m_size--; } } internal void SetDigit( int index, byte digit, ref int size ) { if( index >= 0 && index < m_maxbytes ) { m_elements[ index ] = digit; if( index >= size && digit != 0 ) size = ( index + 1 ); if( index == size - 1 && digit == 0 ) size = ( size - 1 ); } } // // overloaded operators. // public static bool operator <( BigInt value1, BigInt value2 ) { if( value1 == null ) return true; else if( value2 == null ) return false; int Len1 = value1.Size; int Len2 = value2.Size; if( Len1 != Len2 ) return ( Len1 < Len2 ); while( Len1-- > 0 ) { if( value1.m_elements[ Len1 ] != value2.m_elements[ Len1 ] ) return ( value1.m_elements[ Len1 ] < value2.m_elements[ Len1 ] ); } return false; } public static bool operator >( BigInt value1, BigInt value2 ) { if( value1 == null ) return false; else if( value2 == null ) return true; int Len1 = value1.Size; int Len2 = value2.Size; if( Len1 != Len2 ) return ( Len1 > Len2 ); while( Len1-- > 0 ) { if( value1.m_elements[ Len1 ] != value2.m_elements[ Len1 ] ) return ( value1.m_elements[ Len1 ] > value2.m_elements[ Len1 ] ); } return false; } public static bool operator ==( BigInt value1, BigInt value2 ) { if( (Object)value1 == null ) return ( (Object)value2 == null ); else if( (Object)value2 == null ) return ( (Object)value1 == null ); int Len1 = value1.Size; int Len2 = value2.Size; if( Len1 != Len2 ) return false; for( int index = 0; index < Len1; index++ ) { if( value1.m_elements[ index ] != value2.m_elements[ index ] ) return false; } return true; } public static bool operator !=( BigInt value1, BigInt value2 ) { return !( value1 == value2 ); } public override bool Equals( Object obj ) { BigInt bi = obj as BigInt; if( null != bi ) { return bi == this; } return false; } public override int GetHashCode() { int hash = 0; for( int index = 0; index < m_size; index++ ) { hash += GetDigit( index ); } return hash; } // // Adds a and b and outputs the result in c. // internal static void Add( BigInt a, byte b, ref BigInt c ) { byte carry = b; int sum = 0; int size = a.Size; int newSize = 0; for( int index = 0; index < size; index++ ) { sum = a.GetDigit( index ) + carry; c.SetDigit( index, (byte)( sum & 0xFF ), ref newSize ); carry = (byte)( ( sum >> 8 ) & 0xFF ); } if( carry != 0 ) c.SetDigit( a.Size, carry, ref newSize ); c.Size = newSize; } // // Negates a BigInt value. Each byte is complemented, then we add 1 to it. // internal static void Negate( ref BigInt a ) { int newSize = 0; for( int index = 0; index < m_maxbytes; index++ ) { a.SetDigit( index, (byte)( ~a.GetDigit( index ) & 0xFF ), ref newSize ); } for( int index = 0; index < m_maxbytes; index++ ) { a.SetDigit( index, (byte)( a.GetDigit( index ) + 1 ), ref newSize ); if( ( a.GetDigit( index ) & 0xFF ) != 0 ) break; a.SetDigit( index, (byte)( a.GetDigit( index ) & 0xFF ), ref newSize ); } a.Size = newSize; } // // Subtracts b from a and outputs the result in c. // internal static void Subtract( BigInt a, BigInt b, ref BigInt c ) { byte borrow = 0; int diff = 0; if( a < b ) { Subtract( b, a, ref c ); Negate( ref c ); return; } int index = 0; int size = a.Size; int newSize = 0; for( index = 0; index < size; index++ ) { diff = a.GetDigit( index ) - b.GetDigit( index ) - borrow; borrow = 0; if( diff < 0 ) { diff += m_base; borrow = 1; } c.SetDigit( index, (byte)( diff & 0xFF ), ref newSize ); } c.Size = newSize; } // // multiplies a BigInt by an integer. // private void Multiply( int b ) { if( b == 0 ) { Clear(); return; } int carry = 0, product = 0; int size = this.Size; int newSize = 0; for( int index = 0; index < size; index++ ) { product = b * GetDigit( index ) + carry; carry = product / m_base; SetDigit( index, (byte)( product % m_base ), ref newSize ); } if( carry != 0 ) { byte[ ] bytes = BitConverter.GetBytes( carry ); for( int index = 0; index < bytes.Length; index++ ) { SetDigit( size + index, bytes[ index ], ref newSize ); } } this.Size = newSize; } private static void Multiply( BigInt a, int b, ref BigInt c ) { if( b == 0 ) { c.Clear(); return; } int carry = 0, product = 0; int size = a.Size; int newSize = 0; for( int index = 0; index < size; index++ ) { product = b * a.GetDigit( index ) + carry; carry = product / m_base; c.SetDigit( index, (byte)( product % m_base ), ref newSize ); } if( carry != 0 ) { byte[ ] bytes = BitConverter.GetBytes( carry ); for( int index = 0; index < bytes.Length; index++ ) { c.SetDigit( size + index, bytes[ index ], ref newSize ); } } c.Size = newSize; } // // Divides a BigInt by a single byte. // private void Divide( int b ) { int carry = 0, quotient = 0; int bLen = this.Size; int newSize = 0; while( bLen-- > 0 ) { quotient = m_base * carry + GetDigit( bLen ); carry = quotient % b; SetDigit( bLen, (byte)( quotient / b ), ref newSize ); } this.Size = newSize; } // // Integer division of one BigInt by another. // internal static void Divide( BigInt numerator, BigInt denominator, ref BigInt quotient, ref BigInt remainder ) { // Avoid extra computations in special cases. if( numerator < denominator ) { quotient.Clear(); remainder.CopyFrom( numerator ); return; } if( numerator == denominator ) { quotient.Clear(); quotient.SetDigit( 0, 1 ); remainder.Clear(); return; } BigInt dividend = new BigInt(); dividend.CopyFrom( numerator ); BigInt divisor = new BigInt(); divisor.CopyFrom( denominator ); uint zeroCount = 0; // We pad the divisor with zeros until its size equals that of the dividend. while( divisor.Size < dividend.Size ) { divisor.Multiply( m_base ); zeroCount++; } if( divisor > dividend ) { divisor.Divide( m_base ); zeroCount--; } // Use school division techniques, make a guess for how many times // divisor goes into dividend, making adjustment if necessary. int a = 0; int b = 0; int c = 0; BigInt hold = new BigInt(); quotient.Clear(); for( int index = 0; index <= zeroCount; index++ ) { a = dividend.Size == divisor.Size ? dividend.GetDigit( dividend.Size - 1 ) : m_base * dividend.GetDigit( dividend.Size - 1 ) + dividend.GetDigit( dividend.Size - 2 ); b = divisor.GetDigit( divisor.Size - 1 ); c = a / b; if( c >= m_base ) c = 0xFF; Multiply( divisor, c, ref hold ); while( hold > dividend ) { c--; Multiply( divisor, c, ref hold ); } quotient.Multiply( m_base ); Add( quotient, (byte)c, ref quotient ); Subtract( dividend, hold, ref dividend ); divisor.Divide( m_base ); } remainder.CopyFrom( dividend ); } // // copies a BigInt value. // internal void CopyFrom( BigInt a ) { Array.Copy( a.m_elements, m_elements, m_maxbytes ); m_size = a.m_size; } // // This method returns true if the BigInt is equal to 0, false otherwise. // internal bool IsZero() { for( int index = 0; index < m_size; index++ ) { if( m_elements[ index ] != 0 ) return false; } return true; } // // returns the array in machine format, i.e. little endian format (as an integer). // internal byte[ ] ToByteArray() { byte[ ] result = new byte[ this.Size ]; Array.Copy( m_elements, result, this.Size ); return result; } // // zeroizes the content of the internal array. // internal void Clear() { m_size = 0; } // // Imports a hexadecimal string into a BigInt bit representation. // // // Imports a decimal string into a BigInt bit representation. // internal void FromDecimal( string decNum ) { BigInt c = new BigInt(); BigInt tmp = new BigInt(); int length = decNum.Length; for( int index = 0; index < length; index++ ) { // check for invalid characters. if( decNum[ index ] > '9' || decNum[ index ] < '0' ) { throw IDT.ThrowHelperError( new FormatException() ); } Multiply( c, 10, ref tmp ); Add( tmp, (byte)( decNum[ index ] - '0' ), ref c ); } CopyFrom( c ); } // // Exports the BigInt representation as a decimal string. // private static readonly char[ ] decValues = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; internal string ToDecimal() { BigInt ten = new BigInt( 0xA ); BigInt numerator = new BigInt(); BigInt quotient = new BigInt(); BigInt remainder = new BigInt(); numerator.CopyFrom( this ); char[ ] dec = new char[ 8 * m_size / 3 ]; // 10 > (2^3 = 8) int index = 0; do { Divide( numerator, ten, ref quotient, ref remainder ); dec[ index++ ] = decValues[ remainder.m_elements[ 0 ] ]; numerator.CopyFrom( quotient ); } while( quotient.IsZero() == false ); Array.Reverse( dec, 0, index ); return new String( dec, 0, index ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HashRepartitionStream.cs
- Wow64ConfigurationLoader.cs
- TextTreeObjectNode.cs
- ListBox.cs
- ParseNumbers.cs
- Monitor.cs
- SessionIDManager.cs
- VisualBasicReference.cs
- FrameworkObject.cs
- ValueSerializerAttribute.cs
- HashCodeCombiner.cs
- ClientProxyGenerator.cs
- StreamFormatter.cs
- NamedPermissionSet.cs
- NullRuntimeConfig.cs
- EventLogEntry.cs
- AuthenticationConfig.cs
- StringConcat.cs
- UInt16.cs
- TreeNode.cs
- DirectionalLight.cs
- TransportChannelListener.cs
- SchemaImporterExtensionsSection.cs
- UserControlDesigner.cs
- CodeMemberProperty.cs
- BitmapEffectState.cs
- GenericIdentity.cs
- XmlSchemaImporter.cs
- ListItem.cs
- SrgsSubset.cs
- CatalogPart.cs
- JoinTreeNode.cs
- Registration.cs
- ListDictionary.cs
- SrgsGrammar.cs
- IImplicitResourceProvider.cs
- QueueProcessor.cs
- FreezableCollection.cs
- ApplicationDirectoryMembershipCondition.cs
- PlatformCulture.cs
- COM2IDispatchConverter.cs
- SimpleWorkerRequest.cs
- XamlReader.cs
- SafeFileHandle.cs
- DefaultProxySection.cs
- ComponentSerializationService.cs
- EnumMemberAttribute.cs
- ImageField.cs
- NotFiniteNumberException.cs
- Base64Encoder.cs
- SwitchDesigner.xaml.cs
- RuntimeArgumentHandle.cs
- BreakRecordTable.cs
- EpmContentSerializerBase.cs
- CreatingCookieEventArgs.cs
- Latin1Encoding.cs
- GZipStream.cs
- DataRecordObjectView.cs
- Group.cs
- Vector3DKeyFrameCollection.cs
- HealthMonitoringSection.cs
- UIAgentAsyncEndRequest.cs
- PropertyEmitterBase.cs
- XmlHelper.cs
- CompositeFontFamily.cs
- SoapRpcServiceAttribute.cs
- FontNameConverter.cs
- ControlUtil.cs
- FontStretches.cs
- LockedHandleGlyph.cs
- DataList.cs
- CurrentChangedEventManager.cs
- WpfKnownType.cs
- PeerChannelFactory.cs
- ObjectDataSourceStatusEventArgs.cs
- ContentOperations.cs
- ImageMap.cs
- XmlTextReader.cs
- CompilationUtil.cs
- GlyphElement.cs
- Pair.cs
- Image.cs
- KnownTypesProvider.cs
- TriState.cs
- SqlBinder.cs
- ProcessHost.cs
- NegotiateStream.cs
- WindowsRichEdit.cs
- ContainerParagraph.cs
- Base64Decoder.cs
- RoleServiceManager.cs
- LicFileLicenseProvider.cs
- StaticFileHandler.cs
- BatchWriter.cs
- XmlCDATASection.cs
- WindowsPen.cs
- TextChangedEventArgs.cs
- EntityDescriptor.cs
- EntityDataSourceMemberPath.cs
- InputProviderSite.cs