comp.lang.ada
 help / color / mirror / Atom feed
From: "Hibou57 (Yannick Duchêne)" <yannick_duchene@yahoo.fr>
Subject: Re: Copying rows in a two dimensional array.
Date: Thu, 4 Feb 2010 01:23:36 -0800 (PST)
Date: 2010-02-04T01:23:36-08:00	[thread overview]
Message-ID: <4cd50297-178c-4172-a2f7-3793675b26ec@h2g2000yqj.googlegroups.com> (raw)
In-Reply-To: 1fmfi9p68s4an$.1q50he325y45g.dlg@40tude.net

On 4 fév, 10:10, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> This does not work either, I mean at the user interface level, because
> slice does not have a type. In Ada types system you cannot express "the
> subtype S is a vector of the type M". Therefore making it abstract types
> you will loose most of the comfort built-in arrays offer.
I've was to post him some seed of a package (not tested, I sincerely
apologize for that) :

package Matrix is
   -- Provides a matrix type with an efficient implementation
   -- of a row swapping method. A similar method as the one
   -- provided here, may be used to get a matrix type with an
   -- efficient implementation of column swapping method.
   -- This package most likely need to be extended in order
   -- to be fully useful to something in real life.

   subtype Float_Type is Float;

   subtype One_Dimensional_Size_Type is Natural range 1 .. 2 ** 15;
   -- Either a number of rows or a number of columns.
   -- The maximum size is so that One_Dimensional_Size_Type ** 2 is
   -- most unlikely to commit an overflow and will mostly be a valid
   -- value on most of target machines.

   First_Index : constant := 1;
   -- This may be changed to zero if needed, whenever the
   -- C indexing convention is preferred. This may not be
   -- changed to a value greater than one, otherwise
   -- Index_Type may potentially go out of Natural range.

   subtype Index_Type is Natural
      range
        (First_Index) ..
        (First_Index + (One_Dimensional_Size_Type'Last - 1));

   type Instance_Type (<>) is private;
   -- The type must be initialized at declaration :
   -- use New_Instance in that purpose (see below).

   -- The methods First_Row, Last_Row, First_Column,
   -- Last_Column and Item, are at least required to
   -- define pre- and post- condition of the New_Instance
   -- and Swap_Rows method.

   function First_Row
     (Instance : Instance_Type)
      return Index_Type;
   --|Ensures: Result = First_Index

   function Last_Row
     (Instance : Instance_Type)
      return Index_Type;

   function First_Column
     (Instance : Instance_Type)
      return Index_Type;
   --|Ensures: Result = First_Index

   function Last_Column
     (Instance : Instance_Type)
      return Index_Type;

   function Item
     (Instance : Instance_Type;
      Row      : Index_Type;
      Column   : Index_Type)
      return Float_Type;
   --|Requires: Row in First_Row (Instance) .. Last_Row (Instance);
   --|Requires:
   --|   Column in First_Column (Instance) ..
   --|   Last_Column (Instance);

   function New_Instance
      (Number_Of_Rows    : One_Dimensional_Size_Type;
       Number_Of_Columns : One_Dimensional_Size_Type)
       return Instance_Type;
   --|Ensures:
   --|   Last_Row (Instance) =
   --|   First_Index + Number_Of_Rows - 1;
   --|Ensures:
   --|   Last_Column (Instance) =
   --|   First_Index + Number_Of_Column - 1;
   --|Ensures:
   --|   for each Row in First_Row (Instance) .. Last_Row (Instance)
   --|   => for each Column in First_Column (Instance) ..
   --|   Last_Column (Instance) => Item (Row, Column) = 0.0;
   -- Note : all items are zero initialized.

   procedure Swap_Rows
      (Instance : in out Instance_Type;
       Row_1    : in Index_Type;
       Row_2    : in Index_Type);
   --|Requires: Row_1 in First_Row (Instance) .. Last_Row (Instance);
   --|Requires: Row_2 in First_Row (Instance) .. Last_Row (Instance);
   --|Ensures:
   --|   for each Column in First_Column (Instance) ..
   --|   Last_Column (Instance) => (Item (Instance, Row_1, Column) =
   --|   old Item (Instance, Row_2, Column));
   --|Ensures:
   --|   for each Column in First_Column (Instance) ..
   --|   Last_Column (Instance) => (Item (Instance, Row_2, Column) =
   --|   old Item (Instance, Row_1, Column));
   -- Note: Row_1 and Row_2 may be equal.

   --
===================================================================
   -- *** DO NOT CROSS *** DO NOT CROSS *** DO NOT CROSS *** DO NOT
CROSS
   --
-------------------------------------------------------------------

private

   pragma Assert
     ((First_Index + (One_Dimensional_Size_Type'Last ** 2)) <=
      (Natural'Last));
   -- Ensure computation on indexes will never go out of range.

   pragma Inline (First_Row);
   pragma Inline (Last_Row);
   pragma Inline (First_Column);
   pragma Inline (Last_Column);

   type Storage_Type is array (Natural range <>) of Float_Type;
   -- Flatenned array rows first columns next.
   -- Ex. (Row-1,Col-1),(Row-2,Col-1),(Row-1,Col-2),(Row-2,Col-2)
   --
   -- This way of flatening the matrix is the one which gives
   -- better performance to swap rows, as all items of a row
   -- appears to be consecutive, allowing slice access.
   --
   -- If good performance at swaping columns is targeting instead,
   -- then use the reverse representation (that is, like the
   -- Fortran convention), and update implementation of methods
   -- accordingly.
   --
   -- Note: the index type musn't be Index_Type,
   -- which is an index in one dimension, not in the overall storage.

   type Instance_Type
      (Number_Of_Rows    : One_Dimensional_Size_Type;
       Number_Of_Columns : One_Dimensional_Size_Type;
       Last_Data_Index   : Natural)
   is record
      Data : Storage_Type (First_Index .. Last_Data_Index);
   end record;

end Matrix;

package body Matrix is

   function First_Row
     (Instance : Instance_Type)
      return Index_Type
   is
   begin
      return First_Index;
   end First_Row;

   function Last_Row
     (Instance : Instance_Type)
      return Index_Type
   is
   begin
      return First_Index + (Instance.Number_Of_Rows - 1);
   end Last_Row;

   function First_Column
     (Instance : Instance_Type)
      return Index_Type
   is
   begin
      return First_Index;
   end First_Column;

   function Last_Column
     (Instance : Instance_Type)
      return Index_Type
   is
   begin
      return First_Index + (Instance.Number_Of_Columns - 1);
   end Last_Column;

   function Start_Of_Row
      (Instance : Instance_Type;
       Row     : Index_Type)
       return Natural
   -- Index in Data for the first item of the row
   -- whose index is Row. Used for accessing a matrix items
   -- and for row slice accesses.
   is
      Rows_Size : constant Natural := Instance.Number_Of_Columns;
   begin
      return First_Index +  (Rows_Size * (Row - First_Index));
   end Start_Of_Row;

   pragma Inline (Start_Of_Row);

   function End_Of_Row
      (Instance : Instance_Type;
       Row     : Index_Type)
       return Natural
   -- Index in Data for the last item of the row
   -- whose index is Row. Used for row slice accesses.
   is
      Rows_Size : constant Natural := Instance.Number_Of_Columns;
   begin
      return Start_Of_Row (Instance, Row) +  (Rows_Size - 1);
      -- This is an upper bound, not a limit, so
      -- Rows_Size - 1 is used. We add an offset starting
      -- the fist index of the row.
   end End_Of_Row;

   pragma Inline (End_Of_Row);

   function Item
     (Instance : Instance_Type;
      Row      : Index_Type;
      Column   : Index_Type)
      return Float_Type
   is
   begin
      Validity_Constraints :
      begin
         if Row not in First_Index .. Last_Row (Instance) then
            raise Program_Error;
         end if;
         if Column not in First_Index .. Last_Column (Instance) then
            raise Program_Error;
         end if;
      end Validity_Constraints;

      Method:
      declare
         Row_Start : constant Natural := Start_Of_Row (Instance, Row);
         Column_Offset : constant Natural := Column - First_Index;
         Data_Index : constant Natural := Row_Start + Column_Offset;
      begin
         return Instance.Data (Data_Index);
      end Method;
   end Item; -- Procedure

   function New_Instance
      (Number_Of_Rows    : One_Dimensional_Size_Type;
       Number_Of_Columns : One_Dimensional_Size_Type)
       return Instance_Type
   is
      Data_Size : constant Natural :=
        (Number_Of_Rows * Number_Of_Columns);

      Last_Data_Index : constant Natural :=
        (First_Index + (Data_Size - 1));
   begin
      return
        (Number_Of_Rows    => Number_Of_Rows,
         Number_Of_Columns => Number_Of_Columns,
         Last_Data_Index   => Last_Data_Index,
         Data              => (others => 0.0));
   end New_Instance; -- Function

   procedure Swap_Rows
      (Instance : in out Instance_Type;
       Row_1    : in Index_Type;
       Row_2    : in Index_Type)
   is
   begin
      Validity_Constraints :
      begin
         if Row_1 not in First_Index .. Last_Row (Instance) then
            raise Program_Error;
         end if;
         if Row_2 not in First_Index .. Last_Row (Instance) then
            raise Program_Error;
         end if;
      end Validity_Constraints;

      Special_Cases :
      begin
         if Row_1 = Row_2 then
            return;
         end if;
      end Special_Cases;

      Method :
      declare
         -- See comments in the package's private part.

         Rows_Size : constant Natural :=
           (Instance.Number_Of_Columns);

         Slice_Start_Of_Row_1 : constant Natural :=
            Start_Of_Row (Instance, Row_1);

         Slice_End_Of_Row_1 : constant Natural :=
            End_Of_Row (Instance, Row_1);

         Slice_Start_Of_Row_2 : constant Natural :=
            Start_Of_Row (Instance, Row_1);

         Slice_End_Of_Row_2 : constant Natural :=
            End_Of_Row (Instance, Row_2);

         Row_1_Slice : constant Storage_Type
         -- Backup of Row-1
           (Slice_Start_Of_Row_1 .. Slice_End_Of_Row_1) :=
               Instance.Data
                 (Slice_Start_Of_Row_1 ..
                  Slice_End_Of_Row_1);
      begin
         -- Copy Row-2 at the place of Row-1 (Row-1 was
         -- backed up).
         Instance.Data
           (Slice_Start_Of_Row_1 ..
            Slice_End_Of_Row_1)
            :=
               Instance.Data
                 (Slice_Start_Of_Row_2 ..
                  Slice_End_Of_Row_2);

         -- Copy backup of Row-1 at the place of
         -- Row-2.
         Instance.Data
           (Slice_Start_Of_Row_2 ..
            Slice_End_Of_Row_2)
            :=
               Row_1_Slice;
      end Method;

   end Swap_Rows; -- Procedure

end Matrix; -- Package



      reply	other threads:[~2010-02-04  9:23 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-01  2:11 Copying rows in a two dimensional array Peter C. Chapin
2010-02-01  4:42 ` Jeffrey R. Carter
2010-02-01  6:55 ` Niklas Holsti
2010-02-01 23:36   ` Peter C. Chapin
2010-02-04  4:27   ` Hibou57 (Yannick Duchêne)
2010-02-01  8:37 ` Dmitry A. Kazakov
2010-02-02  0:11   ` Randy Brukardt
2010-02-07 16:13     ` Robert A Duff
2010-02-08  6:30       ` tmoran
2010-02-08 13:15         ` Robert A Duff
2010-02-08 13:45           ` Dmitry A. Kazakov
2010-02-08 21:20             ` Robert A Duff
2010-02-08 23:26               ` (see below)
2010-02-09  0:36                 ` Randy Brukardt
2010-02-09  1:03                   ` (see below)
2010-02-09  7:11                   ` Pascal Obry
2010-02-09  8:14                     ` AdaMagica
2010-02-09 14:33                 ` Robert A Duff
2010-02-09  1:05               ` Adam Beneschan
2010-02-09 14:45                 ` Robert A Duff
2010-02-09 18:50                   ` tmoran
2010-02-09 19:51                   ` Pascal Obry
2010-02-09 23:03                     ` Robert A Duff
2010-02-08 18:53           ` tmoran
2010-02-08 21:14             ` Robert A Duff
2010-02-08 21:29               ` Pascal Obry
2010-02-09  8:56                 ` Jean-Pierre Rosen
2010-02-09  9:14                   ` AdaMagica
2010-02-09 11:19                     ` Jean-Pierre Rosen
2010-02-09 14:26                 ` Robert A Duff
2010-02-09  6:34               ` tmoran
2010-02-09 14:29                 ` Robert A Duff
2010-02-09 18:49                   ` tmoran
2010-02-09 22:58                     ` Robert A Duff
2010-02-01 22:10 ` Jerry
2010-02-02  0:07   ` Randy Brukardt
2010-02-02  8:52   ` Jean-Pierre Rosen
2010-02-02 22:23     ` Jerry
2010-02-03  1:24       ` Adam Beneschan
2010-02-04  4:42     ` Hibou57 (Yannick Duchêne)
2010-02-14  0:42     ` jonathan
2010-02-14  1:54       ` Hibou57 (Yannick Duchêne)
2010-02-14 16:16         ` jonathan
2010-03-22  8:56           ` Ole-Hjalmar Kristensen
2010-02-16  6:51     ` David Thompson
2010-02-04  4:13 ` Hibou57 (Yannick Duchêne)
2010-02-04  9:10   ` Dmitry A. Kazakov
2010-02-04  9:23     ` Hibou57 (Yannick Duchêne) [this message]
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox