Matrix-matrix and matrix-vector multiplication. :param self: two-dimensional :param other: Matrix or Array of matching size and type :param n_threads: number of threads (default: all in same thread) :rtype: Matrix or Array of appropriate size and type
(self, other, res_params=None, n_threads=None)
| 7199 | return self.dot(other, res_params) |
| 7200 | |
| 7201 | def dot(self, other, res_params=None, n_threads=None): |
| 7202 | """ Matrix-matrix and matrix-vector multiplication. |
| 7203 | |
| 7204 | :param self: two-dimensional |
| 7205 | :param other: Matrix or Array of matching size and type |
| 7206 | :param n_threads: number of threads (default: all in same thread) |
| 7207 | :rtype: Matrix or Array of appropriate size and type |
| 7208 | |
| 7209 | """ |
| 7210 | assert len(self.sizes) == 2 |
| 7211 | if isinstance(other, Array): |
| 7212 | assert len(other) == self.sizes[1] |
| 7213 | if self.value_type.n_elements() == 1: |
| 7214 | matrix = Matrix(len(other), 1, other.value_type, \ |
| 7215 | address=other.address) |
| 7216 | res = self * matrix |
| 7217 | return Array(res.sizes[0], res.value_type, address=res.address) |
| 7218 | else: |
| 7219 | matrix = Matrix(len(other), 1, other.value_type) |
| 7220 | for i, x in enumerate(other): |
| 7221 | matrix[i][0] = x |
| 7222 | res = self * matrix |
| 7223 | library.break_point() |
| 7224 | return Array.create_from(x[0] for x in res) |
| 7225 | elif isinstance(other, SubMultiArray): |
| 7226 | assert len(other.sizes) == 2 |
| 7227 | assert other.sizes[0] == self.sizes[1] |
| 7228 | if res_params is not None: |
| 7229 | class t(self.value_type): |
| 7230 | pass |
| 7231 | t.params = res_params |
| 7232 | else: |
| 7233 | if self.value_type == other.value_type: |
| 7234 | t = self.value_type |
| 7235 | else: |
| 7236 | t = type(self.value_type(0) * other.value_type(0)) |
| 7237 | res_matrix = Matrix(self.sizes[0], other.sizes[1], t) |
| 7238 | try: |
| 7239 | try: |
| 7240 | self.value_type.direct_matrix_mul |
| 7241 | skip_reduce = set((sint, sfix)) == \ |
| 7242 | set((self.value_type, other.value_type)) |
| 7243 | assert self.value_type == other.value_type or skip_reduce |
| 7244 | max_size = _register.maximum_size // res_matrix.sizes[1] |
| 7245 | @library.multithread(n_threads, self.sizes[0], max_size) |
| 7246 | def _(base, size): |
| 7247 | tmp = self.get_part(base, size).direct_mul( |
| 7248 | other, reduce=not skip_reduce, |
| 7249 | res_type=sfix if skip_reduce else None) |
| 7250 | if skip_reduce: |
| 7251 | tmp = t._new(tmp.v) |
| 7252 | else: |
| 7253 | tmp = tmp.reduce_after_mul() |
| 7254 | res_matrix.assign_part_vector(tmp, base) |
| 7255 | except AttributeError: |
| 7256 | assert n_threads is None |
| 7257 | if max(res_matrix.sizes) > 1000: |
| 7258 | raise AttributeError() |
no test coverage detected