PageRenderTime 20ms CodeModel.GetById 10ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 1ms

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