Wm4TInteger.inl

Go to the documentation of this file.
00001 // Wild Magic Source Code
00002 // David Eberly
00003 // http://www.geometrictools.com
00004 // Copyright (c) 1998-2007
00005 //
00006 // This library is free software; you can redistribute it and/or modify it
00007 // under the terms of the GNU Lesser General Public License as published by
00008 // the Free Software Foundation; either version 2.1 of the License, or (at
00009 // your option) any later version.  The license is available for reading at
00010 // either of the locations:
00011 //     http://www.gnu.org/copyleft/lgpl.html
00012 //     http://www.geometrictools.com/License/WildMagicLicense.pdf
00013 // The license applies to versions 0 through 4 of Wild Magic.
00014 //
00015 // Version: 4.0.0 (2006/06/28)
00016 
00017 namespace Wm4
00018 {
00019 //----------------------------------------------------------------------------
00020 template <int N>
00021 TInteger<N>::TInteger (int i)
00022 {
00023     if (i >= 0)
00024     {
00025         memset(m_asBuffer,0,TINT_BYTES);
00026     }
00027     else
00028     {
00029         memset(m_asBuffer,0xFF,TINT_BYTES);
00030     }
00031     System::Memcpy(m_asBuffer,sizeof(int),&i,sizeof(int));
00032 #ifdef WM4_BIG_ENDIAN
00033     short sSave = m_asBuffer[0];
00034     m_asBuffer[0] = m_asBuffer[1];
00035     m_asBuffer[1] = sSave;
00036 #endif
00037 }
00038 //----------------------------------------------------------------------------
00039 template <int N>
00040 TInteger<N>::TInteger (const TInteger& rkI)
00041 {
00042     System::Memcpy(m_asBuffer,TINT_BYTES,rkI.m_asBuffer,TINT_BYTES);
00043 }
00044 //----------------------------------------------------------------------------
00045 template <int N>
00046 TInteger<N>::~TInteger ()
00047 {
00048 }
00049 //----------------------------------------------------------------------------
00050 template <int N>
00051 TInteger<N>& TInteger<N>::operator= (const TInteger& rkI)
00052 {
00053     System::Memcpy(m_asBuffer,TINT_BYTES,rkI.m_asBuffer,TINT_BYTES);
00054     return *this;
00055 }
00056 //----------------------------------------------------------------------------
00057 template <int N>
00058 int TInteger<N>::GetSign () const
00059 {
00060     return (m_asBuffer[TINT_LAST] & 0x8000) ? -1 : +1;
00061 }
00062 //----------------------------------------------------------------------------
00063 template <int N>
00064 bool TInteger<N>::operator== (const TInteger& rkI) const
00065 {
00066     return Compare(*this,rkI) == 0;
00067 }
00068 //----------------------------------------------------------------------------
00069 template <int N>
00070 bool TInteger<N>::operator!= (const TInteger& rkI) const
00071 {
00072     return Compare(*this,rkI) != 0;
00073 }
00074 //----------------------------------------------------------------------------
00075 template <int N>
00076 bool TInteger<N>::operator< (const TInteger& rkI) const
00077 {
00078     int iS0 = GetSign(), iS1 = rkI.GetSign();
00079     if (iS0 > 0)
00080     {
00081         if (iS1 > 0)
00082         {
00083             return Compare(*this,rkI) < 0;
00084         }
00085         else
00086         {
00087             return false;
00088         }
00089     }
00090     else
00091     {
00092         if (iS1 > 0)
00093         {
00094             return true;
00095         }
00096         else
00097         {
00098             return Compare(*this,rkI) < 0;
00099         }
00100     }
00101 }
00102 //----------------------------------------------------------------------------
00103 template <int N>
00104 bool TInteger<N>::operator<= (const TInteger& rkI) const
00105 {
00106     int iS0 = GetSign(), iS1 = rkI.GetSign();
00107     if (iS0 > 0)
00108     {
00109         if (iS1 > 0)
00110         {
00111             return Compare(*this,rkI) <= 0;
00112         }
00113         else
00114         {
00115             return false;
00116         }
00117     }
00118     else
00119     {
00120         if (iS1 > 0)
00121         {
00122             return true;
00123         }
00124         else
00125         {
00126             return Compare(*this,rkI) <= 0;
00127         }
00128     }
00129 }
00130 //----------------------------------------------------------------------------
00131 template <int N>
00132 bool TInteger<N>::operator> (const TInteger& rkI) const
00133 {
00134     int iS0 = GetSign(), iS1 = rkI.GetSign();
00135     if (iS0 > 0)
00136     {
00137         if (iS1 > 0)
00138         {
00139             return Compare(*this,rkI) > 0;
00140         }
00141         else
00142         {
00143             return true;
00144         }
00145     }
00146     else
00147     {
00148         if (iS1 > 0)
00149         {
00150             return false;
00151         }
00152         else
00153         {
00154             return Compare(*this,rkI) > 0;
00155         }
00156     }
00157 }
00158 //----------------------------------------------------------------------------
00159 template <int N>
00160 bool TInteger<N>::operator>= (const TInteger& rkI) const
00161 {
00162     int iS0 = GetSign(), iS1 = rkI.GetSign();
00163     if (iS0 > 0)
00164     {
00165         if (iS1 > 0)
00166         {
00167             return Compare(*this,rkI) >= 0;
00168         }
00169         else
00170         {
00171             return true;
00172         }
00173     }
00174     else
00175     {
00176         if (iS1 > 0)
00177         {
00178             return false;
00179         }
00180         else
00181         {
00182             return Compare(*this,rkI) >= 0;
00183         }
00184     }
00185 }
00186 //----------------------------------------------------------------------------
00187 template <int N>
00188 int TInteger<N>::Compare (const TInteger<N>& rkI0, const TInteger<N>& rkI1)
00189 {
00190     for (int i = TINT_LAST; i >= 0; i--)
00191     {
00192         unsigned int uiValue0 = (unsigned int)rkI0.m_asBuffer[i];
00193         unsigned int uiValue1 = (unsigned int)rkI1.m_asBuffer[i];
00194         if (uiValue0 < uiValue1)
00195         {
00196             return -1;
00197         }
00198         else if (uiValue0 > uiValue1)
00199         {
00200             return +1;
00201         }
00202     }
00203     return 0;
00204 }
00205 //----------------------------------------------------------------------------
00206 template <int N>
00207 TInteger<N> TInteger<N>::operator- () const
00208 {
00209     TInteger kResult = *this;
00210 
00211     // negate the bits
00212     int i;
00213     for (i = 0; i < TINT_SIZE; i++)
00214     {
00215         kResult.m_asBuffer[i] = ~kResult.m_asBuffer[i];
00216     }
00217 
00218     // add 1 (place in carry bit and add zero to 'result')
00219     unsigned int uiCarry = 1;
00220     for (i = 0; i < TINT_SIZE; i++)
00221     {
00222         unsigned int uiB1 = kResult.ToUnsignedInt(i);
00223         unsigned int uiSum = uiB1 + uiCarry;
00224         kResult.FromUnsignedInt(i,uiSum);
00225         uiCarry = (uiSum & 0x00010000) ? 1 : 0;
00226     }
00227 
00228     // test for overflow
00229     if (kResult.GetSign() == GetSign())
00230     {
00231         assert(kResult == 0);
00232     }
00233 
00234     return kResult;
00235 }
00236 //----------------------------------------------------------------------------
00237 template <int N>
00238 TInteger<N> TInteger<N>::operator+ (const TInteger& rkI) const
00239 {
00240     TInteger kResult;
00241 
00242     unsigned int uiCarry = 0;
00243     for (int i = 0; i < TINT_SIZE; i++)
00244     {
00245         unsigned int uiB0 = ToUnsignedInt(i);
00246         unsigned int uiB1 = rkI.ToUnsignedInt(i);
00247         unsigned int uiSum = uiB0 + uiB1 + uiCarry;
00248         kResult.FromUnsignedInt(i,uiSum);
00249         uiCarry = (uiSum & 0x00010000) ? 1 : 0;
00250     }
00251 
00252     // test for overflow
00253     if (GetSign() == rkI.GetSign())
00254     {
00255         assert(kResult.GetSign() == GetSign());
00256     }
00257 
00258     return kResult;
00259 }
00260 //----------------------------------------------------------------------------
00261 template <int N>
00262 TInteger<N> TInteger<N>::operator- (const TInteger& rkI) const
00263 {
00264     return *this + (-rkI);
00265 }
00266 //----------------------------------------------------------------------------
00267 template <int N>
00268 TInteger<N> TInteger<N>::operator* (const TInteger& rkI) const
00269 {
00270     int iS0 = GetSign(), iS1 = rkI.GetSign(), iSProduct = iS0*iS1;
00271     TInteger kOp0 = (iS0 > 0 ? *this : -*this);
00272     TInteger kOp1 = (iS1 > 0 ? rkI : -rkI);
00273 
00274     // product of single-digit number with multiple-digit number
00275     unsigned short ausProduct[2*TINT_SIZE];
00276     unsigned short* pusPCurrent = ausProduct;
00277 
00278     // product of the two multiple-digit operands
00279     unsigned short ausResult[2*TINT_SIZE];
00280     unsigned short* pusRCurrent = ausResult;
00281     memset(ausResult,0,2*TINT_BYTES);
00282 
00283     for (int i0 = 0, iSize = 2*TINT_SIZE; i0 < TINT_SIZE; i0++, iSize--)
00284     {
00285         unsigned int uiB0 = kOp0.ToUnsignedInt(i0);
00286         if (uiB0 > 0)
00287         {
00288             unsigned short* pusPBuffer = pusPCurrent;
00289             unsigned int uiCarry = 0;
00290             int i1;
00291             for (i1 = 0; i1 < TINT_SIZE; i1++)
00292             {
00293                 unsigned int uiB1 = kOp1.ToUnsignedInt(i1);
00294                 unsigned int uiProd = uiB0*uiB1 + uiCarry;
00295                 *pusPBuffer++ = (unsigned short)(uiProd & 0x0000FFFF);
00296                 uiCarry = (uiProd & 0xFFFF0000) >> 16;
00297             }
00298             *pusPBuffer = (unsigned short)uiCarry;
00299 
00300             unsigned short* pusRBuffer = pusRCurrent;
00301             pusPBuffer = pusPCurrent;
00302             uiCarry = 0;
00303             unsigned int uiSum, uiTerm0, uiTerm1;
00304             for (i1 = 0; i1 <= TINT_SIZE; i1++)
00305             {
00306                 uiTerm0 = (unsigned int)(*pusPBuffer++);
00307                 uiTerm1 = (unsigned int)(*pusRBuffer);
00308                 uiSum = uiTerm0 + uiTerm1 + uiCarry;
00309                 *pusRBuffer++ = (unsigned short)(uiSum & 0x0000FFFF);
00310                 uiCarry = (uiSum & 0x00010000) ? 1 : 0;
00311             }
00312 
00313             for (; uiCarry > 0 && i1 < iSize; i1++)
00314             {
00315                 uiTerm0 = (unsigned int)(*pusRBuffer);
00316                 uiSum = uiTerm0 + uiCarry;
00317                 *pusRBuffer++ = (unsigned short)(uiSum & 0x0000FFFF);
00318                 uiCarry = (uiSum & 0x00010000) ? 1 : 0;
00319             }
00320         }
00321 
00322         pusPCurrent++;
00323         pusRCurrent++;
00324     }
00325 
00326     // Test for overflow.  You can test earlier inside the previous loop, but
00327     // testing here allows you to get an idea of how much overflow there is.
00328     // This information might be useful for an application to decide how large
00329     // to choose the integer size.
00330     for (int i = 2*TINT_SIZE-1; i >= TINT_SIZE; i--)
00331     {
00332         assert(ausResult[i] == 0);
00333     }
00334     assert((ausResult[TINT_LAST] & 0x8000) == 0);
00335 
00336     TInteger kResult;
00337     System::Memcpy(kResult.m_asBuffer,TINT_BYTES,ausResult,TINT_BYTES);
00338     if (iSProduct < 0)
00339     {
00340         kResult = -kResult;
00341     }
00342 
00343     return kResult;
00344 }
00345 //----------------------------------------------------------------------------
00346 template <int N>
00347 TInteger<N> operator* (int i, const TInteger<N>& rkI)
00348 {
00349     return rkI*i;
00350 }
00351 //----------------------------------------------------------------------------
00352 template <int N>
00353 TInteger<N> TInteger<N>::operator/ (const TInteger& rkI) const
00354 {
00355     // TO DO.  On division by zero, return INVALID or signed INFINITY?
00356     TInteger kQ, kR;
00357     return (GetDivMod(*this,rkI,kQ,kR) ? kQ : 0);
00358 }
00359 //----------------------------------------------------------------------------
00360 template <int N>
00361 TInteger<N> TInteger<N>::operator% (const TInteger& rkI) const
00362 {
00363     // TO DO.  On division by zero, return INVALID or signed INFINITY?
00364     TInteger kQ, kR;
00365     return (GetDivMod(*this,rkI,kQ,kR) ? kR : 0);
00366 }
00367 //----------------------------------------------------------------------------
00368 template <int N>
00369 TInteger<N>& TInteger<N>::operator+= (const TInteger& rkI)
00370 {
00371     *this = *this + rkI;
00372     return *this;
00373 }
00374 //----------------------------------------------------------------------------
00375 template <int N>
00376 TInteger<N>& TInteger<N>::operator-= (const TInteger& rkI)
00377 {
00378     *this = *this - rkI;
00379     return *this;
00380 }
00381 //----------------------------------------------------------------------------
00382 template <int N>
00383 TInteger<N>& TInteger<N>::operator*= (const TInteger& rkI)
00384 {
00385     *this = *this * rkI;
00386     return *this;
00387 }
00388 //----------------------------------------------------------------------------
00389 template <int N>
00390 TInteger<N>& TInteger<N>::operator/= (const TInteger& rkI)
00391 {
00392     *this = *this / rkI;
00393     return *this;
00394 }
00395 //----------------------------------------------------------------------------
00396 template <int N>
00397 TInteger<N> TInteger<N>::operator<< (int iShift) const
00398 {
00399     if (iShift < 0)
00400     {
00401         return 0;
00402     }
00403     if (iShift == 0)
00404     {
00405         return *this;
00406     }
00407 
00408     // number of 16-bit blocks to shift
00409     TInteger kResult;
00410     int iBlocks = iShift / 16;
00411     if (iBlocks > TINT_LAST)
00412     {
00413         return 0;
00414     }
00415 
00416     int i;
00417     if (iBlocks > 0)
00418     {
00419         int j = TINT_LAST-iBlocks;
00420         for (i = TINT_LAST; j >= 0; i--, j--)
00421         {
00422             kResult.m_asBuffer[i] = m_asBuffer[j];
00423         }
00424 
00425         for (; i >= 0; i--)
00426         {
00427             kResult.m_asBuffer[i] = 0;
00428         }
00429     }
00430 
00431     // number of left-over bits to shift
00432     int iBits = iShift % 16;
00433     if (iBits > 0)
00434     {
00435         unsigned int uiLo, uiHi, uiValue;
00436         int iM1;
00437         for (i = TINT_LAST, iM1 = i-1; iM1 >= 0; i--, iM1--)
00438         {
00439             uiLo = ToUnsignedInt(iM1);
00440             uiHi = ToUnsignedInt(i);
00441             uiValue = (uiLo | (uiHi << 16));
00442             uiValue <<= iBits;
00443             kResult.FromUnsignedInt(i,((0xFFFF0000 & uiValue) >> 16));
00444         }
00445 
00446         uiValue = ToUnsignedInt(0);
00447         uiValue <<= iBits;
00448         kResult.FromUnsignedInt(0,(0x0000FFFF & uiValue));
00449     }
00450 
00451     return kResult;
00452 }
00453 //----------------------------------------------------------------------------
00454 template <int N>
00455 TInteger<N> TInteger<N>::operator>> (int iShift) const
00456 {
00457     if (iShift < 0)
00458     {
00459         return 0;
00460     }
00461     if (iShift == 0)
00462     {
00463         return *this;
00464     }
00465 
00466     // number of 16-bit blocks to shift
00467     TInteger kResult;
00468     int iBlocks = iShift/16;
00469     if (iBlocks > TINT_LAST)
00470     {
00471         return 0;
00472     }
00473 
00474     int i;
00475     if (iBlocks > 0)
00476     {
00477         int j = iBlocks;
00478         for (i = 0; j <= TINT_LAST; i++, j++)
00479         {
00480             kResult.m_asBuffer[i] = m_asBuffer[j];
00481         }
00482 
00483         if (GetSign() > 0)
00484         {
00485             for (; i <= TINT_LAST; i++)
00486             {
00487                 kResult.m_asBuffer[i] = 0;
00488             }
00489         }
00490         else
00491         {
00492             for (; i <= TINT_LAST; i++)
00493             {
00494                 kResult.m_asBuffer[i] = (short)(0x0000FFFF);
00495             }
00496         }
00497     }
00498 
00499     // number of left-over bits to shift
00500     int iBits = iShift % 16;
00501     if (iBits > 0)
00502     {
00503         unsigned int uiValue;
00504         int iP1;
00505         for (i = 0, iP1 = 1; iP1 <= TINT_LAST; i++, iP1++)
00506         {
00507             uiValue = ToUnsignedInt(i,iP1);
00508             uiValue >>= iBits;
00509             kResult.FromUnsignedInt(i,uiValue);
00510         }
00511 
00512         uiValue = ToUnsignedInt(TINT_LAST);
00513         if (GetSign() < 0)
00514         {
00515             uiValue |= 0xFFFF0000;  // sign extension
00516         }
00517         uiValue >>= iBits;
00518         kResult.FromUnsignedInt(TINT_LAST,uiValue);
00519     }
00520 
00521     return kResult;
00522 }
00523 //----------------------------------------------------------------------------
00524 template <int N>
00525 TInteger<N>& TInteger<N>::operator<<= (int iShift)
00526 {
00527     if (iShift <= 0)
00528     {
00529         return *this;
00530     }
00531 
00532     // number of 16-bit blocks to shift
00533     TInteger kResult;
00534     int iBlocks = iShift/16;
00535     if (iBlocks > TINT_LAST)
00536     {
00537         return *this;
00538     }
00539 
00540     int i;
00541     if (iBlocks > 0)
00542     {
00543         int j = TINT_LAST-iBlocks;
00544         for (i = TINT_LAST; j >= 0; i--, j--)
00545         {
00546             m_asBuffer[i] = m_asBuffer[j];
00547         }
00548 
00549         for (; i >= 0; i--)
00550         {
00551             m_asBuffer[i] = 0;
00552         }
00553     }
00554 
00555     // number of left-over bits to shift
00556     int iBits = iShift % 16;
00557     if (iBits > 0)
00558     {
00559         unsigned int uiValue;
00560         int iM1;
00561         for (i = TINT_LAST, iM1 = i-1; iM1 >= 0; i--, iM1--)
00562         {
00563             uiValue = ToUnsignedInt(iM1,i);
00564             uiValue <<= iBits;
00565             FromUnsignedInt(i,((0xFFFF0000 & uiValue) >> 16));
00566         }
00567 
00568         uiValue = ToUnsignedInt(0);
00569         uiValue <<= iBits;
00570         FromUnsignedInt(0,(0x0000FFFF & uiValue));
00571     }
00572 
00573     return *this;
00574 }
00575 //----------------------------------------------------------------------------
00576 template <int N>
00577 TInteger<N>& TInteger<N>::operator>>= (int iShift)
00578 {
00579     if (iShift <= 0)
00580     {
00581         return *this;
00582     }
00583 
00584     // number of 16-bit blocks to shift
00585     int iBlocks = iShift/16;
00586     if (iBlocks > TINT_LAST)
00587     {
00588         return *this;
00589     }
00590 
00591     int i;
00592     if (iBlocks > 0)
00593     {
00594         int j = iBlocks;
00595         for (i = 0, j = iBlocks; j <= TINT_LAST; i++, j++)
00596         {
00597             m_asBuffer[i] = m_asBuffer[j];
00598         }
00599 
00600         if (GetSign() > 0)
00601         {
00602             for (; i <= TINT_LAST; i++)
00603             {
00604                 m_asBuffer[i] = 0;
00605             }
00606         }
00607         else
00608         {
00609             for (; i <= TINT_LAST; i++)
00610             {
00611                 m_asBuffer[i] = (short)(0x0000FFFF);
00612             }
00613         }
00614     }
00615 
00616     // number of left-over bits to shift
00617     int iBits = iShift % 16;
00618     if (iBits > 0)
00619     {
00620         unsigned int uiValue;
00621         int iP1;
00622         for (i = 0, iP1 = 1; iP1 <= TINT_LAST; i++, iP1++)
00623         {
00624             uiValue = ToUnsignedInt(i,iP1);
00625             uiValue >>= iBits;
00626             FromUnsignedInt(i,uiValue);
00627         }
00628 
00629         uiValue = ToUnsignedInt(TINT_LAST);
00630         if (GetSign() < 0)
00631         {
00632             uiValue |= 0xFFFF0000;  // sign extension
00633         }
00634         uiValue >>= iBits;
00635         FromUnsignedInt(TINT_LAST,uiValue);
00636     }
00637 
00638     return *this;
00639 }
00640 //----------------------------------------------------------------------------
00641 template <int N>
00642 bool TInteger<N>::GetDivMod (const TInteger& rkNumer, const TInteger& rkDenom,
00643     TInteger& rkQuo, TInteger& rkRem)
00644 {
00645     if (rkDenom == 0)
00646     {
00647         assert(false);
00648         rkQuo = 0;
00649         rkRem = 0;
00650         return false;
00651     }
00652 
00653     if (rkNumer == 0)
00654     {
00655         rkQuo = 0;
00656         rkRem = 0;
00657         return true;
00658     }
00659 
00660     // work with the absolute values of the numerator and denominator
00661     int iS0 = rkNumer.GetSign(), iS1 = rkDenom.GetSign();
00662     TInteger kAbsNumer = iS0*rkNumer;
00663     TInteger kAbsDenom = iS1*rkDenom;
00664 
00665     int iCompare = Compare(kAbsNumer,kAbsDenom);
00666     if (iCompare < 0)
00667     {
00668         // numerator < denominator:  numerator = 0*denominator + numerator
00669         rkQuo = 0;
00670         rkRem = rkNumer;
00671         return true;
00672     }
00673 
00674     if (iCompare == 0)
00675     {
00676         // numerator == denominator:  numerator = 1*denominator + 0
00677         rkQuo = 1;
00678         rkRem = 0;
00679         return true;
00680     }
00681 
00682     // numerator > denominator, do the division to find quotient and remainder
00683     if (kAbsDenom > 0x0000FFFF)
00684     {
00685         DivMultiple(kAbsNumer,kAbsDenom,rkQuo,rkRem);
00686     }
00687     else
00688     {
00689         DivSingle(kAbsNumer,kAbsDenom.m_asBuffer[0],rkQuo,rkRem);
00690     }
00691 
00692     // apply the original signs of numerator and denominator
00693     rkQuo *= iS0*iS1;
00694     rkRem *= iS0;
00695 
00696 #ifdef _DEBUG
00697     TInteger kTest = rkNumer - rkDenom*rkQuo - rkRem;
00698     assert(kTest == 0);
00699 #endif
00700     return true;
00701 }
00702 //----------------------------------------------------------------------------
00703 template <int N>
00704 void TInteger<N>::DivSingle (const TInteger& rkNumer, short sDenom,
00705     TInteger& rkQuo, TInteger& rkRem)
00706 {
00707     // denominator is a single "digit"
00708     unsigned int uiDenom = 0x0000FFFF & (unsigned int)sDenom;
00709 
00710     // numerator
00711     int iNStart = rkNumer.GetLeadingBlock();
00712     const short* psNumer = &rkNumer.m_asBuffer[iNStart];
00713     unsigned int uiDigit1 = 0;
00714 
00715     // quotient
00716     short* psQuo = &rkQuo.m_asBuffer[iNStart];
00717     rkQuo = 0;
00718     int iLastNonZero = -1;
00719     for (int i = iNStart; i >= 0; i--, psNumer--, psQuo--)
00720     {
00721         unsigned int uiDigitB = uiDigit1;
00722         uiDigit1 = 0x0000FFFF & (unsigned int)(*psNumer);
00723         unsigned int uiNumer = (uiDigitB << 16) | uiDigit1;
00724         unsigned int uiQuo = uiNumer/uiDenom;
00725         uiDigit1 = uiNumer - uiQuo*uiDenom;
00726         *psQuo = (short)(uiQuo & 0x0000FFFF);
00727         if (iLastNonZero == -1 && uiQuo > 0)
00728         {
00729             iLastNonZero = i;
00730         }
00731     }
00732     assert(iLastNonZero >= 0);
00733 
00734     // remainder
00735     size_t uiSize;
00736     rkRem = 0;
00737     if (uiDigit1 & 0xFFFF0000)
00738     {
00739         uiSize = 2*sizeof(short);
00740         System::Memcpy(rkRem.m_asBuffer,uiSize,&uiDigit1,uiSize);
00741 #ifdef WM4_BIG_ENDIAN
00742         short sSave = rkRem.m_asBuffer[0];
00743         rkRem.m_asBuffer[0] = rkRem.m_asBuffer[1];
00744         rkRem.m_asBuffer[1] = sSave;
00745 #endif
00746     }
00747     else
00748     {
00749         unsigned short usDigit1 = (unsigned short)uiDigit1;
00750         uiSize = sizeof(short);
00751         System::Memcpy(rkRem.m_asBuffer,uiSize,&usDigit1,uiSize);
00752     }
00753 }
00754 //----------------------------------------------------------------------------
00755 template <int N>
00756 void TInteger<N>::DivMultiple (const TInteger& rkNumer,
00757     const TInteger& rkDenom, TInteger& rkQuo, TInteger& rkRem)
00758 {
00759     rkQuo = 0;
00760     rkRem = 0;
00761 
00762     // Normalization to allow good estimate of quotient.  TO DO:  It is
00763     // possible that the numerator is large enough that normalization causes
00764     // overflow when computing the product iAdjust*rkNumer; an assertion will
00765     // fire in this case.  Ideally the overflow would be allowed and the
00766     // digit in the overflow position becomes the first digit of the numerator
00767     // in the division algorithm.  This will require a mixture of TInteger<N>
00768     // and TInteger<N+1>, though.
00769     int iDInit = rkDenom.GetLeadingBlock();
00770     int iLeadingDigit = rkDenom.ToInt(iDInit);
00771     int iAdjust = 0x10000/(iLeadingDigit+1);
00772     TInteger kANum = iAdjust*rkNumer;
00773     TInteger kADen = iAdjust*rkDenom;
00774     assert(kADen.GetLeadingBlock() == iDInit);
00775 
00776     // get first two "digits" of denominator
00777     unsigned int uiD1 = kADen.ToUnsignedInt(iDInit);
00778     unsigned int uiD2 = kADen.ToUnsignedInt(iDInit-1);
00779 
00780     // determine the maximum necessary division steps
00781     int iNInit = kANum.GetLeadingBlock();
00782     assert(iNInit >= iDInit);
00783     int iQInit;
00784     unsigned int uiRHat;
00785     if (iNInit != iDInit)
00786     {
00787         iQInit = iNInit-iDInit-1;
00788         uiRHat = 1;
00789     }
00790     else
00791     {
00792         iQInit = 0;
00793         uiRHat = 0;
00794     }
00795 
00796     for (; iQInit >= 0; iQInit--)
00797     {
00798         // get first three indices of remainder
00799         unsigned int uiN0, uiN1, uiN2;
00800         if (uiRHat > 0)
00801         {
00802             uiN0 = kANum.ToUnsignedInt(iNInit--);
00803             uiN1 = kANum.ToUnsignedInt(iNInit--);
00804             uiN2 = kANum.ToUnsignedInt(iNInit);
00805         }
00806         else
00807         {
00808             uiN0 = 0;
00809             uiN1 = kANum.ToUnsignedInt(iNInit--);
00810             uiN2 = kANum.ToUnsignedInt(iNInit);
00811         }
00812 
00813         // estimate the quotient
00814         unsigned int uiTmp = (uiN0 << 16) | uiN1;
00815         unsigned int uiQHat = (uiN0 != uiD1 ? uiTmp/uiD1 : 0x0000FFFF);
00816         unsigned int uiProd = uiQHat*uiD1;
00817         assert(uiTmp >= uiProd);
00818         uiRHat = uiTmp - uiProd;
00819         if (uiD2*uiQHat > 0x10000*uiRHat + uiN2)
00820         {
00821             uiQHat--;
00822             uiRHat += uiD1;
00823             if (uiD2*uiQHat > 0x10000*uiRHat + uiN2)
00824             {
00825                 // If this block is entered, we have exactly the quotient for
00826                 // the division.  The adjustment block of code later cannot
00827                 // happen.
00828                 uiQHat--;
00829                 uiRHat += uiD1;
00830             }
00831         }
00832 
00833         // compute the quotient for this step of the division
00834         TInteger kLocalQuo;
00835         kLocalQuo.FromUnsignedInt(iQInit,uiQHat);
00836 
00837         // compute the remainder
00838         TInteger kProduct = kLocalQuo*kADen;
00839         kANum -= kProduct;
00840         if (kANum < 0)
00841         {
00842             uiQHat--;
00843             kANum += kADen;
00844             assert(kANum >= 0);
00845         }
00846 
00847         // set quotient digit
00848         rkQuo.FromUnsignedInt(iQInit,uiQHat);
00849 
00850         if (kANum >= kADen)
00851         {
00852             // prepare to do another division step
00853             iNInit = kANum.GetLeadingBlock();
00854         }
00855         else
00856         {
00857             // remainder is smaller than divisor, finished dividing
00858             break;
00859         }
00860     }
00861 
00862     // unnormalize the remainder
00863     if (kANum > 0)
00864     {
00865         short sDivisor = (short)(iAdjust & 0x0000FFFF);
00866         TInteger kShouldBeZero;
00867         DivSingle(kANum,sDivisor,rkRem,kShouldBeZero);
00868     }
00869     else
00870     {
00871         rkRem = 0;
00872     }
00873 }
00874 //----------------------------------------------------------------------------
00875 template <int N>
00876 int TInteger<N>::GetLeadingBlock () const
00877 {
00878     for (int i = TINT_LAST; i >= 0; i--)
00879     {
00880         if (m_asBuffer[i] != 0)
00881         {
00882             return i;
00883         }
00884     }
00885     return -1;
00886 }
00887 //----------------------------------------------------------------------------
00888 template <int N>
00889 int TInteger<N>::GetTrailingBlock () const
00890 {
00891     for (int i = 0; i <= TINT_LAST; i++)
00892     {
00893         if (m_asBuffer[i] != 0)
00894         {
00895             return i;
00896         }
00897     }
00898     return -1;
00899 }
00900 //----------------------------------------------------------------------------
00901 template <int N>
00902 int TInteger<N>::GetLeadingBit (int i) const
00903 {
00904     assert(0 <= i && i <= TINT_LAST);
00905     if (i < 0 || i > TINT_LAST)
00906     {
00907         return -1;
00908     }
00909 
00910     // This is a binary search for the high-order bit of m_asBuffer[i].  The
00911     // return value is the index into the bits (0 <= index < 16).
00912     int iValue = (int)m_asBuffer[i];
00913     if ((iValue & 0xFF00) != 0)
00914     {
00915         if ((iValue & 0xF000) != 0)
00916         {
00917             if ((iValue & 0xC000) != 0)
00918             {
00919                 if ((iValue & 0x8000) != 0)
00920                 {
00921                     return 15;
00922                 }
00923                 else // (iValue & 0x4000) != 0
00924                 {
00925                     return 14;
00926                 }
00927             }
00928             else  // (iValue & 0x3000) != 0
00929             {
00930                 if ((iValue & 0x2000) != 0)
00931                 {
00932                     return 13;
00933                 }
00934                 else  // (iValue & 0x1000) != 0
00935                 {
00936                     return 12;
00937                 }
00938             }
00939         }
00940         else  // (iValue & 0x0F00) != 0
00941         {
00942             if ((iValue & 0x0C00) != 0)
00943             {
00944                 if ((iValue & 0x0800) != 0)
00945                 {
00946                     return 11;
00947                 }
00948                 else  // (iValue & 0x0400) != 0
00949                 {
00950                     return 10;
00951                 }
00952             }
00953             else  // (iValue & 0x0300) != 0
00954             {
00955                 if ((iValue & 0x0200) != 0)
00956                 {
00957                     return 9;
00958                 }
00959                 else  // (iValue & 0x0100) != 0
00960                 {
00961                     return 8;
00962                 }
00963             }
00964         }
00965     }
00966     else  // (iValue & 0x00FF)
00967     {
00968         if ((iValue & 0x00F0) != 0)
00969         {
00970             if ((iValue & 0x00C0) != 0)
00971             {
00972                 if ((iValue & 0x0080) != 0)
00973                 {
00974                     return 7;
00975                 }
00976                 else  // (iValue & 0x0040) != 0
00977                 {
00978                     return 6;
00979                 }
00980             }
00981             else  // (iValue & 0x0030) != 0
00982             {
00983                 if ((iValue & 0x0020) != 0)
00984                 {
00985                     return 5;
00986                 }
00987                 else  // (iValue & 0x0010) != 0
00988                 {
00989                     return 4;
00990                 }
00991             }
00992         }
00993         else  // (iValue & 0x000F) != 0
00994         {
00995             if ((iValue & 0x000C) != 0)
00996             {
00997                 if ((iValue & 0x0008) != 0)
00998                 {
00999                     return 3;
01000                 }
01001                 else  // (iValue & 0x0004) != 0
01002                 {
01003                     return 2;
01004                 }
01005             }
01006             else  // (iValue & 0x0003) != 0
01007             {
01008                 if ((iValue & 0x0002) != 0)
01009                 {
01010                     return 1;
01011                 }
01012                 else  // (iValue & 0x0001) != 0
01013                 {
01014                     return 0;
01015                 }
01016             }
01017         }
01018     }
01019 
01020     return -1;
01021 }
01022 //----------------------------------------------------------------------------
01023 template <int N>
01024 int TInteger<N>::GetTrailingBit (int i) const
01025 {
01026     assert(0 <= i && i <= TINT_LAST);
01027     if (i < 0 || i > TINT_LAST)
01028     {
01029         return -1;
01030     }
01031 
01032     // This is a binary search for the low-order bit of m_asBuffer[i].  The
01033     // return value is the index into the bits (0 <= index < 16).
01034     int iValue = (int)m_asBuffer[i];
01035     if ((iValue & 0x00FF) != 0)
01036     {
01037         if ((iValue & 0x000F) != 0)
01038         {
01039             if ((iValue & 0x0003) != 0)
01040             {
01041                 if ((iValue & 0x0001) != 0)
01042                 {
01043                     return 0;
01044                 }
01045                 else // (iValue & 0x0002) != 0
01046                 {
01047                     return 1;
01048                 }
01049             }
01050             else  // (iValue & 0x000C) != 0
01051             {
01052                 if ((iValue & 0x0004) != 0)
01053                 {
01054                     return 2;
01055                 }
01056                 else  // (iValue & 0x0080) != 0
01057                 {
01058                     return 3;
01059                 }
01060             }
01061         }
01062         else  // (iValue & 0x00F0) != 0
01063         {
01064             if ((iValue & 0x0030) != 0)
01065             {
01066                 if ((iValue & 0x0010) != 0)
01067                 {
01068                     return 4;
01069                 }
01070                 else  // (iValue & 0x0020) != 0
01071                 {
01072                     return 5;
01073                 }
01074             }
01075             else  // (iValue & 0x00C0) != 0
01076             {
01077                 if ((iValue & 0x0040) != 0)
01078                 {
01079                     return 6;
01080                 }
01081                 else  // (iValue & 0x0080) != 0
01082                 {
01083                     return 7;
01084                 }
01085             }
01086         }
01087     }
01088     else  // (iValue & 0xFF00)
01089     {
01090         if ((iValue & 0x0F00) != 0)
01091         {
01092             if ((iValue & 0x0300) != 0)
01093             {
01094                 if ((iValue & 0x0100) != 0)
01095                 {
01096                     return 8;
01097                 }
01098                 else  // (iValue & 0x0200) != 0
01099                 {
01100                     return 9;
01101                 }
01102             }
01103             else  // (iValue & 0x0C00) != 0
01104             {
01105                 if ((iValue & 0x0400) != 0)
01106                 {
01107                     return 10;
01108                 }
01109                 else  // (iValue & 0x0800) != 0
01110                 {
01111                     return 11;
01112                 }
01113             }
01114         }
01115         else  // (iValue & 0xF000) != 0
01116         {
01117             if ((iValue & 0x3000) != 0)
01118             {
01119                 if ((iValue & 0x1000) != 0)
01120                 {
01121                     return 12;
01122                 }
01123                 else  // (iValue & 0x2000) != 0
01124                 {
01125                     return 13;
01126                 }
01127             }
01128             else  // (iValue & 0xC000) != 0
01129             {
01130                 if ((iValue & 0x4000) != 0)
01131                 {
01132                     return 14;
01133                 }
01134                 else  // (iValue & 0x8000) != 0
01135                 {
01136                     return 15;
01137                 }
01138             }
01139         }
01140     }
01141 
01142     return -1;
01143 }
01144 //----------------------------------------------------------------------------
01145 template <int N>
01146 int TInteger<N>::GetLeadingBit () const
01147 {
01148     int iBlock = GetLeadingBlock();
01149     if (iBlock >= 0)
01150     {
01151         int iBit = GetLeadingBit(iBlock);
01152         if (iBit >= 0)
01153         {
01154             return iBit+16*iBlock;
01155         }
01156     }
01157 
01158     return -1;
01159 }
01160 //----------------------------------------------------------------------------
01161 template <int N>
01162 int TInteger<N>::GetTrailingBit () const
01163 {
01164     int iBlock = GetTrailingBlock();
01165     if (iBlock >= 0)
01166     {
01167         int iBit = GetTrailingBit(iBlock);
01168         if (iBit >= 0)
01169         {
01170             return iBit+16*iBlock;
01171         }
01172     }
01173 
01174     return -1;
01175 }
01176 //----------------------------------------------------------------------------
01177 template <int N>
01178 void TInteger<N>::SetBit (int i, bool bOn)
01179 {
01180     // assert(0 <= i && i <= TINT_LAST);
01181     int iBlock = i/16;
01182     int iBit = i%16;
01183     if (bOn)
01184     {
01185         m_asBuffer[iBlock] |= (1 << iBit);
01186     }
01187     else
01188     {
01189         m_asBuffer[iBlock] &= ~(1 << iBit);
01190     }
01191 }
01192 //----------------------------------------------------------------------------
01193 template <int N>
01194 bool TInteger<N>::GetBit (int i) const
01195 {
01196     // assert(0 <= i && i <= TINT_LAST);
01197     int iBlock = i/16;
01198     int iBit = i%16;
01199     return (m_asBuffer[iBlock] & (1 << iBit)) != 0;
01200 }
01201 //----------------------------------------------------------------------------
01202 template <int N>
01203 unsigned int TInteger<N>::ToUnsignedInt (int i) const
01204 {
01205     // assert(0 <= i && i <= TINT_LAST);
01206     return 0x0000FFFF & (unsigned int)m_asBuffer[i];
01207 }
01208 //----------------------------------------------------------------------------
01209 template <int N>
01210 void TInteger<N>::FromUnsignedInt (int i, unsigned int uiValue)
01211 {
01212     // assert(0 <= i && i <= TINT_LAST);
01213     m_asBuffer[i] = (short)(uiValue & 0x0000FFFF);
01214 }
01215 //----------------------------------------------------------------------------
01216 template <int N>
01217 unsigned int TInteger<N>::ToUnsignedInt (int iLo, int iHi) const
01218 {
01219     unsigned int uiLo = ToUnsignedInt(iLo);
01220     unsigned int uiHi = ToUnsignedInt(iHi);
01221     return (uiLo | (uiHi << 16));
01222 }
01223 //----------------------------------------------------------------------------
01224 template <int N>
01225 int TInteger<N>::ToInt (int i) const
01226 {
01227     // assert(0 <= i && i <= TINT_LAST);
01228     return (int)(0x0000FFFF & (unsigned int)m_asBuffer[i]);
01229 }
01230 //----------------------------------------------------------------------------
01231 } //namespace Wm4

Generated on Wed Nov 23 19:01:09 2011 for FreeCAD by  doxygen 1.6.1