Library for big numbers from http://www.ttmath.org/
Dependents: PIDHeater82 Conceptcontroller_v_1_0 AlarmClockApp COG4050_adxl355_tilt ... more
ttmathuint_noasm.h
00001 /* 00002 * This file is a part of TTMath Bignum Library 00003 * and is distributed under the (new) BSD licence. 00004 * Author: Tomasz Sowa <t.sowa@ttmath.org> 00005 */ 00006 00007 /* 00008 * Copyright (c) 2006-2010, Tomasz Sowa 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * 00014 * * Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 00017 * * Redistributions in binary form must reproduce the above copyright 00018 * notice, this list of conditions and the following disclaimer in the 00019 * documentation and/or other materials provided with the distribution. 00020 * 00021 * * Neither the name Tomasz Sowa nor the names of contributors to this 00022 * project may be used to endorse or promote products derived 00023 * from this software without specific prior written permission. 00024 * 00025 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00026 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00028 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00029 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00030 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00031 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00032 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00033 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00034 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 00035 * THE POSSIBILITY OF SUCH DAMAGE. 00036 */ 00037 00038 #ifndef headerfilettmathuint_noasm 00039 #define headerfilettmathuint_noasm 00040 00041 00042 #ifdef TTMATH_NOASM 00043 00044 /*! 00045 \file ttmathuint_noasm.h 00046 \brief template class UInt<uint> with methods without any assembler code 00047 00048 this file is included at the end of ttmathuint.h 00049 */ 00050 00051 00052 namespace ttmath 00053 { 00054 00055 /*! 00056 returning the string represents the currect type of the library 00057 we have following types: 00058 asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits) 00059 asm_gcc_32 - with asm code designed for GCC (32 bits) 00060 asm_vc_64 - with asm for VC (64 bit) 00061 asm_gcc_64 - with asm for GCC (64 bit) 00062 no_asm_32 - pure C++ version (32 bit) - without any asm code 00063 no_asm_64 - pure C++ version (64 bit) - without any asm code 00064 */ 00065 template<uint value_size> 00066 const char * UInt<value_size>::LibTypeStr () 00067 { 00068 #ifdef TTMATH_PLATFORM32 00069 static const char info[] = "no_asm_32"; 00070 #endif 00071 00072 #ifdef TTMATH_PLATFORM64 00073 static const char info[] = "no_asm_64"; 00074 #endif 00075 00076 return info; 00077 } 00078 00079 00080 /*! 00081 returning the currect type of the library 00082 */ 00083 template<uint value_size> 00084 LibTypeCode UInt<value_size>::LibType () 00085 { 00086 #ifdef TTMATH_PLATFORM32 00087 LibTypeCode info = no_asm_32; 00088 #endif 00089 00090 #ifdef TTMATH_PLATFORM64 00091 LibTypeCode info = no_asm_64; 00092 #endif 00093 00094 return info; 00095 } 00096 00097 00098 /*! 00099 this method adds two words together 00100 returns carry 00101 00102 this method is created only when TTMATH_NOASM macro is defined 00103 */ 00104 template<uint value_size> 00105 uint UInt<value_size>::AddTwoWords (uint a, uint b, uint carry, uint * result) 00106 { 00107 uint temp; 00108 00109 if( carry == 0 ) 00110 { 00111 temp = a + b; 00112 00113 if( temp < a ) 00114 carry = 1; 00115 } 00116 else 00117 { 00118 carry = 1; 00119 temp = a + b + carry; 00120 00121 if( temp > a ) // !(temp<=a) 00122 carry = 0; 00123 } 00124 00125 *result = temp; 00126 00127 return carry; 00128 } 00129 00130 00131 00132 /*! 00133 this method adding ss2 to the this and adding carry if it's defined 00134 (this = this + ss2 + c) 00135 00136 c must be zero or one (might be a bigger value than 1) 00137 function returns carry (1) (if it was) 00138 */ 00139 00140 template<uint value_size> 00141 uint UInt<value_size>::Add (const UInt<value_size> & ss2, uint c) 00142 { 00143 uint i; 00144 00145 for(i=0 ; i<value_size ; ++i) 00146 c = AddTwoWords(table[i], ss2.table [i], c, &table[i]); 00147 00148 TTMATH_LOGC("UInt::Add", c) 00149 00150 return c; 00151 } 00152 00153 00154 /*! 00155 this method adds one word (at a specific position) 00156 and returns a carry (if it was) 00157 00158 if we've got (value_size=3): 00159 table[0] = 10; 00160 table[1] = 30; 00161 table[2] = 5; 00162 and we call: 00163 AddInt(2,1) 00164 then it'll be: 00165 table[0] = 10; 00166 table[1] = 30 + 2; 00167 table[2] = 5; 00168 00169 of course if there was a carry from table[2] it would be returned 00170 */ 00171 template<uint value_size> 00172 uint UInt<value_size>::AddInt (uint value, uint index) 00173 { 00174 uint i, c; 00175 00176 TTMATH_ASSERT( index < value_size ) 00177 00178 00179 c = AddTwoWords(table[index], value, 0, &table[index]); 00180 00181 for(i=index+1 ; i<value_size && c ; ++i) 00182 c = AddTwoWords(table[i], 0, c, &table[i]); 00183 00184 TTMATH_LOGC("UInt::AddInt", c) 00185 00186 return c; 00187 } 00188 00189 00190 00191 00192 00193 /*! 00194 this method adds only two unsigned words to the existing value 00195 and these words begin on the 'index' position 00196 (it's used in the multiplication algorithm 2) 00197 00198 index should be equal or smaller than value_size-2 (index <= value_size-2) 00199 x1 - lower word, x2 - higher word 00200 00201 for example if we've got value_size equal 4 and: 00202 table[0] = 3 00203 table[1] = 4 00204 table[2] = 5 00205 table[3] = 6 00206 then let 00207 x1 = 10 00208 x2 = 20 00209 and 00210 index = 1 00211 00212 the result of this method will be: 00213 table[0] = 3 00214 table[1] = 4 + x1 = 14 00215 table[2] = 5 + x2 = 25 00216 table[3] = 6 00217 00218 and no carry at the end of table[3] 00219 00220 (of course if there was a carry in table[2](5+20) then 00221 this carry would be passed to the table[3] etc.) 00222 */ 00223 template<uint value_size> 00224 uint UInt<value_size>::AddTwoInts (uint x2, uint x1, uint index) 00225 { 00226 uint i, c; 00227 00228 TTMATH_ASSERT( index < value_size - 1 ) 00229 00230 00231 c = AddTwoWords(table[index], x1, 0, &table[index]); 00232 c = AddTwoWords(table[index+1], x2, c, &table[index+1]); 00233 00234 for(i=index+2 ; i<value_size && c ; ++i) 00235 c = AddTwoWords(table[i], 0, c, &table[i]); 00236 00237 TTMATH_LOGC("UInt::AddTwoInts", c) 00238 00239 return c; 00240 } 00241 00242 00243 00244 /*! 00245 this static method addes one vector to the other 00246 'ss1' is larger in size or equal to 'ss2' 00247 00248 ss1 points to the first (larger) vector 00249 ss2 points to the second vector 00250 ss1_size - size of the ss1 (and size of the result too) 00251 ss2_size - size of the ss2 00252 result - is the result vector (which has size the same as ss1: ss1_size) 00253 00254 Example: ss1_size is 5, ss2_size is 3 00255 ss1: ss2: result (output): 00256 5 1 5+1 00257 4 3 4+3 00258 2 7 2+7 00259 6 6 00260 9 9 00261 of course the carry is propagated and will be returned from the last item 00262 (this method is used by the Karatsuba multiplication algorithm) 00263 */ 00264 template<uint value_size> 00265 uint UInt<value_size>::AddVector (const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) 00266 { 00267 uint i, c = 0; 00268 00269 TTMATH_ASSERT( ss1_size >= ss2_size ) 00270 00271 for(i=0 ; i<ss2_size ; ++i) 00272 c = AddTwoWords(ss1[i], ss2[i], c, &result[i]); 00273 00274 for( ; i<ss1_size ; ++i) 00275 c = AddTwoWords(ss1[i], 0, c, &result[i]); 00276 00277 TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size) 00278 00279 return c; 00280 } 00281 00282 00283 00284 00285 /*! 00286 this method subtractes one word from the other 00287 returns carry 00288 00289 this method is created only when TTMATH_NOASM macro is defined 00290 */ 00291 template<uint value_size> 00292 uint UInt<value_size>::SubTwoWords (uint a, uint b, uint carry, uint * result) 00293 { 00294 if( carry == 0 ) 00295 { 00296 *result = a - b; 00297 00298 if( a < b ) 00299 carry = 1; 00300 } 00301 else 00302 { 00303 carry = 1; 00304 *result = a - b - carry; 00305 00306 if( a > b ) // !(a <= b ) 00307 carry = 0; 00308 } 00309 00310 return carry; 00311 } 00312 00313 00314 00315 00316 /*! 00317 this method's subtracting ss2 from the 'this' and subtracting 00318 carry if it has been defined 00319 (this = this - ss2 - c) 00320 00321 c must be zero or one (might be a bigger value than 1) 00322 function returns carry (1) (if it was) 00323 */ 00324 template<uint value_size> 00325 uint UInt<value_size>::Sub (const UInt<value_size> & ss2, uint c) 00326 { 00327 uint i; 00328 00329 for(i=0 ; i<value_size ; ++i) 00330 c = SubTwoWords(table[i], ss2.table [i], c, &table[i]); 00331 00332 TTMATH_LOGC("UInt::Sub", c) 00333 00334 return c; 00335 } 00336 00337 00338 00339 00340 /*! 00341 this method subtracts one word (at a specific position) 00342 and returns a carry (if it was) 00343 00344 if we've got (value_size=3): 00345 table[0] = 10; 00346 table[1] = 30; 00347 table[2] = 5; 00348 and we call: 00349 SubInt(2,1) 00350 then it'll be: 00351 table[0] = 10; 00352 table[1] = 30 - 2; 00353 table[2] = 5; 00354 00355 of course if there was a carry from table[2] it would be returned 00356 */ 00357 template<uint value_size> 00358 uint UInt<value_size>::SubInt (uint value, uint index) 00359 { 00360 uint i, c; 00361 00362 TTMATH_ASSERT( index < value_size ) 00363 00364 00365 c = SubTwoWords(table[index], value, 0, &table[index]); 00366 00367 for(i=index+1 ; i<value_size && c ; ++i) 00368 c = SubTwoWords(table[i], 0, c, &table[i]); 00369 00370 TTMATH_LOGC("UInt::SubInt", c) 00371 00372 return c; 00373 } 00374 00375 00376 /*! 00377 this static method subtractes one vector from the other 00378 'ss1' is larger in size or equal to 'ss2' 00379 00380 ss1 points to the first (larger) vector 00381 ss2 points to the second vector 00382 ss1_size - size of the ss1 (and size of the result too) 00383 ss2_size - size of the ss2 00384 result - is the result vector (which has size the same as ss1: ss1_size) 00385 00386 Example: ss1_size is 5, ss2_size is 3 00387 ss1: ss2: result (output): 00388 5 1 5-1 00389 4 3 4-3 00390 2 7 2-7 00391 6 6-1 (the borrow from previous item) 00392 9 9 00393 return (carry): 0 00394 of course the carry (borrow) is propagated and will be returned from the last item 00395 (this method is used by the Karatsuba multiplication algorithm) 00396 */ 00397 template<uint value_size> 00398 uint UInt<value_size>::SubVector (const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) 00399 { 00400 uint i, c = 0; 00401 00402 TTMATH_ASSERT( ss1_size >= ss2_size ) 00403 00404 for(i=0 ; i<ss2_size ; ++i) 00405 c = SubTwoWords(ss1[i], ss2[i], c, &result[i]); 00406 00407 for( ; i<ss1_size ; ++i) 00408 c = SubTwoWords(ss1[i], 0, c, &result[i]); 00409 00410 TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size) 00411 00412 return c; 00413 } 00414 00415 00416 00417 /*! 00418 this method moves all bits into the left hand side 00419 return value <- this <- c 00420 00421 the lowest *bit* will be held the 'c' and 00422 the state of one additional bit (on the left hand side) 00423 will be returned 00424 00425 for example: 00426 let this is 001010000 00427 after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0 00428 */ 00429 template<uint value_size> 00430 uint UInt<value_size>::Rcl2_one(uint c) 00431 { 00432 uint i, new_c; 00433 00434 if( c != 0 ) 00435 c = 1; 00436 00437 for(i=0 ; i<value_size ; ++i) 00438 { 00439 new_c = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; 00440 table[i] = (table[i] << 1) | c; 00441 c = new_c; 00442 } 00443 00444 TTMATH_LOGC("UInt::Rcl2_one", c) 00445 00446 return c; 00447 } 00448 00449 00450 00451 00452 00453 00454 00455 /*! 00456 this method moves all bits into the right hand side 00457 c -> this -> return value 00458 00459 the highest *bit* will be held the 'c' and 00460 the state of one additional bit (on the right hand side) 00461 will be returned 00462 00463 for example: 00464 let this is 000000010 00465 after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0 00466 */ 00467 template<uint value_size> 00468 uint UInt<value_size>::Rcr2_one(uint c) 00469 { 00470 sint i; // signed i 00471 uint new_c; 00472 00473 if( c != 0 ) 00474 c = TTMATH_UINT_HIGHEST_BIT; 00475 00476 for(i=sint(value_size)-1 ; i>=0 ; --i) 00477 { 00478 new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0; 00479 table[i] = (table[i] >> 1) | c; 00480 c = new_c; 00481 } 00482 00483 c = (c != 0)? 1 : 0; 00484 00485 TTMATH_LOGC("UInt::Rcr2_one", c) 00486 00487 return c; 00488 } 00489 00490 00491 00492 00493 /*! 00494 this method moves all bits into the left hand side 00495 return value <- this <- c 00496 00497 the lowest *bits* will be held the 'c' and 00498 the state of one additional bit (on the left hand side) 00499 will be returned 00500 00501 for example: 00502 let this is 001010000 00503 after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1 00504 */ 00505 template<uint value_size> 00506 uint UInt<value_size>::Rcl2(uint bits, uint c) 00507 { 00508 TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT ) 00509 00510 uint move = TTMATH_BITS_PER_UINT - bits; 00511 uint i, new_c; 00512 00513 if( c != 0 ) 00514 c = TTMATH_UINT_MAX_VALUE >> move; 00515 00516 for(i=0 ; i<value_size ; ++i) 00517 { 00518 new_c = table[i] >> move; 00519 table[i] = (table[i] << bits) | c; 00520 c = new_c; 00521 } 00522 00523 TTMATH_LOGC("UInt::Rcl2", (c & 1)) 00524 00525 return (c & 1); 00526 } 00527 00528 00529 00530 00531 /*! 00532 this method moves all bits into the right hand side 00533 C -> this -> return value 00534 00535 the highest *bits* will be held the 'c' and 00536 the state of one additional bit (on the right hand side) 00537 will be returned 00538 00539 for example: 00540 let this is 000000010 00541 after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1 00542 */ 00543 template<uint value_size> 00544 uint UInt<value_size>::Rcr2(uint bits, uint c) 00545 { 00546 TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT ) 00547 00548 uint move = TTMATH_BITS_PER_UINT - bits; 00549 sint i; // signed 00550 uint new_c; 00551 00552 if( c != 0 ) 00553 c = TTMATH_UINT_MAX_VALUE << move; 00554 00555 for(i=value_size-1 ; i>=0 ; --i) 00556 { 00557 new_c = table[i] << move; 00558 table[i] = (table[i] >> bits) | c; 00559 c = new_c; 00560 } 00561 00562 c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0; 00563 00564 TTMATH_LOGC("UInt::Rcr2", c) 00565 00566 return c; 00567 } 00568 00569 00570 00571 00572 /*! 00573 this method returns the number of the highest set bit in x 00574 if the 'x' is zero this method returns '-1' 00575 */ 00576 template<uint value_size> 00577 sint UInt<value_size>::FindLeadingBitInWord(uint x) 00578 { 00579 if( x == 0 ) 00580 return -1; 00581 00582 uint bit = TTMATH_BITS_PER_UINT - 1; 00583 00584 while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 ) 00585 { 00586 x = x << 1; 00587 --bit; 00588 } 00589 00590 return bit; 00591 } 00592 00593 00594 00595 /*! 00596 this method returns the number of the highest set bit in x 00597 if the 'x' is zero this method returns '-1' 00598 */ 00599 template<uint value_size> 00600 sint UInt<value_size>::FindLowestBitInWord (uint x) 00601 { 00602 if( x == 0 ) 00603 return -1; 00604 00605 uint bit = 0; 00606 00607 while( (x & 1) == 0 ) 00608 { 00609 x = x >> 1; 00610 ++bit; 00611 } 00612 00613 return bit; 00614 } 00615 00616 00617 00618 /*! 00619 this method sets a special bit in the 'value' 00620 and returns the last state of the bit (zero or one) 00621 00622 bit is from <0,TTMATH_BITS_PER_UINT-1> 00623 00624 e.g. 00625 uint x = 100; 00626 uint bit = SetBitInWord(x, 3); 00627 now: x = 108 and bit = 0 00628 */ 00629 template<uint value_size> 00630 uint UInt<value_size>::SetBitInWord (uint & value, uint bit) 00631 { 00632 TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT ) 00633 00634 uint mask = 1; 00635 00636 if( bit > 0 ) 00637 mask = mask << bit; 00638 00639 uint last = value & mask; 00640 value = value | mask; 00641 00642 return (last != 0) ? 1 : 0; 00643 } 00644 00645 00646 00647 00648 00649 00650 /*! 00651 * 00652 * Multiplication 00653 * 00654 * 00655 */ 00656 00657 00658 /*! 00659 multiplication: result_high:result_low = a * b 00660 result_high - higher word of the result 00661 result_low - lower word of the result 00662 00663 this methos never returns a carry 00664 this method is used in the second version of the multiplication algorithms 00665 */ 00666 template<uint value_size> 00667 void UInt<value_size>::MulTwoWords (uint a, uint b, uint * result_high, uint * result_low) 00668 { 00669 #ifdef TTMATH_PLATFORM32 00670 00671 /* 00672 on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace 00673 this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit 00674 */ 00675 00676 union uint_ 00677 { 00678 struct 00679 { 00680 uint low; // 32 bits 00681 uint high; // 32 bits 00682 } u_; 00683 00684 ulint u; // 64 bits 00685 } res; 00686 00687 res.u = ulint (a) * ulint (b); // multiply two 32bit words, the result has 64 bits 00688 00689 *result_high = res.u_.high; 00690 *result_low = res.u_.low; 00691 00692 #else 00693 00694 /* 00695 64 bits platforms 00696 00697 we don't have a native type which has 128 bits 00698 then we're splitting 'a' and 'b' to 4 parts (high and low halves) 00699 and using 4 multiplications (with additions and carry correctness) 00700 */ 00701 00702 uint_ a_; 00703 uint_ b_; 00704 uint_ res_high1, res_high2; 00705 uint_ res_low1, res_low2; 00706 00707 a_.u = a; 00708 b_.u = b; 00709 00710 /* 00711 the multiplication is as follows (schoolbook algorithm with O(n^2) ): 00712 00713 32 bits 32 bits 00714 00715 +--------------------------------+ 00716 | a_.u_.high | a_.u_.low | 00717 +--------------------------------+ 00718 | b_.u_.high | b_.u_.low | 00719 +--------------------------------+--------------------------------+ 00720 | res_high1.u | res_low1.u | 00721 +--------------------------------+--------------------------------+ 00722 | res_high2.u | res_low2.u | 00723 +--------------------------------+--------------------------------+ 00724 00725 64 bits 64 bits 00726 */ 00727 00728 00729 uint_ temp; 00730 00731 res_low1.u = uint (b_.u_.low) * uint (a_.u_.low); 00732 00733 temp.u = uint (res_low1.u_.high) + uint (b_.u_.low) * uint (a_.u_.high); 00734 res_low1.u_.high = temp.u_.low; 00735 res_high1.u_.low = temp.u_.high; 00736 res_high1.u_.high = 0; 00737 00738 res_low2.u_.low = 0; 00739 temp.u = uint (b_.u_.high) * uint (a_.u_.low); 00740 res_low2.u_.high = temp.u_.low; 00741 00742 res_high2.u = uint (b_.u_.high) * uint (a_.u_.high) + uint (temp.u_.high); 00743 00744 uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u); 00745 AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here 00746 00747 *result_high = res_high2.u; 00748 *result_low = res_low2.u; 00749 00750 #endif 00751 } 00752 00753 00754 00755 00756 /*! 00757 * 00758 * Division 00759 * 00760 * 00761 */ 00762 00763 00764 /*! 00765 this method calculates 64bits word a:b / 32bits c (a higher, b lower word) 00766 r = a:b / c and rest - remainder 00767 00768 * 00769 * WARNING: 00770 * the c has to be suitably large for the result being keeped in one word, 00771 * if c is equal zero there'll be a hardware interruption (0) 00772 * and probably the end of your program 00773 * 00774 */ 00775 template<uint value_size> 00776 void UInt<value_size>::DivTwoWords (uint a, uint b, uint c, uint * r, uint * rest) 00777 { 00778 // (a < c ) for the result to be one word 00779 TTMATH_ASSERT( c != 0 && a < c ) 00780 00781 #ifdef TTMATH_PLATFORM32 00782 00783 union 00784 { 00785 struct 00786 { 00787 uint low; // 32 bits 00788 uint high; // 32 bits 00789 } u_; 00790 00791 ulint u; // 64 bits 00792 } ab; 00793 00794 ab.u_.high = a; 00795 ab.u_.low = b; 00796 00797 *r = uint (ab.u / c); 00798 *rest = uint (ab.u % c); 00799 00800 #else 00801 00802 uint_ c_; 00803 c_.u = c; 00804 00805 00806 if( a == 0 ) 00807 { 00808 *r = b / c; 00809 *rest = b % c; 00810 } 00811 else 00812 if( c_.u_.high == 0 ) 00813 { 00814 // higher half of 'c' is zero 00815 // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c') 00816 uint_ a_, b_, res_, temp1, temp2; 00817 00818 a_.u = a; 00819 b_.u = b; 00820 00821 temp1.u_.high = a_.u_.low; 00822 temp1.u_.low = b_.u_.high; 00823 00824 res_.u_.high = (unsigned int)(temp1.u / c); 00825 temp2.u_.high = (unsigned int)(temp1.u % c); 00826 temp2.u_.low = b_.u_.low; 00827 00828 res_.u_.low = (unsigned int)(temp2.u / c); 00829 *rest = temp2.u % c; 00830 00831 *r = res_.u; 00832 } 00833 else 00834 { 00835 return DivTwoWords2(a, b, c, r, rest); 00836 } 00837 00838 #endif 00839 } 00840 00841 00842 #ifdef TTMATH_PLATFORM64 00843 00844 00845 /*! 00846 this method is available only on 64bit platforms 00847 00848 the same algorithm like the third division algorithm in ttmathuint.h 00849 but now with the radix=2^32 00850 */ 00851 template<uint value_size> 00852 void UInt<value_size>::DivTwoWords2 (uint a, uint b, uint c, uint * r, uint * rest) 00853 { 00854 // a is not zero 00855 // c_.u_.high is not zero 00856 00857 uint_ a_, b_, c_, u_, q_; 00858 unsigned int u3; // 32 bit 00859 00860 a_.u = a; 00861 b_.u = b; 00862 c_.u = c; 00863 00864 // normalizing 00865 uint d = DivTwoWordsNormalize(a_, b_, c_); 00866 00867 // loop from j=1 to j=0 00868 // the first step (for j=2) is skipped because our result is only in one word, 00869 // (first 'q' were 0 and nothing would be changed) 00870 u_.u_.high = a_.u_.high; 00871 u_.u_.low = a_.u_.low; 00872 u3 = b_.u_.high; 00873 q_.u_.high = DivTwoWordsCalculate(u_, u3, c_); 00874 MultiplySubtract(u_, u3, q_.u_.high, c_); 00875 00876 u_.u_.high = u_.u_.low; 00877 u_.u_.low = u3; 00878 u3 = b_.u_.low; 00879 q_.u_.low = DivTwoWordsCalculate(u_, u3, c_); 00880 MultiplySubtract(u_, u3, q_.u_.low, c_); 00881 00882 *r = q_.u; 00883 00884 // unnormalizing for the remainder 00885 u_.u_.high = u_.u_.low; 00886 u_.u_.low = u3; 00887 *rest = DivTwoWordsUnnormalize(u_.u, d); 00888 } 00889 00890 00891 00892 00893 template<uint value_size> 00894 uint UInt<value_size>::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_) 00895 { 00896 uint d = 0; 00897 00898 for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d ) 00899 { 00900 c_.u = c_.u << 1; 00901 00902 uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b' 00903 00904 b_.u = b_.u << 1; 00905 a_.u = a_.u << 1; // carry bits from 'a' are simply skipped 00906 00907 if( bc ) 00908 a_.u = a_.u | 1; 00909 } 00910 00911 return d; 00912 } 00913 00914 00915 template<uint value_size> 00916 uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d) 00917 { 00918 if( d == 0 ) 00919 return u; 00920 00921 u = u >> d; 00922 00923 return u; 00924 } 00925 00926 00927 template<uint value_size> 00928 unsigned int UInt<value_size>::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_) 00929 { 00930 bool next_test; 00931 uint_ qp_, rp_, temp_; 00932 00933 qp_.u = u_.u / uint (v_.u_.high); 00934 rp_.u = u_.u % uint (v_.u_.high); 00935 00936 TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 ) 00937 00938 do 00939 { 00940 bool decrease = false; 00941 00942 if( qp_.u_.high == 1 ) 00943 decrease = true; 00944 else 00945 { 00946 temp_.u_.high = rp_.u_.low; 00947 temp_.u_.low = u3; 00948 00949 if( qp_.u * uint (v_.u_.low) > temp_.u ) 00950 decrease = true; 00951 } 00952 00953 next_test = false; 00954 00955 if( decrease ) 00956 { 00957 --qp_.u; 00958 rp_.u += v_.u_.high; 00959 00960 if( rp_.u_.high == 0 ) 00961 next_test = true; 00962 } 00963 } 00964 while( next_test ); 00965 00966 return qp_.u_.low; 00967 } 00968 00969 00970 template<uint value_size> 00971 void UInt<value_size>::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_) 00972 { 00973 uint_ temp_; 00974 00975 uint res_high; 00976 uint res_low; 00977 00978 MulTwoWords(v_.u, q, &res_high, &res_low); 00979 00980 uint_ sub_res_high_; 00981 uint_ sub_res_low_; 00982 00983 temp_.u_.high = u_.u_.low; 00984 temp_.u_.low = u3; 00985 00986 uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u); 00987 00988 temp_.u_.high = 0; 00989 temp_.u_.low = u_.u_.high; 00990 c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); 00991 00992 if( c ) 00993 { 00994 --q; 00995 00996 c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); 00997 AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); 00998 } 00999 01000 u_.u_.high = sub_res_high_.u_.low; 01001 u_.u_.low = sub_res_low_.u_.high; 01002 u3 = sub_res_low_.u_.low; 01003 } 01004 01005 #endif // #ifdef TTMATH_PLATFORM64 01006 01007 01008 01009 } //namespace 01010 01011 01012 #endif //ifdef TTMATH_NOASM 01013 #endif 01014 01015 01016 01017 01018
Generated on Tue Jul 12 2022 14:03:18 by 1.7.2