ttmathuint_noasm.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017
  1. /*
  2. * This file is a part of TTMath Bignum Library
  3. * and is distributed under the (new) BSD licence.
  4. * Author: Tomasz Sowa <[email protected]>
  5. */
  6. /*
  7. * Copyright (c) 2006-2010, Tomasz Sowa
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * * Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. *
  20. * * Neither the name Tomasz Sowa nor the names of contributors to this
  21. * project may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  34. * THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. #ifndef headerfilettmathuint_noasm
  37. #define headerfilettmathuint_noasm
  38. #ifdef TTMATH_NOASM
  39. /*!
  40. \file ttmathuint_noasm.h
  41. \brief template class UInt<uint> with methods without any assembler code
  42. this file is included at the end of ttmathuint.h
  43. */
  44. namespace ttmath
  45. {
  46. /*!
  47. returning the string represents the currect type of the library
  48. we have following types:
  49. asm_vc_32 - with asm code designed for Microsoft Visual C++ (32 bits)
  50. asm_gcc_32 - with asm code designed for GCC (32 bits)
  51. asm_vc_64 - with asm for VC (64 bit)
  52. asm_gcc_64 - with asm for GCC (64 bit)
  53. no_asm_32 - pure C++ version (32 bit) - without any asm code
  54. no_asm_64 - pure C++ version (64 bit) - without any asm code
  55. */
  56. template<uint value_size>
  57. const char * UInt<value_size>::LibTypeStr()
  58. {
  59. #ifdef TTMATH_PLATFORM32
  60. static const char info[] = "no_asm_32";
  61. #endif
  62. #ifdef TTMATH_PLATFORM64
  63. static const char info[] = "no_asm_64";
  64. #endif
  65. return info;
  66. }
  67. /*!
  68. returning the currect type of the library
  69. */
  70. template<uint value_size>
  71. LibTypeCode UInt<value_size>::LibType()
  72. {
  73. #ifdef TTMATH_PLATFORM32
  74. LibTypeCode info = no_asm_32;
  75. #endif
  76. #ifdef TTMATH_PLATFORM64
  77. LibTypeCode info = no_asm_64;
  78. #endif
  79. return info;
  80. }
  81. /*!
  82. this method adds two words together
  83. returns carry
  84. this method is created only when TTMATH_NOASM macro is defined
  85. */
  86. template<uint value_size>
  87. uint UInt<value_size>::AddTwoWords(uint a, uint b, uint carry, uint * result)
  88. {
  89. uint temp;
  90. if( carry == 0 )
  91. {
  92. temp = a + b;
  93. if( temp < a )
  94. carry = 1;
  95. }
  96. else
  97. {
  98. carry = 1;
  99. temp = a + b + carry;
  100. if( temp > a ) // !(temp<=a)
  101. carry = 0;
  102. }
  103. *result = temp;
  104. return carry;
  105. }
  106. /*!
  107. this method adding ss2 to the this and adding carry if it's defined
  108. (this = this + ss2 + c)
  109. c must be zero or one (might be a bigger value than 1)
  110. function returns carry (1) (if it was)
  111. */
  112. template<uint value_size>
  113. uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
  114. {
  115. uint i;
  116. for(i=0 ; i<value_size ; ++i)
  117. c = AddTwoWords(table[i], ss2.table[i], c, &table[i]);
  118. TTMATH_LOGC("UInt::Add", c)
  119. return c;
  120. }
  121. /*!
  122. this method adds one word (at a specific position)
  123. and returns a carry (if it was)
  124. if we've got (value_size=3):
  125. table[0] = 10;
  126. table[1] = 30;
  127. table[2] = 5;
  128. and we call:
  129. AddInt(2,1)
  130. then it'll be:
  131. table[0] = 10;
  132. table[1] = 30 + 2;
  133. table[2] = 5;
  134. of course if there was a carry from table[2] it would be returned
  135. */
  136. template<uint value_size>
  137. uint UInt<value_size>::AddInt(uint value, uint index)
  138. {
  139. uint i, c;
  140. TTMATH_ASSERT( index < value_size )
  141. c = AddTwoWords(table[index], value, 0, &table[index]);
  142. for(i=index+1 ; i<value_size && c ; ++i)
  143. c = AddTwoWords(table[i], 0, c, &table[i]);
  144. TTMATH_LOGC("UInt::AddInt", c)
  145. return c;
  146. }
  147. /*!
  148. this method adds only two unsigned words to the existing value
  149. and these words begin on the 'index' position
  150. (it's used in the multiplication algorithm 2)
  151. index should be equal or smaller than value_size-2 (index <= value_size-2)
  152. x1 - lower word, x2 - higher word
  153. for example if we've got value_size equal 4 and:
  154. table[0] = 3
  155. table[1] = 4
  156. table[2] = 5
  157. table[3] = 6
  158. then let
  159. x1 = 10
  160. x2 = 20
  161. and
  162. index = 1
  163. the result of this method will be:
  164. table[0] = 3
  165. table[1] = 4 + x1 = 14
  166. table[2] = 5 + x2 = 25
  167. table[3] = 6
  168. and no carry at the end of table[3]
  169. (of course if there was a carry in table[2](5+20) then
  170. this carry would be passed to the table[3] etc.)
  171. */
  172. template<uint value_size>
  173. uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
  174. {
  175. uint i, c;
  176. TTMATH_ASSERT( index < value_size - 1 )
  177. c = AddTwoWords(table[index], x1, 0, &table[index]);
  178. c = AddTwoWords(table[index+1], x2, c, &table[index+1]);
  179. for(i=index+2 ; i<value_size && c ; ++i)
  180. c = AddTwoWords(table[i], 0, c, &table[i]);
  181. TTMATH_LOGC("UInt::AddTwoInts", c)
  182. return c;
  183. }
  184. /*!
  185. this static method addes one vector to the other
  186. 'ss1' is larger in size or equal to 'ss2'
  187. ss1 points to the first (larger) vector
  188. ss2 points to the second vector
  189. ss1_size - size of the ss1 (and size of the result too)
  190. ss2_size - size of the ss2
  191. result - is the result vector (which has size the same as ss1: ss1_size)
  192. Example: ss1_size is 5, ss2_size is 3
  193. ss1: ss2: result (output):
  194. 5 1 5+1
  195. 4 3 4+3
  196. 2 7 2+7
  197. 6 6
  198. 9 9
  199. of course the carry is propagated and will be returned from the last item
  200. (this method is used by the Karatsuba multiplication algorithm)
  201. */
  202. template<uint value_size>
  203. uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
  204. {
  205. uint i, c = 0;
  206. TTMATH_ASSERT( ss1_size >= ss2_size )
  207. for(i=0 ; i<ss2_size ; ++i)
  208. c = AddTwoWords(ss1[i], ss2[i], c, &result[i]);
  209. for( ; i<ss1_size ; ++i)
  210. c = AddTwoWords(ss1[i], 0, c, &result[i]);
  211. TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
  212. return c;
  213. }
  214. /*!
  215. this method subtractes one word from the other
  216. returns carry
  217. this method is created only when TTMATH_NOASM macro is defined
  218. */
  219. template<uint value_size>
  220. uint UInt<value_size>::SubTwoWords(uint a, uint b, uint carry, uint * result)
  221. {
  222. if( carry == 0 )
  223. {
  224. *result = a - b;
  225. if( a < b )
  226. carry = 1;
  227. }
  228. else
  229. {
  230. carry = 1;
  231. *result = a - b - carry;
  232. if( a > b ) // !(a <= b )
  233. carry = 0;
  234. }
  235. return carry;
  236. }
  237. /*!
  238. this method's subtracting ss2 from the 'this' and subtracting
  239. carry if it has been defined
  240. (this = this - ss2 - c)
  241. c must be zero or one (might be a bigger value than 1)
  242. function returns carry (1) (if it was)
  243. */
  244. template<uint value_size>
  245. uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
  246. {
  247. uint i;
  248. for(i=0 ; i<value_size ; ++i)
  249. c = SubTwoWords(table[i], ss2.table[i], c, &table[i]);
  250. TTMATH_LOGC("UInt::Sub", c)
  251. return c;
  252. }
  253. /*!
  254. this method subtracts one word (at a specific position)
  255. and returns a carry (if it was)
  256. if we've got (value_size=3):
  257. table[0] = 10;
  258. table[1] = 30;
  259. table[2] = 5;
  260. and we call:
  261. SubInt(2,1)
  262. then it'll be:
  263. table[0] = 10;
  264. table[1] = 30 - 2;
  265. table[2] = 5;
  266. of course if there was a carry from table[2] it would be returned
  267. */
  268. template<uint value_size>
  269. uint UInt<value_size>::SubInt(uint value, uint index)
  270. {
  271. uint i, c;
  272. TTMATH_ASSERT( index < value_size )
  273. c = SubTwoWords(table[index], value, 0, &table[index]);
  274. for(i=index+1 ; i<value_size && c ; ++i)
  275. c = SubTwoWords(table[i], 0, c, &table[i]);
  276. TTMATH_LOGC("UInt::SubInt", c)
  277. return c;
  278. }
  279. /*!
  280. this static method subtractes one vector from the other
  281. 'ss1' is larger in size or equal to 'ss2'
  282. ss1 points to the first (larger) vector
  283. ss2 points to the second vector
  284. ss1_size - size of the ss1 (and size of the result too)
  285. ss2_size - size of the ss2
  286. result - is the result vector (which has size the same as ss1: ss1_size)
  287. Example: ss1_size is 5, ss2_size is 3
  288. ss1: ss2: result (output):
  289. 5 1 5-1
  290. 4 3 4-3
  291. 2 7 2-7
  292. 6 6-1 (the borrow from previous item)
  293. 9 9
  294. return (carry): 0
  295. of course the carry (borrow) is propagated and will be returned from the last item
  296. (this method is used by the Karatsuba multiplication algorithm)
  297. */
  298. template<uint value_size>
  299. uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
  300. {
  301. uint i, c = 0;
  302. TTMATH_ASSERT( ss1_size >= ss2_size )
  303. for(i=0 ; i<ss2_size ; ++i)
  304. c = SubTwoWords(ss1[i], ss2[i], c, &result[i]);
  305. for( ; i<ss1_size ; ++i)
  306. c = SubTwoWords(ss1[i], 0, c, &result[i]);
  307. TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
  308. return c;
  309. }
  310. /*!
  311. this method moves all bits into the left hand side
  312. return value <- this <- c
  313. the lowest *bit* will be held the 'c' and
  314. the state of one additional bit (on the left hand side)
  315. will be returned
  316. for example:
  317. let this is 001010000
  318. after Rcl2_one(1) there'll be 010100001 and Rcl2_one returns 0
  319. */
  320. template<uint value_size>
  321. uint UInt<value_size>::Rcl2_one(uint c)
  322. {
  323. uint i, new_c;
  324. if( c != 0 )
  325. c = 1;
  326. for(i=0 ; i<value_size ; ++i)
  327. {
  328. new_c = (table[i] & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
  329. table[i] = (table[i] << 1) | c;
  330. c = new_c;
  331. }
  332. TTMATH_LOGC("UInt::Rcl2_one", c)
  333. return c;
  334. }
  335. /*!
  336. this method moves all bits into the right hand side
  337. c -> this -> return value
  338. the highest *bit* will be held the 'c' and
  339. the state of one additional bit (on the right hand side)
  340. will be returned
  341. for example:
  342. let this is 000000010
  343. after Rcr2_one(1) there'll be 100000001 and Rcr2_one returns 0
  344. */
  345. template<uint value_size>
  346. uint UInt<value_size>::Rcr2_one(uint c)
  347. {
  348. sint i; // signed i
  349. uint new_c;
  350. if( c != 0 )
  351. c = TTMATH_UINT_HIGHEST_BIT;
  352. for(i=sint(value_size)-1 ; i>=0 ; --i)
  353. {
  354. new_c = (table[i] & 1) ? TTMATH_UINT_HIGHEST_BIT : 0;
  355. table[i] = (table[i] >> 1) | c;
  356. c = new_c;
  357. }
  358. c = (c != 0)? 1 : 0;
  359. TTMATH_LOGC("UInt::Rcr2_one", c)
  360. return c;
  361. }
  362. /*!
  363. this method moves all bits into the left hand side
  364. return value <- this <- c
  365. the lowest *bits* will be held the 'c' and
  366. the state of one additional bit (on the left hand side)
  367. will be returned
  368. for example:
  369. let this is 001010000
  370. after Rcl2(3, 1) there'll be 010000111 and Rcl2 returns 1
  371. */
  372. template<uint value_size>
  373. uint UInt<value_size>::Rcl2(uint bits, uint c)
  374. {
  375. TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
  376. uint move = TTMATH_BITS_PER_UINT - bits;
  377. uint i, new_c;
  378. if( c != 0 )
  379. c = TTMATH_UINT_MAX_VALUE >> move;
  380. for(i=0 ; i<value_size ; ++i)
  381. {
  382. new_c = table[i] >> move;
  383. table[i] = (table[i] << bits) | c;
  384. c = new_c;
  385. }
  386. TTMATH_LOGC("UInt::Rcl2", (c & 1))
  387. return (c & 1);
  388. }
  389. /*!
  390. this method moves all bits into the right hand side
  391. C -> this -> return value
  392. the highest *bits* will be held the 'c' and
  393. the state of one additional bit (on the right hand side)
  394. will be returned
  395. for example:
  396. let this is 000000010
  397. after Rcr2(2, 1) there'll be 110000000 and Rcr2 returns 1
  398. */
  399. template<uint value_size>
  400. uint UInt<value_size>::Rcr2(uint bits, uint c)
  401. {
  402. TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
  403. uint move = TTMATH_BITS_PER_UINT - bits;
  404. sint i; // signed
  405. uint new_c;
  406. if( c != 0 )
  407. c = TTMATH_UINT_MAX_VALUE << move;
  408. for(i=value_size-1 ; i>=0 ; --i)
  409. {
  410. new_c = table[i] << move;
  411. table[i] = (table[i] >> bits) | c;
  412. c = new_c;
  413. }
  414. c = (c & TTMATH_UINT_HIGHEST_BIT) ? 1 : 0;
  415. TTMATH_LOGC("UInt::Rcr2", c)
  416. return c;
  417. }
  418. /*!
  419. this method returns the number of the highest set bit in x
  420. if the 'x' is zero this method returns '-1'
  421. */
  422. template<uint value_size>
  423. sint UInt<value_size>::FindLeadingBitInWord(uint x)
  424. {
  425. if( x == 0 )
  426. return -1;
  427. uint bit = TTMATH_BITS_PER_UINT - 1;
  428. while( (x & TTMATH_UINT_HIGHEST_BIT) == 0 )
  429. {
  430. x = x << 1;
  431. --bit;
  432. }
  433. return bit;
  434. }
  435. /*!
  436. this method returns the number of the highest set bit in x
  437. if the 'x' is zero this method returns '-1'
  438. */
  439. template<uint value_size>
  440. sint UInt<value_size>::FindLowestBitInWord(uint x)
  441. {
  442. if( x == 0 )
  443. return -1;
  444. uint bit = 0;
  445. while( (x & 1) == 0 )
  446. {
  447. x = x >> 1;
  448. ++bit;
  449. }
  450. return bit;
  451. }
  452. /*!
  453. this method sets a special bit in the 'value'
  454. and returns the last state of the bit (zero or one)
  455. bit is from <0,TTMATH_BITS_PER_UINT-1>
  456. e.g.
  457. uint x = 100;
  458. uint bit = SetBitInWord(x, 3);
  459. now: x = 108 and bit = 0
  460. */
  461. template<uint value_size>
  462. uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
  463. {
  464. TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
  465. uint mask = 1;
  466. if( bit > 0 )
  467. mask = mask << bit;
  468. uint last = value & mask;
  469. value = value | mask;
  470. return (last != 0) ? 1 : 0;
  471. }
  472. /*!
  473. *
  474. * Multiplication
  475. *
  476. *
  477. */
  478. /*!
  479. multiplication: result_high:result_low = a * b
  480. result_high - higher word of the result
  481. result_low - lower word of the result
  482. this methos never returns a carry
  483. this method is used in the second version of the multiplication algorithms
  484. */
  485. template<uint value_size>
  486. void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
  487. {
  488. #ifdef TTMATH_PLATFORM32
  489. /*
  490. on 32bit platforms we have defined 'unsigned long long int' type known as 'ulint' in ttmath namespace
  491. this type has 64 bits, then we're using only one multiplication: 32bit * 32bit = 64bit
  492. */
  493. union uint_
  494. {
  495. struct
  496. {
  497. uint low; // 32 bits
  498. uint high; // 32 bits
  499. } u_;
  500. ulint u; // 64 bits
  501. } res;
  502. res.u = ulint(a) * ulint(b); // multiply two 32bit words, the result has 64 bits
  503. *result_high = res.u_.high;
  504. *result_low = res.u_.low;
  505. #else
  506. /*
  507. 64 bits platforms
  508. we don't have a native type which has 128 bits
  509. then we're splitting 'a' and 'b' to 4 parts (high and low halves)
  510. and using 4 multiplications (with additions and carry correctness)
  511. */
  512. uint_ a_;
  513. uint_ b_;
  514. uint_ res_high1, res_high2;
  515. uint_ res_low1, res_low2;
  516. a_.u = a;
  517. b_.u = b;
  518. /*
  519. the multiplication is as follows (schoolbook algorithm with O(n^2) ):
  520. 32 bits 32 bits
  521. +--------------------------------+
  522. | a_.u_.high | a_.u_.low |
  523. +--------------------------------+
  524. | b_.u_.high | b_.u_.low |
  525. +--------------------------------+--------------------------------+
  526. | res_high1.u | res_low1.u |
  527. +--------------------------------+--------------------------------+
  528. | res_high2.u | res_low2.u |
  529. +--------------------------------+--------------------------------+
  530. 64 bits 64 bits
  531. */
  532. uint_ temp;
  533. res_low1.u = uint(b_.u_.low) * uint(a_.u_.low);
  534. temp.u = uint(res_low1.u_.high) + uint(b_.u_.low) * uint(a_.u_.high);
  535. res_low1.u_.high = temp.u_.low;
  536. res_high1.u_.low = temp.u_.high;
  537. res_high1.u_.high = 0;
  538. res_low2.u_.low = 0;
  539. temp.u = uint(b_.u_.high) * uint(a_.u_.low);
  540. res_low2.u_.high = temp.u_.low;
  541. res_high2.u = uint(b_.u_.high) * uint(a_.u_.high) + uint(temp.u_.high);
  542. uint c = AddTwoWords(res_low1.u, res_low2.u, 0, &res_low2.u);
  543. AddTwoWords(res_high1.u, res_high2.u, c, &res_high2.u); // there is no carry from here
  544. *result_high = res_high2.u;
  545. *result_low = res_low2.u;
  546. #endif
  547. }
  548. /*!
  549. *
  550. * Division
  551. *
  552. *
  553. */
  554. /*!
  555. this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
  556. r = a:b / c and rest - remainder
  557. *
  558. * WARNING:
  559. * the c has to be suitably large for the result being keeped in one word,
  560. * if c is equal zero there'll be a hardware interruption (0)
  561. * and probably the end of your program
  562. *
  563. */
  564. template<uint value_size>
  565. void UInt<value_size>::DivTwoWords(uint a, uint b, uint c, uint * r, uint * rest)
  566. {
  567. // (a < c ) for the result to be one word
  568. TTMATH_ASSERT( c != 0 && a < c )
  569. #ifdef TTMATH_PLATFORM32
  570. union
  571. {
  572. struct
  573. {
  574. uint low; // 32 bits
  575. uint high; // 32 bits
  576. } u_;
  577. ulint u; // 64 bits
  578. } ab;
  579. ab.u_.high = a;
  580. ab.u_.low = b;
  581. *r = uint(ab.u / c);
  582. *rest = uint(ab.u % c);
  583. #else
  584. uint_ c_;
  585. c_.u = c;
  586. if( a == 0 )
  587. {
  588. *r = b / c;
  589. *rest = b % c;
  590. }
  591. else
  592. if( c_.u_.high == 0 )
  593. {
  594. // higher half of 'c' is zero
  595. // then higher half of 'a' is zero too (look at the asserts at the beginning - 'a' is smaller than 'c')
  596. uint_ a_, b_, res_, temp1, temp2;
  597. a_.u = a;
  598. b_.u = b;
  599. temp1.u_.high = a_.u_.low;
  600. temp1.u_.low = b_.u_.high;
  601. res_.u_.high = (unsigned int)(temp1.u / c);
  602. temp2.u_.high = (unsigned int)(temp1.u % c);
  603. temp2.u_.low = b_.u_.low;
  604. res_.u_.low = (unsigned int)(temp2.u / c);
  605. *rest = temp2.u % c;
  606. *r = res_.u;
  607. }
  608. else
  609. {
  610. return DivTwoWords2(a, b, c, r, rest);
  611. }
  612. #endif
  613. }
  614. #ifdef TTMATH_PLATFORM64
  615. /*!
  616. this method is available only on 64bit platforms
  617. the same algorithm like the third division algorithm in ttmathuint.h
  618. but now with the radix=2^32
  619. */
  620. template<uint value_size>
  621. void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest)
  622. {
  623. // a is not zero
  624. // c_.u_.high is not zero
  625. uint_ a_, b_, c_, u_, q_;
  626. unsigned int u3; // 32 bit
  627. a_.u = a;
  628. b_.u = b;
  629. c_.u = c;
  630. // normalizing
  631. uint d = DivTwoWordsNormalize(a_, b_, c_);
  632. // loop from j=1 to j=0
  633. // the first step (for j=2) is skipped because our result is only in one word,
  634. // (first 'q' were 0 and nothing would be changed)
  635. u_.u_.high = a_.u_.high;
  636. u_.u_.low = a_.u_.low;
  637. u3 = b_.u_.high;
  638. q_.u_.high = DivTwoWordsCalculate(u_, u3, c_);
  639. MultiplySubtract(u_, u3, q_.u_.high, c_);
  640. u_.u_.high = u_.u_.low;
  641. u_.u_.low = u3;
  642. u3 = b_.u_.low;
  643. q_.u_.low = DivTwoWordsCalculate(u_, u3, c_);
  644. MultiplySubtract(u_, u3, q_.u_.low, c_);
  645. *r = q_.u;
  646. // unnormalizing for the remainder
  647. u_.u_.high = u_.u_.low;
  648. u_.u_.low = u3;
  649. *rest = DivTwoWordsUnnormalize(u_.u, d);
  650. }
  651. template<uint value_size>
  652. uint UInt<value_size>::DivTwoWordsNormalize(uint_ & a_, uint_ & b_, uint_ & c_)
  653. {
  654. uint d = 0;
  655. for( ; (c_.u & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
  656. {
  657. c_.u = c_.u << 1;
  658. uint bc = b_.u & TTMATH_UINT_HIGHEST_BIT; // carry from 'b'
  659. b_.u = b_.u << 1;
  660. a_.u = a_.u << 1; // carry bits from 'a' are simply skipped
  661. if( bc )
  662. a_.u = a_.u | 1;
  663. }
  664. return d;
  665. }
  666. template<uint value_size>
  667. uint UInt<value_size>::DivTwoWordsUnnormalize(uint u, uint d)
  668. {
  669. if( d == 0 )
  670. return u;
  671. u = u >> d;
  672. return u;
  673. }
  674. template<uint value_size>
  675. unsigned int UInt<value_size>::DivTwoWordsCalculate(uint_ u_, unsigned int u3, uint_ v_)
  676. {
  677. bool next_test;
  678. uint_ qp_, rp_, temp_;
  679. qp_.u = u_.u / uint(v_.u_.high);
  680. rp_.u = u_.u % uint(v_.u_.high);
  681. TTMATH_ASSERT( qp_.u_.high==0 || qp_.u_.high==1 )
  682. do
  683. {
  684. bool decrease = false;
  685. if( qp_.u_.high == 1 )
  686. decrease = true;
  687. else
  688. {
  689. temp_.u_.high = rp_.u_.low;
  690. temp_.u_.low = u3;
  691. if( qp_.u * uint(v_.u_.low) > temp_.u )
  692. decrease = true;
  693. }
  694. next_test = false;
  695. if( decrease )
  696. {
  697. --qp_.u;
  698. rp_.u += v_.u_.high;
  699. if( rp_.u_.high == 0 )
  700. next_test = true;
  701. }
  702. }
  703. while( next_test );
  704. return qp_.u_.low;
  705. }
  706. template<uint value_size>
  707. void UInt<value_size>::MultiplySubtract(uint_ & u_, unsigned int & u3, unsigned int & q, uint_ v_)
  708. {
  709. uint_ temp_;
  710. uint res_high;
  711. uint res_low;
  712. MulTwoWords(v_.u, q, &res_high, &res_low);
  713. uint_ sub_res_high_;
  714. uint_ sub_res_low_;
  715. temp_.u_.high = u_.u_.low;
  716. temp_.u_.low = u3;
  717. uint c = SubTwoWords(temp_.u, res_low, 0, &sub_res_low_.u);
  718. temp_.u_.high = 0;
  719. temp_.u_.low = u_.u_.high;
  720. c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u);
  721. if( c )
  722. {
  723. --q;
  724. c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u);
  725. AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u);
  726. }
  727. u_.u_.high = sub_res_high_.u_.low;
  728. u_.u_.low = sub_res_low_.u_.high;
  729. u3 = sub_res_low_.u_.low;
  730. }
  731. #endif // #ifdef TTMATH_PLATFORM64
  732. } //namespace
  733. #endif //ifdef TTMATH_NOASM
  734. #endif