/src/lib/storage/collection3/fast_array3.e

http://github.com/tybor/Liberty · Specman e · 456 lines · 368 code · 34 blank · 54 comment · 6 complexity · 538a3468f35ee2d37080ae1fc203677a MD5 · raw file

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