"L. Spiro Engine"
|
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__