35 """Vectors and Matrices"""
40 from amino.mixin import VecMixin, SSDEqMixin, DivCompatMixin, MatMixin
41 from amino.util import ensure, is_int, is_scalar
45 CBLAS_CONJ_TRANS = 113
48 class DVec(ctypes.Structure, VecMixin):
49 """Vector of double floats."""
50 _fields_ = [(
"_size", ctypes.c_size_t),
51 (
"_data", ctypes.POINTER(ctypes.c_double)),
52 (
"_inc", ctypes.c_size_t)]
56 return (ctypes.c_double * size)()
59 """Constructs a vector.
61 If arg is None -- Create an unitialized DVec
62 If arg is a list -- Fill the DVec with list contents
63 If arg is an int -- Create a DVec of that size
66 super(DVec, self).
__init__(0,
None, 0)
68 super(DVec, self).
__init__(arg, DVec._alloc(arg), 1)
71 super(DVec, self).
__init__(s, DVec._alloc(s), 1)
76 """If thing is not a DVec, construct a DVec containging thing.
79 thing if already a DVec, other a newly-constructed DVec.
84 """Copies the contents of thing into self"""
88 elif isinstance(src, DVec):
89 libamino.aa_dvec_copy(src, self)
95 """Copies self to thing."""
99 elif isinstance(dst, DVec):
100 libamino.aa_dvec_copy(self, dst)
105 def axpy(self, alpha, x):
106 """self = alpha*x, where alpha is a scalar and x is a DVec"""
107 libamino.aa_dvec_axpy(alpha, x, self)
111 """Fills self with zeros"""
112 libamino.aa_dvec_zero(self)
115 def set(self, alpha):
116 """Sets all elements of self to scalar alpha"""
117 libamino.aa_dvec_set(self, alpha)
121 """self = self + alpha, for scalar alpha"""
122 libamino.aa_dvec_inc(alpha, self)
125 def gemv(self, trans, alpha, A, x, beta):
126 """General matrix-vector multiply.
128 self = alpha*A*x + beta*self
135 if A.rows != len(self):
139 libamino.aa_dmat_gemv(trans, alpha, A, x, beta, self)
142 def ssd(self, other):
143 """Sum of square differences"""
144 return libamino.aa_dvec_ssd(self, DVec.ensure(other))
147 """Euclidean norm of self"""
148 return libamino.aa_dvec_nrm2(self)
151 """Returns an item or slice of self"""
152 if isinstance(key, slice):
153 step = 1
if key.step
is None else key.step
154 start = 0
if key.start
is None else key.start
155 stop = self._size
if key.stop
is None else key.stop
157 libamino.aa_dvec_slice(self, start, stop, step, x)
159 elif key >= 0
and key < len(self):
160 return self._data[key * self._inc]
162 raise IndexError(key)
165 """Set an item of self"""
166 if key >= 0
and key < len(self):
167 self._data[key * self._inc] = item
169 raise IndexError(key)
172 """Number of elements in self"""
177 """Increment between elements."""
181 """Add a scalar or vector to self"""
182 if isinstance(other, DVec):
183 return self.
axpyaxpy(1, other)
184 if isinstance(other, list):
185 return self.
axpyaxpy(1,
DVec(other))
188 raise Exception(
'Invalid argument')
191 """Add a scalar or vector to self"""
195 """Add a scalar or vector to self"""
198 def __isub(self, other):
199 """Subtract a scalar or vector from self"""
200 if isinstance(other, DVec):
201 return self.
axpyaxpy(-1, other)
202 if isinstance(other, list):
203 return self.
axpyaxpy(-1,
DVec(other))
206 raise Exception(
'Invalid argument')
209 """Subtract a scalar or vector from self"""
210 if isinstance(other, DVec):
212 if isinstance(other, list):
216 raise Exception(
'Invalid argument')
219 """Subtract a self from a scalar or vector"""
222 if isinstance(other, list):
224 raise Exception(
'Invalid argument')
227 """Multiply self by a scalar"""
228 libamino.aa_dvec_scal(other, self)
236 """Multiply self by a scalar"""
240 """Multiply self by a scalar"""
244 """Divide self by a scalar"""
245 return self.
__imul____imul__(1.0 / other)
248 """Divide self by a scalar"""
256 s +=
"%f, " % self._data[self._inc * i]
259 s +=
"%f" % self._data[self._inc * i]
265 """Matrix of double floats."""
266 _fields_ = [(
"_rows", ctypes.c_size_t), (
"_cols", ctypes.c_size_t),
267 (
"_data", ctypes.POINTER(ctypes.c_double)),
268 (
"_ld", ctypes.c_size_t)]
271 def _alloc(rows, cols):
272 return (ctypes.c_double * (rows * cols))()
275 """Constructs a matrix."""
277 super(DMat, self).
__init__(0, 0,
None, 0)
278 elif isinstance(arg, tuple):
280 data = DMat._alloc(rows, cols)
281 super(DMat, self).
__init__(rows, cols, data, rows)
282 elif isinstance(arg, DMat):
285 data = DMat._alloc(arg.rows, arg.cols)
286 super(DMat, self).
__init__(rows, cols, data, rows)
289 raise Exception(
'Invalid argument')
292 """Copies elements from src into self"""
293 if self._rows != src._rows
or self._cols != src._cols:
295 if isinstance(src, DMat):
296 libamino.aa_dmat_copy(src, self)
300 """Number of rows."""
305 """Number of columns."""
310 """Leading dimension of data."""
315 """Pointer to data."""
319 return self._rows * self._cols
322 """Returns the i'th row as a DVec."""
325 libamino.aa_dmat_row_vec(self, i, v)
329 """Returns the j'th column as a DVec."""
332 libamino.aa_dmat_col_vec(self, j, v)
336 """Returns the diagonal as a DVec."""
338 libamino.aa_dmat_diag_vec(self, v)
342 """Returns the tranpose of the matrix"""
343 At =
DMat((self._cols, self._rows))
344 libamino.aa_dmat_trans(self, At)
349 """Creates a matrix from rows passed in args."""
351 n = len(args[0])
if m > 0
else 0
353 for i
in range(0, m):
359 """Creates a matrix from columns passed in args."""
361 m = len(args[0])
if n > 0
else 0
363 for j
in range(0, n):
367 def ssd(self, other):
368 """Returns Sum of square differences."""
369 return libamino.aa_dmat_ssd(self, other)
372 """Returns the Euclidean norm of self"""
373 return libamino.aa_dmat_nrm2(self)
375 def gemm(self, transA, transB, alpha, A, B, beta):
376 """General matrix-matrix multiply.
378 Thin wrapper of BLAS dgemm().
380 self := alpha*op(A)*op(B) + beta*self
383 transA: whether to transpose A
384 transB: whether to transpose B
385 alpha: scale factor for A and B
386 beta: scale factor for self
389 if (A.rows != C.rows
or A.cols != B.rows
or B.cols != C.cols):
391 libamino.aa_dmat_gemm(transA, transB, alpha, A, B, beta, C)
394 def pinv(self, tol=-1):
395 """Returns the pseudoinverse.
398 tol: singular values less than tol are ignored. Negative values use a default.
400 M =
DMat((self._cols, self._rows))
401 libamino.aa_dmat_pinv(self, tol, M)
405 """Returns the inverse."""
407 libamino.aa_dmat_inv(M)
410 def _check_row(self, i):
411 if (i < 0
or i >= self._rows):
414 def _check_col(self, j):
415 if (j < 0
or j >= self._cols):
418 def _check_index(self, i, j):
424 def __getitem__(self, key):
426 if isinstance(i, slice)
and isinstance(j, slice):
427 if not ((i.step
is None)
or i.step == 0):
429 if not ((j.step
is None)
or j.step == 0):
432 libamino.aa_dmat_block(self, i.start, j.start, i.stop, j.stop, M)
436 return self._data[i + j * self._ld]
438 def __setitem__(self, key, item):
441 self._data[i + j * self._ld] = item
443 def __imul__(self, other):
445 libamino.aa_dmat_scal(self, other)
448 raise TypeError(
'Cannot cale matrix with %s' % type(other))
452 return DMat(self).__imul__(-1)
454 def __mul__(self, other):
456 return DMat(self).__imul__(other)
457 elif isinstance(other, DVec):
459 y.gemv(CBLAS_NO_TRANS, 1, self, other, 0)
461 elif isinstance(other, list):
462 return self *
DVec(other)
463 elif isinstance(other, DMat):
465 C =
DMat((A._rows, B._cols))
466 return C.gemm(CBLAS_NO_TRANS, CBLAS_NO_TRANS, 1, A, B, 1)
468 raise TypeError(
'Cannot multiply matrix with %s' % type(other))
470 def __rmul__(self, other):
472 return DMat(self).__imul__(other)
473 raise TypeError(
'Cannot multiply matrix with %s' % type(other))
476 """Divide self by a scalar"""
477 return self.
__imul____imul__(1.0 / other)
480 """Divide self by a scalar"""
483 def __iadd__(self, other):
485 libamino.aa_dmat_inc(self, other)
487 if isinstance(other, DMat):
488 libamino.aa_dmat_axpy(1, other, self)
490 raise TypeError(
'Cannot increment matrix with %s' % type(other))
492 def __add__(self, other):
493 if is_scalar(other)
or isinstance(other, DMat):
494 return DMat(self).__iadd__(other)
495 raise TypeError(
'Cannot add matrix add %s' % type(other))
497 def __radd__(self, other):
499 return DMat(self).__iadd__(other)
500 raise TypeError(
'Cannot add matrix add %s' % type(other))
502 def __isub__(self, other):
504 libamino.aa_dmat_inc(self, -other)
506 if isinstance(other, DMat):
507 libamino.aa_dmat_axpy(-1, other, self)
509 raise TypeError(
'Cannot increment matrix with %s' % type(other))
511 def __sub__(self, other):
512 if is_scalar(other)
or isinstance(other, DMat):
513 return DMat(self).__isub__(other)
514 raise TypeError(
'Cannot subtract matrix with %s' % type(other))
516 def __rsub__(self, other):
518 return self.
__neg____neg__().__iadd__(other)
519 raise TypeError(
'Cannot subtract matrix with %s' % type(other))
522 return self.
_str_helper_str_helper(
"TfMat.row_matrix")
530 libamino.aa_dvec_axpy.argtypes = [
532 ctypes.POINTER(DVec),
535 libamino.aa_dvec_copy.argtypes = [ctypes.POINTER(DVec), ctypes.POINTER(DVec)]
536 libamino.aa_dvec_scal.argtypes = [ctypes.c_double, ctypes.POINTER(DVec)]
537 libamino.aa_dvec_inc.argtypes = [ctypes.c_double, ctypes.POINTER(DVec)]
539 libamino.aa_dvec_dot.argtypes = [ctypes.POINTER(DVec), ctypes.POINTER(DVec)]
540 libamino.aa_dvec_dot.restype = ctypes.c_double
542 libamino.aa_dvec_nrm2.argtypes = [ctypes.POINTER(DVec)]
543 libamino.aa_dvec_nrm2.restype = ctypes.c_double
545 libamino.aa_dvec_set.argtypes = [ctypes.POINTER(DVec), ctypes.c_double]
547 libamino.aa_dvec_zero.argtypes = [ctypes.POINTER(DVec)]
549 libamino.aa_dvec_slice.argtypes = [
550 ctypes.POINTER(DVec), ctypes.c_size_t, ctypes.c_size_t, ctypes.c_size_t,
554 libamino.aa_dvec_ssd.argtypes = [ctypes.POINTER(DVec), ctypes.POINTER(DVec)]
555 libamino.aa_dvec_ssd.restype = ctypes.c_double
558 libamino.aa_dmat_row_vec.argtypes = [
559 ctypes.POINTER(DMat), ctypes.c_size_t,
562 libamino.aa_dmat_col_vec.argtypes = [
563 ctypes.POINTER(DMat), ctypes.c_size_t,
566 libamino.aa_dmat_diag_vec.argtypes = [
567 ctypes.POINTER(DMat), ctypes.POINTER(DVec)
570 libamino.aa_dmat_block.argtypes = [
571 ctypes.POINTER(DMat), ctypes.c_size_t, ctypes.c_size_t, ctypes.c_size_t,
576 libamino.aa_dmat_gemv.argtypes = [
577 ctypes.c_int, ctypes.c_double,
578 ctypes.POINTER(DMat),
579 ctypes.POINTER(DVec), ctypes.c_double,
584 libamino.aa_dmat_gemm.argtypes = [
585 ctypes.c_int, ctypes.c_int, ctypes.c_double,
586 ctypes.POINTER(DMat),
587 ctypes.POINTER(DMat), ctypes.c_double,
592 libamino.aa_dmat_ssd.argtypes = [ctypes.POINTER(DMat), ctypes.POINTER(DMat)]
593 libamino.aa_dmat_ssd.restype = ctypes.c_double
595 libamino.aa_dmat_scal.argtypes = [ctypes.POINTER(DMat), ctypes.c_double]
596 libamino.aa_dmat_inc.argtypes = [ctypes.POINTER(DMat), ctypes.c_double]
597 libamino.aa_dmat_axpy.argtypes = [
599 ctypes.POINTER(DMat),
603 libamino.aa_dmat_nrm2.argtypes = [ctypes.POINTER(DMat)]
604 libamino.aa_dmat_nrm2.restype = ctypes.c_double
606 libamino.aa_dmat_trans.argtypes = [ctypes.POINTER(DMat), ctypes.POINTER(DMat)]
608 libamino.aa_dmat_pinv.argtypes = [
609 ctypes.POINTER(DMat), ctypes.c_double,
612 libamino.aa_dmat_inv.argtypes = [ctypes.POINTER(DMat)]
614 libamino.aa_dmat_copy.argtypes = [ctypes.POINTER(DMat), ctypes.POINTER(DMat)]
def row_matrix(args)
Creates a matrix from rows passed in args.
def rows(self)
Number of rows.
def __init__(self, arg=None)
Constructs a matrix.
def data(self)
Pointer to data.
def __imul__(self, other)
def transpose(self)
Returns the tranpose of the matrix.
def inv(self)
Returns the inverse.
def ssd(self, other)
Returns Sum of square differences.
def pinv(self, tol=-1)
Returns the pseudoinverse.
def ld(self)
Leading dimension of data.
def col_matrix(args)
Creates a matrix from columns passed in args.
def gemm(self, transA, transB, alpha, A, B, beta)
General matrix-matrix multiply.
def diag_vec(self)
Returns the diagonal as a DVec.
def __itruediv__(self, other)
Divide self by a scala.
def cols(self)
Number of columns.
def __truediv__(self, other)
Divide self by a scala.
def col_vec(self, j)
Returns the j'th column as a DVec.
def row_vec(self, i)
Returns the i'th row as a DVec.
def copy_from(self, src)
Copies elements from src into self.
def _check_index(self, i, j)
def nrm2(self)
Returns the Euclidean norm of self.
def __neg__(self)
Negate self.
def set(self, alpha)
Sets all elements of self to scalar alpha.
def __rsub__(self, other)
Subtract a self from a scalar or vecto.
def __rmul__(self, other)
Multiply self by a scala.
def __iadd__(self, other)
Add a scalar or vector to self.
def nrm2(self)
Euclidean norm of self.
def zero(self)
Fills self with zeros.
def __init__(self, arg=None)
Constructs a vector.
def __radd__(self, other)
Add a scalar or vector to self.
def gemv(self, trans, alpha, A, x, beta)
General matrix-vector multiply.
def __sub__(self, other)
Subtract a scalar or vector from self.
def __imul__(self, other)
Multiply self by a scala.
def __len__(self)
Number of elements in self.
def axpy(self, alpha, x)
self = alpha*x, where alpha is a scalar and x is a DVec
def ensure(thing)
If thing is not a DVec, construct a DVec containging thing.
def copy_from(self, src)
Copies the contents of thing into self.
def __itruediv__(self, other)
Divide self by a scala.
def __setitem__(self, key, item)
Set an item of self.
def increment(self, alpha)
self = self + alpha, for scalar alpha
def __add__(self, other)
Add a scalar or vector to self.
def copy_to(self, dst)
Copies self to thing.
def __neg__(self)
Negate self.
def __getitem__(self, key)
Returns an item or slice of self.
def inc(self)
Increment between elements.
def __mul__(self, other)
Multiply self by a scala.
def __truediv__(self, other)
Divide self by a scala.
def ssd(self, other)
Sum of square differences.
def copy_from(self, src)
Copy elements from src to self.
Mixin for compatibility division operator.
Mixin for matrix-like objects.
def _str_helper(self, name, m=None, n=None)