-----------------------------------------------------------
--                   Eiffel/S examples                   --
-----------------------------------------------------------
--               Copyright (C) 1991 - 1993               --
--                           by                          --
--                   SiG Computer GmbH                   --
--                  All rights reserved                  --
-----------------------------------------------------------
-- Release : 1.3 - October 1993                          --
-----------------------------------------------------------
-- Authors : Lambert Strether & Michael Schweitzer       --
-----------------------------------------------------------

  
  
class   SQUARE_MATRIX [T -> NUMERIC]
                -- Square matrices with coefficients T.
                -- This is only a demo - not a serious implementation.

inherit
    NUMERIC
        redefine
            infix "+", infix "-", infix "*", infix "/",
            valid_divisor, one, zero
    end
-----------------------------------------------------------
creation {ANY}
    make
-----------------------------------------------------------
feature {ANY}
-----------------------------------------------------------

    dimension : INTEGER

-----------------------------------------------------------

    make (dim : INTEGER, init_value : T) is
                -- Make 'dim' x 'dim' matrix. Set all coefficients
                -- to 'init_value'.
        require
            positive_dimension : dim > 0

        local
            i : INTEGER
        do
            dimension := dim
            !!coefficients.make (1, dim * dim)

            from
                i := 1
            until
                i > dim * dim
            loop
                coefficients.put (init_value, i)
                i := i + 1
            end
        end
-----------------------------------------------------------

    put (c : T, i, j : INTEGER) is
                -- Put 'c' at index (i, j)
        require
            valid_index : 1 <= i and then i <= dimension and then
                          1 <= j and then j <= dimension
        do
            coefficients.put (c, (i-1) * dimension + j)
        end
-----------------------------------------------------------

    item (i, j : INTEGER) : T is
                -- Coefficient at index (i, j)
        require
            valid_index : 1 <= i and then i <= dimension and then
                          1 <= j and then j <= dimension
        do
            Result := coefficients.item ((i-1) * dimension + j)
        end
-----------------------------------------------------------

    infix "+" (other : SQUARE_MATRIX [T]) : SQUARE_MATRIX [T] is

        require else
            same_dimension : dimension = other.dimension

        local
            i, j : INTEGER
        do
            Result := zero

            from 
                i := 1
            until
                i > dimension
            loop
                from
                    j := 1
                until
                    j > dimension
                loop
                    Result.put (item (i, j) + other.item (i, j), i, j)
                    j := j + 1
                end
                i := i + 1
            end
        end
-----------------------------------------------------------

    infix "-" (other : SQUARE_MATRIX [T]) : SQUARE_MATRIX [T] is

        require else
            same_dimension : dimension = other.dimension

        local
            i, j : INTEGER
        do
            Result := zero

            from 
                i := 1
            until
                i > dimension
            loop
                from
                    j := 1
                until
                    j > dimension
                loop
                    Result.put (item (i, j) - other.item (i, j), i, j)
                    j := j + 1
                end
                i := i + 1
            end
        end
-----------------------------------------------------------

    infix "*" (other : SQUARE_MATRIX [T]) : SQUARE_MATRIX [T] is

        require else
            same_dimension : dimension = other.dimension

        local
            i, j, k : INTEGER
            sum, z  : T
        do
            Result := zero
            z      := Result.item (1, 1)

            from
                i := 1
            until
                i > dimension
            loop
                from
                    j := 1
                until
                    j > dimension
                loop
                    from
                        k   := 1
                        sum := z
                    until
                        k > dimension
                    loop
                        sum := sum + item (i, k) * other.item (k, j)
                        k   := k + 1
                    end
                    Result.put (sum, i, j)
                    j := j + 1
                end
                i := i + 1
            end
        end
-----------------------------------------------------------

    infix "/" (other : SQUARE_MATRIX [T]) : SQUARE_MATRIX [T] is

        require else
            same_dimension : dimension = other.dimension

        do
            -- Not implemented. 
        end
-----------------------------------------------------------

    valid_divisor (other : SQUARE_MATRIX [T]) : BOOLEAN is

        do
            -- Not implemented. 
        end
-----------------------------------------------------------

    zero : SQUARE_MATRIX [T] is

        local
            z : T
        do
            z := coefficients.item (1).zero

            !!Result.make (dimension, z)
        end
-----------------------------------------------------------

    one : SQUARE_MATRIX [T] is

        local
            z : T
            o : T
            i : INTEGER
        do
            z := coefficients.item (1).zero
            o := coefficients.item (1).one

            !!Result.make (dimension, z)

            from
                i := 1
            until
                i > dimension
            loop
                Result.put (o, i, i)
                i := i + 1
            end
        end
-----------------------------------------------------------
feature {SQUARE_MATRIX}
-----------------------------------------------------------

    coefficients : ARRAY [T]

-----------------------------------------------------------

end -- class SQUARE_MATRIX

