00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00304 return;
00305 }
00306
00307 int iBlock0 = m_kNumer.GetTrailingBlock();
00308 if (iBlock0 == -1)
00309 {
00310
00311 m_kDenom = 1;
00312 return;
00313 }
00314
00315 int iBlock1 = m_kDenom.GetTrailingBlock();
00316 assert(iBlock1 >= 0);
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
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
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
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
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
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
00433
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
00444 if (iBlock >= 8)
00445 {
00446
00447 if (iSign > 0)
00448 {
00449 uiResult = 0x7F7FFFFFu;
00450 rfValue = *(float*)&uiResult;
00451 }
00452 else
00453 {
00454 uiResult = 0xFF7FFFFFu;
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
00466 if (iSign > 0)
00467 {
00468 uiResult = 0x7F7FFFFFu;
00469 rfValue = *(float*)&uiResult;
00470 }
00471 else
00472 {
00473 uiResult = 0xFF7FFFFFu;
00474 rfValue = *(float*)&uiResult;
00475 }
00476 return;
00477 }
00478 }
00479
00480
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
00492 for (iBlock = 0; iBlock < 8; iBlock++)
00493 {
00494
00495
00496
00497
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
00512 if (iSign > 0)
00513 {
00514 uiResult = 0x00800000;
00515 rfValue = *(float*)&uiResult;
00516 }
00517 else
00518 {
00519 uiResult = 0x80800000;
00520 rfValue = *(float*)&uiResult;
00521 }
00522 return;
00523 }
00524
00525
00526 GetPositiveFloat(kAbsDenom,kQuo,kRem,0,uiExponent,uiMantissa);
00527
00528
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
00550
00551
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
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
00572 for (uiMask = 0x00400000; iFirstBit >= 0; uiMask >>= 1, iFirstBit--)
00573 {
00574 if (rkQuo.GetBit(iFirstBit))
00575 {
00576 ruiMantissa |= uiMask;
00577 }
00578 }
00579
00580
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;
00588 if (rkQuo != 0)
00589 {
00590 ruiMantissa |= uiMask;
00591 }
00592 rkRem = kNRem;
00593 }
00594 }
00595 }
00596
00597
00598
00599
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
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
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
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
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
00717
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
00728 if (iBlock >= 64)
00729 {
00730
00731 if (iSign > 0)
00732 {
00733 auiResult[0] = 0xFFFFFFFF;
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;
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
00764 if (iSign > 0)
00765 {
00766 auiResult[0] = 0xFFFFFFFF;
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;
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
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
00809 for (iBlock = 0; iBlock < 64; iBlock++)
00810 {
00811
00812
00813
00814
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
00829 if (iSign > 0)
00830 {
00831 auiResult[1] = 0x00100000;
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;
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
00855 GetPositiveDouble(kAbsDenom,kQuo,kRem,0,uiExponent,uiMantissaHi,
00856 uiMantissaLo);
00857
00858
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
00886
00887
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
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
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
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 }