ANY FAST_ARRAY3 NONE
class interface FAST_ARRAY3[E]
   --
   -- Resizable three dimensional array.
   -- Unlike ARRAY3, the lower1, lower2 and lower3 bounds are
   -- frozen to 0. Thus, one can expect better performances.
   --

creation
   make (new_count1, new_count2, new_count3: INTEGER)
      -- Create or reset Current with new dimensions.
      -- All elements are set to the default value of type E.
      require
         new_count1 > 0;
         new_count2 > 0;
         new_count3 > 0
      ensure
         count1 = new_count1;
         count2 = new_count2;
         count3 = new_count3;
         all_default

   copy (other: like Current)
      require
         same_dynamic_type(other)
      ensure
         is_equal(other)

   from_collection3 (model: COLLECTION3[E])
      -- Uses the model to update Current.
      require
         model /= Void
      ensure
         count1 = model.count1;
         count2 = model.count2;
         count3 = model.count3

   from_collection (contents: COLLECTION[E]; new_count1, new_count2, new_count3: INTEGER)
      --  Reset all bounds using new_count#i.
      --  Copy all elements of contents, line by line into Current.
      require
         new_count1 >= 0;
         new_count2 >= 0;
         new_count3 >= 0;
         contents.count = new_count1 * new_count2 * new_count3
      ensure
         line_maximum = new_count1 - 1;
         column_maximum = new_count2 - 1;
         depth_maximum = new_count3 - 1;
         count = contents.count

   from_model (model: COLLECTION[COLLECTION[COLLECTION[E]]])
      -- The model is used to fill line by line the COLLECTION3.
      -- Assume all sub-collections of have the same indexing.
      require
         model /= Void
      ensure
         line_maximum = model.upper - model.lower;
         column_maximum = model.first.upper - model.first.lower;
         depth_maximum = model.first.first.upper - model.first.first.lower;
         count1 = model.count;
         count2 > 0 implies count2 = model.first.count;
         count3 > 0 implies count3 = model.first.first.count

feature(s) from SAFE_EQUAL
   test (e1, e2: E): BOOLEAN
      -- In order to avoid run-time type errors, feature safe_equal calls
      -- is_equal only when e1 and e2 have exactly the same dynamic
      -- type. Furthermore, this feature avoids argument passing from some
      -- expanded type to the corresponding reference type (no automatic
      -- allocation of some reference type during the comparison).

   safe_equal (e1, e2: E): BOOLEAN
      -- In order to avoid run-time type errors, feature safe_equal calls
      -- is_equal only when e1 and e2 have exactly the same dynamic
      -- type. Furthermore, this feature avoids argument passing from some
      -- expanded type to the corresponding reference type (no automatic
      -- allocation of some reference type during the comparison).

feature(s) from COLLECTION3
   -- Indexing:

   lower1: INTEGER
      -- Lower index bound for dimension 1.

   lower2: INTEGER
      -- Lower index bound for dimension 2.

   lower3: INTEGER
      -- Lower index bound for dimension 3.

   line_minimum: INTEGER
      -- Equivalent of lower1.

   column_minimum: INTEGER
      -- Equivalent of lower2.

   depth_minimum: INTEGER
      -- Equivalent of lower3.

   upper1: INTEGER
      -- Upper index bound for dimension 1.

   upper2: INTEGER
      -- Upper index bound for dimension 2.

   upper3: INTEGER
      -- Upper index bound for dimension 3.

   line_maximum: INTEGER
      -- Equivalent of upper1.

   column_maximum: INTEGER
      -- Equivalent of upper2.

   depth_maximum: INTEGER
      -- Equivalent of upper3.

feature(s) from COLLECTION3
   -- Reading:

   item (line, column, depth: INTEGER): E
      require
         valid_index(line,column,depth)

feature(s) from COLLECTION3
   -- Writing:

   put (x: E; line, column, depth: INTEGER)
      require
         valid_index(line,column,depth)
      ensure
         item(line,column,depth) = x

   force (element: E; line, column, depth: INTEGER)
      -- Put element at position (line,column,depth).
      -- Collection is resized first when (line,column,depth)
      -- is not inside current bounds.
      -- New bounds are initialized with default values.
      require
         line >= 0;
         column >= 0;
         depth >= 0
      ensure
         item(line,column,depth) = element;
         count >= old count

feature(s) from COLLECTION3
   -- Index validity:

   valid_line (line: INTEGER): BOOLEAN
      ensure
         Result = (lower1 <= line and line <= upper1)

   valid_index1 (line: INTEGER): BOOLEAN
      ensure
         Result = (lower1 <= line and line <= upper1)

   valid_column (column: INTEGER): BOOLEAN
      ensure
         Result = (lower2 <= column and column <= upper2)

   valid_index2 (column: INTEGER): BOOLEAN
      ensure
         Result = (lower2 <= column and column <= upper2)

   valid_depth (depth: INTEGER): BOOLEAN
      ensure
         Result = (lower3 <= depth and depth <= upper3)

   valid_index3 (depth: INTEGER): BOOLEAN
      ensure
         Result = (lower3 <= depth and depth <= upper3)

   valid_index (line, column, depth: INTEGER): BOOLEAN
      ensure
         Result = (valid_line(line) and valid_column(column) and valid_depth(depth))

feature(s) from COLLECTION3
   -- Counting:

   count1: INTEGER
      -- Size of the first dimension.
      ensure
         Result = upper1 - lower1 + 1

   line_count: INTEGER
      -- Equivalent of count1.

   count2: INTEGER
      -- Size of the second dimension.
      ensure
         Result = upper2 - lower2 + 1

   column_count: INTEGER

   count3: INTEGER
      -- Size of the third dimension.
      ensure
         Result = upper3 - lower3 + 1

   depth_count: INTEGER

   count: INTEGER
      -- Total number of elements.
      ensure
         Result = line_count * column_count * depth_count

feature(s) from COLLECTION3
   swap (line1, column1, depth1, line2, column2, depth2: INTEGER)
      -- Swap the element at index (line1,column1,depth1)
      -- with the element at index (line2,column2,depth2).
      require
         valid_index(line1,column1,depth1);
         valid_index(line2,column2,depth2)
      ensure
         item(line1,column1,depth1) = old item(line2,column2,depth2);
         item(line2,column2,depth2) = old item(line1,column1,depth1);
         count = old count

   set_all_with (x: E)
      --  All element are set with the value x.
      ensure
         count = old count

   clear_all
      -- Set all items to default values.
      ensure
         count = old count;
         all_default

feature(s) from COLLECTION3
   -- Creating or initializing:

   from_collection3 (model: COLLECTION3[E])
      -- Uses the model to update Current.
      require
         model /= Void
      ensure
         count1 = model.count1;
         count2 = model.count2;
         count3 = model.count3

   from_model (model: COLLECTION[COLLECTION[COLLECTION[E]]])
      -- The model is used to fill line by line the COLLECTION3.
      -- Assume all sub-collections of have the same indexing.
      require
         model /= Void
      ensure
         line_maximum = model.upper - model.lower;
         column_maximum = model.first.upper - model.first.lower;
         depth_maximum = model.first.first.upper - model.first.first.lower;
         count1 = model.count;
         count2 > 0 implies count2 = model.first.count;
         count3 > 0 implies count3 = model.first.first.count

feature(s) from COLLECTION3
   -- Looking and comparison:

   all_default: BOOLEAN
      -- Do all items have their type's default value?

   is_equal (other: COLLECTION3[E]): BOOLEAN
      -- Do both collections have the same lower1, lower2, lower3, upper1, upper2 and
      -- upper3, and items?
      -- The basic = is used for comparison of items.
      -- See also is_equal_map.
      require
         other /= Void
      ensure
         generating_type = other.generating_type implies Result = other.is_equal(Current)

   is_equal_map (other: COLLECTION3[E]): BOOLEAN
      -- Do both collections have the same lower1, lower2, lower3, upper1, upper2 and upper3,
      -- and items?
      -- Feature is_equal is used for comparison of items.
      -- See also is_equal.

feature(s) from COLLECTION3
   -- Printing:

   fill_tagged_out_memory
      -- Append a viewable information in tagged_out_memory in
      -- order to affect the behavior of out, tagged_out, etc.

feature(s) from COLLECTION3
   -- Miscellaneous features:

   occurrences (elt: E): INTEGER
      -- Number of occurrences using equal.
      -- See also fast_occurrences to choose the apropriate one.
      ensure
         Result >= 0

   fast_occurrences (elt: E): INTEGER
      -- Number of occurrences using =.
      -- See also occurrences to choose the apropriate one.
      ensure
         Result >= 0

   has (x: E): BOOLEAN
      -- Look for x using equal for comparison.

   fast_has (x: E): BOOLEAN
      -- Same as has but use = for comparison

   replace_all (old_value, new_value: E)
      -- Replace all occurrences of the element old_value by new_value
      -- using equal for comparison.
      -- See also fast_replace_all to choose the apropriate one.
      ensure
         count = old count;
         occurrences(old_value) = 0

   fast_replace_all (old_value, new_value: E)
      -- Replace all occurrences of the element old_value by new_value
      -- using operator = for comparison.
      -- See also replace_all to choose the apropriate one.
      ensure
         count = old count;
         fast_occurrences(old_value) = 0

   sub_collection3 (line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER): like Current
      -- Create a new object using selected area of Current.
      require
         valid_index(line_min,column_min,depth_min);
         valid_index(line_max,column_max,depth_max)
      ensure
         Result.upper1 = line_max - line_min;
         Result.upper2 = column_max - column_min;
         Result.upper3 = depth_max - depth_min;
         Result /= Void

   set_area (element: E; line_min, line_max, column_min, column_max, depth_min, depth_max: INTEGER)
      -- Set all the elements of the selected area rectangle with element.
      require
         valid_index(line_min,column_min,depth_min);
         valid_index(line_max,column_max,depth_max)
      ensure
         count = old count

feature(s) from FAST_ARRAY3
   count2x3: INTEGER
      -- To speed up access, this value is always equal to
      -- count2 * count3

feature(s) from FAST_ARRAY3
   storage: NATIVE_ARRAY[E]

   capacity: INTEGER
      -- of storage.

feature(s) from FAST_ARRAY3
   make (new_count1, new_count2, new_count3: INTEGER)
      -- Create or reset Current with new dimensions.
      -- All elements are set to the default value of type E.
      require
         new_count1 > 0;
         new_count2 > 0;
         new_count3 > 0
      ensure
         count1 = new_count1;
         count2 = new_count2;
         count3 = new_count3;
         all_default

   from_collection (contents: COLLECTION[E]; new_count1, new_count2, new_count3: INTEGER)
      --  Reset all bounds using new_count#i.
      --  Copy all elements of contents, line by line into Current.
      require
         new_count1 >= 0;
         new_count2 >= 0;
         new_count3 >= 0;
         contents.count = new_count1 * new_count2 * new_count3
      ensure
         line_maximum = new_count1 - 1;
         column_maximum = new_count2 - 1;
         depth_maximum = new_count3 - 1;
         count = contents.count

feature(s) from FAST_ARRAY3
   -- Implementation of others feature from COLLECTION3:

   copy (other: like Current)
      require
         same_dynamic_type(other)
      ensure
         is_equal(other)

feature(s) from FAST_ARRAY3
   -- Writing:

   slice (l1, up1, l2, up2, l3, up3: INTEGER): like Current
      -- Create a new collection initialized with elements of
      -- range low..up. Result has the same dynamic type
      -- as Current collection.

   set_slice (element: E; l1, up1, l2, up2, l3, up3: INTEGER)
      -- Set all the elements in the
      -- range [(l1,up1),(l2,up2),(l3,up3)] of
      -- Current with the element 'element'.

feature(s) from FAST_ARRAY3
   -- Resizing:

   resize (new_count1, new_count2, new_count3: INTEGER)
      require
         new_count1 > 0;
         new_count2 > 0;
         new_count3 > 0
      ensure
         upper1 = new_count1 - 1;
         count1 = new_count1;
         upper2 = new_count2 - 1;
         count2 = new_count2;
         upper3 = new_count3 - 1;
         count3 = new_count3;
         count = new_count1 * new_count2 * new_count3


invariant

    count1 = upper1 + 1;

    count2 = upper2 + 1;

    count3 = upper3 + 1;

    count = count1 * count2 * count3;

    count2x3 = count2 * count3;

    capacity >= count;

end of FAST_ARRAY3[E]