diff options
Diffstat (limited to 'scipy/base/matrix.py')
-rw-r--r-- | scipy/base/matrix.py | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/scipy/base/matrix.py b/scipy/base/matrix.py new file mode 100644 index 000000000..5c2ecf94e --- /dev/null +++ b/scipy/base/matrix.py @@ -0,0 +1,202 @@ + +import numeric as N +import types +import string as str_ + +# make translation table +_table = [None]*256 +for k in range(256): + _table[k] = chr(k) +_table = ''.join(_table) + +_numchars = str_.digits + ".-+jeEL" +del str_ +_todelete = [] +for k in _table: + if k not in _numchars: + _todelete.append(k) +_todelete = ''.join(_todelete) + +def _eval(astr): + return eval(astr.translate(_table,_todelete)) + +def _convert_from_string(data): + rows = data.split(';') + newdata = [] + count = 0 + for row in rows: + trow = row.split(',') + newrow = [] + for col in trow: + temp = col.split() + newrow.extend(map(_eval,temp)) + if count == 0: + Ncols = len(newrow) + elif len(newrow) != Ncols: + raise ValueError, "Rows not the same size." + count += 1 + newdata.append(newrow) + return newdata + +_lkup = {'0':'000', + '1':'001', + '2':'010', + '3':'011', + '4':'100', + '5':'101', + '6':'110', + '7':'111'} + +def _binary(num): + ostr = oct(num) + bin = '' + for ch in ostr[1:]: + bin += _lkup[ch] + ind = 0 + while bin[ind] == '0': + ind += 1 + return bin[ind:] + + +class matrix(N.ndarray): + __array_priority__ = 1.0 + def __new__(self, data, dtype=None, copy=0): + if isinstance(data, matrix): + dtype2 = data.type + if (dtype is None): + dtype = dtype2 + if (dtype2 is dtype) and (not copy): + return data + return data.astype(dtype) + + if dtype is None: + dtype = N.intp + intype = N.totype(dtype) + + if isinstance(data, types.StringType): + data = _convert_from_string(data) + + # now convert data to an array + arr = N.array(data, dtype=intype, copy=copy) + ndim = arr.ndim + shape = arr.shape + if (ndim > 2): + raise ValueError, "matrix must be 2-dimensional" + elif ndim == 0: + shape = (1,1) + elif ndim == 1: + shape = (1,shape[0]) + + fortran = False; + if (ndim == 2) and arr.flags['FORTRAN']: + fortran = True + + if not (fortran or arr.flags['CONTIGUOUS']): + arr = arr.copy() + + ret = N.ndarray.__new__(matrix, shape, intype, buffer=arr, fortran=fortran, + swapped=(not arr.flags['NOTSWAPPED'])) + return ret; + + def __array_wrap__(self, obj): + try: + ret = matrix(obj,typecode=obj.type) + except: + ret = obj + return ret + + def _update_meta(self, obj): + ndim = self.ndim + if ndim == 0: + self.shape = (1,1) + elif ndim == 1: + self.shape = (1, self.shape[0]) + return + + def __getitem__(self, index): + out = N.ndarray.__getitem__(self, index) + # Need to swap if slice is on first index + try: + n = len(index) + if (n > 1) and isinstance(index[0], types.SliceType) \ + and (isinstance(index[1], types.IntType) or + isinstance(index[1], types.LongType)): + sh = out.shape + out.shape = (sh[1], sh[0]) + except TypeError: + pass + return out + + def __mul__(self, other): + return N.dot(self, other) + + def __rmul__(self, other): + return N.dot(other, self) + + def __pow__(self, other): + if len(shape)!=2 or shape[0]!=shape[1]: + raise TypeError, "matrix is not square" + if type(other) in (type(1), type(1L)): + if other==0: + return matrix(N.identity(shape[0])) + if other<0: + x = self.I + other=-other + else: + x=self + result = x + if other <= 3: + while(other>1): + result=result*x + other=other-1 + return result + # binary decomposition to reduce the number of Matrix + # Multiplies for other > 3. + beta = _binary(other) + t = len(beta) + Z,q = x.copy(),0 + while beta[t-q-1] == '0': + Z *= Z + q += 1 + result = Z.copy() + for k in range(q+1,t): + Z *= Z + if beta[t-k-1] == '1': + result *= Z + return result + else: + raise TypeError, "exponent must be an integer" + + def __rpow__(self, other): + raise NotImplementedError + + def getA(self): + arr = self + fortran = False; + if (self.ndim == 2) and arr.flags['FORTRAN']: + fortran = True + + if not (fortran or arr.flags['CONTIGUOUS']): + arr = arr.copy() + + return N.ndarray.__new__(N.ndarray, self.shape, self.type, buffer=arr, + fortran=fortran, + swapped=(not arr.flags['NOTSWAPPED'])) + + def getT(self): + return N.transpose(self) + + def getH(self): + return N.conjugate(N.transpose(self)) + + # inverse doesn't work yet.... + def getI(self): + return self + + A = property(getA, None, doc="Get base array") + T = property(getT, None, doc="transpose") + H = property(getH, None, doc="hermitian (conjugate) transpose") + + + + |