PageRenderTime 30ms CodeModel.GetById 19ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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