/src/lib/numeric/integral.e

http://github.com/tybor/Liberty · Specman e · 581 lines · 352 code · 69 blank · 160 comment · 0 complexity · 4c157ff13ecacb916dfd25fc66e54d1c MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. deferred class INTEGRAL
  5. --
  6. -- General integer abstraction for both integers and naturals.
  7. --
  8. inherit
  9. COMPARABLE
  10. undefine infix "<=", infix ">", infix ">=", is_equal
  11. end
  12. insert
  13. NUMERIC
  14. PLATFORM
  15. feature {ANY}
  16. infix "+" (other: like Current): like Current
  17. require
  18. no_overflow: Current > zero = (other > zero) implies Current #+ other > zero = (Current > zero) -- this means: if operand are of same sign, it will be sign of the Result.
  19. deferred
  20. ensure
  21. Result #- other = Current
  22. end
  23. infix "-" (other: like Current): like Current
  24. require
  25. no_overflow: Current > zero /= (other > zero) implies Current #- other > zero = (Current > zero) -- this means: if operand are of different sign, sign of the Result will be the same sign as Current.
  26. deferred
  27. ensure
  28. Result #+ other = Current
  29. end
  30. infix "*" (other: like Current): like Current
  31. require
  32. no_overflow: (other /= zero) implies Current #* other #// other = Current
  33. deferred
  34. ensure
  35. Current /= zero and other /= zero implies Result /= zero
  36. Result /= zero implies Result #// other = Current
  37. Result /= zero implies Result #\\ other = zero
  38. end
  39. infix "/" (other: like Current): REAL
  40. deferred
  41. end
  42. infix "//" (other: like Current): like Current
  43. -- Quotient of the Euclidian division of `Current' by `other'.
  44. -- The corresponding remainder is given by infix "\\".
  45. --
  46. -- See also infix "#//".
  47. require
  48. other /= zero
  49. no_overflow: other = -one implies Current = zero or Current |<< 1 /= zero
  50. deferred
  51. ensure
  52. euclidian_divide_case1: Current >= zero implies Result * other + Current \\ other = Current
  53. euclidian_divide_case2: Current < zero implies Result #* other #+ (Current \\ other) = Current
  54. end
  55. infix "\\" (other: like Current): like Current
  56. -- Remainder of the Euclidian division of `Current' by `other'.
  57. -- By definition, `zero <= Result < other.abs'.
  58. --
  59. -- See also infix "#\\", infix "//".
  60. require
  61. other /= zero
  62. deferred
  63. ensure
  64. Result >= zero
  65. other |<< 1 /= zero implies Result < other.abs
  66. good_remainder: Result #- (Current #\\ other) #\\ other = zero
  67. end
  68. infix "^" (exp: like Current): INTEGER_64
  69. -- Integer power of `Current' by `other'
  70. require
  71. exp >= zero
  72. deferred
  73. end
  74. abs: like Current
  75. -- Absolute value of `Current'.
  76. require
  77. not_minimum_value: Current < zero implies zero < #-Current
  78. deferred
  79. ensure
  80. Result >= zero
  81. end
  82. infix "<" (other: like Current): BOOLEAN
  83. deferred
  84. end
  85. infix "<=" (other: like Current): BOOLEAN
  86. deferred
  87. end
  88. infix ">" (other: like Current): BOOLEAN
  89. deferred
  90. end
  91. infix ">=" (other: like Current): BOOLEAN
  92. deferred
  93. end
  94. prefix "+": like Current
  95. deferred
  96. end
  97. prefix "-": like Current
  98. require
  99. not_minimum_value: Current < zero implies zero < #-Current
  100. deferred
  101. end
  102. is_odd: BOOLEAN
  103. -- Is odd?
  104. deferred
  105. end
  106. is_even: BOOLEAN
  107. -- Is even?
  108. deferred
  109. end
  110. sqrt: REAL
  111. -- Square root of `Current'.
  112. require
  113. Current >= zero
  114. deferred
  115. end
  116. log: REAL
  117. -- Natural Logarithm of `Current'.
  118. require
  119. Current > zero
  120. deferred
  121. end
  122. log10: REAL
  123. -- Base-10 Logarithm of Current.
  124. require
  125. Current > zero
  126. deferred
  127. end
  128. gcd (other: like Current): like Current
  129. -- Greatest Common Divisor of `Current' and `other'.
  130. deferred
  131. ensure
  132. Result >= zero
  133. Result = zero implies Current = zero and other = zero
  134. Result >= (one + one) implies Current \\ Result = zero and other \\ Result = zero and (Current // Result).gcd(other // Result) = one
  135. end
  136. lcm (other: like Current): like Current
  137. -- Least Common Multiple of `Current' and `other'.
  138. do
  139. Result := abs // gcd(other) * other.abs
  140. ensure
  141. Result >= zero
  142. Result = zero implies Current = zero or other = zero
  143. Result * gcd(other) = (Current * other).abs
  144. end
  145. feature {ANY} -- Conversions:
  146. to_string: STRING
  147. -- The decimal view of `Current' into a new allocated STRING.
  148. -- For example, if `Current' is -1 the `Result' is "-1".
  149. --
  150. -- See also `append_in', `to_string_format', `to_unicode_string', `to_hexadecimal', `to_octal'.
  151. deferred
  152. end
  153. to_unicode_string: UNICODE_STRING
  154. -- The decimal view of `Current' into a new allocated UNICODE_STRING.
  155. -- For example, if `Current' is -1 the `Result' is U"-1".
  156. --
  157. -- See also `append_in_unicode', `to_unicode_string_format', `to_string', `to_hexadecimal', `to_octal'.
  158. deferred
  159. end
  160. to_boolean: BOOLEAN
  161. -- Return False for 0, otherwise True.
  162. --
  163. -- See also `to_string', `to_character', `to_hexadecimal', `to_number'.
  164. deferred
  165. ensure
  166. Result = (Current /= zero)
  167. end
  168. to_number: NUMBER
  169. -- Convert `Current' into a new allocated NUMBER.
  170. --
  171. -- See also `to_boolean', `to_string', `to_character', `to_hexadecimal'.
  172. deferred
  173. ensure
  174. Result.to_string.is_equal(to_string)
  175. end
  176. append_in (buffer: STRING)
  177. -- Append in the `buffer' the equivalent of `to_string'.
  178. -- If you look for performances, you should always prefer `append_in' which allow you to recycle
  179. -- a unique common `buffer' (each call of `to_string' allocate a new object!).
  180. --
  181. -- See also `append_in_format', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'.
  182. require
  183. buffer /= Void
  184. deferred
  185. end
  186. append_in_unicode (buffer: UNICODE_STRING)
  187. -- Append in the `buffer' the equivalent of `to_unicode_string'.
  188. -- If you look for performances, you should always prefer `append_in_unicode' which allow you to recycle
  189. -- a unique common `buffer' (each call of `to_unicode_string' allocate a new object!).
  190. --
  191. -- See also `append_in_unicode_format', `append_in', `append_in_format', `to_hexadecimal_in'.
  192. require
  193. buffer /= Void
  194. deferred
  195. end
  196. to_string_format (s: INTEGER): STRING
  197. -- Same as `to_string' but the result is on `s' character and the number is right aligned.
  198. --
  199. -- See also `append_in_format', `to_character', `to_number', `to_hexadecimal'.
  200. require
  201. to_string.count <= s
  202. deferred
  203. ensure
  204. Result.count = s
  205. end
  206. to_unicode_string_format (s: INTEGER): UNICODE_STRING
  207. -- Same as `to_unicode_string' but the result is on `s' character and the number is right aligned.
  208. --
  209. -- See also `append_in_unicode_format', `to_string', `to_hexadecimal', `to_octal'.
  210. require
  211. to_string.count <= s
  212. deferred
  213. ensure
  214. Result.count = s
  215. end
  216. append_in_format (buffer: STRING; s: INTEGER)
  217. -- Append in the `buffer' the equivalent of `to_string_format'.
  218. -- If you look for performances, you should always prefer `append_in_format' which allow you to recycle
  219. -- a unique common `buffer' (each call of `to_string_format' allocate a new object!).
  220. --
  221. -- See also `append_in', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'.
  222. require
  223. to_string.count <= s
  224. deferred
  225. ensure
  226. buffer.count >= old buffer.count + s
  227. end
  228. append_in_unicode_format (buffer: UNICODE_STRING; s: INTEGER)
  229. -- Append in the `buffer' the equivalent of `to_unicode_string_format'.
  230. -- If you look for performances, you should always prefer `append_in_unicode_format' which allow you to recycle
  231. -- a unique common `buffer' (each call of `to_unicode_string_format' allocate a new object!).
  232. --
  233. -- See also `append_in_format', `append_in', `append_in_format', `to_hexadecimal_in'.
  234. require
  235. to_string.count <= s
  236. deferred
  237. ensure
  238. buffer.count >= old buffer.count + s
  239. end
  240. digit: CHARACTER
  241. -- Legacy synonym for `decimal_digit'.
  242. -- Note: already prefer `decimal_digit' because digit may become obsolete (feb 4th 2006).
  243. deferred
  244. ensure
  245. Result = decimal_digit
  246. end
  247. is_decimal_digit: BOOLEAN
  248. deferred
  249. end
  250. decimal_digit: CHARACTER
  251. -- Gives the corresponding CHARACTER for range 0..9.
  252. require
  253. is_decimal_digit
  254. deferred
  255. ensure
  256. (once "0123456789").has(Result)
  257. --Current.is_equal(Result.value)
  258. end
  259. is_hexadecimal_digit: BOOLEAN
  260. deferred
  261. end
  262. hexadecimal_digit: CHARACTER
  263. -- Gives the corresponding CHARACTER for range 0..15.
  264. require
  265. is_hexadecimal_digit
  266. deferred
  267. ensure
  268. (once "0123456789ABCDEF").has(Result)
  269. end
  270. to_character: CHARACTER
  271. -- Return the corresponding ASCII character.
  272. --
  273. -- See also `to_boolean', `to_number', `to_string', `to_hexadecimal'.
  274. require
  275. Current >= zero
  276. --Current <= Maximum_character_code
  277. deferred
  278. end
  279. to_octal_in (buffer: STRING)
  280. -- Append in the `buffer' the equivalent of `to_octal'.
  281. -- If you look for performances, you should always prefer `to_octal_in' which allow you to recycle
  282. -- a unique common `buffer' (each call of `to_octal' allocate a new object!).
  283. --
  284. -- See also `to_hexadecimal_in', `append_in', `append_in_format', `append_in_unicode'.
  285. deferred
  286. ensure
  287. buffer.count = old buffer.count + bit_count #// 3 + 1
  288. end
  289. to_octal: STRING
  290. -- The octal view of `Current' into a new allocated STRING.
  291. -- For example, if `Current' is -1 and if `Current' is a 16 bits integer the `Result' is "177777".
  292. --
  293. -- See also `to_octal_in', `to_hexadecimal', `to_number', `to_string'.
  294. deferred
  295. ensure
  296. Result.count = bit_count #// 3 + 1
  297. end
  298. to_hexadecimal: STRING
  299. -- The hexadecimal view of `Current' into a new allocated STRING.
  300. -- For example, if `Current' is -1 and if `Current' is a 32 bits integer the `Result' is "FFFFFFFF".
  301. --
  302. -- See also `to_hexadecimal_in', `to_octal', `to_number', `to_string'.
  303. deferred
  304. ensure
  305. Result.count = object_size * 2
  306. end
  307. to_hexadecimal_in (buffer: STRING)
  308. -- Append in the `buffer' the equivalent of `to_hexadecimal'.
  309. -- If you look for performances, you should always prefer `to_hexadecimal_in' which allow you to recycle
  310. -- a unique common `buffer' (each call of `to_hexadecimal' allocate a new object!).
  311. --
  312. -- See also `to_octal_in', `append_in', `append_in_format', `append_in_unicode'.
  313. deferred
  314. ensure
  315. buffer.count = old buffer.count + object_size * 2
  316. end
  317. feature {ANY} -- Bitwise Logical Operators:
  318. bit_test (idx: INTEGER_8): BOOLEAN
  319. -- The value of the `idx'-ith bit (the right-most bit is at index 0).
  320. require
  321. idx.in_range(0, bit_count - 1)
  322. deferred
  323. end
  324. bit_set (idx: INTEGER_8): like Current
  325. -- The value of the `idx'-ith bit (the right-most bit is at index 0).
  326. require
  327. idx.in_range(0, bit_count - 1)
  328. deferred
  329. ensure
  330. Result.bit_test(idx)
  331. Result = Current or Result.bit_reset(idx) = Current
  332. end
  333. bit_reset (idx: INTEGER_8): like Current
  334. -- The value of the `idx'-ith bit (the right-most bit is at index 0).
  335. require
  336. idx.in_range(0, bit_count - 1)
  337. deferred
  338. ensure
  339. not Result.bit_test(idx)
  340. Result = Current or Result.bit_set(idx) = Current
  341. end
  342. infix "|>>", bit_shift_right (s: INTEGER_8): like Current
  343. -- Shift by `s' positions right (sign bit copied) bits falling off the end are lost.
  344. require
  345. s.in_range(0, bit_count - 1)
  346. deferred
  347. end
  348. infix "|>>>", bit_shift_right_unsigned (s: INTEGER_8): like Current
  349. -- Shift by `s' positions right (sign bit not copied) bits falling off the end are lost.
  350. require
  351. s.in_range(0, bit_count - 1)
  352. deferred
  353. end
  354. infix "|<<", bit_shift_left (s: INTEGER_8): like Current
  355. -- Shift by `s' positions left bits falling off the end are lost.
  356. require
  357. s.in_range(0, bit_count - 1)
  358. deferred
  359. end
  360. infix "#>>", bit_rotate_right (s: INTEGER_8): like Current
  361. -- Rotate by `s' positions right.
  362. --
  363. -- See also `bit_rotate_left' and `bit_rotate'.
  364. require
  365. s.in_range(1, bit_count - 1)
  366. deferred
  367. end
  368. infix "#<<", bit_rotate_left (s: INTEGER_8): like Current
  369. -- Rotate by `s' positions left.
  370. --
  371. -- See also `bit_rotate_right' and `bit_rotate'.
  372. require
  373. s.in_range(1, bit_count - 1)
  374. deferred
  375. end
  376. bit_rotate (s: INTEGER_8): like Current
  377. -- Rotate by `s' positions (positive `s' shifts right, negative left
  378. --
  379. -- See also `bit_rotate_right' and `bit_rotate_left'.
  380. require
  381. s.in_range(- (bit_count - 1), bit_count - 1)
  382. deferred
  383. end
  384. prefix "~", bit_not: like Current
  385. -- One's complement of `Current'.
  386. deferred
  387. end
  388. infix "&", bit_and (other: like Current): like Current
  389. -- Bitwise logical and of `Current' with `other'.
  390. deferred
  391. end
  392. infix "|", bit_or (other: like Current): like Current
  393. -- Bitwise logical inclusive or of `Current' with `other'.
  394. deferred
  395. end
  396. bit_xor (other: like Current): like Current
  397. -- Bitwise logical exclusive or of `Current' with `other'.
  398. deferred
  399. end
  400. bit_shift (s: INTEGER_8): like Current
  401. -- Shift by `s' positions (positive `s' shifts right (sign bit
  402. -- copied), negative shifts left bits falling off the end are lost).
  403. --
  404. -- See also infix "|>>" and infix "|<<".
  405. require
  406. s /= 0
  407. deferred
  408. end
  409. bit_shift_unsigned (s: INTEGER_8): like Current
  410. -- Shift by `s' positions (positive `s' shifts right (sign bit not
  411. -- copied), negative left bits falling off the end are lost).
  412. --
  413. -- See also infix "|>>>" and infix "|<<".
  414. require
  415. s /= 0
  416. deferred
  417. end
  418. feature {ANY} -- Miscellaneous:
  419. sign: INTEGER_8
  420. -- Sign of `Current' (0 or -1 or 1).
  421. deferred
  422. end
  423. divisible (other: like Current): BOOLEAN
  424. deferred
  425. ensure
  426. definition: Result = (other /= zero)
  427. end
  428. is_a_power_of_2: BOOLEAN
  429. -- Is `Current' a power of 2?
  430. require
  431. Current > zero
  432. deferred
  433. end
  434. feature {ANY} -- Modular arithmetic (these wrap around on overflow)
  435. infix "#+" (other: like Current): like Current
  436. deferred
  437. end
  438. prefix "#-": like Current
  439. deferred
  440. end
  441. infix "#-" (other: like Current): like Current
  442. deferred
  443. end
  444. infix "#*" (other: like Current): like Current
  445. deferred
  446. end
  447. infix "#//" (other: like Current): like Current
  448. -- Integer division of `Current' by `other'.
  449. --
  450. -- According to the ANSI C99: if `Current' and `other' are both non-negative, the `Result' is the
  451. -- quotient of the Euclidian division; but this is not the general case, the `Result' value is the
  452. -- algebraic quotient `Current/other' with any fractional part discarded. (This is often called
  453. -- "truncated toward zero"). So, the corresponding remainder value only verifies the expression
  454. -- `remainder.abs < other.abs'.
  455. --
  456. -- See also infix "//", infix "#\\".
  457. require
  458. other /= zero
  459. deferred
  460. ensure
  461. Result * other + Current #\\ other = Current
  462. ansi_c_remainder: (other |<< 1 /= zero) implies (Current - Result * other).abs < other.abs
  463. ansi_c_good_case: Current >= zero and other > zero implies Current - Result * other >= zero
  464. end
  465. infix "#\\" (other: like Current): like Current
  466. -- Remainder of the integer division of `Current' by `other'.
  467. -- According to the ANSI C99:
  468. -- * if `Current' and `other' are both non-negative,
  469. -- the `Result' is the remainder of the Euclidian division.
  470. -- * but this is not the general case,
  471. -- `Result' as the same sign as `Current' and only verify
  472. -- the expression `Result.abs < other.abs'.
  473. --
  474. -- See also infix "\\", infix "#//".
  475. require
  476. other /= zero
  477. deferred
  478. ensure
  479. (Current - Result) #\\ other = zero
  480. ansi_c_remainder: (other |<< 1 /= zero) implies Result.abs < other.abs
  481. ansi_c_good_case: (Current >= zero and other > zero) implies Result >= zero
  482. end
  483. feature {}
  484. bit_count: INTEGER_8
  485. -- Well, it is 8 for INTEGER_8, 16 for INTEGER_16 and so on.
  486. -- Note that this feature is not exported because this information is part of the type.
  487. -- This is actually used only for assertion here, in INTEGER_GENERAL.
  488. deferred
  489. ensure
  490. Result = (object_size * 8)
  491. end
  492. end -- class INTEGRAL
  493. --
  494. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  495. --
  496. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  497. -- of this software and associated documentation files (the "Software"), to deal
  498. -- in the Software without restriction, including without limitation the rights
  499. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  500. -- copies of the Software, and to permit persons to whom the Software is
  501. -- furnished to do so, subject to the following conditions:
  502. --
  503. -- The above copyright notice and this permission notice shall be included in
  504. -- all copies or substantial portions of the Software.
  505. --
  506. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  507. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  508. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  509. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  510. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  511. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  512. -- THE SOFTWARE.