PageRenderTime 94ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/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
Possible License(s): GPL-3.0, LGPL-2.1, GPL-2.0
  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
  1404. i := other_offset
  1405. up_i := other_offset + other_integer_length - 1
  1406. down_j := offset
  1407. j := offset + integer_length - 1
  1408. k := j
  1409. v := storage.item(j)
  1410. overflow := mbi_multiply(other_storage.item(i), v, storage_at(storage, k))
  1411. until
  1412. i = up_i
  1413. loop
  1414. i := i + 1
  1415. k := k + 1
  1416. overflow := mbi_multiply_with_add(other_storage.item(i), v, overflow, storage_at(storage, k))
  1417. end
  1418. k := k + 1
  1419. check
  1420. k <= j + other_integer_length
  1421. end
  1422. storage.put(overflow, k)
  1423. from
  1424. down_k := j - 1
  1425. until
  1426. j = down_j
  1427. loop
  1428. j := j - 1
  1429. from
  1430. k := down_k
  1431. i := other_offset
  1432. v := storage.item(j)
  1433. overflow := mbi_multiply(other_storage.item(i), v, storage_at(storage, k))
  1434. until
  1435. i = up_i
  1436. loop
  1437. i := i + 1
  1438. k := k + 1
  1439. overflow := mbi_multiply_with_2_add(other_storage.item(i), v, overflow, storage.item(k), storage_at(storage, k))
  1440. end
  1441. k := k + 1
  1442. inc := mbi_add(storage.item(k), overflow, storage_at(storage, k))
  1443. check
  1444. k < offset + integer_length + other_integer_length
  1445. end
  1446. from
  1447. until
  1448. not inc
  1449. loop
  1450. k := k + 1
  1451. check
  1452. k < offset + integer_length + other_integer_length
  1453. end
  1454. inc := mbi_inc(storage_at(storage, k))
  1455. end
  1456. down_k := down_k - 1
  1457. end
  1458. -- Adjust `res.integer_length'
  1459. if storage.item(offset + integer_length + other_integer_length - 1) = 0 then
  1460. integer_length := integer_length + other_integer_length - 1
  1461. else
  1462. integer_length := integer_length + other_integer_length
  1463. end
  1464. negative := negative /= other.negative
  1465. end
  1466. multiply_to_like_human (other, res: like Current)
  1467. -- Simple multiply.
  1468. -- Complexity = O(`integer_length'*`other.integer_length').
  1469. require
  1470. res /= Current
  1471. not is_zero
  1472. not other.is_zero
  1473. local
  1474. overflow, res_integer_length, res_capacity, i, j, k, up_i, up_j, down_k, v: INTEGER
  1475. res_storage: like storage; res_negative: BOOLEAN
  1476. do
  1477. res_negative := negative /= other.negative -- Pessimistique estimation
  1478. res_integer_length := integer_length + other.integer_length -- Reallocation ?
  1479. res_capacity := res.capacity
  1480. if res_capacity < res_integer_length then
  1481. res_capacity := capacity_from_lower_bound(res_capacity, res_integer_length)
  1482. res_storage := storage.calloc(res_capacity)
  1483. else
  1484. res_storage := res.storage
  1485. end
  1486. -- To avoid class invariant violation
  1487. res.set_with_zero
  1488. -- Multiply
  1489. -- First pass
  1490. from
  1491. k := 0
  1492. i := offset
  1493. up_i := offset + integer_length - 1
  1494. j := other.offset
  1495. up_j := j + other.integer_length - 1
  1496. v := other.item(j)
  1497. overflow := mbi_multiply(item(i), v, storage_at(res_storage, k))
  1498. until
  1499. i = up_i
  1500. loop
  1501. i := i + 1
  1502. k := k + 1
  1503. overflow := mbi_multiply_with_add(item(i), v, overflow, storage_at(res_storage, k))
  1504. end
  1505. k := k + 1
  1506. res_storage.put(overflow, k)
  1507. from
  1508. down_k := 1
  1509. until
  1510. j = up_j
  1511. loop
  1512. j := j + 1
  1513. from
  1514. k := down_k
  1515. i := offset
  1516. v := other.item(j)
  1517. overflow := mbi_multiply_with_add(item(i), v, res_storage.item(k), storage_at(res_storage, k))
  1518. until
  1519. i = up_i
  1520. loop
  1521. i := i + 1
  1522. k := k + 1
  1523. overflow := mbi_multiply_with_2_add(item(i), v, overflow, res_storage.item(k), storage_at(res_storage, k))
  1524. end
  1525. k := k + 1
  1526. res_storage.put(overflow, k)
  1527. down_k := down_k + 1
  1528. end
  1529. -- Adjust `res.integer_length'
  1530. if overflow = 0 then
  1531. res.set_all(res_storage, res_capacity, res_integer_length - 1, 0, res_negative)
  1532. else
  1533. res.set_all(res_storage, res_capacity, res_integer_length, 0, res_negative)
  1534. end
  1535. end
  1536. feature {ANY} -- Comparison:
  1537. is_zero: BOOLEAN
  1538. -- Is it 0?
  1539. do
  1540. Result := integer_length = 0
  1541. ensure
  1542. Result implies not is_negative
  1543. end
  1544. is_one: BOOLEAN
  1545. -- Is it 1?
  1546. do
  1547. if integer_length = 1 then
  1548. if not negative then
  1549. Result := item(offset) = 1
  1550. end
  1551. end
  1552. ensure
  1553. Result implies not is_negative
  1554. end
  1555. is_one_negative: BOOLEAN
  1556. -- Is it -1 ?
  1557. do
  1558. if integer_length = 1 then
  1559. if negative then
  1560. Result := item(offset) = 1
  1561. end
  1562. end
  1563. ensure
  1564. Result implies is_negative
  1565. end
  1566. is_negative: BOOLEAN
  1567. -- Is `Current' negative integer?
  1568. do
  1569. Result := negative
  1570. ensure
  1571. Result implies not is_positive
  1572. end
  1573. is_positive: BOOLEAN
  1574. -- Is `Current' positive integer?
  1575. do
  1576. Result := not negative and then integer_length /= 0
  1577. ensure
  1578. Result implies not is_negative
  1579. end
  1580. is_even: BOOLEAN
  1581. -- Is `Current' even?
  1582. do
  1583. if integer_length = 0 then
  1584. Result := True
  1585. else
  1586. Result := item(offset).is_even
  1587. end
  1588. ensure
  1589. Result = not Current.is_odd
  1590. end
  1591. is_odd: BOOLEAN
  1592. -- Is `Current' odd?
  1593. do
  1594. if integer_length > 0 then
  1595. Result := item(offset).is_odd
  1596. end
  1597. ensure
  1598. Result = not Current.is_even
  1599. end
  1600. is_equal (other: like Current): BOOLEAN
  1601. local
  1602. a, b, c: INTEGER
  1603. do
  1604. if Current = other then
  1605. Result := True
  1606. elseif integer_length /= other.integer_length then
  1607. elseif negative /= other.negative then
  1608. else
  1609. check
  1610. other.integer_length = integer_length
  1611. end
  1612. from
  1613. c := offset + integer_length
  1614. a := offset
  1615. b := other.offset
  1616. Result := True
  1617. until
  1618. a = c
  1619. loop
  1620. if item(a) /= other.item(b) then
  1621. Result := False
  1622. a := c
  1623. else
  1624. a := a + 1
  1625. b := b + 1
  1626. end
  1627. end
  1628. end
  1629. end
  1630. infix "<" (other: like Current): BOOLEAN
  1631. local
  1632. a, b: INTEGER; va, vb: INTEGER
  1633. do
  1634. if Current = other then
  1635. elseif negative /= other.negative then
  1636. Result := negative
  1637. elseif integer_length /= other.integer_length then
  1638. Result := integer_length < other.integer_length xor negative
  1639. else
  1640. check
  1641. other.negative = negative
  1642. end
  1643. check
  1644. other.integer_length = integer_length
  1645. end
  1646. from
  1647. a := offset + integer_length - 1
  1648. b := other.offset + integer_length - 1
  1649. until
  1650. a < offset
  1651. loop
  1652. va := item(a)
  1653. vb := other.item(b)
  1654. if unsigned_less_than(va, vb) then
  1655. Result := not negative
  1656. a := -1
  1657. elseif unsigned_less_than(vb, va) then
  1658. Result := negative
  1659. a := -1
  1660. else
  1661. a := a - 1
  1662. b := b - 1
  1663. end
  1664. end
  1665. end
  1666. end
  1667. abs_compare (other: like Current): INTEGER
  1668. -- Compare the magnitude of `Current' and `other'. Returns -1, 0 or 1
  1669. -- as this MutableBigInteger is numerically less than, equal to, or
  1670. -- greater than other.
  1671. local
  1672. a, b: INTEGER; va, vb: INTEGER
  1673. do
  1674. if Current = other then
  1675. --Result := 0
  1676. elseif integer_length < other.integer_length then
  1677. Result := -1
  1678. elseif integer_length > other.integer_length then
  1679. Result := 1
  1680. else
  1681. check
  1682. other.integer_length = integer_length
  1683. end
  1684. from
  1685. a := offset + integer_length
  1686. b := other.offset + integer_length
  1687. check
  1688. Result = 0
  1689. end
  1690. until
  1691. a <= offset
  1692. loop
  1693. a := a - 1
  1694. b := b - 1
  1695. va := item(a)
  1696. vb := other.item(b)
  1697. if unsigned_less_than(va, vb) then
  1698. Result := -1
  1699. a := -1
  1700. elseif unsigned_less_than(vb, va) then
  1701. Result := 1
  1702. a := -1
  1703. end
  1704. end
  1705. end
  1706. end
  1707. feature {ANY} -- Printing:
  1708. to_string: STRING
  1709. -- The decimal view of `Current' into a new allocated STRING.
  1710. -- For example, if `Current' is -1 the `Result' is "-1".
  1711. --
  1712. -- See also `append_in', `to_string_format', `to_unicode_string', `to_integer'.
  1713. do
  1714. string_buffer.clear_count
  1715. append_in(string_buffer)
  1716. Result := string_buffer.twin
  1717. end
  1718. to_unicode_string: UNICODE_STRING
  1719. -- The decimal view of `Current' into a new allocated UNICODE_STRING.
  1720. -- For example, if `Current' represents -1 the `Result' is U"-1".
  1721. --
  1722. -- See also `append_in_unicode', `to_unicode_string_format', `to_string'.
  1723. do
  1724. unicode_string_buffer.clear_count
  1725. append_in_unicode(unicode_string_buffer)
  1726. Result := unicode_string_buffer.twin
  1727. end
  1728. append_in (buffer: STRING)
  1729. -- Append in the `buffer' the equivalent of `to_string'. No new
  1730. -- STRING creation during the process.
  1731. require
  1732. is_printable
  1733. local
  1734. k: INTEGER
  1735. do
  1736. if is_zero then
  1737. buffer.extend('0')
  1738. else
  1739. -- Put the sign in `buffer'
  1740. if negative then
  1741. buffer.extend('-')
  1742. end
  1743. -- Put it in `buffer'
  1744. from
  1745. k := append_in_char_buffer
  1746. until
  1747. k = 0
  1748. loop
  1749. k := k - 1
  1750. buffer.extend(char_buffer.item(k))
  1751. end
  1752. end
  1753. end
  1754. append_in_unicode (buffer: UNICODE_STRING)
  1755. -- Append in the `buffer' the equivalent of `to_string'. No new
  1756. -- STRING creation during the process.
  1757. require
  1758. is_printable
  1759. local
  1760. k: INTEGER
  1761. do
  1762. if is_zero then
  1763. buffer.extend('0'.code)
  1764. else
  1765. -- Put the sign in `buffer'
  1766. if negative then
  1767. buffer.extend('-'.code)
  1768. end
  1769. -- Put it in `buffer'
  1770. from
  1771. k := append_in_char_buffer
  1772. until
  1773. k = 0
  1774. loop
  1775. k := k - 1
  1776. buffer.extend(char_buffer.item(k).code)
  1777. end
  1778. end
  1779. end
  1780. to_string_format (s: INTEGER): STRING
  1781. -- Same as `to_string' but the result is on `s' character and the
  1782. -- number is right aligned.
  1783. -- Note: see `append_in_format' to save memory.
  1784. require
  1785. to_string.count <= s
  1786. do
  1787. create Result.make(s)
  1788. append_in_format(Result, s)
  1789. ensure
  1790. Result.count = s
  1791. end
  1792. to_unicode_string_format (s: INTEGER): UNICODE_STRING
  1793. -- Same as `to_unicode_string' but the result is on `s' character and
  1794. -- the number is right aligned.
  1795. -- Note: see `append_in_unicode_format' to save memory.
  1796. require
  1797. to_string.count <= s
  1798. do
  1799. create Result.make(s)
  1800. append_in_unicode_format(Result, s)
  1801. ensure
  1802. Result.count = s
  1803. end
  1804. append_in_format (str: STRING; s: INTEGER)
  1805. -- Append the equivalent of `to_string_format' at the end of `str'. Thus you can save
  1806. -- memory because no other STRING is allocated for the job.
  1807. require
  1808. to_string.count <= s
  1809. local
  1810. i, k: INTEGER
  1811. do
  1812. if is_zero then
  1813. -- Put spaces
  1814. from
  1815. i := s - 1
  1816. variant
  1817. i
  1818. until
  1819. i = 0
  1820. loop
  1821. str.extend(' ')
  1822. i := i - 1
  1823. end
  1824. -- Put number
  1825. str.extend('0')
  1826. else
  1827. k := append_in_char_buffer
  1828. -- Put spaces
  1829. from
  1830. if negative then
  1831. i := s - k - 1
  1832. else
  1833. i := s - k
  1834. end
  1835. variant
  1836. i
  1837. until
  1838. i = 0
  1839. loop
  1840. str.extend(' ')
  1841. i := i - 1
  1842. end
  1843. -- Put number
  1844. from
  1845. -- Put the sign in `buffer'
  1846. if negative then
  1847. str.extend('-')
  1848. end
  1849. variant
  1850. k
  1851. until
  1852. k = 0
  1853. loop
  1854. k := k - 1
  1855. str.extend(char_buffer.item(k))
  1856. end
  1857. end
  1858. ensure
  1859. str.count >= old str.count + s
  1860. end
  1861. append_in_unicode_format (str: UNICODE_STRING; s: INTEGER)
  1862. -- Append the equivalent of `to_unicode_string_format' at the end of
  1863. -- `str'. Thus you can save memory because no other
  1864. -- UNICODE_STRING is allocated for the job.
  1865. require
  1866. to_string.count <= s
  1867. local
  1868. i, k: INTEGER
  1869. do
  1870. if is_zero then
  1871. -- Put spaces
  1872. from
  1873. i := s - 1
  1874. variant
  1875. i
  1876. until
  1877. i = 0
  1878. loop
  1879. str.extend(' '.code)
  1880. i := i - 1
  1881. end
  1882. -- Put number
  1883. str.extend('0'.code)
  1884. else
  1885. k := append_in_char_buffer
  1886. -- Put spaces
  1887. from
  1888. if negative then
  1889. i := s - k - 1
  1890. else
  1891. i := s - k
  1892. end
  1893. variant
  1894. i
  1895. until
  1896. i = 0
  1897. loop
  1898. str.extend(' '.code)
  1899. i := i - 1
  1900. end
  1901. -- Put number
  1902. from
  1903. -- Put the sign in `buffer'
  1904. if negative then
  1905. str.extend('-'.code)
  1906. end
  1907. variant
  1908. k
  1909. until
  1910. k = 0
  1911. loop
  1912. k := k - 1
  1913. str.extend(char_buffer.item(k).code)
  1914. end
  1915. end
  1916. ensure
  1917. str.count >= old str.count + s
  1918. end
  1919. is_printable: BOOLEAN
  1920. -- True if decimal view of `Current' is short enough
  1921. -- to be put in a STRING.
  1922. do
  1923. --|*** MUST BE REWRITE (Vincent Croizier, 14/07/04) ***
  1924. Result := integer_length <= 2 ^ 27
  1925. end
  1926. out_in_tagged_out_memory, fill_tagged_out_memory
  1927. do
  1928. append_in(tagged_out_memory)
  1929. end
  1930. feature {ANY} -- Miscellaneous:
  1931. negate
  1932. -- Negate the sign of `Current'.
  1933. do
  1934. if integer_length /= 0 then
  1935. negative := not negative
  1936. end
  1937. end
  1938. abs
  1939. -- Absolute value of `Current'.
  1940. do
  1941. negative := False
  1942. end
  1943. sign: INTEGER_8
  1944. -- Sign of `Current' (0 -1 or 1).
  1945. do
  1946. if negative then
  1947. Result := -1
  1948. elseif integer_length > 0 then
  1949. Result := 1
  1950. else
  1951. check
  1952. is_zero
  1953. end
  1954. end
  1955. end
  1956. set_with_zero
  1957. do
  1958. integer_length := 0
  1959. negative := False
  1960. ensure
  1961. is_zero
  1962. end
  1963. hash_code: INTEGER
  1964. local
  1965. i, c, v: INTEGER
  1966. do
  1967. from
  1968. i := offset
  1969. c := 2
  1970. until
  1971. c = 0 or else i = offset + integer_length
  1972. loop
  1973. v := item(i)
  1974. if v /= 0 then
  1975. Result := Result #+ v
  1976. c := c - 1
  1977. end
  1978. i := i + 1
  1979. end
  1980. Result := integer_length #* Result
  1981. if negative then
  1982. Result := Result #+ 1
  1983. end
  1984. if Result < 0 then
  1985. Result := ~Result
  1986. end
  1987. end
  1988. copy (other: like Current)
  1989. do
  1990. negative := other.negative
  1991. offset := 0
  1992. integer_length := other.integer_length
  1993. if capacity < other.integer_length then
  1994. capacity := capacity_from_upper_bound(other.capacity, integer_length)
  1995. storage := storage.calloc(capacity)
  1996. elseif capacity = 0 then
  1997. capacity := 4
  1998. storage := storage.calloc(capacity)
  1999. end
  2000. if integer_length /= 0 then
  2001. storage.slice_copy(offset, other.storage, other.offset, other.offset + integer_length - 1)
  2002. end
  2003. end
  2004. swap_with (other: like Current)
  2005. -- Swap the value of `Current' with the value of `other'.
  2006. local
  2007. s: like storage; c: like capacity; il: like integer_length; o: like offset; n: like negative
  2008. do
  2009. s := other.storage
  2010. c := other.capacity
  2011. il := other.integer_length
  2012. o := other.offset
  2013. n := other.negative -- Put Current in other
  2014. other.set_all(storage, capacity, integer_length, offset, negative)
  2015. --
  2016. storage := s
  2017. capacity := c
  2018. integer_length := il
  2019. offset := o
  2020. negative := n
  2021. end
  2022. feature {MUTABLE_BIG_INTEGER}
  2023. storage: NATIVE_ARRAY[INTEGER_32]
  2024. -- Holds the magnitude of `Current' in natural order (the most significant INTEGER_32 word
  2025. -- has the highest address). To avoid many reallocation of this `storage' area, only some
  2026. -- words are significant. The magnitude is stored in the following significant
  2027. -- range [`offset' .. `offset + integer_length - 1'].
  2028. capacity: INTEGER
  2029. -- Of the allocated `storage' area.
  2030. integer_length: INTEGER
  2031. -- The number of significant INTEGER_32 words in the `storage' area.
  2032. offset: INTEGER
  2033. -- The `offset' of the less significant word into the `storage' area.
  2034. negative: BOOLEAN
  2035. -- True when `Current' is negative.
  2036. item (index: INTEGER): INTEGER_32
  2037. require
  2038. -- index.in_range(0, capacity - 1)
  2039. index.in_range(offset, offset + integer_length - 1)
  2040. do
  2041. Result := storage.item(index)
  2042. end
  2043. put (value: INTEGER; index: INTEGER)
  2044. require
  2045. index.in_range(0, capacity - 1)
  2046. do
  2047. storage.put(value, index)
  2048. end
  2049. set_negative (n: like negative)
  2050. require
  2051. n implies not is_zero
  2052. do
  2053. negative := n
  2054. ensure
  2055. negative = n or is_zero
  2056. end
  2057. set_integer_length (il: like integer_length)
  2058. require
  2059. il.in_range(0, capacity - offset)
  2060. do
  2061. integer_length := il
  2062. ensure
  2063. integer_length = il
  2064. end
  2065. set_offset (o: like offset)
  2066. require
  2067. o.in_range(0, capacity - integer_length)
  2068. do
  2069. offset := o
  2070. ensure
  2071. offset = o
  2072. end
  2073. set_ilo (il: like integer_length; o: like offset)
  2074. require
  2075. il.in_range(0, capacity)
  2076. o.in_range(0, capacity - il)
  2077. do
  2078. integer_length := il
  2079. offset := o
  2080. ensure
  2081. integer_length = il
  2082. offset = o
  2083. end
  2084. set_storage (new_storage: like storage)
  2085. do
  2086. storage := new_storage
  2087. end
  2088. set_capacity (new_capacity: like capacity)
  2089. do
  2090. capacity := new_capacity
  2091. end
  2092. set_all (new_storage: like storage; new_capacity, new_integer_length, new_offset: INTEGER; new_negative: BOOLEAN)
  2093. require
  2094. new_capacity > 0
  2095. new_storage.is_not_null
  2096. new_integer_length.in_range(0, new_capacity)
  2097. new_integer_length /= 0 implies new_offset.in_range(0, new_capacity - new_integer_length) and new_storage.item(new_offset + new_integer_length - 1) /= 0
  2098. new_integer_length = 0 implies not new_negative
  2099. new_capacity.is_a_power_of_2
  2100. do
  2101. storage := new_storage
  2102. capacity := new_capacity
  2103. integer_length := new_integer_length
  2104. offset := new_offset
  2105. negative := new_negative
  2106. ensure
  2107. storage = new_storage
  2108. capacity = new_capacity
  2109. integer_length = new_integer_length
  2110. offset = new_offset
  2111. negative = new_negative
  2112. end
  2113. primitive_shift_left (n: INTEGER_8)
  2114. -- Left shift `Current' with no need to extend the `storage'.
  2115. --|*** Can be a little faster (Vincent Croizier, 26/04/04) ***
  2116. require
  2117. integer_length > 0
  2118. n.in_range(1, 31)
  2119. no_bit_lost: item(offset + integer_length - 1) |<< n |>>> n = item(offset + integer_length - 1)
  2120. local
  2121. n2: INTEGER_8; i, up, b, c: INTEGER
  2122. do
  2123. n2 := 32 - n
  2124. from
  2125. i := offset
  2126. up := i + integer_length - 1
  2127. until
  2128. i > up
  2129. loop
  2130. b := item(i)
  2131. put(b |<< n | c, i)
  2132. c := b |>>> n2
  2133. i := i + 1
  2134. end
  2135. check
  2136. c = 0
  2137. end
  2138. end
  2139. primitive_shift_right (n: INTEGER_8)
  2140. -- Right shift `Current' of `n' bits.
  2141. require
  2142. integer_length > 0
  2143. n.in_range(1, 31)
  2144. local
  2145. n2: INTEGER_8; i, j, up, b, c: INTEGER
  2146. do
  2147. n2 := 32 - n
  2148. from
  2149. up := integer_length - 1
  2150. j := 0
  2151. i := offset
  2152. c := item(i)
  2153. until
  2154. j >= up
  2155. loop
  2156. b := c
  2157. i := i + 1
  2158. c := item(i)
  2159. put(b |>>> n | (c |<< n2), j)
  2160. j := j + 1
  2161. end
  2162. check
  2163. j = up
  2164. i = offset + j
  2165. end
  2166. put(c |>>> n, up)
  2167. offset := 0
  2168. if item(integer_length - 1) = 0 then
  2169. integer_length := integer_length - 1
  2170. end
  2171. ensure
  2172. offset = 0
  2173. end
  2174. divide_one_word (divisor: INTEGER): INTEGER
  2175. -- This method is used by `divide'. The one word divisor
  2176. -- specified by `divisor' is saw as unsigned.
  2177. -- `Current' is the dividend (saw positive) at invocation but is replaced by
  2178. -- the quotient. The remainder is returned as unsigned INTEGER.
  2179. -- Note: `Current' is modified by this method.
  2180. require
  2181. divisor /= 0
  2182. local
  2183. i, remainder_word1, remainder_word0: INTEGER
  2184. do
  2185. if integer_length = 1 then
  2186. Result := item(offset)
  2187. if unsigned_less_than(Result, divisor) then
  2188. integer_length := 0
  2189. negative := False
  2190. else
  2191. put(mbi_divide(0, Result, divisor, $remainder_word1), offset)
  2192. Result := remainder_word1
  2193. end
  2194. else
  2195. from
  2196. i := offset + integer_length - 1
  2197. until
  2198. i < offset
  2199. loop
  2200. remainder_word0 := item(i)
  2201. put(mbi_divide(remainder_word1, remainder_word0, divisor, $remainder_word1), i)
  2202. i := i - 1
  2203. end
  2204. if item(offset + integer_length - 1) = 0 then
  2205. integer_length := integer_length - 1
  2206. check
  2207. item(offset + integer_length - 1) /= 0
  2208. end
  2209. end
  2210. Result := remainder_word1
  2211. end
  2212. end
  2213. divide_sign_correction (other, quotient, remainder: like Current)
  2214. -- Correct the value of `quotient' and `remainder' after an
  2215. -- "unsigned" division.
  2216. -- Only used by `divide'.
  2217. require
  2218. not remainder.is_negative
  2219. do
  2220. if remainder.is_zero then
  2221. quotient.set_negative(negative /= other.negative)
  2222. elseif negative then
  2223. quotient.set_negative(False)
  2224. if other.negative then
  2225. quotient.add_integer(1)
  2226. remainder.set_negative(True)
  2227. -- other is negative
  2228. remainder.subtract(other)
  2229. check
  2230. not remainder.is_negative
  2231. end
  2232. else
  2233. quotient.add_integer(1)
  2234. quotient.set_negative(True)
  2235. remainder.set_negative(True)
  2236. remainder.add(other)
  2237. check
  2238. not remainder.is_negative
  2239. end
  2240. end
  2241. elseif other.negative then
  2242. quotient.set_negative(True)
  2243. else
  2244. quotient.set_negative(False)
  2245. end
  2246. ensure
  2247. not remainder.is_negative
  2248. end
  2249. divide_sign_correction_bis (other, quotient: like Current; current_negative: BOOLEAN)
  2250. -- Correct the value of `quotient' and `remainder' after an
  2251. -- "unsigned" division.
  2252. -- Only used by `divide'.
  2253. require
  2254. not is_negative
  2255. do
  2256. if is_zero then
  2257. quotient.set_negative(current_negative /= other.negative)
  2258. elseif current_negative then
  2259. quotient.set_negative(False)
  2260. if other.negative then
  2261. quotient.add_integer(1)
  2262. set_negative(True)
  2263. -- other is negative
  2264. subtract(other)
  2265. check
  2266. not is_negative
  2267. end
  2268. else
  2269. quotient.add_integer(1)
  2270. quotient.set_negative(True)
  2271. set_negative(True)
  2272. add(other)
  2273. check
  2274. not is_negative
  2275. end
  2276. end
  2277. elseif other.negative then
  2278. quotient.set_negative(True)
  2279. else
  2280. quotient.set_negative(False)
  2281. end
  2282. ensure
  2283. not is_negative
  2284. end
  2285. multiply_and_subtract (u1, qhat: INTEGER; d_storage: like storage; d_offset: INTEGER; r_storage: like storage
  2286. r_offset, length: INTEGER): BOOLEAN
  2287. -- Only used by `divide'.
  2288. require
  2289. qhat /= 0
  2290. local
  2291. i, j, jmax, m1, m2: INTEGER; dec: BOOLEAN
  2292. do
  2293. if qhat = 1 then
  2294. from
  2295. i := d_offset
  2296. j := r_offset
  2297. jmax := r_offset + length
  2298. until
  2299. j = jmax
  2300. loop
  2301. if dec then
  2302. dec := mbi_subtract_with_dec(r_storage.item(j), d_storage.item(i), storage_at(r_storage, j))
  2303. else
  2304. dec := mbi_subtract(r_storage.item(j), d_storage.item(i), storage_at(r_storage, j))
  2305. end
  2306. i := i + 1
  2307. j := j + 1
  2308. end
  2309. if dec then
  2310. if u1 = 0 then
  2311. Result := True
  2312. else
  2313. Result := mbi_dec(storage_at(r_storage, j))
  2314. check
  2315. not Result
  2316. end
  2317. end
  2318. end
  2319. else
  2320. from
  2321. i := d_offset
  2322. j := r_offset
  2323. jmax := r_offset + length
  2324. until
  2325. j = jmax
  2326. loop
  2327. m1 := mbi_multiply_with_add(qhat, d_storage.item(i), m1, $m2)
  2328. if dec then
  2329. dec := mbi_subtract_with_dec(r_storage.item(j), m2, storage_at(r_storage, j))
  2330. else
  2331. dec := mbi_subtract(r_storage.item(j), m2, storage_at(r_storage, j))
  2332. end
  2333. i := i + 1
  2334. j := j + 1
  2335. end
  2336. if dec then
  2337. if u1 = 0 then
  2338. Result := True
  2339. else
  2340. Result := mbi_subtract_with_dec(r_storage.item(j), m1, storage_at(r_storage, j))
  2341. end
  2342. elseif m1 = 0 then
  2343. -- nothing to do
  2344. elseif u1 = 0 then
  2345. Result := True
  2346. else
  2347. Result := mbi_subtract(r_storage.item(j), m1, storage_at(r_storage, j))
  2348. end
  2349. end
  2350. end
  2351. add_back (old_u1: INTEGER; d_storage: like storage; d_offset: INTEGER; r_storage: like storage
  2352. r_offset, length: INTEGER): BOOLEAN
  2353. -- Only used by `divide'.
  2354. -- `old_u1' is the value of `u1' before `multiply_and_subtract'.
  2355. local
  2356. i, j, jmax: INTEGER; inc: BOOLEAN
  2357. do
  2358. from
  2359. i := d_offset
  2360. j := r_offset
  2361. jmax := r_offset + length
  2362. until
  2363. j = jmax
  2364. loop
  2365. if inc then
  2366. inc := mbi_add_with_inc(r_storage.item(j), d_storage.item(i), storage_at(r_storage, j))
  2367. else
  2368. inc := mbi_add(r_storage.item(j), d_storage.item(i), storage_at(r_storage, j))
  2369. end
  2370. i := i + 1
  2371. j := j + 1
  2372. end
  2373. if inc then
  2374. if old_u1 = 0 then
  2375. Result := True
  2376. else
  2377. Result := mbi_inc(storage_at(r_storage, j))
  2378. end
  2379. end
  2380. end
  2381. is_a_good_divide (other, quotient, remainder: like Current): BOOLEAN
  2382. require
  2383. other /= Void
  2384. quotient /= Void
  2385. remainder /= Void
  2386. local
  2387. v: like Current
  2388. do
  2389. v := other.twin
  2390. v.multiply(quotient)
  2391. v.add(remainder)
  2392. Result := Current.is_equal(v)
  2393. end
  2394. normalize: INTEGER_8
  2395. -- Shift left until the most significant bit is on.
  2396. -- Result give the number of left shift.
  2397. require
  2398. not is_zero
  2399. local
  2400. head: INTEGER
  2401. do
  2402. head := item(offset + integer_length - 1)
  2403. from
  2404. until
  2405. head < 0
  2406. loop
  2407. head := head.bit_shift_left(1)
  2408. Result := Result + 1
  2409. end
  2410. if Result > 0 then
  2411. shift_left(Result)
  2412. end
  2413. ensure
  2414. item(offset + integer_length - 1) < 0
  2415. end
  2416. feature {MUTABLE_BIG_INTEGER} -- Implementation:
  2417. register1: MUTABLE_BIG_INTEGER
  2418. once
  2419. create Result.from_integer(0)
  2420. end
  2421. register2: MUTABLE_BIG_INTEGER
  2422. once
  2423. create Result.from_integer(0)
  2424. end
  2425. Real_base: REAL_64
  2426. once
  2427. Result := (0x0000000100000000).force_to_real_64
  2428. end
  2429. add_magnitude (other: like Current)
  2430. -- Add the magnitude of `Current' and `other' regardless of signs.
  2431. require
  2432. not is_zero
  2433. not other.is_zero
  2434. local
  2435. a, b: like Current; inc: BOOLEAN; i, j, k, n: INTEGER; new_storage, a_storage, b_storage: like storage
  2436. new_capacity, a_capacity, a_offset, a_integer_length, b_offset, b_integer_length: INTEGER
  2437. do
  2438. --|*** First tests can be certainely optimized.
  2439. --|*** (Vincent Croizier, 26/03/2004)
  2440. if integer_length > other.integer_length and then capacity - offset > integer_length then
  2441. ---- Add in place (`offset' doesn't change)
  2442. -- Add common parts of both numbers:
  2443. from
  2444. i := offset
  2445. j := other.offset
  2446. n := j + other.integer_length
  2447. until
  2448. j = n
  2449. loop
  2450. if inc then
  2451. -- overflow in the last addition step
  2452. inc := mbi_add_with_inc(item(i), other.item(j), storage_at(storage, i))
  2453. else
  2454. -- no overflow in the last addition step
  2455. inc := mbi_add(item(i), other.item(j), storage_at(storage, i))
  2456. end
  2457. i := i + 1
  2458. j := j + 1
  2459. end
  2460. -- Add remainder of the longer number with increment (if necessary):
  2461. from
  2462. n := offset + integer_length
  2463. until
  2464. not inc or else i = n
  2465. loop
  2466. inc := mbi_inc(storage_at(storage, i))
  2467. i := i + 1
  2468. end
  2469. if inc then
  2470. storage.put(1, n)
  2471. check
  2472. n < capacity
  2473. end
  2474. integer_length := integer_length + 1
  2475. end
  2476. else
  2477. ---- Add, after this `offset' will be 0
  2478. -- Set `a' to the longest number and `b' to the smallest.
  2479. if integer_length >= other.integer_length then
  2480. a := Current
  2481. b := other
  2482. else
  2483. a := other
  2484. b := Current
  2485. end
  2486. a_capacity := a.capacity
  2487. a_storage := a.storage
  2488. b_storage := b.storage
  2489. a_integer_length := a.integer_length
  2490. b_integer_length := b.integer_length
  2491. a_offset := a.offset
  2492. b_offset := b.offset -- Verify capacity
  2493. if capacity < a_integer_length then
  2494. new_capacity := capacity_from_lower_bound(capacity, a_integer_length)
  2495. new_storage := new_storage.calloc(new_capacity)
  2496. elseif capacity = a_integer_length then
  2497. --|*** It's possible to make a more restrictive test
  2498. --|*** that can exclude more case of reallocation. (Vincent Croizier, 24/03/2004)
  2499. new_capacity := capacity_from_lower_bound(capacity, a_integer_length + 1)
  2500. new_storage := new_storage.calloc(new_capacity)
  2501. elseif a = other then
  2502. -- protect `other'
  2503. new_storage := a_storage.calloc(a_capacity)
  2504. new_capacity := a_capacity
  2505. else
  2506. new_storage := a_storage
  2507. new_capacity := a_capacity
  2508. end
  2509. -- Add common parts of both numbers:
  2510. n := b_integer_length
  2511. check
  2512. n.in_range(0, new_capacity)
  2513. end
  2514. from
  2515. i := a_offset
  2516. j := b_offset -- k := 0
  2517. until
  2518. k = n
  2519. loop
  2520. if inc then
  2521. -- overflow in the last addition step
  2522. inc := mbi_add_with_inc(a_storage.item(i), b_storage.item(j), storage_at(new_storage, k))
  2523. else
  2524. -- no overflow in the last addition step
  2525. inc := mbi_add(a_storage.item(i), b_storage.item(j), storage_at(new_storage, k))
  2526. end
  2527. i := i + 1
  2528. j := j + 1
  2529. k := k + 1
  2530. end
  2531. -- Add remainder of the longer number with increment (if necessary):
  2532. from
  2533. n := a_integer_length
  2534. until
  2535. not inc or else k = a_integer_length
  2536. loop
  2537. new_storage.put(a_storage.item(i), k)
  2538. inc := mbi_inc(storage_at(new_storage, k))
  2539. i := i + 1
  2540. k := k + 1
  2541. end
  2542. if inc then
  2543. new_storage.put(1, k)
  2544. check
  2545. n < new_capacity
  2546. end
  2547. n := n + 1
  2548. else
  2549. -- copy the reste of `a'
  2550. from
  2551. until
  2552. k = n
  2553. loop
  2554. new_storage.put(a_storage.item(i), k)
  2555. i := i + 1
  2556. k := k + 1
  2557. end
  2558. end
  2559. capacity := new_capacity
  2560. storage := new_storage
  2561. integer_length := n
  2562. offset := 0
  2563. end
  2564. end
  2565. feature {MUTABLE_BIG_INTEGER} -- Implementation:
  2566. subtract_magnitude (other: like Current)
  2567. -- Subtract `other' from `Current' (The result is placed in `Current')
  2568. -- and change `negative' (the sign) if necessary.
  2569. require
  2570. not is_zero
  2571. not other.is_zero
  2572. local
  2573. i, j, v1, v2: INTEGER; test: BOOLEAN; new: like Current
  2574. do
  2575. -- Compare the number
  2576. if integer_length = other.integer_length then
  2577. -- Compare the most significant part of the numbers
  2578. from
  2579. i := offset + integer_length - 1
  2580. j := other.offset + integer_length - 1
  2581. v1 := item(i)
  2582. v2 := other.item(j)
  2583. test := v1 /= v2
  2584. until
  2585. test or else i = offset
  2586. loop
  2587. integer_length := integer_length - 1
  2588. i := i - 1
  2589. j := j - 1
  2590. v1 := item(i)
  2591. v2 := other.item(j)
  2592. test := v1 /= v2
  2593. end
  2594. if test then
  2595. if unsigned_greater_than(v1, v2) then
  2596. -- Current > other
  2597. subtract_magnitude_raw_truncated(other)
  2598. if storage.item(integer_length - 1) = 0 then
  2599. integer_length := integer_length - 1
  2600. check
  2601. integer_length /= 0 implies item(integer_length - 1) /= 0
  2602. end
  2603. end
  2604. else
  2605. -- Current < other
  2606. check
  2607. unsigned_less_than(v1, v2)
  2608. end
  2609. negative := not negative
  2610. subtract_magnitude_raw_reverse_truncated(other)
  2611. if storage.item(integer_length - 1) = 0 then
  2612. integer_length := integer_length - 1
  2613. check
  2614. integer_length /= 0 implies item(integer_length - 1) /= 0
  2615. end
  2616. end
  2617. end
  2618. else
  2619. -- Current = other
  2620. set_with_zero
  2621. end
  2622. elseif integer_length > other.integer_length then
  2623. subtract_magnitude_raw(other)
  2624. elseif capacity >= other.integer_length then
  2625. negative := not negative
  2626. subtract_magnitude_raw_reverse(other)
  2627. else
  2628. -- Reallocation
  2629. --|*** Can be faster (Vincent Croizier, 10/06/04) ***
  2630. create new.copy(other)
  2631. new.subtract_magnitude(Current)
  2632. negative := not negative
  2633. integer_length := new.integer_length
  2634. storage := new.storage
  2635. offset := new.offset
  2636. end
  2637. end
  2638. subtract_magnitude_raw (other: like Current)
  2639. -- Subtract (raw) the storage of `other' from `Current'.
  2640. -- Used by `subtract_magnitude'.
  2641. require
  2642. not is_zero
  2643. not other.is_zero
  2644. abs_compare(other) = 1
  2645. local
  2646. i, j, k, up: INTEGER; dec: BOOLEAN
  2647. do
  2648. from
  2649. k := 0
  2650. i := offset
  2651. j := other.offset
  2652. up := other.integer_length - 1
  2653. until
  2654. k > up
  2655. loop
  2656. if dec then
  2657. dec := mbi_subtract_with_dec(item(i), other.item(j), storage_at(storage, k))
  2658. else
  2659. dec := mbi_subtract(item(i), other.item(j), storage_at(storage, k))
  2660. end
  2661. i := i + 1
  2662. j := j + 1
  2663. k := k + 1
  2664. end
  2665. from
  2666. until
  2667. not dec
  2668. loop
  2669. --|*** Could be done in one step with a mbi_dec_bis
  2670. --| routine (Vincent Croizier, 10/06/04) ***
  2671. put(item(i), k)
  2672. dec := mbi_dec(storage_at(storage, k))
  2673. i := i + 1
  2674. k := k + 1
  2675. end
  2676. if k = integer_length then
  2677. from
  2678. k := k - 1
  2679. until
  2680. item(k) /= 0
  2681. loop
  2682. k := k - 1
  2683. end
  2684. integer_length := k + 1
  2685. end
  2686. offset := 0
  2687. ensure
  2688. offset = 0
  2689. end
  2690. subtract_magnitude_raw_reverse (other: like Current)
  2691. -- Subtract (raw) the storage of `Current' from `other' and
  2692. -- put it in `Current'.
  2693. -- Used by `subtract_magnitude'.
  2694. require
  2695. not is_zero
  2696. not other.is_zero
  2697. abs_compare(other) = -1
  2698. local
  2699. i, j, k, up: INTEGER; dec: BOOLEAN
  2700. do
  2701. from
  2702. -- k := 0
  2703. i := offset
  2704. j := other.offset
  2705. up := integer_length - 1
  2706. until
  2707. k > up
  2708. loop
  2709. if dec then
  2710. dec := mbi_subtract_with_dec(other.item(j), item(i), storage_at(storage, k))
  2711. else
  2712. dec := mbi_subtract(other.item(j), item(i), storage_at(storage, k))
  2713. end
  2714. i := i + 1
  2715. j := j + 1
  2716. k := k + 1
  2717. end
  2718. from
  2719. until
  2720. not dec
  2721. loop
  2722. --|*** Could be done in one step with a mbi_dec_bis
  2723. --| routine (Vincent Croizier, 10/06/04) ***
  2724. put(other.item(j), k)
  2725. dec := mbi_dec(storage_at(storage, k))
  2726. j := j + 1
  2727. k := k + 1
  2728. end
  2729. check
  2730. not dec
  2731. end
  2732. up := other.integer_length
  2733. if k < up then
  2734. from
  2735. until
  2736. k = up
  2737. loop
  2738. put(other.item(j), k)
  2739. j := j + 1
  2740. k := k + 1
  2741. end
  2742. integer_length := up
  2743. else
  2744. check
  2745. k = up
  2746. end
  2747. from
  2748. k := k - 1
  2749. until
  2750. storage.item(k) /= 0
  2751. loop
  2752. k := k - 1
  2753. end
  2754. integer_length := k + 1
  2755. offset := 0
  2756. end
  2757. ensure
  2758. offset = 0
  2759. end
  2760. subtract_magnitude_raw_truncated (other: like Current)
  2761. -- Subtract (raw) the storage of `other' from `Current'
  2762. -- where `other' is truncated to the size of `Current'.
  2763. -- Used by `subtract_magnitude'.
  2764. require
  2765. not other.is_zero
  2766. other.integer_length >= integer_length
  2767. unsigned_greater_than(item(offset + integer_length - 1), other.item(offset + integer_length - 1))
  2768. local
  2769. i, j, k, up: INTEGER; dec: BOOLEAN
  2770. do
  2771. from
  2772. k := 0
  2773. i := offset
  2774. j := other.offset
  2775. up := integer_length - 1
  2776. until
  2777. k > up
  2778. loop
  2779. if dec then
  2780. dec := mbi_subtract_with_dec(item(i), other.item(j), storage_at(storage, k))
  2781. else
  2782. dec := mbi_subtract(item(i), other.item(j), storage_at(storage, k))
  2783. end
  2784. i := i + 1
  2785. j := j + 1
  2786. k := k + 1
  2787. end
  2788. check
  2789. not dec
  2790. end
  2791. offset := 0
  2792. ensure
  2793. offset = 0
  2794. end
  2795. subtract_magnitude_raw_reverse_truncated (other: like Current)
  2796. -- Subtract (raw) the storage of `Current' from `other' and
  2797. -- put it in `Current',
  2798. -- where `other' is truncated to the size of `Current'.
  2799. -- Used by `subtract_magnitude'.
  2800. require
  2801. not other.is_zero
  2802. other.integer_length >= integer_length
  2803. unsigned_less_than(item(offset + integer_length - 1), other.item(offset + integer_length - 1))
  2804. local
  2805. i, j, k, up: INTEGER; dec: BOOLEAN
  2806. do
  2807. from
  2808. k := 0
  2809. i := offset
  2810. j := other.offset
  2811. up := integer_length - 1
  2812. until
  2813. k > up
  2814. loop
  2815. if dec then
  2816. dec := mbi_subtract_with_dec(other.item(j), item(i), storage_at(storage, k))
  2817. else
  2818. dec := mbi_subtract(other.item(j), item(i), storage_at(storage, k))
  2819. end
  2820. i := i + 1
  2821. j := j + 1
  2822. k := k + 1
  2823. end
  2824. check
  2825. not dec
  2826. end
  2827. offset := 0
  2828. ensure
  2829. offset = 0
  2830. end
  2831. feature {} -- For printing
  2832. char_buffer: FAST_ARRAY[CHARACTER]
  2833. once
  2834. create Result.make(4096)
  2835. end
  2836. append_in_char_buffer: INTEGER
  2837. -- Tool for `append_in' and `append_in_unicode'.
  2838. -- Put absolute value of Current in `char_buffer' and return
  2839. -- the number of characteres really used.
  2840. require
  2841. is_printable
  2842. not is_zero
  2843. local
  2844. base, max_char, i, r: INTEGER
  2845. do
  2846. -- Allocate space in `char_buffer'
  2847. max_char := integer_length * 9 + (2 * integer_length + 2) #// 3
  2848. if char_buffer.capacity < max_char then
  2849. char_buffer.resize(max_char)
  2850. end
  2851. -- Begin of extracting digits
  2852. register1.copy(Current)
  2853. base := 1000000000
  2854. from
  2855. r := register1.divide_one_word(base)
  2856. until
  2857. register1.is_zero
  2858. loop
  2859. check
  2860. r >= 0
  2861. end
  2862. from
  2863. i := 9
  2864. until
  2865. r = 0
  2866. loop
  2867. char_buffer.put((r #\\ 10).decimal_digit, Result)
  2868. r := r #// 10
  2869. Result := Result + 1
  2870. i := i - 1
  2871. end
  2872. from
  2873. until
  2874. i = 0
  2875. loop
  2876. char_buffer.put('0', Result)
  2877. Result := Result + 1
  2878. i := i - 1
  2879. end
  2880. -- extract next digit group
  2881. r := register1.divide_one_word(base)
  2882. end
  2883. from
  2884. check
  2885. r > 0
  2886. end
  2887. until
  2888. r = 0
  2889. loop
  2890. char_buffer.put((r #\\ 10).decimal_digit, Result)
  2891. r := r #// 10
  2892. Result := Result + 1
  2893. end
  2894. end
  2895. feature {} -- Tools for capacity:
  2896. capacity_from_lower_bound (actual_capacity, needed_capacity: INTEGER): INTEGER
  2897. -- Give the smallest power of 2 greater than
  2898. -- `needed_capacity' and `actual_capacity'.
  2899. -- Based on `actual_capacity' (the actual capacity).
  2900. require
  2901. actual_capacity.is_a_power_of_2
  2902. actual_capacity >= 4
  2903. do
  2904. from
  2905. Result := actual_capacity
  2906. until
  2907. Result >= needed_capacity
  2908. loop
  2909. Result := Result.bit_shift_left(1)
  2910. end
  2911. ensure
  2912. Result.is_a_power_of_2
  2913. Result >= 4
  2914. Result >= actual_capacity
  2915. Result >= needed_capacity
  2916. Result = actual_capacity or Result #// 2 < needed_capacity
  2917. end
  2918. capacity_from_upper_bound (actual_capacity, needed_capacity: INTEGER): INTEGER
  2919. -- Give the smallest power of 2 greater than `needed_capacity'.
  2920. -- Based on `actual_capacity' (the actual capacity).
  2921. require
  2922. actual_capacity >= 4
  2923. actual_capacity >= needed_capacity
  2924. actual_capacity.is_a_power_of_2
  2925. local
  2926. v: INTEGER
  2927. do
  2928. from
  2929. Result := actual_capacity
  2930. v := Result.bit_shift_right(1)
  2931. until
  2932. v < needed_capacity or else v = 2
  2933. loop
  2934. Result := v
  2935. v := Result.bit_shift_right(1)
  2936. end
  2937. ensure
  2938. Result.is_a_power_of_2
  2939. Result <= actual_capacity
  2940. Result >= needed_capacity
  2941. Result = 4 or Result.bit_shift_right(1) < needed_capacity
  2942. end
  2943. feature {}
  2944. unsigned_less_than (a, b: INTEGER): BOOLEAN
  2945. -- Unsigned "<".
  2946. external "plug_in"
  2947. alias "{
  2948. location: "${sys}/runtime"
  2949. module_name: "mutable_big_integer"
  2950. feature_name: "mbi_unsigned_less_than"
  2951. }"
  2952. end
  2953. unsigned_greater_than (a, b: INTEGER): BOOLEAN
  2954. -- Unsigned ">".
  2955. external "plug_in"
  2956. alias "{
  2957. location: "${sys}/runtime"
  2958. module_name: "mutable_big_integer"
  2959. feature_name: "mbi_unsigned_greater_than"
  2960. }"
  2961. end
  2962. unsigned_greater_or_equal (a, b: INTEGER): BOOLEAN
  2963. -- Unsigned ">=".
  2964. external "plug_in"
  2965. alias "{
  2966. location: "${sys}/runtime"
  2967. module_name: "mutable_big_integer"
  2968. feature_name: "mbi_unsigned_greater_or_equal"
  2969. }"
  2970. end
  2971. unsigned_32_to_integer_64 (integer_32: INTEGER): INTEGER_64
  2972. -- Return the unsigned value of the `integer_32'.
  2973. --
  2974. --|*** Ajouter ou pas cette fonction dans INTEGER_32 ? plug_in ou built_in ?(Dom. 27/02/2004) ***
  2975. --|*** Or finally, do it as a simple C iniline? (Dom. 14/09/2007) ***
  2976. --
  2977. external "plug_in"
  2978. alias "{
  2979. location: "${sys}/runtime"
  2980. module_name: "mutable_big_integer"
  2981. feature_name: "mbi_unsigned_32_to_integer_64"
  2982. }"
  2983. end
  2984. storage_at (s: like storage; n: INTEGER): POINTER
  2985. -- Give the address of the corresponding word of `s'.
  2986. external "plug_in"
  2987. alias "{
  2988. location: "${sys}/runtime"
  2989. module_name: "mutable_big_integer"
  2990. feature_name: "mbi_storage_at"
  2991. }"
  2992. end
  2993. mbi_inc (integer_32_adr: POINTER): BOOLEAN
  2994. -- Increment the value at `integer_32_adr'. The `Result' is True only in case of overflow.
  2995. external "plug_in"
  2996. alias "{
  2997. location: "${sys}/runtime"
  2998. module_name: "mutable_big_integer"
  2999. feature_name: "mbi_inc"
  3000. }"
  3001. end
  3002. mbi_add (a, b: INTEGER; integer_32_adr: POINTER): BOOLEAN
  3003. -- t.item(n) := a + b
  3004. -- Overflow if "Result = True".
  3005. external "plug_in"
  3006. alias "{
  3007. location: "${sys}/runtime"
  3008. module_name: "mutable_big_integer"
  3009. feature_name: "mbi_add"
  3010. }"
  3011. end
  3012. mbi_add_with_inc (a, b: INTEGER; integer_32_adr: POINTER): BOOLEAN
  3013. -- t.item(n) := a + b + 1
  3014. -- Overflow if "Result = True".
  3015. external "plug_in"
  3016. alias "{
  3017. location: "${sys}/runtime"
  3018. module_name: "mutable_big_integer"
  3019. feature_name: "mbi_add_with_inc"
  3020. }"
  3021. end
  3022. mbi_dec (integer_32_adr: POINTER): BOOLEAN
  3023. -- Put a - 1 in the item n in the NATIVE_ARRAY t.
  3024. -- t.item(n) := a - 1
  3025. -- Underflow if "Result = True".
  3026. external "plug_in"
  3027. alias "{
  3028. location: "${sys}/runtime"
  3029. module_name: "mutable_big_integer"
  3030. feature_name: "mbi_dec"
  3031. }"
  3032. end
  3033. mbi_subtract (a, b: INTEGER; integer_32_adr: POINTER): BOOLEAN
  3034. -- t.item(n) := a - b
  3035. -- Underflow if "Result = True".
  3036. external "plug_in"
  3037. alias "{
  3038. location: "${sys}/runtime"
  3039. module_name: "mutable_big_integer"
  3040. feature_name: "mbi_subtract"
  3041. }"
  3042. end
  3043. mbi_subtract_with_dec (a, b: INTEGER; integer_32_adr: POINTER): BOOLEAN
  3044. -- t.item(n) := a - b - 1
  3045. -- Underflow if "Result = True".
  3046. external "plug_in"
  3047. alias "{
  3048. location: "${sys}/runtime"
  3049. module_name: "mutable_big_integer"
  3050. feature_name: "mbi_subtract_with_dec"
  3051. }"
  3052. end
  3053. mbi_multiply (a, b: INTEGER; integer_32_adr: POINTER): INTEGER_32
  3054. -- put a * b in t@n and return the overflow.
  3055. external "plug_in"
  3056. alias "{
  3057. location: "${sys}/runtime"
  3058. module_name: "mutable_big_integer"
  3059. feature_name: "mbi_multiply"
  3060. }"
  3061. end
  3062. mbi_multiply_with_add (a, b, c: INTEGER; integer_32_adr: POINTER): INTEGER_32
  3063. -- put a * b + c in t@n and return the overflow.
  3064. external "plug_in"
  3065. alias "{
  3066. location: "${sys}/runtime"
  3067. module_name: "mutable_big_integer"
  3068. feature_name: "mbi_multiply_with_add"
  3069. }"
  3070. end
  3071. mbi_multiply_with_2_add (a, b, c, d: INTEGER; integer_32_adr: POINTER): INTEGER_32
  3072. -- put a * b + c + d in t@n and return the overflow.
  3073. external "plug_in"
  3074. alias "{
  3075. location: "${sys}/runtime"
  3076. module_name: "mutable_big_integer"
  3077. feature_name: "mbi_multiply_with_2_add"
  3078. }"
  3079. end
  3080. mbi_divide (u1, u0, d: INTEGER; r_int32adr: POINTER): INTEGER_32
  3081. -- Divide `u1u0' by `d', put the remainder in `r' and return the quotient.
  3082. external "plug_in"
  3083. alias "{
  3084. location: "${sys}/runtime"
  3085. module_name: "mutable_big_integer"
  3086. feature_name: "mbi_divide"
  3087. }"
  3088. end
  3089. string_buffer: STRING
  3090. once
  3091. create Result.make(128)
  3092. end
  3093. unicode_string_buffer: UNICODE_STRING
  3094. once
  3095. create Result.make(128)
  3096. end
  3097. invariant
  3098. capacity > 0
  3099. storage.is_not_null
  3100. integer_length.in_range(0, capacity)
  3101. integer_length /= 0 implies offset.in_range(0, capacity - integer_length) and item(offset + integer_length - 1) /= 0
  3102. integer_length = 0 implies not negative
  3103. capacity.is_a_power_of_2
  3104. end -- class MUTABLE_BIG_INTEGER
  3105. --
  3106. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  3107. --
  3108. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  3109. -- of this software and associated documentation files (the "Software"), to deal
  3110. -- in the Software without restriction, including without limitation the rights
  3111. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  3112. -- copies of the Software, and to permit persons to whom the Software is
  3113. -- furnished to do so, subject to the following conditions:
  3114. --
  3115. -- The above copyright notice and this permission notice shall be included in
  3116. -- all copies or substantial portions of the Software.
  3117. --
  3118. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  3119. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  3120. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  3121. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  3122. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  3123. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  3124. -- THE SOFTWARE.