/src/lib/storage/collection3/array3.e

http://github.com/tybor/Liberty · Specman e · 421 lines · 338 code · 34 blank · 49 comment · 6 complexity · 1444abd3defaee6d5ef9e43f9f3392d6 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class ARRAY3[E_]
  5. --
  6. -- General purpose, resizable, three dimensional array.
  7. --
  8. inherit
  9. COLLECTION3[E_]
  10. insert
  11. NATIVE_ARRAY_COLLECTOR[E_]
  12. create {ANY}
  13. make, copy, from_collection3, from_collection, from_model
  14. feature {ANY}
  15. lower1, lower2, lower3, upper1, upper2, upper3: INTEGER
  16. count1, count2, count3, count: INTEGER
  17. feature {ARRAY3}
  18. storage: NATIVE_ARRAY[E_]
  19. -- To store elements line by line.
  20. capacity: INTEGER
  21. -- Number of elements in `storage'.
  22. set_limits(line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER)
  23. -- set lower1,2,3 and upper1,2,3 to the given values and alloc storage if necessary
  24. require
  25. line_min <= line_max + 1
  26. column_min <= column_max + 1
  27. depth_min <= depth_max + 1
  28. do
  29. lower1 := line_min
  30. upper1 := line_max
  31. lower2 := column_min
  32. upper2 := column_max
  33. lower3 := depth_min
  34. upper3 := depth_max
  35. count1 := upper1 - lower1 + 1
  36. count2 := upper2 - lower2 + 1
  37. count3 := upper3 - lower3 + 1
  38. count := count1 * count2 * count3
  39. if count > capacity then
  40. storage := storage.calloc(count)
  41. capacity := count
  42. end
  43. ensure
  44. lower1_set: lower1 = line_min
  45. lower2_set: upper1 = line_max
  46. upper1_set: lower2 = column_min
  47. upper2_set: upper2 = column_max
  48. sufficient_storage: capacity >= count
  49. end
  50. feature {ANY} -- Creation / modification:
  51. make (line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER)
  52. -- Reset all bounds `line_minimum' / `line_maximum' / `column_minimum'
  53. -- `column_maximum' / `depth_min' and `depth_max' using arguments as
  54. -- new values. All elements are set to the default value of type E_.
  55. require
  56. line_min <= line_max
  57. column_min <= column_max
  58. depth_min <= depth_max
  59. do
  60. lower1 := line_min
  61. upper1 := line_max
  62. lower2 := column_min
  63. upper2 := column_max
  64. lower3 := depth_min
  65. upper3 := depth_max
  66. count1 := upper1 - lower1 + 1
  67. count2 := upper2 - lower2 + 1
  68. count3 := upper3 - lower3 + 1
  69. count := count1 * count2 * count3
  70. if capacity >= count then
  71. storage.clear_all(count - 1)
  72. else
  73. capacity := count
  74. storage := storage.calloc(count)
  75. end
  76. ensure
  77. line_minimum = line_min
  78. line_maximum = line_max
  79. column_minimum = column_min
  80. column_maximum = column_max
  81. depth_minimum = depth_min
  82. depth_maximum = depth_max
  83. end
  84. from_collection3 (model: COLLECTION3[like item])
  85. local
  86. i, j, k: INTEGER
  87. do
  88. make(model.line_minimum, model.line_maximum, model.column_minimum, model.column_maximum, model.depth_minimum, model.depth_maximum)
  89. from
  90. i := line_minimum
  91. until
  92. i > line_maximum
  93. loop
  94. from
  95. j := column_minimum
  96. until
  97. j > column_maximum
  98. loop
  99. from
  100. k := depth_minimum
  101. until
  102. k > depth_maximum
  103. loop
  104. put(model.item(i, j, k), i, j, k)
  105. k := k + 1
  106. end
  107. j := j + 1
  108. end
  109. i := i + 1
  110. end
  111. ensure then
  112. lower1 = model.lower1
  113. lower2 = model.lower2
  114. lower3 = model.lower3
  115. end
  116. from_collection (contents: COLLECTION[E_]
  117. line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER)
  118. -- Reset all bounds using `line_min', `line_max', `column_min',
  119. -- `column_max', `depth_min', and `depth_max'.
  120. -- Copy all elements of `contents', line by line into Current.
  121. require
  122. line_min <= line_max
  123. column_min <= column_max
  124. depth_min <= depth_max
  125. contents.count = (line_max - line_min + 1) * (column_max - column_min + 1) * (depth_max - depth_min + 1)
  126. local
  127. i: INTEGER
  128. do
  129. make(line_min, line_max, column_min, column_max, depth_min, depth_max)
  130. from
  131. i := 0
  132. until
  133. i >= count
  134. loop
  135. storage.put(contents.item(contents.lower + i), i)
  136. i := i + 1
  137. end
  138. ensure
  139. line_minimum = line_min
  140. line_maximum = line_max
  141. column_minimum = column_min
  142. column_maximum = column_max
  143. depth_minimum = depth_min
  144. depth_maximum = depth_max
  145. count = contents.count
  146. end
  147. from_model (model: COLLECTION[COLLECTION[COLLECTION[E_]]])
  148. -- The `model' is used to fill line by line the COLLECTION3.
  149. -- Assume all sub-collections of have the same indexing.
  150. local
  151. line, column, depth: INTEGER
  152. do
  153. make(model.lower, model.upper, model.first.lower, model.first.upper, model.first.first.lower, model.first.first.upper)
  154. from
  155. line := model.lower
  156. until
  157. line > model.upper
  158. loop
  159. from
  160. column := model.first.lower
  161. until
  162. column > model.first.upper
  163. loop
  164. from
  165. depth := model.first.first.lower
  166. until
  167. depth > model.first.first.upper
  168. loop
  169. put(model.item(line).item(column).item(depth), line, column, depth)
  170. depth := depth + 1
  171. end
  172. column := column + 1
  173. end
  174. line := line + 1
  175. end
  176. ensure then
  177. line_minimum = model.lower
  178. line_maximum = model.upper
  179. column_minimum = model.first.lower
  180. column_maximum = model.first.upper
  181. depth_minimum = model.first.first.lower
  182. depth_maximum = model.first.first.upper
  183. end
  184. feature {ANY} -- Resizing:
  185. resize (line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER)
  186. -- Resize bounds of the Current array
  187. require
  188. line_max >= line_min
  189. column_max >= column_min
  190. depth_max >= depth_min
  191. local
  192. tmp: like Current; l, c, d: INTEGER
  193. do
  194. tmp := standard_twin
  195. tmp.set_limits(line_min, line_max, column_min, column_max, depth_min, depth_max)
  196. -- It may be possible to avoid this creation when :
  197. -- new `capacity' <= old `capacity'
  198. from
  199. l := lower1
  200. until
  201. l > line_maximum
  202. loop
  203. from
  204. c := lower2
  205. until
  206. c > column_maximum
  207. loop
  208. from
  209. d := lower3
  210. until
  211. d > depth_maximum
  212. loop
  213. if tmp.valid_index(l, c, d) then
  214. tmp.put(item(l, c, d), l, c, d)
  215. end
  216. d := d + 1
  217. end
  218. c := c + 1
  219. end
  220. l := l + 1
  221. end
  222. standard_copy(tmp)
  223. ensure
  224. line_minimum = line_min
  225. line_maximum = line_max
  226. column_minimum = column_min
  227. column_maximum = column_max
  228. depth_minimum = depth_min
  229. depth_maximum = depth_max
  230. end
  231. feature {ANY} -- Implementation of others feature from COLLECTION3:
  232. item (line, column, depth: INTEGER): E_
  233. do
  234. Result := storage.item((line - lower1) * count2 * count3 + (column - lower2) * count3 + depth - lower3)
  235. end
  236. put (element: like item; line, column, depth: INTEGER)
  237. do
  238. storage.put(element, (line - lower1) * count2 * count3 + (column - lower2) * count3 + depth - lower3)
  239. end
  240. force (x: like item; line, column, depth: INTEGER)
  241. require else
  242. True
  243. do
  244. if not valid_index(line, column, depth) then
  245. resize(line.min(lower1), line.max(upper1), column.min(lower2), column.max(upper2), depth.min(lower3), depth.max(upper3))
  246. end
  247. put(x, line, column, depth)
  248. end
  249. set_all_with (element: E_)
  250. do
  251. storage.set_all_with(element, count - 1)
  252. end
  253. replace_all (old_value, new_value: like item)
  254. do
  255. storage.replace_all(old_value, new_value, count - 1)
  256. end
  257. fast_replace_all (old_value, new_value: like item)
  258. do
  259. storage.fast_replace_all(old_value, new_value, count - 1)
  260. end
  261. sub_collection3 (line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER): like Current
  262. local
  263. i, j, k, n: INTEGER
  264. do
  265. Result := standard_twin
  266. Result.set_limits(line_min, line_max, column_min, column_max, depth_min, depth_max)
  267. from
  268. i := line_min
  269. k := 0
  270. until
  271. i > line_max
  272. loop
  273. from
  274. j := column_min
  275. until
  276. j > column_max
  277. loop
  278. from
  279. k := depth_min
  280. until
  281. k > depth_max
  282. loop
  283. Result.storage.put(item(i, j, k), n)
  284. n := n + 1
  285. k := k + 1
  286. end
  287. j := j + 1
  288. end
  289. i := i + 1
  290. end
  291. ensure then
  292. Result.lower1 = line_min
  293. Result.lower2 = column_min
  294. Result.lower3 = depth_min
  295. Result.upper1 = line_max
  296. Result.upper2 = column_max
  297. Result.upper3 = depth_max
  298. end
  299. feature {ANY} -- Looking and comparison:
  300. occurrences (elt: E_): INTEGER
  301. do
  302. Result := storage.occurrences(elt, count - 1)
  303. end
  304. fast_occurrences (elt: E_): INTEGER
  305. do
  306. Result := storage.fast_occurrences(elt, count - 1)
  307. end
  308. has (x: like item): BOOLEAN
  309. -- Search if a element x is in the array using `equal'.
  310. -- See also `fast_has' to choose the appropriate one.
  311. do
  312. if count > 0 then
  313. Result := storage.first_index_of(x, count - 1) <= count - 1
  314. end
  315. end
  316. fast_has (x: like item): BOOLEAN
  317. -- Search if a element x is in the array using `='.
  318. do
  319. if count > 0 then
  320. Result := storage.fast_first_index_of(x, count - 1) <= count - 1
  321. end
  322. end
  323. all_default: BOOLEAN
  324. do
  325. Result := storage.all_default(count - 1)
  326. end
  327. swap (line1, column1, depth1, line2, column2, depth2: INTEGER)
  328. local
  329. tmp: like item; index1, index2: INTEGER
  330. do
  331. index1 := (line1 - lower1) * count2 * count3 + (column1 - lower2) * count3 + depth1 - lower3
  332. index2 := (line2 - lower1) * count2 * count3 + (column2 - lower2) * count3 + depth2 - lower3
  333. tmp := storage.item(index1)
  334. storage.put(storage.item(index2), index1)
  335. storage.put(tmp, index2)
  336. end
  337. copy (other: like Current)
  338. do
  339. set_limits(other.lower1, other.upper1, other.lower2, other.upper2, other.lower3, other.upper3)
  340. storage.copy_from(other.storage, count - 1)
  341. end
  342. feature {} -- Garbage collector tuning (very low-level):
  343. mark_native_arrays
  344. -- For performance reasons, the unused area of `storage' is always left as it is when
  345. -- some elements are removed. No time is lost to clean the released area with a Void
  346. -- or a 0 value. Thus, the unused area of `storage' may contains references of
  347. -- actually unreachable objects. The following `mark_native_arrays' actually replace
  348. -- the default behavior (the call is automatic) in order to mark only reachable
  349. -- objects.
  350. local
  351. i: INTEGER
  352. do
  353. from
  354. i := count - 1
  355. until
  356. i < 0
  357. loop
  358. mark_item(storage, i)
  359. i := i - 1
  360. end
  361. end
  362. invariant
  363. count1 = upper1 - lower1 + 1
  364. count2 = upper2 - lower2 + 1
  365. count3 = upper3 - lower3 + 1
  366. capacity >= count
  367. end -- class ARRAY3
  368. --
  369. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  370. --
  371. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  372. -- of this software and associated documentation files (the "Software"), to deal
  373. -- in the Software without restriction, including without limitation the rights
  374. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  375. -- copies of the Software, and to permit persons to whom the Software is
  376. -- furnished to do so, subject to the following conditions:
  377. --
  378. -- The above copyright notice and this permission notice shall be included in
  379. -- all copies or substantial portions of the Software.
  380. --
  381. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  382. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  383. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  384. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  385. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  386. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  387. -- THE SOFTWARE.