# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from ..helper import is_complex, is_real, complex_variable_exists from ....fluid.framework import ComplexVariable from ....fluid import layers __all__ = ['matmul', ] def matmul(x, y, transpose_x=False, transpose_y=False, alpha=1.0, name=None): """ Applies matrix multiplication to two complex number tensors. See the detailed description in :ref:`api_fluid_layers_matmul`. Args: x (ComplexVariable|Variable): The first input, can be a ComplexVariable with data type complex64 or complex128, or a Variable with data type float32 or float64. y (ComplexVariable|Variable): The second input, can be a ComplexVariable with data type complex64 or complex128, or a Variable with data type float32 or float64. transpose_x (bool): Whether to transpose :math:`x` before multiplication. transpose_y (bool): Whether to transpose :math:`y` before multiplication. alpha (float): The scale of output. Default 1.0. name(str|None): A name for this layer(optional). If set None, the layer will be named automatically. Returns: ComplexVariable: The product result, with the same data type as inputs. Examples: .. code-block:: python import numpy as np import paddle import paddle.fluid.dygraph as dg with dg.guard(): x = np.array([[1.0 + 1j, 2.0 + 1j], [3.0+1j, 4.0+1j]]) y = np.array([1.0 + 1j, 1.0 + 1j]) x_var = dg.to_variable(x) y_var = dg.to_variable(y) result = paddle.complex.matmul(x_var, y_var) print(result.numpy()) # [1.+5.j 5.+9.j] """ # x = a + bi, y = c + di # P1 = ac; P2 = (a + b)(c + d); P3 = bd; then mm(x, y) = (P1-P3) + (P2-P1-P3)j complex_variable_exists([x, y], "matmul") a, b = (x.real, x.imag) if is_complex(x) else (x, None) c, d = (y.real, y.imag) if is_complex(y) else (y, None) P1 = layers.matmul(a, c, transpose_x, transpose_y, alpha, name) if is_real(b) and is_real(d): P2 = layers.matmul(a + b, c + d, transpose_x, transpose_y, alpha, name) P3 = layers.matmul(b, d, transpose_x, transpose_y, alpha, name) real = P1 - P3 imag = P2 - P1 - P3 elif is_real(b): real = P1 imag = layers.matmul(b, c, transpose_x, transpose_y, alpha, name) else: real = P1 imag = layers.matmul(a, d, transpose_x, transpose_y, alpha, name) return ComplexVariable(real, imag)