"""mems.instrument.client.tk.matrix.py

3x3 matrix arithmetic for computing 2D transformations, used by the
CIF layout rendering.
"""

__revision__ = "$Id: matrix.py,v 1.5 2002/02/19 23:20:38 akuchlin Exp $"

class Matrix3x3:
    """Class for 3x3 matrix operations.
    """

    def __init__ (self, initial = None):
        """Create matrix; if provided, 'initial' must be a list containing
        3 three-element lists."""
        
        if initial is None:
            initial = [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0] ]

        # Sanity-check the initial value
        if len(initial) != 3:
            raise ValueError, ('Initial value must contain only 3 rows: %r'
                               % initial)
        for row in initial:
            if len(row) != 3:
                raise ValueError, ('Row of initial values '
                                   'must contain only 3 values: %r'
                                   % initial)

        self.value = initial
        
    def __mul__ (self, other):
        if isinstance(other, Matrix3x3):
            # Perform 3x3 matrix multiplication
            result = Matrix3x3()
            for i in range(3):
                for j in range(3):
                    for k in range(3):
                        result.value[i][j] = (
                            self.value[i][0] * other.value[0][j] + 
                            self.value[i][1] * other.value[1][j] + 
                            self.value[i][2] * other.value[2][j])
            return result

        # Assume 'other' is a 3-element list representing a point,
        # and multiply it
        elif type(other) == type([]) and len(other) == 3:
            result = [0.0, 0.0, 0.0]
            for i in range(3):
                row = self.value[i]
                result[i] = (row[0] * other[0] +
                             row[1] * other[1] +
                             row[2] * other[2])
            return result
        else:
            raise ValueError, "Can't multiply matrix by " + repr(other)
        
    def __rmul__ (self, other):
        if type(other) == type([]) and len(other) == 3:
            result = [0.0, 0.0, 0.0]
            for i in range(3):
                result[i] = (other[0] * self.value[0][i] +
                             other[1] * self.value[1][i] +
                             other[2] * self.value[2][i] 
                            )
            return result
        else:
            raise ValueError, "Can't multiply matrix by " + repr(other)

    def __repr__ (self):
        s = "<Matrix:%s\n\t%s\n\t%s >" % (self.value[0], self.value[1],
                                            self.value[2])
        return s
    
    __str__ = __repr__
    
if __name__ == '__main__':
    I = Matrix3x3()
    cross = Matrix3x3([[1, 2, 3], [4,5,6], [7,8,9]])
    print I
    print I*I
    print cross * I
    print cross * cross
    
    
