summaryrefslogtreecommitdiff
path: root/scipy/base/matrix.py
diff options
context:
space:
mode:
Diffstat (limited to 'scipy/base/matrix.py')
-rw-r--r--scipy/base/matrix.py202
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")
+
+
+
+