"L. Spiro Engine"

F:/My Projects/LSEngine/Modules/LSStandardLib/Src/LargeInteger/LSSTD128BitInteger.h

00001 
00017 #ifndef __LSE_128BITINTEGER_H__
00018 #define __LSE_128BITINTEGER_H__
00019 
00020 #include "../LSSTDStandardLib.h"
00021 
00022 namespace lsstd {
00023 
00031         class C128BitInteger {
00032         public :
00033                 // == Various constructors.
00034                 LSE_CALLCTOR                                                            C128BitInteger() {}
00035                 LSE_CALLCTOR                                                            C128BitInteger( const C128BitInteger &_biOp ) {
00036                         m_ui32Digits[0] = _biOp.m_ui32Digits[0];
00037                         m_ui32Digits[1] = _biOp.m_ui32Digits[1];
00038                         m_ui32Digits[2] = _biOp.m_ui32Digits[2];
00039                         m_ui32Digits[3] = _biOp.m_ui32Digits[3];
00040                 }
00041                 LSE_CALLCTOR                                                            C128BitInteger( LSINT64 _i64Src ) {
00042                         m_ui32Digits[0] = static_cast<LSUINT32>(_i64Src & 0xFFFFFFFFULL);
00043                         m_ui32Digits[1] = static_cast<LSUINT32>(_i64Src >> 32ULL);
00044                         _i64Src = (_i64Src >> 63);
00045 
00046                         m_ui32Digits[2] = m_ui32Digits[3] = static_cast<LSUINT32>(_i64Src);
00047                 }
00048                 LSE_CALLCTOR                                                            C128BitInteger( LSUINT64 _ui64Src ) {
00049                         m_ui32Digits[0] = static_cast<LSUINT32>(_ui64Src & 0xFFFFFFFFULL);
00050                         m_ui32Digits[1] = static_cast<LSUINT32>(_ui64Src >> 32ULL);
00051                         m_ui32Digits[2] = m_ui32Digits[3] = 0UL;
00052                 }
00053                 LSE_CALLCTOR                                                            C128BitInteger( const LSUINT32 * _pui32Src ) {
00054                         LSUINT32 ui32Len = 4UL;
00055                         while ( ui32Len && !_pui32Src[--ui32Len] ) {}
00056                         ++ui32Len;
00057                         LSUINT32 I, J = ui32Len - 1UL;
00058                         for ( I = 0UL; I < ui32Len; ++I, --J ) {
00059                                 m_ui32Digits[I] = _pui32Src[J];
00060                         }
00061                         for ( ; I < 4UL; ++I ) {
00062                                 m_ui32Digits[I] = 0UL;
00063                         }
00064                 }
00065 
00066 
00067                 // == Operators.
00073                 C128BitInteger LSE_CALL                                         operator - () const {
00074                         C128BitInteger biReturn;
00075                         Negate( (*this), biReturn );
00076 
00077                         return biReturn;
00078                 }
00079 
00086                 C128BitInteger LSE_CALL                                         operator + ( const C128BitInteger &_biOp ) const {
00087                         C128BitInteger biReturn;
00088                         Add( (*this), _biOp, biReturn );
00089 
00090                         return biReturn;
00091                 }
00092 
00099                 C128BitInteger LSE_CALL                                         operator * ( const C128BitInteger &_biOp ) const {
00100                         C128BitInteger biReturn;
00101                         Multiply( (*this), _biOp, biReturn );
00102 
00103                         return biReturn;
00104                 }
00105 
00113                 C128BitInteger LSE_CALL                                         operator *= ( const C128BitInteger &_biOp ) {
00114                         C128BitInteger biReturn;
00115                         Multiply( (*this), _biOp, biReturn );
00116                         (*this) = biReturn;
00117 
00118                         return (*this);
00119                 }
00120 
00128                 C128BitInteger LSE_CALL                                         operator / ( const C128BitInteger &_biOp ) const {
00129                         C128BitInteger biReturn;
00130                         Divide( (*this), _biOp, biReturn );
00131 
00132                         return biReturn;
00133                 }
00134 
00142                 C128BitInteger LSE_CALL                                         operator /= ( const C128BitInteger &_biOp ) {
00143                         C128BitInteger biReturn;
00144                         Divide( (*this), _biOp, biReturn );
00145                         (*this) = biReturn;
00146 
00147                         return (*this);
00148                 }
00149 
00157                 C128BitInteger LSE_CALL                                         operator % ( const C128BitInteger &_biOp ) const {
00158                         C128BitInteger biReturn;
00159                         Modulus( (*this), _biOp, biReturn );
00160 
00161                         return biReturn;
00162                 }
00163 
00171                 C128BitInteger LSE_CALL                                         operator - ( const C128BitInteger &_biOp ) const {
00172                         C128BitInteger biReturn;
00173                         Subtract( (*this), _biOp, biReturn );
00174 
00175                         return biReturn;
00176                 }
00177 
00184                 C128BitInteger LSE_CALL                                         operator << ( LSUINT32 _ui32Shift ) const {
00185                         C128BitInteger biReturn( (*this) );
00186                         ShiftLeft( biReturn.m_ui32Digits, 4UL, _ui32Shift );
00187 
00188                         return biReturn;
00189                 }
00190 
00197                 C128BitInteger & LSE_CALL               operator <<= ( LSUINT32 _ui32Shift ) {
00198                         ShiftLeft( m_ui32Digits, 4UL, _ui32Shift );
00199 
00200                         return (*this);
00201                 }
00202 
00209                 C128BitInteger LSE_CALL                                         operator >> ( LSUINT32 _ui32Shift ) const {
00210                         C128BitInteger biReturn( (*this) );
00211                         ShiftRight( biReturn.m_ui32Digits, 4UL, _ui32Shift );
00212 
00213                         // Fix sign bits on negative numbers.
00214                         if ( m_ui32Digits[4UL-1UL] & 0x80000000UL ) {
00215                                 for ( LSUINT32 I = 4UL - 1UL; I >= 4UL; --I ) {
00216                                         biReturn.m_ui32Digits[I] = 0xFFFFFFFF;
00217                                 }
00218 
00219                                 LSUINT32 ui32Mask = 0x80000000UL;
00220                                 for ( LSUINT32 I = 0UL; I < 32UL; ++I ) {
00221                                         if ( biReturn.m_ui32Digits[4UL-1] & ui32Mask ) {
00222                                                 break;
00223                                         }
00224                                         biReturn.m_ui32Digits[4UL-1] |= ui32Mask;
00225                                         ui32Mask >>= 1UL;
00226                                 }
00227                         }
00228 
00229                         return biReturn;
00230                 }
00231 
00238                 C128BitInteger & LSE_CALL               operator >>= ( LSUINT32 _ui32Shift ) {
00239                         LSUINT32 ui32Used = ShiftRight( m_ui32Digits, 4UL, _ui32Shift );
00240                         ui32Used = CStd::Max<LSUINT32>( ui32Used, 1UL );
00241 
00242                         // Fix sign bits on negative numbers.
00243                         if ( m_ui32Digits[4UL-1UL] & 0x80000000UL ) {
00244                                 for ( LSUINT32 I = 4UL - 1UL; I >= ui32Used; --I ) {
00245                                         m_ui32Digits[I] = 0xFFFFFFFF;
00246                                 }
00247 
00248                                 LSUINT32 ui32Mask = 0x80000000UL;
00249                                 for ( LSUINT32 I = 0UL; I < 32UL; ++I ) {
00250                                         if ( m_ui32Digits[ui32Used-1] & ui32Mask ) {
00251                                                 break;
00252                                         }
00253                                         m_ui32Digits[ui32Used-1] |= ui32Mask;
00254                                         ui32Mask >>= 1UL;
00255                                 }
00256                                 ui32Used = 4UL;
00257                         }
00258 
00259                         return (*this);
00260                 }
00261 
00268                 bool LSE_CALL                                                           operator > ( const C128BitInteger &_biOp ) const {
00269                         LSINT32 i32Pos = 4UL - 1;
00270 
00271                         if ( (m_ui32Digits[i32Pos] & 0x80000000UL) && !(_biOp.m_ui32Digits[i32Pos] & 0x80000000UL) ) {
00272                                 return false;
00273                         }
00274                         if ( !(m_ui32Digits[i32Pos] & 0x80000000UL) && (_biOp.m_ui32Digits[i32Pos] & 0x80000000UL) ) {
00275                                 return true;
00276                         }
00277 
00278                         // Skip past all digits that are the same.
00279                         for ( i32Pos = 4UL; i32Pos >= 0 && m_ui32Digits[i32Pos] == _biOp.m_ui32Digits[i32Pos]; --i32Pos ) {}
00280 
00281                         // If we found a different digit.
00282                         if ( i32Pos >= 0 ) {
00283                                 return m_ui32Digits[i32Pos] > _biOp.m_ui32Digits[i32Pos];
00284                         }
00285 
00286                         // They are the same.
00287                         return false;
00288                 }
00289 
00296                 bool LSE_CALL                                                           operator < ( const C128BitInteger &_biOp ) const {
00297                         LSINT32 i32Pos = 4UL - 1;
00298 
00299                         if ( (m_ui32Digits[i32Pos] & 0x80000000UL) && !(_biOp.m_ui32Digits[i32Pos] & 0x80000000UL) ) {
00300                                 return true;
00301                         }
00302                         if ( !(m_ui32Digits[i32Pos] & 0x80000000UL) && (_biOp.m_ui32Digits[i32Pos] & 0x80000000UL) ) {
00303                                 return false;
00304                         }
00305 
00306                         // Skip past all digits that are the same.
00307                         for ( i32Pos = 3; i32Pos >= 0 && m_ui32Digits[i32Pos] == _biOp.m_ui32Digits[i32Pos]; --i32Pos ) {}
00308 
00309                         // If we found a different digit.
00310                         if ( i32Pos >= 0 ) {
00311                                 return m_ui32Digits[i32Pos] < _biOp.m_ui32Digits[i32Pos];
00312                         }
00313 
00314                         // They are the same.
00315                         return false;
00316                 }
00317 
00318 
00319                 // == Functions.
00326                 static LSVOID LSE_CALL                                          Negate( const C128BitInteger &_biValue,
00327                         C128BitInteger &_biResult ) {
00328                         // Handle negation of 0 manually.
00329                         if ( _biValue.m_ui32Digits[0] == 0ULL && _biValue.m_ui32Digits[1] == 0ULL &&
00330                                 _biValue.m_ui32Digits[2] == 0ULL && _biValue.m_ui32Digits[3] == 0ULL ) {
00331                                 _biResult.m_ui32Digits[0] = _biResult.m_ui32Digits[1] = _biResult.m_ui32Digits[2] = _biResult.m_ui32Digits[3] = 0ULL;
00332                                 return;
00333                         }
00334 
00335                         // Perform 1's compliment.
00336                         for ( LSINT32 I = 4UL; --I >= 0; ) {
00337                                 _biResult.m_ui32Digits[I] = ~_biValue.m_ui32Digits[I];
00338                         }
00339 
00340                         // Add 1 to the result.
00341                         LSUINT64 ui64Value, ui64Carry = 1UL;
00342                         for ( LSUINT32 I = 0; ui64Carry && I < 4UL; ++I ) {
00343                                 ui64Value = _biResult.m_ui32Digits[I] + 1UL;
00344                                 _biResult.m_ui32Digits[I] = static_cast<LSUINT32>(ui64Value & 0xFFFFFFFFULL);
00345                                 ui64Carry = ui64Value >> 32UL;
00346                         }
00347                 }
00348 
00357                 static LSUINT32 LSE_CALL                                        ShiftLeft( LSUINT32 * _pui32Data, LSUINT32 _ui32Len,
00358                         LSUINT32 _ui32Amount ) {
00359 
00360                         LSUINT32 ui32ShiftAmt = 32UL;
00361                         LSUINT32 ui32Used = _ui32Len;
00362 
00363                         while ( ui32Used > 1UL && _pui32Data[ui32Used-1] == 0 ) {
00364                                 --ui32Used;
00365                         }
00366 
00367 
00368                         for ( LSUINT32 I = _ui32Amount; I > 0UL; ) {
00369                                 if ( I < ui32ShiftAmt ) {
00370                                         ui32ShiftAmt = I;
00371                                 }
00372 
00373                                 LSUINT64 ui64Carry = 0ULL;
00374 
00375                                 for ( LSUINT32 J = 0UL; J < ui32Used; ++J ) {
00376                                         LSUINT64 ui64Value = static_cast<LSUINT64>(_pui32Data[J]) << ui32ShiftAmt;
00377                                         ui64Value |= ui64Carry;
00378 
00379                                         _pui32Data[J] = static_cast<LSUINT32>(ui64Value);
00380                                         ui64Carry = ui64Value >> 32ULL;
00381                                 }
00382 
00383                                 if ( ui64Carry ) {
00384                                         if ( ui32Used + 1UL <= _ui32Len ) {
00385                                                 _pui32Data[ui32Used++] = static_cast<LSUINT32>(ui64Carry);
00386                                         }
00387                                 }
00388 
00389                                 I -= ui32ShiftAmt;
00390                         }
00391                         return ui32Used;
00392                 }
00393 
00402                 static LSUINT32 LSE_CALL                                        ShiftRight( LSUINT32 * _pui32Data, LSUINT32 _ui32Len,
00403                         LSUINT32 _ui32Amount ) {
00404 
00405                         LSUINT32 ui32ShiftAmt = 32ULL;
00406                         LSUINT32 ui32InvShift = 0UL;
00407                         LSUINT32 ui32Used = _ui32Len;
00408 
00409                         while ( ui32Used > 1UL && _pui32Data[ui32Used-1] == 0 ) {
00410                                 --ui32Used;
00411                         }
00412 
00413 
00414                         for ( LSUINT32 I = _ui32Amount; I > 0UL; ) {
00415                                 if ( I < ui32ShiftAmt ) {
00416                                         ui32ShiftAmt = I;
00417                                         ui32InvShift = 32ULL - ui32ShiftAmt;
00418                                 }
00419 
00420                                 LSUINT64 ui64Carry = 0ULL;
00421 
00422                                 for ( LSINT32 J = static_cast<LSINT32>(ui32Used - 1UL); J >= 0; --J ) {
00423                                         LSUINT64 ui64Value = static_cast<LSUINT64>(_pui32Data[J]) >> static_cast<LSUINT64>(ui32ShiftAmt);
00424                                         ui64Value |= ui64Carry;
00425 
00426                                         ui64Carry = _pui32Data[J] << ui32InvShift;
00427                                         _pui32Data[J] = static_cast<LSUINT32>(ui64Value);
00428                                 }
00429 
00430                                 I -= ui32ShiftAmt;
00431                         }
00432 
00433                         // Remove opening 0's.
00434                         while ( ui32Used > 1UL && _pui32Data[ui32Used-1UL] == 0 ) {
00435                                 --ui32Used;
00436                         }
00437 
00438                         return ui32Used;
00439                 }
00440 
00449                 static LSVOID LSE_CALL                                          Add( const C128BitInteger &_biLeft,
00450                         const C128BitInteger &_biRight,
00451                         C128BitInteger &_biResult ) {
00452 
00453                         LSUINT64 ui64Carry = 0ULL;
00454                         for ( LSUINT32 I = 0UL; I < 4UL; ++I ) {
00455                                 LSUINT64 ui64Sum = static_cast<LSUINT64>(_biLeft.m_ui32Digits[I]) + static_cast<LSUINT64>(_biRight.m_ui32Digits[I]) + ui64Carry;
00456                                 ui64Carry = ui64Sum >> 32ULL;
00457                                 _biResult.m_ui32Digits[I] = static_cast<LSUINT32>(ui64Sum & 0xFFFFFFFFULL);
00458                         }
00459                         // Carries are simply lost.  This class behaves like a real 128-bit integer would.
00460                 }
00461 
00470                 static LSVOID LSE_CALL                                          Subtract( const C128BitInteger &_biLeft,
00471                         const C128BitInteger &_biRight,
00472                         C128BitInteger &_biResult ) {
00473                         LSUINT32 ui32LeftUsed = 4UL;
00474                         while ( ui32LeftUsed && !_biLeft.m_ui32Digits[--ui32LeftUsed] ) {}
00475                         ++ui32LeftUsed;
00476                         LSUINT32 ui32RightUsed = 4UL;
00477                         while ( ui32RightUsed && !_biRight.m_ui32Digits[--ui32RightUsed] ) {}
00478                         ++ui32RightUsed;
00479                         LSUINT32 ui32Total = CStd::Max( ui32LeftUsed, ui32RightUsed );
00480 
00481                         LSINT64 i64Carry = 0;
00482                         LSUINT32 I;
00483                         for ( I = 0UL; I < ui32Total; ++I ) {
00484                                 LSINT64 i64Dif = static_cast<LSINT64>(_biLeft.m_ui32Digits[I]) - static_cast<LSINT64>(_biRight.m_ui32Digits[I]) - i64Carry;
00485                                 _biResult.m_ui32Digits[I] = static_cast<LSUINT32>(i64Dif & 0xFFFFFFFF);
00486 
00487                                 if ( i64Dif < 0LL ) {
00488                                         i64Carry = 1LL;
00489                                 }
00490                                 else {
00491                                         i64Carry = 0LL;
00492                                 }
00493                         }
00494 
00495                         if ( i64Carry ) {
00496                                 for ( ; I < 4UL; ++I ) {
00497                                         _biResult.m_ui32Digits[I] = 0xFFFFFFFFUL;
00498                                 }
00499                         }
00500                         else {
00501                                 for ( ; I < 4UL; ++I ) {
00502                                         _biResult.m_ui32Digits[I] = 0UL;
00503                                 }
00504                         }
00505                 }
00506 
00515                 static LSVOID LSE_CALL                                          Multiply( const C128BitInteger &_biLeft,
00516                         const C128BitInteger &_biRight,
00517                         C128BitInteger &_biResult ) {
00518                         const LSUINT32 ui32LastPos = 4UL - 1UL;
00519 
00520                         // We work on positive values only, then negate at the end.
00521                         LSBOOL bLeftNeg = false, bRightNeg = false;
00522 
00523                         C128BitInteger biLeftAbs( _biLeft );
00524                         C128BitInteger biRightAbs( _biRight );
00525 
00526                         if ( _biLeft.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00527                                 bLeftNeg = true;
00528                                 biLeftAbs = -_biLeft;
00529                         }
00530                         if ( _biRight.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00531                                 bRightNeg = true;
00532                                 biRightAbs = -_biRight;
00533                         }
00534 
00535                         // Clear the return.
00536                         _biResult = C128BitInteger( 0ULL );
00537 
00538 
00539                         // Multiply.
00540                         for ( LSUINT32 I = 0UL; I < 4UL; ++I ) {
00541                                 if ( biLeftAbs.m_ui32Digits[I] == 0 ) { continue; }
00542                                 LSUINT64 ui64Carry = 0ULL;
00543                                 for ( LSUINT32 J = 0UL, K = I; J < 4UL; ++J, ++K ) {
00544                                         LSUINT64 ui64Value = static_cast<LSUINT64>(biLeftAbs.m_ui32Digits[I]) * static_cast<LSUINT64>(biRightAbs.m_ui32Digits[J]) +
00545                                                 static_cast<LSUINT64>(_biResult.m_ui32Digits[K]) + ui64Carry;
00546 
00547                                         _biResult.m_ui32Digits[K] = static_cast<LSUINT32>(ui64Value & 0xFFFFFFFF);
00548 
00549                                         ui64Carry = ui64Value >> 32UL;
00550                                 }
00551                                 if ( ui64Carry ) {
00552                                         _biResult.m_ui32Digits[I+4UL] = static_cast<LSUINT32>(ui64Carry);
00553                                 }
00554                         }
00555 
00556                         // Reverse the signs if necessary.
00557                         if ( bLeftNeg != bRightNeg ) {
00558                                 Negate( _biResult, _biResult );
00559                         }
00560                 }
00561 
00570                 static LSVOID LSE_CALL                                          Divide( const C128BitInteger &_biLeft,
00571                         const C128BitInteger &_biRight,
00572                         C128BitInteger &_biResult ) {
00573                         if ( !_biRight.m_ui32Digits[0] && !_biRight.m_ui32Digits[1] && !_biRight.m_ui32Digits[2] && !_biRight.m_ui32Digits[3] ) {
00574                                 _biResult = C128BitInteger( 0ULL );
00575                                 return;
00576                         }
00577                         const LSUINT32 ui32LastPos = 4UL - 1UL;
00578 
00579                         
00580 
00581                         C128BitInteger biNewLeft( _biLeft );
00582                         C128BitInteger biNewRight( _biRight );
00583                         
00584                         LSBOOL bDivisorNeg = false, bDividendNeg = false;
00585                         if ( _biLeft.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00586                                 bDividendNeg = true;
00587                                 biNewLeft = -biNewLeft;
00588                         }
00589                         if ( _biRight.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00590                                 bDivisorNeg = true;
00591                                 biNewRight = -biNewRight;
00592                         }
00593 
00594                         if ( biNewLeft < biNewRight ) {
00595                                 _biResult = C128BitInteger( 0ULL );
00596                                 return;
00597                         }
00598 
00599                         // Get the highest used value.
00600                         LSUINT32 ui32Used = 4UL;
00601                         while ( ui32Used && !biNewRight.m_ui32Digits[--ui32Used] ) {}
00602                         ++ui32Used;
00603 
00604                         // Hold the results.
00605                         C128BitInteger biRem;
00606                         if ( ui32Used == 1UL ) {
00607                                 DivideS( biNewLeft, biNewRight,
00608                                         _biResult, biRem );
00609                         }
00610                         else {
00611                                 DivideM( biNewLeft, biNewRight,
00612                                         _biResult, biRem );
00613                         }
00614 
00615                         if ( bDivisorNeg != bDividendNeg ) {
00616                                 // Flip the sign.
00617                                 _biResult = -_biResult;
00618                         }
00619                 }
00620 
00629                 static LSVOID LSE_CALL                                          Modulus( const C128BitInteger &_biLeft,
00630                         const C128BitInteger &_biRight,
00631                         C128BitInteger &_biResult ) {
00632                         if ( !_biRight.m_ui32Digits[0] && !_biRight.m_ui32Digits[1] && !_biRight.m_ui32Digits[2] && !_biRight.m_ui32Digits[3] ) {
00633                                 _biResult = C128BitInteger( 0ULL );
00634                                 return;
00635                         }
00636                         const LSUINT32 ui32LastPos = 4UL - 1UL;
00637 
00638                         
00639 
00640                         C128BitInteger biNewLeft( _biLeft );
00641                         C128BitInteger biNewRight( _biRight );
00642                         
00643                         LSBOOL bDividendNeg = false;
00644                         if ( _biLeft.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00645                                 bDividendNeg = true;
00646                                 biNewLeft = -biNewLeft;
00647                         }
00648                         if ( _biRight.m_ui32Digits[ui32LastPos] & 0x80000000UL ) {
00649                                 biNewRight = -biNewRight;
00650                         }
00651 
00652                         if ( biNewLeft < biNewRight ) {
00653                                 _biResult = _biLeft;
00654                                 return;
00655                         }
00656 
00657                         // Hold the results.
00658                         // Get the highest used value.
00659                         LSUINT32 ui32Used = 4UL;
00660                         while ( ui32Used && !biNewRight.m_ui32Digits[--ui32Used] ) {}
00661                         ++ui32Used;
00662 
00663                         C128BitInteger biRes;
00664                         if ( ui32Used == 1UL ) {
00665                                 DivideS( biNewLeft, biNewRight,
00666                                         biRes, _biResult );
00667                         }
00668                         else {
00669                                 DivideM( biNewLeft, biNewRight,
00670                                         biRes, _biResult );
00671                         }
00672 
00673                         if ( bDividendNeg ) {
00674                                 // Flip the sign.
00675                                 _biResult = -_biResult;
00676                         }
00677                 }
00678 
00679 
00680         protected :
00681                 // == Members.
00685                 LSUINT32                                                                        m_ui32Digits[4];
00686 
00687 
00688                 // == Functions.
00698                 static LSVOID LSE_CALL                                          DivideM( const C128BitInteger &_biLeft,
00699                         const C128BitInteger &_biRight,
00700                         C128BitInteger &_biQuotient,
00701                         C128BitInteger &_biRemainder ) {
00702 
00703                         C128BitInteger biResult = C128BitInteger( 0ULL );
00704                         LSUINT32 ui32Remainder[4UL+1UL];
00705 
00706                         LSUINT32 ui32Mask = 0x80000000UL;
00707                         LSUINT32 ui32Used = 4UL;
00708                         while ( ui32Used && !_biRight.m_ui32Digits[--ui32Used] ) {}
00709                         ++ui32Used;
00710                         LSUINT32 ui32Value = _biRight.m_ui32Digits[ui32Used-1UL];
00711                         LSUINT32 ui32Shift = 0UL, ui32ResPos = 0UL;
00712                         while ( ui32Mask && (ui32Value & ui32Mask) == 0 ) {
00713                                 ++ui32Shift;
00714                                 ui32Mask >>= 1UL;
00715                         }
00716 
00717                         for ( LSUINT32 I = 4UL; I--; ) {
00718                                 ui32Remainder[I] = _biLeft.m_ui32Digits[I];
00719                         }
00720                         ui32Remainder[4] = 0UL;
00721 
00722                         ShiftLeft( ui32Remainder, 5UL, ui32Shift );
00723                         C128BitInteger biNewRight = _biRight << ui32Shift;
00724 
00725                         LSUINT32 ui32RemainderUsed = 4UL;
00726                         while ( ui32RemainderUsed && !ui32Remainder[--ui32RemainderUsed] ) {}
00727                         ++ui32RemainderUsed;
00728                         LSUINT32 ui32NewRightUsed = 4UL;
00729                         while ( ui32NewRightUsed && !biNewRight.m_ui32Digits[--ui32NewRightUsed] ) {}
00730                         ++ui32NewRightUsed;
00731 
00732                         LSUINT32 ui32J = ui32RemainderUsed - ui32NewRightUsed;
00733                         LSUINT32 ui32Pos = ui32RemainderUsed - 1UL;
00734 
00735                         LSUINT32 ui32FirstDivisorByte = biNewRight.m_ui32Digits[ui32NewRightUsed-1UL];
00736                         LSUINT32 ui32SecondDivisorByte = biNewRight.m_ui32Digits[ui32NewRightUsed-2UL];
00737 
00738                         LSUINT32 ui32DivisorLen = ui32NewRightUsed + 1UL;
00739                         LSUINT32 ui32DividendPart[5] = { 0UL };
00740 
00741                         for ( ; ui32J > 0UL; --ui32J ) {
00742                                 LSUINT64 ui64Dividend = (static_cast<LSUINT64>(ui32Remainder[ui32Pos]) << 32ULL) + ui32Remainder[ui32Pos-1UL];
00743 
00744                                 LSUINT64 ui64Q = ui64Dividend / ui32FirstDivisorByte;
00745                                 LSUINT64 ui64R = ui64Dividend % ui32FirstDivisorByte;
00746 
00747                                 LSBOOL bDone = false;
00748                                 while ( !bDone ) {
00749                                         bDone = true;
00750 
00751                                         if ( ui64Q == 0x100000000ULL ||
00752                                                 (ui64Q * ui32SecondDivisorByte) > ((ui64R << 32UL) + ui32Remainder[ui32Pos-2UL]) ) {
00753                                                 --ui64Q;
00754                                                 ui64R += ui32FirstDivisorByte;
00755                                                 if ( ui64R < 0x100000000ULL ) {
00756                                                         bDone = false;
00757                                                 }
00758                                         }
00759                                 }
00760 
00761                                 for ( LSUINT32 I = 0UL; I < ui32DivisorLen; ++I ) {
00762                                         ui32DividendPart[I] = ui32Remainder[ui32Pos-I];
00763                                 }
00764 
00765                                 // Again on the heap instead of on the stack.
00766                                 C128BitInteger biK( ui32DividendPart );
00767                                 C128BitInteger biS( biNewRight * C128BitInteger( static_cast<LSUINT64>(ui64Q) ) );
00768 
00769                                 while ( biS > biK ) {
00770                                         --ui64Q;
00771                                         biS = biS - biNewRight;
00772                                 }
00773 
00774                                 C128BitInteger liY = biK - biS;
00775                                 for ( LSUINT32 I = 0UL; I < ui32DivisorLen; ++I ) {
00776                                         ui32Remainder[ui32Pos-I] = liY.m_ui32Digits[ui32NewRightUsed-I];
00777                                 }
00778 
00779                                 biResult.m_ui32Digits[ui32ResPos++] = static_cast<LSUINT32>(ui64Q);
00780                                 --ui32Pos;
00781                         }
00782 
00783                         LSUINT32 Y = 0UL;
00784                         for ( LSINT32 X = static_cast<LSINT32>(ui32ResPos) - 1; X >= 0; --X, ++Y ) {
00785                                 _biQuotient.m_ui32Digits[Y] = biResult.m_ui32Digits[X];
00786                         }
00787 
00788                         for ( ; Y < 4UL; ++Y ) {
00789                                 _biQuotient.m_ui32Digits[Y] = 0UL;
00790                         }
00791 
00792                         LSUINT32 ui32Size = ShiftRight( ui32Remainder, ui32RemainderUsed, ui32Shift );
00793                         for ( Y = ui32Size; Y < 4UL; ++Y ) {
00794                                 ui32Remainder[Y] = 0UL;
00795                         }
00796                         LSUINT64 * pui64Dest = reinterpret_cast<LSUINT64 *>(_biRemainder.m_ui32Digits);
00797                         LSUINT64 * pui64Src = reinterpret_cast<LSUINT64 *>(ui32Remainder);
00798                         (*pui64Dest++) = (*pui64Src++);
00799                         (*pui64Dest) = (*pui64Src);
00800                 }
00801 
00811                 static LSVOID LSE_CALL                                          DivideS( const C128BitInteger &_biLeft,
00812                         const C128BitInteger &_biRight,
00813                         C128BitInteger &_biQuotient,
00814                         C128BitInteger &_biRemainder ) {
00815 
00816                         C128BitInteger liResult( 0ULL );
00817                         LSUINT32 ui32ResPos = 0UL;
00818 
00819                         // Copy dividend to remainder.
00820                         _biRemainder = _biLeft;
00821                         LSINT32 i32Pos = 4;
00822                         while ( i32Pos && !_biRemainder.m_ui32Digits[--i32Pos] ) {}
00823                         ++i32Pos;
00824 
00825                         LSUINT64 ui64Divisor = _biRight.m_ui32Digits[0UL];
00826                         LSUINT64 ui64Dividend = _biRemainder.m_ui32Digits[i32Pos];
00827 
00828                         if ( ui64Dividend >= ui64Divisor ) {
00829                                 LSUINT64 ui64Quotient = ui64Dividend / ui64Divisor;
00830                                 liResult.m_ui32Digits[ui32ResPos++] = static_cast<LSUINT32>(ui64Quotient);
00831                                 _biRemainder.m_ui32Digits[i32Pos] = static_cast<LSUINT32>(ui64Dividend % ui64Divisor);
00832                         }
00833                         --i32Pos;
00834 
00835                         while ( i32Pos >= 0 ) {
00836                                 ui64Dividend = (static_cast<LSUINT64>(_biRemainder.m_ui32Digits[i32Pos+1]) << 32ULL) + _biRemainder.m_ui32Digits[i32Pos];
00837                                 LSUINT64 ui64Quotient = ui64Dividend / ui64Divisor;
00838                                 liResult.m_ui32Digits[ui32ResPos++] = static_cast<LSUINT32>(ui64Quotient);
00839 
00840                                 _biRemainder.m_ui32Digits[i32Pos+1] = 0;
00841                                 _biRemainder.m_ui32Digits[i32Pos--] = static_cast<LSUINT32>(ui64Dividend % ui64Divisor);
00842                         }
00843 
00844                         // Copy the result over the output quotient.
00845                         LSUINT32 J = 0UL;
00846                         for ( LSINT32 I = static_cast<LSINT32>(ui32ResPos) - 1; I >= 0; --I, ++J ) {
00847                                 _biQuotient.m_ui32Digits[J] = liResult.m_ui32Digits[I];
00848                         }
00849 
00850                         for ( ; J < 4UL; ++J ) {
00851                                 _biQuotient.m_ui32Digits[J] = 0;
00852                         }
00853                 }
00854 
00855         };
00856 
00857 }       // namespace lsstd
00858 
00859 #endif  // __LSE_128BITINTEGER_H__
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator