/src/lib/numeric/mutable_big_integer.e

http://github.com/tybor/Liberty · Specman e · 3242 lines · 2778 code · 118 blank · 346 comment · 173 complexity · 1607f00f3277ea7f98b3afbcb3c85bf5 MD5 · raw file

Large files are truncated click here to view the full file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class MUTABLE_BIG_INTEGER
  5. --
  6. -- A class used to represent multiprecision integers that makes efficient use of allocated space
  7. -- by allowing a number to occupy only part of an array so that the arrays do not have to be
  8. -- reallocated as often. When performing an operation with many iterations the array used to
  9. -- hold a number is only reallocated when necessary and does not have to be the same size as
  10. -- the number it represents. A mutable number allows calculations to occur on the same number
  11. -- without having to create a new number for every step of the calculation as it occurs with
  12. -- NUMBERs.
  13. --
  14. inherit
  15. HASHABLE
  16. redefine copy, fill_tagged_out_memory, out_in_tagged_out_memory
  17. end
  18. COMPARABLE
  19. redefine copy, fill_tagged_out_memory, out_in_tagged_out_memory, is_equal
  20. end
  21. insert
  22. PLATFORM
  23. redefine copy, fill_tagged_out_memory, out_in_tagged_out_memory, is_equal
  24. end
  25. create {ANY}
  26. from_integer, from_integer_64, from_string, copy
  27. feature {ANY} -- Creation / initialization from INTEGER_32 or INTEGER_64:
  28. from_integer (value: INTEGER)
  29. -- Create or initialize `Current' using `value' as an initializer.
  30. do
  31. if capacity = 0 then
  32. storage := storage.calloc(4)
  33. capacity := 4
  34. end
  35. offset := 0
  36. if value > 0 then
  37. negative := False
  38. put(value, 0)
  39. integer_length := 1
  40. elseif value < 0 then
  41. negative := True
  42. put(#-value, 0)
  43. integer_length := 1
  44. else
  45. check
  46. value = 0
  47. end
  48. set_with_zero
  49. end
  50. ensure
  51. to_integer_32 = value
  52. end
  53. is_integer_32: BOOLEAN
  54. -- Does `Current' fit on an INTEGER_32?
  55. do
  56. if integer_length = 0 then
  57. Result := True
  58. elseif integer_length = 1 then
  59. if item(offset) > 0 then
  60. Result := True
  61. elseif negative then
  62. Result := item(offset) = 0x80000000
  63. end
  64. end
  65. ensure
  66. Result implies is_integer_64
  67. Result implies integer_length <= 1
  68. end
  69. to_integer_32: INTEGER
  70. -- Convert `Current' as a 32 bit INTEGER.
  71. require
  72. is_integer_32
  73. do
  74. if integer_length > 0 then
  75. Result := item(offset)
  76. if negative then
  77. Result := #-Result
  78. end
  79. end
  80. end
  81. from_integer_64 (value: INTEGER_64)
  82. -- Create or set `Current' using `value' as an initializer.
  83. local
  84. v32: INTEGER
  85. do
  86. if capacity < 2 then
  87. storage := storage.calloc(4)
  88. capacity := 4
  89. end
  90. if value > 0 then
  91. negative := False
  92. put(value.low_32, 0)
  93. offset := 0
  94. v32 := value.high_32
  95. if v32 = 0 then
  96. integer_length := 1
  97. else
  98. put(v32, 1)
  99. integer_length := 2
  100. end
  101. elseif value < 0 then
  102. negative := True
  103. put((#-value).low_32, 0)
  104. offset := 0
  105. v32 := (#-value).high_32
  106. if v32 = 0 then
  107. integer_length := 1
  108. else
  109. put(v32, 1)
  110. integer_length := 2
  111. end
  112. else
  113. check
  114. value = 0
  115. end
  116. set_with_zero
  117. end
  118. ensure
  119. to_integer_64 = value
  120. end
  121. is_integer_64: BOOLEAN
  122. -- Does `Current' fit on an INTEGER_64?
  123. do
  124. if integer_length <= 1 then
  125. Result := True
  126. elseif integer_length = 2 then
  127. if negative then
  128. if item(offset + 1) > 0 then
  129. Result := True
  130. elseif item(offset) = 0 then
  131. Result := item(offset + 1) = 0x80000000
  132. end
  133. else
  134. Result := item(offset + 1) > 0
  135. end
  136. end
  137. ensure
  138. not Result implies not is_integer_32
  139. Result implies integer_length <= 2
  140. end
  141. to_integer_64: INTEGER_64
  142. -- Convert `Current' as a INTEGER_64.
  143. require
  144. is_integer_64
  145. local
  146. v: INTEGER_64
  147. do
  148. inspect
  149. integer_length
  150. when 0 then
  151. when 1 then
  152. Result := unsigned_32_to_integer_64(item(offset))
  153. if negative then
  154. Result := -Result
  155. end
  156. when 2 then
  157. Result := unsigned_32_to_integer_64(item(offset))
  158. v := item(offset + 1)
  159. v := v.bit_shift_left(32)
  160. Result := Result.bit_xor(v)
  161. if negative then
  162. Result := #-Result
  163. end
  164. end
  165. end
  166. feature {ANY} -- Creation / initialization from STRING:
  167. from_string (str: STRING)
  168. -- Create or initialize `Current' using `value' as an
  169. -- initializer. (value = [-][0-9]^+)
  170. local
  171. i: INTEGER; cc: CHARACTER; neg: BOOLEAN; ten: like Current
  172. do
  173. --|*** This feature should be improved one day... (Vincent Croizier, 25/12/2004)
  174. create ten.from_integer(10)
  175. from
  176. i := 1
  177. variant
  178. str.count - i
  179. until
  180. not str.item(i).is_separator
  181. loop
  182. i := i + 1
  183. end
  184. cc := str.item(i)
  185. i := i + 1
  186. if cc = '+' then
  187. cc := str.item(i)
  188. i := i + 1
  189. elseif cc = '-' then
  190. neg := True
  191. cc := str.item(i)
  192. i := i + 1
  193. end
  194. check
  195. cc.is_digit
  196. end
  197. from_integer(cc.value)
  198. from
  199. variant
  200. str.count - i
  201. until
  202. i > str.count
  203. loop
  204. cc := str.item(i)
  205. if cc.is_digit then
  206. multiply(ten)
  207. add_integer(cc.value)
  208. else
  209. check
  210. cc.is_separator
  211. end
  212. i := str.count -- terminate the loop
  213. end
  214. i := i + 1
  215. end
  216. if neg then
  217. negate
  218. end
  219. end
  220. feature {ANY} -- Conversion tool
  221. force_to_real_64: REAL_64
  222. -- only a tool
  223. -- unsigned conversion *** require ou changer export ? *** (Dom Oct 4th 2004) ***
  224. local
  225. i: INTEGER
  226. do
  227. from
  228. i := offset + integer_length - 1
  229. until
  230. i < offset or else Result > Maximum_real_64
  231. loop
  232. Result := Result * Real_base + unsigned_32_to_integer_64(storage.item(i)).force_to_real_64
  233. i := i - 1
  234. end
  235. if Result = Maximum_real_64 and then storage.item(offset) /= 0 then
  236. Result := Maximum_real_64 * 2
  237. end
  238. if negative then
  239. Result := -Result
  240. end
  241. end
  242. feature {NUMBER}
  243. from_native_array (na: NATIVE_ARRAY[INTEGER]; cap: INTEGER; neg: BOOLEAN)
  244. require
  245. na.item(cap - 1) /= 0
  246. do
  247. negative := neg
  248. offset := 0
  249. integer_length := cap
  250. if cap > capacity then
  251. capacity := capacity_from_lower_bound(capacity, cap)
  252. storage := storage.calloc(capacity)
  253. end
  254. storage.slice_copy(0, na, 0, cap - 1)
  255. end
  256. to_integer_general_number: INTEGER_GENERAL_NUMBER
  257. local
  258. na: like storage
  259. do
  260. if is_integer_64 then
  261. create {INTEGER_64_NUMBER} Result.make(to_integer_64)
  262. else
  263. na := storage.calloc(integer_length)
  264. na.slice_copy(0, storage, offset, offset + integer_length - 1)
  265. create {BIG_INTEGER_NUMBER} Result.from_native_array(na, integer_length, negative)
  266. end
  267. end
  268. feature {ANY} -- Addition:
  269. add (other: like Current)
  270. -- Add `other' into `Current'.
  271. --
  272. -- See also `add_integer', `add_integer_64', `add_natural'.
  273. require
  274. other /= Void
  275. do
  276. -- Choose the appropriate absolute operator depending on `Current' and `other' sign.
  277. if other.integer_length = 0 then
  278. -- Nothing to do, `Current' remains unchanged.
  279. elseif integer_length = 0 then
  280. -- `Current' is zero so simply copy the value of other
  281. Current.copy(other)
  282. elseif negative = other.negative then
  283. -- same sign
  284. add_magnitude(other)
  285. else
  286. -- different sign
  287. subtract_magnitude(other)
  288. end
  289. end
  290. add_to (other, res: like Current)
  291. -- Add `other' and `Current', and put the result in `res'.
  292. require
  293. other /= Void
  294. res /= Void
  295. res /= Current
  296. res /= other
  297. do
  298. --|*** Must be optimized later (Vincent Croizier, 15/07/04) ***
  299. res.copy(Current)
  300. res.add(other)
  301. end
  302. add_integer (other: INTEGER)
  303. -- Add `other' into `Current'.
  304. local
  305. inc: BOOLEAN; v, i, n: INTEGER
  306. do
  307. if other = 0 then
  308. -- Nothing to do, `Current' remains unchanged
  309. elseif integer_length = 0 then
  310. -- `Current' is null so simply copy the value of other
  311. from_integer(other)
  312. elseif negative = (other < 0) then
  313. -- Same sign
  314. if other < 0 then
  315. v := #-other
  316. else
  317. v := other
  318. end
  319. -- Add `v' into `storage'
  320. from
  321. inc := mbi_add(item(offset), v, storage_at(storage, offset))
  322. i := offset + 1
  323. n := offset + integer_length
  324. until
  325. not inc or else i >= n
  326. loop
  327. inc := mbi_inc(storage_at(storage, i))
  328. i := i + 1
  329. end
  330. if inc then
  331. check
  332. i = n
  333. end
  334. -- Extend the number length by 1
  335. if n < capacity then
  336. integer_length := integer_length + 1
  337. put(1, n)
  338. else
  339. -- It's good only if the reallocation initialize
  340. -- `storage' with 0.
  341. v := item(offset)
  342. capacity := capacity * 2
  343. storage := storage.calloc(capacity)
  344. offset := 0
  345. put(v, 0)
  346. put(1, integer_length)
  347. integer_length := integer_length + 1
  348. end
  349. end
  350. -- Different sign
  351. elseif integer_length = 1 then
  352. if other < 0 then
  353. v := #-other
  354. else
  355. v := other
  356. end
  357. if mbi_subtract(item(offset), v, storage_at(storage, offset)) then
  358. negative := not negative
  359. put(-item(offset), offset)
  360. end
  361. if item(offset) = 0 then
  362. integer_length := 0
  363. negative := False
  364. end
  365. else
  366. if other < 0 then
  367. v := #-other
  368. else
  369. v := other
  370. end
  371. if mbi_subtract(item(offset), v, storage_at(storage, offset)) then
  372. from
  373. i := offset + 1
  374. inc := mbi_dec(storage_at(storage, i))
  375. n := offset + integer_length - 1
  376. until
  377. not inc
  378. loop
  379. check
  380. i < n
  381. end
  382. i := i + 1
  383. inc := mbi_dec(storage_at(storage, i))
  384. end
  385. if item(n) = 0 then
  386. integer_length := integer_length - 1
  387. end
  388. end
  389. end
  390. end
  391. add_integer_64 (other: INTEGER_64)
  392. -- Add `other' into `Current'.
  393. do
  394. register1.from_integer_64(other)
  395. add(register1)
  396. end
  397. add_natural (other: like Current)
  398. -- Same behavior as `add', but this one works only when `Current'
  399. -- and `other' are both positive numbers and are both greater than
  400. -- zero. The only one advantage of using `add_natural' instead of the
  401. -- general `add' is the gain of efficiency.
  402. require
  403. not is_zero and not is_negative
  404. not other.is_zero and not other.is_negative
  405. do
  406. add_magnitude(other)
  407. end
  408. feature {ANY} -- Subtract:
  409. subtract (other: like Current)
  410. -- Subtract `other' from `Current'.
  411. require
  412. other /= Void
  413. do
  414. if other = Current then
  415. set_with_zero
  416. elseif other.integer_length = 0 then
  417. -- nothing to do, `Current' remains unchanged
  418. elseif integer_length = 0 then
  419. -- current is null so simply copy the value of other, the sign is also fixed
  420. copy(other)
  421. negative := not other.negative
  422. elseif negative = other.negative then
  423. -- same sign
  424. subtract_magnitude(other)
  425. else
  426. -- different sign
  427. add_magnitude(other)
  428. end
  429. end
  430. subtract_to (other, res: like Current)
  431. -- Subtract `other' from `Current' and put it in `res'.
  432. require
  433. other /= Void
  434. res /= Void
  435. res /= Current
  436. res /= other
  437. do
  438. --|*** Must be optimized later (Vincent Croizier, 15/07/04) ***
  439. res.copy(Current)
  440. res.subtract(other)
  441. end
  442. subtract_integer (other: INTEGER)
  443. do
  444. if other = Minimum_integer then
  445. add_integer(1)
  446. add_integer(Maximum_integer)
  447. else
  448. add_integer(-other)
  449. end
  450. end
  451. feature {ANY} -- To divide:
  452. divide (other: like Current)
  453. -- Put the quotient of the Euclidian division of
  454. -- `Current' by `other' in `Current'.
  455. -- (The contents of `other' is not changed.)
  456. require
  457. not other.is_zero
  458. other /= Current
  459. do
  460. -- `divide_with_remainder_to' already uses `register1'.
  461. divide_with_remainder_to(other, register2)
  462. end
  463. mod (other: like Current)
  464. -- Put the remainder of the Euclidian division of
  465. -- `Current' by `other' in `Current'.
  466. -- (The contents of `other' is not changed.)
  467. require
  468. not other.is_zero
  469. other /= Current
  470. local
  471. quotient: like Current
  472. do
  473. --|*** Must be optimized (Vincent Croizier, 12/07/04) ***
  474. create quotient.from_integer(0)
  475. remainder_with_quotient_to(other, quotient)
  476. ensure
  477. not negative and abs_compare(other) = -1
  478. end
  479. divide_with_remainder_to (other, remainder: like Current)
  480. -- Euclidian division.
  481. -- Calculates the `quotient' and `remainder' of `Current'
  482. -- divided by `other'.
  483. -- Quotient is put in `Current'.
  484. -- (The contents of `other' is not changed.)
  485. require
  486. not other.is_zero
  487. remainder /= Void
  488. remainder /= other
  489. remainder /= Current
  490. do
  491. Current.remainder_with_quotient_to(other, remainder)
  492. Current.swap_with(remainder)
  493. ensure
  494. not remainder.negative and remainder.abs_compare(other) = -1
  495. end
  496. remainder_with_quotient_to (other, quotient: like Current)
  497. -- Euclidian division.
  498. -- Calculates the `quotient' and `remainder' of `Current'
  499. -- divided by `other'.
  500. -- Remainder is put in `Current'.
  501. -- (The contents of `other' is not changed.)
  502. --
  503. -- Note: Uses Algorithm D in Knuth section 4.3.1.
  504. require
  505. not other.is_zero
  506. quotient /= Void
  507. quotient /= other
  508. quotient /= Current
  509. local
  510. cmp, shift, dlen, qlen, j, k, v1, v2, u1, u2, rem: INTEGER; qhat, rhat, v2qhat_1, v2qhat_2, d_offset: INTEGER
  511. q_storage, d_storage: like storage; q_capacity: like capacity; current_negative, borrow: BOOLEAN
  512. do
  513. if integer_length = 0 then
  514. -- Dividend is zero:
  515. quotient.set_with_zero
  516. set_with_zero
  517. else
  518. current_negative := negative
  519. cmp := Current.abs_compare(other)
  520. if cmp < 0 then
  521. -- Dividend less than divisor:
  522. quotient.set_with_zero
  523. -- Sign correction
  524. set_negative(False)
  525. divide_sign_correction_bis(other, quotient, current_negative)
  526. elseif cmp = 0 then
  527. -- Dividend equal to divisor:
  528. if negative = other.negative then
  529. quotient.from_integer(1)
  530. else
  531. quotient.from_integer(-1)
  532. end
  533. set_with_zero
  534. elseif other.integer_length = 1 then
  535. -- Special case one word divisor:
  536. quotient.swap_with(Current)
  537. --|*** replace by "from_unsigned_integer" ? (Vincent Croizier)
  538. set_with_zero
  539. rem := quotient.divide_one_word(other.item(other.offset))
  540. if rem /= 0 then
  541. put(rem, 0)
  542. set_integer_length(1)
  543. else
  544. check
  545. is_zero
  546. end
  547. end
  548. -- Sign correction
  549. divide_sign_correction_bis(other, quotient, current_negative)
  550. else
  551. -- Copy divisor storage to protect divisor:
  552. register1.copy(other)
  553. -- D1 normalize the divisor:
  554. shift := register1.normalize
  555. if shift /= 0 then
  556. shift_left(shift)
  557. end
  558. -- D2 Initialize j:
  559. from
  560. d_storage := register1.storage
  561. d_offset := register1.offset
  562. dlen := register1.integer_length
  563. j := offset + integer_length - 1
  564. u2 := storage.item(j)
  565. k := register1.offset + dlen - 1
  566. v1 := register1.item(k)
  567. v2 := register1.item(k - 1)
  568. if unsigned_greater_or_equal(u2, v1) then
  569. k := integer_length - dlen
  570. qlen := k + 1
  571. else
  572. qlen := integer_length - dlen
  573. k := qlen - 1
  574. j := j - 1
  575. u1 := u2
  576. u2 := storage.item(j)
  577. end
  578. -- Resize quotient if necessary
  579. q_capacity := quotient.capacity
  580. if q_capacity < qlen then
  581. -- reallocation
  582. q_capacity := capacity_from_lower_bound(q_capacity, qlen)
  583. q_storage := storage.calloc(q_capacity)
  584. else
  585. q_storage := quotient.storage
  586. end
  587. -- To avoid invariant violation on `quotient'
  588. quotient.set_with_zero
  589. until
  590. k < 0
  591. loop
  592. j := j - 1 -- D3 Calculate qhat - estimate qhat
  593. if u1 = v1 then
  594. qhat := ~0
  595. else
  596. qhat := mbi_divide(u1, u2, v1, $rhat) -- Correct qhat
  597. if qhat = 0 then
  598. else
  599. v2qhat_1 := mbi_multiply(v2, qhat, $v2qhat_2)
  600. if unsigned_greater_than(v2qhat_1, rhat) then
  601. qhat := qhat - 1
  602. if mbi_subtract(v2qhat_2, v2, $v2qhat_2) then
  603. v2qhat_1 := v2qhat_1 - 1
  604. end
  605. if mbi_add(rhat, v1, $rhat) then
  606. elseif unsigned_greater_than(v2qhat_1, rhat) then
  607. qhat := qhat - 1
  608. elseif j < 0 then
  609. if v2qhat_1 = rhat and then v2qhat_2 /= 0 then
  610. qhat := qhat - 1
  611. end
  612. elseif v2qhat_1 = rhat and then unsigned_greater_than(v2qhat_2, storage.item(j)) then
  613. qhat := qhat - 1
  614. end
  615. elseif j < 0 then
  616. if v2qhat_1 = rhat and then v2qhat_2 /= 0 then
  617. qhat := qhat - 1
  618. end
  619. elseif v2qhat_1 = rhat and then unsigned_greater_than(v2qhat_2, storage.item(j)) then
  620. qhat := qhat - 1
  621. end
  622. end
  623. end
  624. -- D4 Multiply and subtract:
  625. if qhat = 0 then
  626. q_storage.put(0, k)
  627. else
  628. borrow := multiply_and_subtract(u1, qhat, d_storage, d_offset, storage, j - dlen + 2, dlen)
  629. -- D5 Test remainder: Result is negative ?
  630. if borrow then
  631. -- D6 Add back
  632. borrow := add_back(u1, d_storage, d_offset, storage, j - dlen + 2, dlen)
  633. check
  634. borrow
  635. end
  636. q_storage.put(qhat - 1, k)
  637. else
  638. q_storage.put(qhat, k)
  639. end
  640. end
  641. -- D7 loop on j
  642. k := k - 1
  643. u1 := storage.item(j + 1)
  644. u2 := storage.item(j)
  645. end
  646. -- Remove leading zero of quotient
  647. k := qlen - 1
  648. if q_storage.item(k) = 0 then
  649. qlen := k
  650. end
  651. quotient.set_all(q_storage, q_capacity, qlen, 0, False)
  652. -- Remove leading zero of remainder
  653. from
  654. j := dlen - 1
  655. until
  656. j < 0 or else storage.item(j) /= 0
  657. loop
  658. j := j - 1
  659. end
  660. j := j + 1
  661. check
  662. j >= 0
  663. end
  664. if j = 0 then
  665. set_with_zero
  666. else
  667. offset := 0
  668. integer_length := j
  669. negative := False
  670. end
  671. -- D8 Unnormalize:
  672. if shift > 0 then
  673. shift_right(shift)
  674. end
  675. -- Sign correction
  676. divide_sign_correction_bis(other, quotient, current_negative)
  677. end
  678. end
  679. ensure
  680. not negative and abs_compare(other) = -1
  681. end
  682. divide_to (other, quotient, remainder: like Current)
  683. -- Euclidian division.
  684. -- Calculates the `quotient' and `remainder' of `Current'
  685. -- divided by `other'. (The contents of `Current' and `other' are
  686. -- not changed.)
  687. --
  688. -- Note: Uses Algorithm D in Knuth section 4.3.1.
  689. require
  690. not other.is_zero
  691. quotient /= Void
  692. remainder /= Void
  693. quotient /= other
  694. quotient /= Current
  695. remainder /= other
  696. remainder /= Current
  697. local
  698. cmp, shift, nlen, dlen, qlen, j, k, v1, v2, u1, u2, rem: INTEGER
  699. qhat, rhat, v2qhat_1, v2qhat_2, d_offset: INTEGER; q_storage, r_storage, d_storage: like storage
  700. q_capacity, r_capacity: like capacity; borrow: BOOLEAN
  701. do
  702. if integer_length = 0 then
  703. -- Dividend is zero:
  704. quotient.set_with_zero
  705. remainder.set_with_zero
  706. else
  707. cmp := Current.abs_compare(other)
  708. if cmp < 0 then
  709. -- Dividend less than divisor:
  710. quotient.set_with_zero
  711. remainder.copy(Current)
  712. -- Sign correction
  713. remainder.set_negative(False)
  714. divide_sign_correction(other, quotient, remainder)
  715. elseif cmp = 0 then
  716. -- Dividend equal to divisor:
  717. if negative = other.negative then
  718. quotient.from_integer(1)
  719. else
  720. quotient.from_integer(-1)
  721. end
  722. remainder.set_with_zero
  723. elseif other.integer_length = 1 then
  724. -- Special case one word divisor:
  725. quotient.copy(Current)
  726. --|*** replace by "from_unsigned_integer" ? (Vincent Croizier)
  727. remainder.set_with_zero
  728. rem := quotient.divide_one_word(other.item(other.offset))
  729. if rem /= 0 then
  730. remainder.put(rem, 0)
  731. remainder.set_ilo(1, 0)
  732. else
  733. check
  734. remainder.is_zero
  735. end
  736. end
  737. -- Sign correction
  738. divide_sign_correction(other, quotient, remainder)
  739. else
  740. -- Copy divisor storage to protect divisor:
  741. register1.copy(other)
  742. --|***
  743. remainder.copy(Current)
  744. -- D1 normalize the divisor:
  745. shift := register1.normalize
  746. if shift /= 0 then
  747. remainder.shift_left(shift)
  748. end
  749. -- D2 Initialize j:
  750. from
  751. r_storage := remainder.storage
  752. r_capacity := remainder.capacity
  753. check
  754. remainder.offset = 0
  755. end
  756. nlen := remainder.integer_length -- To avoid invariant class violation
  757. remainder.set_with_zero
  758. d_storage := register1.storage
  759. d_offset := register1.offset
  760. dlen := register1.integer_length
  761. j := nlen - 1
  762. u2 := r_storage.item(j)
  763. k := register1.offset + dlen - 1
  764. v1 := register1.item(k)
  765. v2 := register1.item(k - 1)
  766. if unsigned_greater_or_equal(u2, v1) then
  767. k := nlen - dlen
  768. qlen := k + 1
  769. else
  770. qlen := nlen - dlen
  771. k := qlen - 1
  772. j := j - 1
  773. u1 := u2
  774. u2 := r_storage.item(j)
  775. end
  776. -- Resize quotient if necessary
  777. q_capacity := quotient.capacity
  778. if q_capacity < qlen then
  779. -- reallocation
  780. q_capacity := capacity_from_lower_bound(q_capacity, qlen)
  781. q_storage := storage.calloc(q_capacity)
  782. else
  783. q_storage := quotient.storage
  784. end
  785. -- To avoid invariant violation on `quotient'
  786. quotient.set_with_zero
  787. until
  788. k < 0
  789. loop
  790. j := j - 1 -- D3 Calculate qhat - estimate qhat
  791. if u1 = v1 then
  792. qhat := ~0
  793. else
  794. qhat := mbi_divide(u1, u2, v1, $rhat) -- Correct qhat
  795. if qhat = 0 then
  796. else
  797. v2qhat_1 := mbi_multiply(v2, qhat, $v2qhat_2)
  798. if unsigned_greater_than(v2qhat_1, rhat) then
  799. qhat := qhat - 1
  800. if mbi_subtract(v2qhat_2, v2, $v2qhat_2) then
  801. v2qhat_1 := v2qhat_1 - 1
  802. end
  803. if mbi_add(rhat, v1, $rhat) then
  804. elseif unsigned_greater_than(v2qhat_1, rhat) then
  805. qhat := qhat - 1
  806. elseif j < 0 then
  807. if v2qhat_1 = rhat and then v2qhat_2 /= 0 then
  808. qhat := qhat - 1
  809. end
  810. elseif v2qhat_1 = rhat and then unsigned_greater_than(v2qhat_2, r_storage.item(j)) then
  811. qhat := qhat - 1
  812. end
  813. elseif j < 0 then
  814. if v2qhat_1 = rhat and then v2qhat_2 /= 0 then
  815. qhat := qhat - 1
  816. end
  817. elseif v2qhat_1 = rhat and then unsigned_greater_than(v2qhat_2, r_storage.item(j)) then
  818. qhat := qhat - 1
  819. end
  820. end
  821. end
  822. -- D4 Multiply and subtract:
  823. if qhat = 0 then
  824. q_storage.put(0, k)
  825. else
  826. borrow := multiply_and_subtract(u1, qhat, d_storage, d_offset, r_storage, j - dlen + 2, dlen)
  827. -- D5 Test remainder: Result is negative ?
  828. if borrow then
  829. -- D6 Add back
  830. borrow := add_back(u1, d_storage, d_offset, r_storage, j - dlen + 2, dlen)
  831. check
  832. borrow
  833. end
  834. q_storage.put(qhat - 1, k)
  835. else
  836. q_storage.put(qhat, k)
  837. end
  838. end
  839. -- D7 loop on j
  840. k := k - 1
  841. u1 := r_storage.item(j + 1)
  842. u2 := r_storage.item(j)
  843. end
  844. -- Remove leading zero of quotient
  845. k := qlen - 1
  846. if q_storage.item(k) = 0 then
  847. qlen := k
  848. end
  849. quotient.set_all(q_storage, q_capacity, qlen, 0, False)
  850. -- Remove leading zero of remainder
  851. from
  852. j := dlen - 1
  853. until
  854. j < 0 or else r_storage.item(j) /= 0
  855. loop
  856. j := j - 1
  857. end
  858. j := j + 1
  859. check
  860. j >= 0
  861. end
  862. if j = 0 then
  863. check
  864. remainder.is_zero
  865. end
  866. else
  867. remainder.set_all(r_storage, r_capacity, j, 0, False)
  868. end
  869. -- D8 Unnormalize:
  870. if shift > 0 then
  871. remainder.shift_right(shift)
  872. end
  873. -- Sign correction
  874. divide_sign_correction(other, quotient, remainder)
  875. end
  876. end
  877. ensure
  878. is_a_good_divide(other, quotient, remainder)
  879. not remainder.negative and remainder.abs_compare(other) = -1
  880. end
  881. shift_left (n: INTEGER)
  882. -- Shift bits of magnitude by `n' position left. (Note that no bit can
  883. -- be lost because the `storage' area is automatically extended when
  884. -- it is necessary.)
  885. require
  886. n > 0
  887. local
  888. new_storage: like storage; left, right: INTEGER_8
  889. new_capacity, new_integer_length, new_head, word_shift, i, j, k, val1, val2, val3: INTEGER
  890. do
  891. if integer_length > 0 then
  892. word_shift := n |>>> 5
  893. left := (n & 0x0000001F).to_integer_8 -- Optimistic prediction
  894. new_integer_length := integer_length + word_shift
  895. if left = 0 then
  896. -- Just word shift
  897. if offset >= word_shift then
  898. -- no need to deplace the number in the storage
  899. from
  900. i := offset
  901. offset := offset - word_shift
  902. integer_length := new_integer_length
  903. until
  904. i = offset
  905. loop
  906. i := i - 1
  907. put(0, i)
  908. end
  909. elseif capacity >= new_integer_length then
  910. -- deplacing the number
  911. from
  912. i := offset + integer_length - 1
  913. j := word_shift + integer_length - 1
  914. until
  915. i < offset
  916. loop
  917. put(item(i), j)
  918. i := i - 1
  919. j := j - 1
  920. end
  921. from
  922. check
  923. j = word_shift - 1
  924. end
  925. until
  926. j < 0
  927. loop
  928. put(0, j)
  929. j := j - 1
  930. end
  931. offset := 0
  932. integer_length := new_integer_length
  933. else
  934. -- reallocation
  935. new_capacity := capacity_from_lower_bound(capacity, new_integer_length)
  936. new_storage := storage.calloc(new_capacity)
  937. from
  938. i := offset + integer_length
  939. j := word_shift + integer_length
  940. until
  941. i = offset
  942. loop
  943. i := i - 1
  944. j := j - 1
  945. new_storage.put(item(i), j)
  946. end
  947. storage := new_storage
  948. capacity := new_capacity
  949. offset := 0
  950. integer_length := new_integer_length
  951. end
  952. else
  953. right := 32 - left -- Compute real `integer_length'
  954. i := offset + integer_length - 1
  955. val1 := item(i)
  956. new_head := val1 |>>> right
  957. if new_head = 0 then
  958. -- new_integer_length is good
  959. if capacity < new_integer_length then
  960. -- reallocation
  961. new_capacity := capacity_from_lower_bound(capacity, new_integer_length)
  962. new_storage := storage.calloc(new_capacity)
  963. from
  964. j := new_integer_length - 1
  965. check
  966. i = offset + integer_length - 1
  967. j = word_shift + integer_length - 1
  968. val1 = item(i)
  969. end
  970. until
  971. i = offset
  972. loop
  973. i := i - 1
  974. val2 := item(i)
  975. new_storage.put(val1 |<< left | (val2 |>>> right), j)
  976. val1 := val2
  977. j := j - 1
  978. end
  979. new_storage.put(val1 |<< left, j)
  980. storage := new_storage
  981. capacity := new_capacity
  982. offset := 0
  983. integer_length := new_integer_length
  984. elseif offset > word_shift then
  985. from
  986. check
  987. j = 0
  988. end
  989. until
  990. j = word_shift
  991. loop
  992. put(0, j)
  993. j := j + 1
  994. end
  995. from
  996. k := offset
  997. check
  998. i = offset + integer_length - 1
  999. j = word_shift
  1000. end
  1001. until
  1002. k = i
  1003. loop
  1004. val3 := item(k)
  1005. put(val3 |<< left | (val2 |>>> right), j)
  1006. val2 := val3
  1007. k := k + 1
  1008. j := j + 1
  1009. end
  1010. put(val1 |<< left | (val2 |>>> right), j)
  1011. offset := 0
  1012. integer_length := new_integer_length
  1013. else
  1014. from
  1015. j := new_integer_length - 1
  1016. check
  1017. i = offset + integer_length - 1
  1018. j = word_shift + integer_length - 1
  1019. val1 = item(i)
  1020. end
  1021. until
  1022. i = offset
  1023. loop
  1024. i := i - 1
  1025. val2 := item(i)
  1026. put(val1 |<< left | (val2 |>>> right), j)
  1027. val1 := val2
  1028. j := j - 1
  1029. end
  1030. put(val1 |<< left, j)
  1031. from
  1032. until
  1033. j = 0
  1034. loop
  1035. j := j - 1
  1036. put(0, j)
  1037. end
  1038. offset := 0
  1039. integer_length := new_integer_length
  1040. end
  1041. else
  1042. new_integer_length := new_integer_length + 1
  1043. if capacity < new_integer_length then
  1044. -- Reallocation
  1045. new_capacity := capacity_from_lower_bound(capacity, new_integer_length)
  1046. new_storage := storage.calloc(new_capacity)
  1047. from
  1048. j := new_integer_length - 2
  1049. check
  1050. i = offset + integer_length - 1
  1051. j = word_shift + integer_length - 1
  1052. val1 = item(i)
  1053. end
  1054. new_storage.put(new_head, j + 1)
  1055. until
  1056. i = offset
  1057. loop
  1058. i := i - 1
  1059. val2 := item(i)
  1060. new_storage.put(val1 |<< left | (val2 |>>> right), j)
  1061. val1 := val2
  1062. j := j - 1
  1063. end
  1064. new_storage.put(val1 |<< left, j)
  1065. storage := new_storage
  1066. capacity := new_capacity
  1067. offset := 0
  1068. integer_length := new_integer_length
  1069. elseif offset > word_shift then
  1070. from
  1071. check
  1072. j = 0
  1073. end
  1074. until
  1075. j = word_shift
  1076. loop
  1077. put(0, j)
  1078. j := j + 1
  1079. end
  1080. from
  1081. k := offset
  1082. check
  1083. i = offset + integer_length - 1
  1084. end
  1085. until
  1086. k = i
  1087. loop
  1088. val3 := item(k)
  1089. put(val3 |<< left | (val2 |>>> right), j)
  1090. val2 := val3
  1091. k := k + 1
  1092. j := j + 1
  1093. end
  1094. put(val1 |<< left | (val2 |>>> right), j)
  1095. put(new_head, j + 1)
  1096. offset := 0
  1097. integer_length := new_integer_length
  1098. else
  1099. from
  1100. j := new_integer_length - 2
  1101. check
  1102. i = offset + integer_length - 1
  1103. j = word_shift + integer_length - 1
  1104. val1 = item(i)
  1105. end
  1106. until
  1107. i = offset
  1108. loop
  1109. i := i - 1
  1110. val2 := item(i)
  1111. put(val1 |<< left | (val2 |>>> right), j)
  1112. val1 := val2
  1113. j := j - 1
  1114. end
  1115. put(val1 |<< left, j)
  1116. put(new_head, new_integer_length - 1)
  1117. from
  1118. until
  1119. j = 0
  1120. loop
  1121. j := j - 1
  1122. put(0, j)
  1123. end
  1124. offset := 0
  1125. integer_length := new_integer_length
  1126. end
  1127. end
  1128. end
  1129. end
  1130. end
  1131. shift_right (n: INTEGER)
  1132. -- Right shift `Current' n bits. (`Current' is left in normal form.)
  1133. require
  1134. n > 0
  1135. local
  1136. n_ints, n_bits: INTEGER
  1137. do
  1138. if integer_length > 0 then
  1139. n_ints := n |>>> 5
  1140. n_bits := n & 0x0000001F
  1141. integer_length := integer_length - n_ints
  1142. offset := offset + n_ints
  1143. if n_bits = 0 then
  1144. else
  1145. primitive_shift_right(n_bits.to_integer_8)
  1146. end
  1147. end
  1148. end
  1149. feature {ANY} -- GCD
  1150. gcd (other: like Current)
  1151. -- Compute GCD of `Current' and `other'.
  1152. -- GCD is put in `Current' (`other' is not modified).
  1153. require
  1154. other /= Void
  1155. do
  1156. if other = Current then
  1157. Current.abs
  1158. elseif other.is_zero then
  1159. Current.abs
  1160. elseif Current.is_zero then
  1161. Current.copy(other)
  1162. Current.abs
  1163. else
  1164. from
  1165. register2.copy(other)
  1166. Current.mod(register2)
  1167. if Current.is_zero then
  1168. Current.swap_with(register2)
  1169. Current.abs
  1170. else
  1171. register2.mod(Current)
  1172. end
  1173. until
  1174. register2.is_zero
  1175. loop
  1176. Current.mod(register2)
  1177. if Current.is_zero then
  1178. Current.swap_with(register2)
  1179. else
  1180. register2.mod(Current)
  1181. end
  1182. end
  1183. end
  1184. ensure
  1185. is_positive or is_zero and other.is_zero
  1186. end
  1187. feature {ANY} -- To multiply:
  1188. multiply (other: like Current)
  1189. -- Multiply `Current' by `other'.
  1190. require
  1191. other /= Void
  1192. do
  1193. if other = Current then
  1194. multiply_to(other, register1)
  1195. swap_with(register1)
  1196. elseif is_zero or other.is_zero then
  1197. set_with_zero
  1198. elseif Current.is_one then
  1199. copy(other)
  1200. elseif other.is_one then
  1201. elseif Current.is_one_negative then
  1202. copy(other)
  1203. set_negative(not negative)
  1204. elseif other.is_one_negative then
  1205. set_negative(not negative)
  1206. else
  1207. --|*** Must be replaced by an algorithm switch. (Vincent Croizier, 09/07/04)
  1208. multiply_like_human(other)
  1209. end
  1210. end
  1211. multiply_to (other, res: like Current)
  1212. -- Multiply the contents of `Current' and `other' and place the
  1213. -- result in `res'. (`Current' and `other' are not modified.)
  1214. require
  1215. other /= Void
  1216. res /= Void
  1217. res /= Current
  1218. do
  1219. if is_zero or other.is_zero then
  1220. res.set_with_zero
  1221. elseif Current.is_one then
  1222. res.copy(other)
  1223. elseif other.is_one then
  1224. res.copy(Current)
  1225. elseif Current.is_one_negative then
  1226. res.copy(other)
  1227. res.set_negative(not res.negative)
  1228. elseif other.is_one_negative then
  1229. res.copy(Current)
  1230. res.set_negative(not negative)
  1231. else
  1232. --|*** Must be replace by an algorithm switch. (Vincent Croizier, 01/05/04)
  1233. multiply_to_like_human(other, res)
  1234. end
  1235. end
  1236. multiply_integer (other: INTEGER; res: like Current)
  1237. -- Multiply the contents of `Current' and `other' and place the
  1238. -- result in `res'. (`Current' is not modified.)
  1239. require
  1240. res /= Current
  1241. res /= Void
  1242. local
  1243. overflow, res_integer_length, res_capacity, i, k, up_i, v: INTEGER; res_storage: like storage
  1244. do
  1245. if other = 0 or else is_zero then
  1246. res.set_with_zero
  1247. elseif other = Minimum_integer then
  1248. res.set_negative(not negative)
  1249. shift_left(31)
  1250. else
  1251. if other > 0 then
  1252. res.set_negative(negative)
  1253. v := other
  1254. else
  1255. res.set_negative(not negative)
  1256. v := -other
  1257. end
  1258. -- Pessimistic estimation
  1259. res_integer_length := integer_length + 1 -- Reallocation ?
  1260. if res.capacity < res_integer_length then
  1261. if capacity < res_integer_length then
  1262. res_capacity := capacity * 2
  1263. else
  1264. res_capacity := capacity_from_upper_bound(capacity, res_integer_length)
  1265. end
  1266. set_capacity(res_capacity)
  1267. res_storage := storage.calloc(res_capacity)
  1268. res.set_storage(res_storage)
  1269. else
  1270. res_storage := res.storage
  1271. end
  1272. res.set_offset(0)
  1273. -- Multiply
  1274. from
  1275. k := 0
  1276. i := offset
  1277. up_i := offset + integer_length - 1
  1278. overflow := mbi_multiply(item(i), v, storage_at(res_storage, k))
  1279. until
  1280. i = up_i
  1281. loop
  1282. i := i + 1
  1283. k := k + 1
  1284. overflow := mbi_multiply_with_add(item(i), v, overflow, storage_at(res_storage, k))
  1285. end
  1286. if overflow = 0 then
  1287. res.set_integer_length(res_integer_length - 1)
  1288. else
  1289. check
  1290. k + 1 = integer_length
  1291. end
  1292. res.put(overflow, integer_length)
  1293. end
  1294. end
  1295. end
  1296. feature {MUTABLE_BIG_INTEGER} -- to multiply
  1297. multiply_like_human (other: like Current)
  1298. -- Simple multiply.
  1299. -- Complexity = O(`integer_length'*`other.integer_length').
  1300. require
  1301. not is_zero
  1302. not other.is_zero
  1303. local
  1304. old_offset, new_integer_length: INTEGER
  1305. do
  1306. -- Pessimistique estimation
  1307. new_integer_length := integer_length + other.integer_length -- Reallocation ?
  1308. if capacity < new_integer_length then
  1309. register1.swap_with(Current)
  1310. register1.multiply_to_like_human(other, Current)
  1311. -- Multiply in place
  1312. elseif offset + new_integer_length <= capacity then
  1313. multiply_like_human_aux_reverse(other)
  1314. elseif offset >= other.integer_length then
  1315. multiply_like_human_aux(other)
  1316. else
  1317. old_offset := offset
  1318. offset := capacity - integer_length
  1319. storage.slice_copy(offset, storage, old_offset, old_offset + integer_length - 1)
  1320. multiply_like_human_aux(other)
  1321. end
  1322. end
  1323. multiply_like_human_aux (other: like Current)
  1324. -- Only used by `multiply_to_like_human'.
  1325. require
  1326. not is_zero
  1327. not other.is_zero
  1328. offset >= other.integer_length
  1329. local
  1330. other_offset, other_integer_length, overflow, i, j, k, up_i, up_j, down_k, v: INTEGER
  1331. other_storage: like storage
  1332. do
  1333. other_offset := other.offset
  1334. other_integer_length := other.integer_length
  1335. other_storage := other.storage -- First pass
  1336. from
  1337. k := 0
  1338. i := other_offset
  1339. up_i := other_offset + other_integer_length - 1
  1340. j := offset
  1341. up_j := offset + integer_length - 1
  1342. v := storage.item(j)
  1343. overflow := mbi_multiply(other_storage.item(i), v, storage_at(storage, k))
  1344. until
  1345. i = up_i
  1346. loop
  1347. i := i + 1
  1348. k := k + 1
  1349. overflow := mbi_multiply_with_add(other_storage.item(i), v, overflow, storage_at(storage, k))
  1350. end
  1351. k := k + 1
  1352. check
  1353. k <= j
  1354. end
  1355. storage.put(overflow, k)
  1356. from
  1357. down_k := 1
  1358. until
  1359. j = up_j
  1360. loop
  1361. j := j + 1
  1362. from
  1363. k := down_k
  1364. i := other_offset
  1365. v := storage.item(j)
  1366. overflow := mbi_multiply_with_add(other_storage.item(i), v, storage.item(k), storage_at(storage, k))
  1367. until
  1368. i = up_i
  1369. loop
  1370. i := i + 1
  1371. k := k + 1
  1372. overflow := mbi_multiply_with_2_add(other_storage.item(i), v, overflow, storage.item(k), storage_at(storage, k))
  1373. end
  1374. k := k + 1
  1375. check
  1376. k <= j
  1377. end
  1378. storage.put(overflow, k)
  1379. down_k := down_k + 1
  1380. end
  1381. -- Adjust `res.integer_length'
  1382. if overflow = 0 then
  1383. integer_length := integer_length + other_integer_length - 1
  1384. else
  1385. integer_length := integer_length + other_integer_length
  1386. end
  1387. negative := negative /= other.negative
  1388. offset := 0
  1389. end
  1390. multiply_like_human_aux_reverse (other: like Current)
  1391. -- Only used by `multiply_to_like_human'.
  1392. require
  1393. not is_zero
  1394. not other.is_zero
  1395. offset + integer_length <= capacity - other.integer_length
  1396. local
  1397. other_offset, other_integer_length, overflow, i, j, k, up_i, down_j, down_k, v: INTEGER
  1398. other_storage: like storage; inc: BOOLEAN
  1399. do
  1400. other_offset := other.offset
  1401. other_integer_length := other.integer_length
  1402. other_storage := other.storage -- First pass
  1403. from…