Wm4TRational.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 TRational<N>::TRational ()
00022     :
00023     m_kNumer(0),
00024     m_kDenom(1)
00025 {
00026     // default construction produces the zero rational number
00027 }
00028 //----------------------------------------------------------------------------
00029 template <int N>
00030 TRational<N>::TRational (const TRational& rkR)
00031     :
00032     m_kNumer(rkR.m_kNumer),
00033     m_kDenom(rkR.m_kDenom)
00034 {
00035 }
00036 //----------------------------------------------------------------------------
00037 template <int N>
00038 TRational<N>::TRational (const TInteger<N>& rkNumer)
00039     :
00040     m_kNumer(rkNumer),
00041     m_kDenom(1)
00042 {
00043 }
00044 //----------------------------------------------------------------------------
00045 template <int N>
00046 TRational<N>::TRational (const TInteger<N>& rkNumer,
00047     const TInteger<N>& rkDenom)
00048     :
00049     m_kNumer(rkNumer),
00050     m_kDenom(rkDenom)
00051 {
00052 }
00053 //----------------------------------------------------------------------------
00054 template <int N>
00055 TRational<N>::TRational (int iNumer)
00056     :
00057     m_kNumer(iNumer),
00058     m_kDenom(1)
00059 {
00060 }
00061 //----------------------------------------------------------------------------
00062 template <int N>
00063 TRational<N>::TRational (int iNumer, int iDenom)
00064     :
00065     m_kNumer(iNumer),
00066     m_kDenom(iDenom)
00067 {
00068 }
00069 //----------------------------------------------------------------------------
00070 template <int N>
00071 TInteger<N>& TRational<N>::Numer ()
00072 {
00073     return m_kNumer;
00074 }
00075 //----------------------------------------------------------------------------
00076 template <int N>
00077 TInteger<N>& TRational<N>::Denom ()
00078 {
00079     return m_kDenom;
00080 }
00081 //----------------------------------------------------------------------------
00082 template <int N>
00083 const TInteger<N>& TRational<N>::Numer () const
00084 {
00085     return m_kNumer;
00086 }
00087 //----------------------------------------------------------------------------
00088 template <int N>
00089 const TInteger<N>& TRational<N>::Denom () const
00090 {
00091     return m_kDenom;
00092 }
00093 //----------------------------------------------------------------------------
00094 template <int N>
00095 TRational<N>& TRational<N>::operator= (const TRational& rkR)
00096 {
00097     m_kNumer = rkR.m_kNumer;
00098     m_kDenom = rkR.m_kDenom;
00099     return *this;
00100 }
00101 //----------------------------------------------------------------------------
00102 template <int N>
00103 bool TRational<N>::operator== (const TRational& rkR) const
00104 {
00105     return (m_kNumer*rkR.m_kDenom == m_kDenom*rkR.m_kNumer);
00106 }
00107 //----------------------------------------------------------------------------
00108 template <int N>
00109 bool TRational<N>::operator!= (const TRational& rkR) const
00110 {
00111     return (m_kNumer*rkR.m_kDenom != m_kDenom*rkR.m_kNumer);
00112 }
00113 //----------------------------------------------------------------------------
00114 template <int N>
00115 bool TRational<N>::operator<= (const TRational& rkR) const
00116 {
00117     TInteger<N> kProd0 = m_kNumer*rkR.m_kDenom;
00118     TInteger<N> kProd1 = m_kDenom*rkR.m_kNumer;
00119     if (m_kDenom > 0)
00120     {
00121         return (rkR.m_kDenom > 0 ? kProd0 <= kProd1 : kProd0 >= kProd1);
00122     }
00123     else
00124     {
00125         return (rkR.m_kDenom > 0 ? kProd0 >= kProd1 : kProd0 <= kProd1);
00126     }
00127 }
00128 //----------------------------------------------------------------------------
00129 template <int N>
00130 bool TRational<N>::operator< (const TRational& rkR) const
00131 {
00132     TInteger<N> kProd0 = m_kNumer*rkR.m_kDenom;
00133     TInteger<N> kProd1 = m_kDenom*rkR.m_kNumer;
00134     if (m_kDenom > 0)
00135     {
00136         return (rkR.m_kDenom > 0 ? kProd0 < kProd1 : kProd0 > kProd1);
00137     }
00138     else
00139     {
00140         return (rkR.m_kDenom > 0 ? kProd0 > kProd1 : kProd0 < kProd1);
00141     }
00142 }
00143 //----------------------------------------------------------------------------
00144 template <int N>
00145 bool TRational<N>::operator>= (const TRational& rkR) const
00146 {
00147     TInteger<N> kProd0 = m_kNumer*rkR.m_kDenom;
00148     TInteger<N> kProd1 = m_kDenom*rkR.m_kNumer;
00149     if (m_kDenom > 0)
00150     {
00151         return (rkR.m_kDenom > 0 ? kProd0 >= kProd1 : kProd0 <= kProd1);
00152     }
00153     else
00154     {
00155         return (rkR.m_kDenom > 0 ? kProd0 <= kProd1 : kProd0 >= kProd1);
00156     }
00157 }
00158 //----------------------------------------------------------------------------
00159 template <int N>
00160 bool TRational<N>::operator> (const TRational& rkR) const
00161 {
00162     TInteger<N> kProd0 = m_kNumer*rkR.m_kDenom;
00163     TInteger<N> kProd1 = m_kDenom*rkR.m_kNumer;
00164     if (m_kDenom > 0)
00165     {
00166         return (rkR.m_kDenom > 0 ? kProd0 > kProd1 : kProd0 < kProd1);
00167     }
00168     else
00169     {
00170         return (rkR.m_kDenom > 0 ? kProd0 < kProd1 : kProd0 > kProd1);
00171     }
00172 }
00173 //----------------------------------------------------------------------------
00174 template <int N>
00175 TRational<N> TRational<N>::operator+ (const TRational& rkR) const
00176 {
00177     TRational kSum;
00178     kSum.m_kNumer = m_kNumer*rkR.m_kDenom + m_kDenom*rkR.m_kNumer;
00179     kSum.m_kDenom = m_kDenom*rkR.m_kDenom;
00180     kSum.EliminatePowersOfTwo();
00181     return kSum;
00182 }
00183 //----------------------------------------------------------------------------
00184 template <int N>
00185 TRational<N> TRational<N>::operator- (const TRational& rkR) const
00186 {
00187     TRational kDiff;
00188     kDiff.m_kNumer = m_kNumer*rkR.m_kDenom - m_kDenom*rkR.m_kNumer;
00189     kDiff.m_kDenom = m_kDenom*rkR.m_kDenom;
00190     kDiff.EliminatePowersOfTwo();
00191     return kDiff;
00192 }
00193 //----------------------------------------------------------------------------
00194 template <int N>
00195 TRational<N> TRational<N>::operator* (const TRational& rkR) const
00196 {
00197     TRational kProd;
00198     kProd.m_kNumer = m_kNumer*rkR.m_kNumer;
00199     kProd.m_kDenom = m_kDenom*rkR.m_kDenom;
00200     kProd.EliminatePowersOfTwo();
00201     return kProd;
00202 }
00203 //----------------------------------------------------------------------------
00204 template <int N>
00205 TRational<N> TRational<N>::operator/ (const TRational& rkR) const
00206 {
00207     TRational kQuot;
00208     kQuot.m_kNumer = m_kNumer*rkR.m_kDenom;
00209     kQuot.m_kDenom = m_kDenom*rkR.m_kNumer;
00210     kQuot.EliminatePowersOfTwo();
00211     return kQuot;
00212 }
00213 //----------------------------------------------------------------------------
00214 template <int N>
00215 TRational<N> TRational<N>::operator- () const
00216 {
00217     TRational kNeg;
00218     kNeg.m_kNumer = -m_kNumer;
00219     kNeg.m_kDenom = m_kDenom;
00220     return kNeg;
00221 }
00222 //----------------------------------------------------------------------------
00223 template <int N>
00224 TRational<N> operator+ (const TInteger<N>& rkI, const TRational<N>& rkR)
00225 {
00226     TRational<N> kSum;
00227     kSum.Numer() = rkI*rkR.Denom() + rkR.Numer();
00228     kSum.Denom() = rkR.Denom();
00229     return kSum;
00230 }
00231 //----------------------------------------------------------------------------
00232 template <int N>
00233 TRational<N> operator- (const TInteger<N>& rkI, const TRational<N>& rkR)
00234 {
00235     TRational<N> kDiff;
00236     kDiff.Numer() = rkI*rkR.Denom() - rkR.Numer();
00237     kDiff.Denom() = rkR.Denom();
00238     return kDiff;
00239 }
00240 //----------------------------------------------------------------------------
00241 template <int N>
00242 TRational<N> operator* (const TInteger<N>& rkI, const TRational<N>& rkR)
00243 {
00244     TRational<N> kProd;
00245     kProd.Numer() = rkI*rkR.Numer();
00246     kProd.Denom() = rkR.Denom();
00247     return kProd;
00248 }
00249 //----------------------------------------------------------------------------
00250 template <int N>
00251 TRational<N> operator/ (const TInteger<N>& rkI, const TRational<N>& rkR)
00252 {
00253     TRational<N> kQuot;
00254     kQuot.Numer() = rkR.Denom()*rkI;
00255     kQuot.Denom() = rkR.Numer();
00256     return kQuot;
00257 }
00258 //----------------------------------------------------------------------------
00259 template <int N>
00260 TRational<N>& TRational<N>::operator+= (const TRational& rkR)
00261 {
00262     *this = *this + rkR;
00263     EliminatePowersOfTwo();
00264     return *this;
00265 }
00266 //----------------------------------------------------------------------------
00267 template <int N>
00268 TRational<N>& TRational<N>::operator-= (const TRational& rkR)
00269 {
00270     *this = *this - rkR;
00271     EliminatePowersOfTwo();
00272     return *this;
00273 }
00274 //----------------------------------------------------------------------------
00275 template <int N>
00276 TRational<N>& TRational<N>::operator*= (const TRational& rkR)
00277 {
00278     *this = (*this)*rkR;
00279     EliminatePowersOfTwo();
00280     return *this;
00281 }
00282 //----------------------------------------------------------------------------
00283 template <int N>
00284 TRational<N>& TRational<N>::operator/= (const TRational& rkR)
00285 {
00286     *this = (*this)/rkR;
00287     EliminatePowersOfTwo();
00288     return *this;
00289 }
00290 //----------------------------------------------------------------------------
00291 template <int N>
00292 TRational<N> TRational<N>::Abs () const
00293 {
00294     return (*this >= 0 ? *this : -(*this));
00295 }
00296 //----------------------------------------------------------------------------
00297 template <int N>
00298 void TRational<N>::EliminatePowersOfTwo ()
00299 {
00300     if ((m_kNumer.m_asBuffer[0] & 1) > 0
00301     ||  (m_kDenom.m_asBuffer[0] & 1) > 0)
00302     {
00303         // neither term is divisible by 2 (quick out)
00304         return;
00305     }
00306 
00307     int iBlock0 = m_kNumer.GetTrailingBlock();
00308     if (iBlock0 == -1)
00309     {
00310         // numerator is zero
00311         m_kDenom = 1;
00312         return;
00313     }
00314 
00315     int iBlock1 = m_kDenom.GetTrailingBlock();
00316     assert(iBlock1 >= 0);  // denominator should never be zero
00317     int iMinBlock = (iBlock0 < iBlock1 ? iBlock0 : iBlock1);
00318     int iBit0 = m_kNumer.GetTrailingBit(iBlock0);
00319     int iBit1 = m_kDenom.GetTrailingBit(iBlock1);
00320     int iMinBit = (iBit0 < iBit1 ? iBit0 : iBit1);
00321     int iShift = 16*iMinBlock + iMinBit;
00322     m_kNumer >>= iShift;
00323     m_kDenom >>= iShift;
00324 }
00325 //----------------------------------------------------------------------------
00326 
00327 //----------------------------------------------------------------------------
00328 // conversions between rational numbers and 'float'
00329 //----------------------------------------------------------------------------
00330 template <int N>
00331 TRational<N>::TRational (float fValue)
00332 {
00333     TInteger<N> kOne(1);
00334     m_kDenom = kOne;
00335     if (fValue == 0.0f)
00336     {
00337         m_kNumer = TInteger<N>(0);
00338         return;
00339     }
00340 
00341     // value = sign * 1.mantissa * 2^exponent
00342 #if 0
00343     unsigned int uiBits = *(unsigned int*)&fValue;
00344 #else
00345     union {float f; unsigned int i;} value = {fValue};
00346     unsigned int uiBits = value.i;
00347 #endif
00348     unsigned int uiSign = (0x80000000u & uiBits);
00349     unsigned int uiExponent = ((0x7F800000 & uiBits) >> 23);
00350     unsigned int uiMantissa = (0x007FFFFF & uiBits);
00351 
00352     // create 1.mantissa
00353     TRational kFraction(1,2);
00354     TInteger<N> kTwo(2);
00355     m_kNumer = kOne;
00356     unsigned int uiMask;
00357     for (uiMask = 0x00400000; uiMask; uiMask >>= 1, kFraction /= kTwo)
00358     {
00359         if (uiMantissa & uiMask)
00360         {
00361             *this += kFraction;
00362         }
00363     }
00364 
00365     // multiply by 2^exponent
00366     TRational kMultiplier;
00367     TInteger<N> kPower(2);
00368     int i, iDelay = 0;
00369     if (uiExponent & 0x00000080)
00370     {
00371         kMultiplier = 2;
00372         for (i = 0; i <= 6; i++, uiExponent >>= 1, iDelay++)
00373         {
00374             if (uiExponent & 1)
00375             {
00376                 while (--iDelay >= 0)
00377                 {
00378                     kPower *= kPower;
00379                 }
00380 
00381                 kMultiplier *= kPower;
00382                 iDelay = 0;
00383             }
00384         }
00385     }
00386     else
00387     {
00388         kMultiplier = 1;
00389         for (i = 0; i <= 6; i++, uiExponent >>= 1, iDelay++)
00390         {
00391             if (!(uiExponent & 1))
00392             {
00393                 while (--iDelay >= 0)
00394                 {
00395                     kPower *= kPower;
00396                 }
00397 
00398                 kMultiplier /= kPower;
00399                 iDelay = 0;
00400             }
00401         }
00402     }
00403 
00404     *this *= kMultiplier;
00405 
00406     EliminatePowersOfTwo();
00407 
00408     if (uiSign)
00409     {
00410         m_kNumer = -m_kNumer;
00411     }
00412 }
00413 //----------------------------------------------------------------------------
00414 template <int N>
00415 void TRational<N>::ConvertTo (float& rfValue) const
00416 {
00417     assert(m_kDenom != 0);
00418     if (m_kNumer == 0)
00419     {
00420         rfValue = 0.0f;
00421         return;
00422     }
00423 
00424     unsigned int uiResult;
00425 
00426     // compute the sign of the number
00427     int iS0 = m_kNumer.GetSign(), iS1 = m_kDenom.GetSign();
00428     int iSign = iS0*iS1;
00429     TInteger<N> kAbsNumer = iS0*m_kNumer;
00430     TInteger<N> kAbsDenom = iS1*m_kDenom;
00431 
00432     // The rational number is N/D = Q + R/D.  We need to extract 24 bits for
00433     // 1.mantissa and determine the biased exponent.
00434     TInteger<N> kQuo, kRem;
00435     bool bSuccess = TInteger<N>::GetDivMod(kAbsNumer,kAbsDenom,kQuo,kRem);
00436     assert(bSuccess);
00437 
00438     unsigned int uiExponent = 0, uiMantissa = 0;
00439 
00440     int iBlock = kQuo.GetLeadingBlock();
00441     if (iBlock >= 0)
00442     {
00443         // quotient is positive
00444         if (iBlock >= 8)
00445         {
00446             // quotient larger than the maximum float in magnitude
00447             if (iSign > 0)
00448             {
00449                 uiResult = 0x7F7FFFFFu;  // FLT_MAX
00450                 rfValue = *(float*)&uiResult;
00451             }
00452             else
00453             {
00454                 uiResult = 0xFF7FFFFFu;  // -FLT_MAX
00455                 rfValue = *(float*)&uiResult;
00456             }
00457             return;
00458         }
00459 
00460         if (iBlock == 7)
00461         {
00462             unsigned int uiValue = kQuo.ToUnsignedInt(iBlock-1,iBlock);
00463             if ((uiValue & 0xFFFFFF00u) == 0xFFFFFF00u)
00464             {
00465                 // quotient larger or equal to the maximum float in magnitude
00466                 if (iSign > 0)
00467                 {
00468                     uiResult = 0x7F7FFFFFu;  // FLT_MAX
00469                     rfValue = *(float*)&uiResult;
00470                 }
00471                 else
00472                 {
00473                     uiResult = 0xFF7FFFFFu;  // -FLT_MAX
00474                     rfValue = *(float*)&uiResult;
00475                 }
00476                 return;
00477             }
00478         }
00479 
00480         // quotient smaller than the maximum float
00481         GetPositiveFloat(kAbsDenom,kQuo,kRem,iBlock,uiExponent,uiMantissa);
00482         uiResult = uiExponent | uiMantissa;
00483         if (iSign < 0)
00484         {
00485             uiResult |= 0x80000000;
00486         }
00487         rfValue = *(float*)&uiResult;
00488         return;
00489     }
00490 
00491     // remainder provides all of 1.mantissa
00492     for (iBlock = 0; iBlock < 8; iBlock++)
00493     {
00494         // Multiply by 2^{16} to search for 1-bits.  We could do this in one
00495         // step by using 2^{128}, but this could require an intermediate
00496         // term of N=16.  The smaller multipliers keep the intermediate terms
00497         // small.
00498         kRem *= 0x10000;
00499         TInteger<N> kNRem;
00500         bSuccess = TInteger<N>::GetDivMod(kRem,kAbsDenom,kQuo,kNRem);
00501         assert(bSuccess);
00502         kRem = kNRem;
00503         if (kQuo != 0)
00504         {
00505             break;
00506         }
00507     }
00508 
00509     if (iBlock == 8 || (iBlock == 7 && kQuo.ToUnsignedInt(0) >= 4))
00510     {
00511         // rational number smaller than the minimum floating point number
00512         if (iSign > 0)
00513         {
00514             uiResult = 0x00800000;  // FLT_MIN
00515             rfValue = *(float*)&uiResult;
00516         }
00517         else
00518         {
00519             uiResult = 0x80800000;  // -FLT_MIN
00520             rfValue = *(float*)&uiResult;
00521         }
00522         return;
00523     }
00524 
00525     // get representation of scaled remainder
00526     GetPositiveFloat(kAbsDenom,kQuo,kRem,0,uiExponent,uiMantissa);
00527 
00528     // adjust exponent by how many blocks were used to scale the remainder
00529     uiExponent >>= 23;
00530     uiExponent -= 127;
00531     uiExponent -= 16*(iBlock+1);
00532     uiExponent += 127;
00533     uiExponent <<= 23;
00534 
00535     uiResult = uiExponent | uiMantissa;
00536     if (iSign < 0)
00537     {
00538         uiResult |= 0x80000000u;
00539     }
00540 
00541     rfValue = *(float*)&uiResult;
00542 }
00543 //----------------------------------------------------------------------------
00544 template <int N>
00545 void TRational<N>::GetPositiveFloat (const TInteger<N>& rkDenom,
00546     TInteger<N>& rkQuo, TInteger<N>& rkRem, int iBlock,
00547     unsigned int& ruiExponent, unsigned int& ruiMantissa)
00548 {
00549     // assert(rkDenom > 0 && rkQuo > 0);
00550 
00551     // quotient smaller than the maximum float
00552     int iFirstBlockBit = rkQuo.GetLeadingBit(iBlock);
00553     int iFirstBit = iFirstBlockBit+16*iBlock;
00554     unsigned int uiMask;
00555     ruiExponent = ((iFirstBit + 127) << 23);
00556     iFirstBit--;
00557     ruiMantissa = 0;
00558     if (iFirstBit >= 23)
00559     {
00560         // quotient provides all of 1.mantissa
00561         for (uiMask = 0x00400000; uiMask; uiMask >>= 1, iFirstBit--)
00562         {
00563             if (rkQuo.GetBit(iFirstBit))
00564             {
00565                 ruiMantissa |= uiMask;
00566             }
00567         }
00568     }
00569     else
00570     {
00571         // quotient contribution to 1.mantissa
00572         for (uiMask = 0x00400000; iFirstBit >= 0; uiMask >>= 1, iFirstBit--)
00573         {
00574             if (rkQuo.GetBit(iFirstBit))
00575             {
00576                 ruiMantissa |= uiMask;
00577             }
00578         }
00579 
00580         // remainder contribution to 1.mantissa
00581         for (; uiMask; uiMask >>= 1)
00582         {
00583             rkRem *= 2;
00584             TInteger<N> kNRem;
00585             bool bSuccess = TInteger<N>::GetDivMod(rkRem,rkDenom,rkQuo,kNRem);
00586             assert(bSuccess);
00587             (void)bSuccess;  // avoid compiler warning in release build
00588             if (rkQuo != 0)
00589             {
00590                 ruiMantissa |= uiMask;
00591             }
00592             rkRem = kNRem;
00593         }
00594     }
00595 }
00596 //----------------------------------------------------------------------------
00597 
00598 //----------------------------------------------------------------------------
00599 // conversions between rational numbers and 'double'
00600 //----------------------------------------------------------------------------
00601 template <int N>
00602 TRational<N>::TRational (double dValue)
00603 {
00604     TInteger<N> kOne(1);
00605     m_kDenom = kOne;
00606     if (dValue == 0.0)
00607     {
00608         m_kNumer = TInteger<N>(0);
00609         return;
00610     }
00611 
00612     // value = sign * 1.mantissa * 2^exponent
00613 #if 0
00614     unsigned int* auiBits = (unsigned int*)&dValue;
00615 #else
00616     union {double *d; unsigned int *i;} value = {&dValue};
00617     unsigned int* auiBits = value.i;
00618 #endif
00619 #ifdef WM4_BIG_ENDIAN
00620     unsigned int uiSave = auiBits[0];
00621     auiBits[0] = auiBits[1];
00622     auiBits[1] = uiSave;
00623 #endif
00624     unsigned int uiSign = (0x80000000u & auiBits[1]);
00625     unsigned int uiExponent = ((0x7FF00000 & auiBits[1]) >> 20);
00626     unsigned int uiMantissaHi = (0x000FFFFF & auiBits[1]);
00627     unsigned int uiMantissaLo = auiBits[0];
00628 
00629     // create 1.mantissa
00630     TRational kFraction(1,2);
00631     TInteger<N> kTwo(2);
00632     m_kNumer = kOne;
00633     unsigned int uiMask;
00634     for (uiMask = 0x00080000; uiMask; uiMask >>= 1, kFraction /= kTwo)
00635     {
00636         if (uiMantissaHi & uiMask)
00637         {
00638             *this += kFraction;
00639         }
00640     }
00641     for (uiMask = 0x80000000u; uiMask; uiMask >>= 1, kFraction /= kTwo)
00642     {
00643         if (uiMantissaLo & uiMask)
00644         {
00645             *this += kFraction;
00646         }
00647     }
00648 
00649     // multiply by 2^exponent
00650     TRational kMultiplier;
00651     TInteger<N> kPower(2);
00652     int i, iDelay = 0;
00653     if (uiExponent & 0x400)
00654     {
00655         kMultiplier = 2;
00656         for (i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++)
00657         {
00658             if (uiExponent & 1)
00659             {
00660                 while (--iDelay >= 0)
00661                 {
00662                     kPower *= kPower;
00663                 }
00664 
00665                 kMultiplier *= kPower;
00666                 iDelay = 0;
00667             }
00668         }
00669     }
00670     else
00671     {
00672         kMultiplier = 1;
00673         for (i = 0; i <= 9; i++, uiExponent >>= 1, iDelay++)
00674         {
00675             if (!(uiExponent & 1))
00676             {
00677                 while (--iDelay >= 0)
00678                 {
00679                     kPower *= kPower;
00680                 }
00681 
00682                 kMultiplier /= kPower;
00683                 iDelay = 0;
00684             }
00685         }
00686     }
00687 
00688     *this *= kMultiplier;
00689 
00690     EliminatePowersOfTwo();
00691 
00692     if (uiSign)
00693     {
00694         m_kNumer = -m_kNumer;
00695     }
00696 }
00697 //----------------------------------------------------------------------------
00698 template <int N>
00699 void TRational<N>::ConvertTo (double& rdValue) const
00700 {
00701     assert(m_kDenom != 0);
00702     if (m_kNumer == 0)
00703     {
00704         rdValue = 0.0;
00705         return;
00706     }
00707 
00708     unsigned int auiResult[2], uiSave = 0;
00709 
00710     // compute the sign of the number
00711     int iS0 = m_kNumer.GetSign(), iS1 = m_kDenom.GetSign();
00712     int iSign = iS0*iS1;
00713     TInteger<N> kAbsNumer = iS0*m_kNumer;
00714     TInteger<N> kAbsDenom = iS1*m_kDenom;
00715 
00716     // The rational number is N/D = Q + R/D.  We need to extract 53 bits for
00717     // 1.mantissa and determine the biased exponent.
00718     TInteger<N> kQuo, kRem;
00719     bool bSuccess = TInteger<N>::GetDivMod(kAbsNumer,kAbsDenom,kQuo,kRem);
00720     assert(bSuccess);
00721 
00722     unsigned int uiExponent = 0, uiMantissaHi = 0, uiMantissaLo;
00723 
00724     int iBlock = kQuo.GetLeadingBlock();
00725     if (iBlock >= 0)
00726     {
00727         // quotient is positive
00728         if (iBlock >= 64)
00729         {
00730             // quotient larger than the maximum double in magnitude
00731             if (iSign > 0)
00732             {
00733                 auiResult[0] = 0xFFFFFFFF;  // DBL_MAX
00734                 auiResult[1] = 0x7FEFFFFF;
00735 #ifdef WM4_BIG_ENDIAN
00736                 uiSave = auiResult[0];
00737                 auiResult[0] = auiResult[1];
00738                 auiResult[1] = uiSave;
00739 #endif
00740                 rdValue = *(double*)auiResult;
00741             }
00742             else
00743             {
00744                 auiResult[0] = 0xFFFFFFFF;  // -DBL_MAX
00745                 auiResult[1] = 0xFFEFFFFF;
00746 #ifdef WM4_BIG_ENDIAN
00747                 uiSave = auiResult[0];
00748                 auiResult[0] = auiResult[1];
00749                 auiResult[1] = uiSave;
00750 #endif
00751                 rdValue = *(double*)auiResult;
00752             }
00753             return;
00754         }
00755 
00756         if (iBlock == 63)
00757         {
00758             unsigned int uiValueHi = kQuo.ToUnsignedInt(iBlock-1,iBlock);
00759             unsigned int uiValueLo = kQuo.ToUnsignedInt(iBlock-3,iBlock-2);
00760             if ((uiValueHi & 0xFFFFFFFF) == 0xFFFFFFFF
00761             &&  (uiValueLo & 0xFFFFF800) == 0xFFFFF800)
00762             {
00763                 // quotient larger or equal to the maximum float in magnitude
00764                 if (iSign > 0)
00765                 {
00766                     auiResult[0] = 0xFFFFFFFF;  // DBL_MAX
00767                     auiResult[1] = 0x7FEFFFFF;
00768 #ifdef WM4_BIG_ENDIAN
00769                     uiSave = auiResult[0];
00770                     auiResult[0] = auiResult[1];
00771                     auiResult[1] = uiSave;
00772 #endif
00773                     rdValue = *(double*)auiResult;
00774                 }
00775                 else
00776                 {
00777                     auiResult[0] = 0xFFFFFFFF;  // -DBL_MAX
00778                     auiResult[1] = 0xFFEFFFFF;
00779 #ifdef WM4_BIG_ENDIAN
00780                     uiSave = auiResult[0];
00781                     auiResult[0] = auiResult[1];
00782                     auiResult[1] = uiSave;
00783 #endif
00784                     rdValue = *(double*)auiResult;
00785                 }
00786                 return;
00787             }
00788         }
00789 
00790         // quotient smaller than the maximum float
00791         GetPositiveDouble(kAbsDenom,kQuo,kRem,iBlock,uiExponent,uiMantissaHi,
00792             uiMantissaLo);
00793         auiResult[1] = uiExponent | uiMantissaHi;
00794         auiResult[0] = uiMantissaLo;
00795         if (iSign < 0)
00796         {
00797             auiResult[1] |= 0x80000000u;
00798         }
00799 #ifdef WM4_BIG_ENDIAN
00800         uiSave = auiResult[0];
00801         auiResult[0] = auiResult[1];
00802         auiResult[1] = uiSave;
00803 #endif
00804         rdValue = *(double*)auiResult;
00805         return;
00806     }
00807 
00808     // remainder provides all of 1.mantissa
00809     for (iBlock = 0; iBlock < 64; iBlock++)
00810     {
00811         // Multiply by 2^{16} to search for 1-bits.  We could do this in one
00812         // step by using 2^{1024}, but this could require an intermediate
00813         // term of large N.  The smaller multipliers keep the intermediate
00814         // terms small.
00815         kRem *= 0x10000;
00816         TInteger<N> kNRem;
00817         bSuccess = TInteger<N>::GetDivMod(kRem,kAbsDenom,kQuo,kNRem);
00818         assert(bSuccess);
00819         kRem = kNRem;
00820         if (kQuo != 0)
00821         {
00822             break;
00823         }
00824     }
00825 
00826     if (iBlock == 64 || (iBlock == 63 && kQuo.ToUnsignedInt(0) >= 4 /*?*/))
00827     {
00828         // rational number smaller than the minimum floating point number
00829         if (iSign > 0)
00830         {
00831             auiResult[1] = 0x00100000;  // DBL_MIN
00832             auiResult[0] = 0x00000000;
00833 #ifdef WM4_BIG_ENDIAN
00834             uiSave = auiResult[0];
00835             auiResult[0] = auiResult[1];
00836             auiResult[1] = uiSave;
00837 #endif
00838             rdValue = *(double*)auiResult;
00839         }
00840         else
00841         {
00842             auiResult[1] = 0x80100000;  // -DBL_MIN
00843             auiResult[0] = 0x00000000;
00844 #ifdef WM4_BIG_ENDIAN
00845             uiSave = auiResult[0];
00846             auiResult[0] = auiResult[1];
00847             auiResult[1] = uiSave;
00848 #endif
00849             rdValue = *(double*)auiResult;
00850         }
00851         return;
00852     }
00853 
00854     // get representation of scaled remainder
00855     GetPositiveDouble(kAbsDenom,kQuo,kRem,0,uiExponent,uiMantissaHi,
00856         uiMantissaLo);
00857 
00858     // adjust exponent by how many blocks were used to scale the remainder
00859     uiExponent >>= 20;
00860     uiExponent -= 1023;
00861     uiExponent -= 16*(iBlock+1);
00862     uiExponent += 1023;
00863     uiExponent <<= 20;
00864 
00865     auiResult[1] = uiExponent | uiMantissaHi;
00866     auiResult[0] = uiMantissaLo;
00867     if (iSign < 0)
00868     {
00869         auiResult[1] |= 0x80000000u;
00870     }
00871 #ifdef WM4_BIG_ENDIAN
00872     uiSave = auiResult[0];
00873     auiResult[0] = auiResult[1];
00874     auiResult[1] = uiSave;
00875 #endif
00876     rdValue = *(double*)auiResult;
00877 }
00878 //----------------------------------------------------------------------------
00879 template <int N>
00880 void TRational<N>::GetPositiveDouble (const TInteger<N>& rkDenom,
00881     TInteger<N>& rkQuo, TInteger<N>& rkRem, int iBlock,
00882     unsigned int& ruiExponent, unsigned int& ruiMantissaHi,
00883     unsigned int& ruiMantissaLo)
00884 {
00885     // assert(rkDenom > 0 && rkQuo > 0);
00886 
00887     // quotient smaller than the maximum double
00888     int iFirstBlockBit = rkQuo.GetLeadingBit(iBlock);
00889     int iFirstBit = iFirstBlockBit+16*iBlock;
00890     unsigned int uiMask;
00891     ruiExponent = ((iFirstBit + 1023) << 20);
00892     iFirstBit--;
00893     ruiMantissaHi = 0;
00894     ruiMantissaLo = 0;
00895     if (iFirstBit >= 52)
00896     {
00897         // quotient provides all of 1.mantissa
00898         for (uiMask = 0x00080000; uiMask; uiMask >>= 1, iFirstBit--)
00899         {
00900             if (rkQuo.GetBit(iFirstBit))
00901             {
00902                 ruiMantissaHi |= uiMask;
00903             }
00904         }
00905         for (uiMask = 0x80000000u; uiMask; uiMask >>= 1, iFirstBit--)
00906         {
00907             if (rkQuo.GetBit(iFirstBit))
00908             {
00909                 ruiMantissaLo |= uiMask;
00910             }
00911         }
00912     }
00913     else
00914     {
00915         // quotient contribution to 1.mantissa
00916         bool bUsingHi = true;
00917         uiMask = 0x00080000;
00918         for (; uiMask && iFirstBit >= 0; uiMask >>= 1, iFirstBit--)
00919         {
00920             if (rkQuo.GetBit(iFirstBit))
00921             {
00922                 ruiMantissaHi |= uiMask;
00923             }
00924         }
00925 
00926         if (iFirstBit > 0)
00927         {
00928             bUsingHi = false;
00929             uiMask = 0x80000000u;
00930             for (; iFirstBit >= 0; uiMask >>= 1, iFirstBit--)
00931             {
00932                 if (rkQuo.GetBit(iFirstBit))
00933                 {
00934                     ruiMantissaLo |= uiMask;
00935                 }
00936             }
00937         }
00938 
00939         // remainder contribution to 1.mantissa
00940         TInteger<N> kNRem;
00941         bool bSuccess;
00942         if (bUsingHi)
00943         {
00944             for (; uiMask; uiMask >>= 1)
00945             {
00946                 rkRem *= 2;
00947                 bSuccess = TInteger<N>::GetDivMod(rkRem,rkDenom,rkQuo,kNRem);
00948                 assert(bSuccess);
00949                 if (rkQuo != 0)
00950                 {
00951                     ruiMantissaHi |= uiMask;
00952                 }
00953                 rkRem = kNRem;
00954             }
00955 
00956             for (uiMask = 0x80000000u; uiMask; uiMask >>= 1)
00957             {
00958                 rkRem *= 2;
00959                 bSuccess = TInteger<N>::GetDivMod(rkRem,rkDenom,rkQuo,kNRem);
00960                 assert(bSuccess);
00961                 if (rkQuo != 0)
00962                 {
00963                     ruiMantissaLo |= uiMask;
00964                 }
00965                 rkRem = kNRem;
00966             }
00967         }
00968         else
00969         {
00970             for (; uiMask; uiMask >>= 1)
00971             {
00972                 rkRem *= 2;
00973                 bSuccess = TInteger<N>::GetDivMod(rkRem,rkDenom,rkQuo,kNRem);
00974                 assert(bSuccess);
00975                 if (rkQuo != 0)
00976                 {
00977                     ruiMantissaLo |= uiMask;
00978                 }
00979                 rkRem = kNRem;
00980             }
00981         }
00982     }
00983 }
00984 //----------------------------------------------------------------------------
00985 } //namespace Wm4

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