From 3e32169088b46f70dc77ae85f596186e16d143bc Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 8 Jun 2026 14:52:29 +0200 Subject: [PATCH 01/20] =?UTF-8?q?=F0=9F=94=A5=20Remove=20Eigen=20dependenc?= =?UTF-8?q?y=20from=20QCO=20MLIR=20dialect=20and=20replace=20with=20custom?= =?UTF-8?q?=20matrix=20types.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Composer via Cursor --- CHANGELOG.md | 2 + cmake/ExternalDependencies.cmake | 30 - mlir/.clang-tidy | 4 - .../mlir/Dialect/QCO/IR/QCOInterfaces.h | 3 +- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 153 +++-- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 62 +- .../mlir/Dialect/QCO/Utils/UnitaryMatrix.h | 642 ++++++++++++++++++ mlir/lib/Dialect/QCO/IR/CMakeLists.txt | 4 +- mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp | 8 +- mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/DCXOp.cpp | 8 +- .../QCO/IR/Operations/StandardGates/ECROp.cpp | 9 +- .../IR/Operations/StandardGates/GPhaseOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/HOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/IdOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/POp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/ROp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/RXOp.cpp | 7 +- .../QCO/IR/Operations/StandardGates/RXXOp.cpp | 9 +- .../QCO/IR/Operations/StandardGates/RYOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/RYYOp.cpp | 9 +- .../QCO/IR/Operations/StandardGates/RZOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RZXOp.cpp | 9 +- .../QCO/IR/Operations/StandardGates/RZZOp.cpp | 9 +- .../QCO/IR/Operations/StandardGates/SOp.cpp | 6 +- .../IR/Operations/StandardGates/SWAPOp.cpp | 8 +- .../QCO/IR/Operations/StandardGates/SXOp.cpp | 7 +- .../IR/Operations/StandardGates/SXdgOp.cpp | 7 +- .../QCO/IR/Operations/StandardGates/SdgOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/TOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/TdgOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/U2Op.cpp | 5 +- .../QCO/IR/Operations/StandardGates/UOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/XOp.cpp | 5 +- .../Operations/StandardGates/XXMinusYYOp.cpp | 9 +- .../Operations/StandardGates/XXPlusYYOp.cpp | 9 +- .../QCO/IR/Operations/StandardGates/YOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/ZOp.cpp | 6 +- .../IR/Operations/StandardGates/iSWAPOp.cpp | 10 +- .../Dialect/QCO/IR/test_qco_ir_matrix.cpp | 280 +++----- 40 files changed, 916 insertions(+), 472 deletions(-) create mode 100644 mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h diff --git a/CHANGELOG.md b/CHANGELOG.md index c8b192e5bf..6dde7d6310 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel ### Removed +- 🔥 Remove the Eigen dependency from the QCO MLIR dialect ([#1774]) ([**@simon1hofmann**]) - 🔥 Remove the density matrix support from the MQT Core DD package ([#1466]) ([**@burgholzer**]) - 🔥 Remove `datastructures` (`ds`) (sub)library from MQT Core ([#1458]) ([**@burgholzer**]) @@ -402,6 +403,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool +[#1774]: https://github.com/munich-quantum-toolkit/core/pull/1774 [#1765]: https://github.com/munich-quantum-toolkit/core/pull/1765 [#1762]: https://github.com/munich-quantum-toolkit/core/pull/1762 [#1749]: https://github.com/munich-quantum-toolkit/core/pull/1749 diff --git a/cmake/ExternalDependencies.cmake b/cmake/ExternalDependencies.cmake index 704a382ce9..e60652a668 100644 --- a/cmake/ExternalDependencies.cmake +++ b/cmake/ExternalDependencies.cmake @@ -23,17 +23,6 @@ if(BUILD_MQT_CORE_BINDINGS) endif() if(BUILD_MQT_CORE_MLIR) - set(Eigen_VERSION - 5.0.1 - CACHE STRING "Eigen version") - set(Eigen_URL - https://gitlab.com/libeigen/eigen/-/archive/${Eigen_VERSION}/eigen-${Eigen_VERSION}.tar.gz) - set(EIGEN_BUILD_TESTING - OFF - CACHE INTERNAL "Disable building Eigen tests") - FetchContent_Declare(Eigen URL ${Eigen_URL} FIND_PACKAGE_ARGS ${Eigen_VERSION}) - list(APPEND FETCH_PACKAGES Eigen) - # Fetch jeff-mlir FetchContent_Declare( jeff-mlir @@ -132,25 +121,6 @@ list(APPEND FETCH_PACKAGES spdlog) # Make all declared dependencies available. FetchContent_MakeAvailable(${FETCH_PACKAGES}) -# Treat Eigen headers as system headers to avoid surfacing third-party warnings. -set(_eigen_target "") -if(TARGET Eigen3::Eigen) - set(_eigen_target Eigen3::Eigen) -elseif(TARGET Eigen::Eigen) - set(_eigen_target Eigen::Eigen) -endif() -if(_eigen_target) - get_target_property(_eigen_alias_target ${_eigen_target} ALIASED_TARGET) - if(_eigen_alias_target) - set(_eigen_target ${_eigen_alias_target}) - endif() - get_target_property(_eigen_includes ${_eigen_target} INTERFACE_INCLUDE_DIRECTORIES) - if(_eigen_includes) - set_target_properties(${_eigen_target} PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES - "${_eigen_includes}") - endif() -endif() - # Install nlohmann_json with explicit MQT components. if(MQT_CORE_JSON_INSTALL AND TARGET nlohmann_json) set(MQT_CORE_JSON_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/cmake/nlohmann_json") diff --git a/mlir/.clang-tidy b/mlir/.clang-tidy index a83fa04cb3..3fb5c4cc0e 100644 --- a/mlir/.clang-tidy +++ b/mlir/.clang-tidy @@ -11,7 +11,3 @@ Checks: | -misc-use-anonymous-namespace, -modernize-type-traits, -*-const-correctness, - -CheckOptions: - - key: misc-include-cleaner.IgnoreHeaders - value: "Eigen/.*;unsupported/Eigen/.*" diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h index 035b0b5268..9104d196a1 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h @@ -10,7 +10,8 @@ #pragma once -#include +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" + #include #include #include diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 3de8255b8e..91d9bfac2b 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -28,57 +28,74 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { let cppNamespace = "::mlir::qco"; - // Generic implementation body for getUnitaryMatrix methods - defvar unitaryMatrixMethodBody = [{ - auto process = [&](MatrixType&& m) -> bool { - using TargetT = std::remove_cvref_t; - using SourceT = std::remove_cvref_t; - - constexpr bool isTargetDynamic = - (TargetT::SizeAtCompileTime == Eigen::Dynamic); - constexpr bool isSourceDynamic = - (SourceT::SizeAtCompileTime == Eigen::Dynamic); - - // Case 1: Target is Dynamic. Always accepts source. - if constexpr (isTargetDynamic) { - out = std::forward(m); + // Size-specific bodies: each helper only accepts the matching matrix type. + defvar unitaryMatrix1x1MethodBody = [{ + if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { + if (auto matrix = $_op.getUnitaryMatrix()) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix1x1>) { + out = *matrix; return true; } - // Case 2: Target is Fixed. - else { - // Case 2a: Source is Dynamic. Runtime dimension check required. - if constexpr (isSourceDynamic) { - if (m.rows() == static_cast(TargetT::RowsAtCompileTime) && - m.cols() == static_cast(TargetT::ColsAtCompileTime)) - [[likely]] { - out = std::forward(m); - return true; - } - } - // Case 2b: Source is Fixed. Compile-time check. - else if constexpr (static_cast( - SourceT::RowsAtCompileTime) == - static_cast( - TargetT::RowsAtCompileTime) && - static_cast( - SourceT::ColsAtCompileTime) == - static_cast( - TargetT::ColsAtCompileTime)) { - out = std::forward(m); - return true; - } - } - return false; - }; + } + return false; + } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix1x1>) { + out = $_op.getUnitaryMatrix(); + return true; + } + return false; + } else { + llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); + } + }]; + defvar unitaryMatrix2x2MethodBody = [{ + if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { + if (auto matrix = $_op.getUnitaryMatrix()) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix2>) { + out = *matrix; + return true; + } + } + return false; + } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix2>) { + out = $_op.getUnitaryMatrix(); + return true; + } + return false; + } else { + llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); + } + }]; + defvar unitaryMatrix4x4MethodBody = [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { - if (auto&& matrix = $_op.getUnitaryMatrix()) { - return process(std::move(*matrix)); + if (auto matrix = $_op.getUnitaryMatrix()) { + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix4>) { + out = *matrix; + return true; + } } return false; } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - return process($_op.getUnitaryMatrix()); + if constexpr (std::is_same_v< + std::remove_cvref_t, + ::mlir::qco::Matrix4>) { + out = $_op.getUnitaryMatrix(); + return true; + } + return false; } else { llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); } @@ -157,47 +174,47 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { // Unitary matrix helpers InterfaceMethod<"Populates the given 1x1 unitary matrix if possible.", "bool", "getUnitaryMatrix1x1", - (ins "Eigen::Matrix, 1, 1>&":$out), - unitaryMatrixMethodBody>, + (ins "::mlir::qco::Matrix1x1&":$out), + unitaryMatrix1x1MethodBody>, InterfaceMethod<"Populates the given 2x2 unitary matrix if possible.", "bool", "getUnitaryMatrix2x2", - (ins "Eigen::Matrix2cd&":$out), unitaryMatrixMethodBody>, + (ins "::mlir::qco::Matrix2&":$out), + unitaryMatrix2x2MethodBody>, InterfaceMethod<"Populates the given 4x4 unitary matrix if possible.", "bool", "getUnitaryMatrix4x4", - (ins "Eigen::Matrix4cd&":$out), unitaryMatrixMethodBody>, + (ins "::mlir::qco::Matrix4&":$out), + unitaryMatrix4x4MethodBody>, InterfaceMethod<"Populates the given dynamic unitary matrix.", "bool", - "getUnitaryMatrixDynamic", (ins "Eigen::MatrixXcd&":$out), - unitaryMatrixMethodBody>]; + "getUnitaryMatrixDynamic", + (ins "::mlir::qco::DynamicMatrix&":$out), [{ + if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { + if (auto matrix = $_op.getUnitaryMatrix()) { + return ::mlir::qco::detail::assignToDynamic(out, *matrix); + } + return false; + } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { + return ::mlir::qco::detail::assignToDynamic(out, $_op.getUnitaryMatrix()); + } else { + llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); + } + }]>]; let extraClassDeclaration = [{ template std::optional getUnitaryMatrix() { + static_assert(::mlir::qco::IS_UNITARY_MATRIX_V, + "MatrixType must be Matrix1x1, Matrix2, Matrix4, or DynamicMatrix"); MatrixType out; bool result = false; - // Dispatch to the appropriate fixed-size or dynamic method based on the - // matrix type. - if constexpr (MatrixType::RowsAtCompileTime == 1 && - MatrixType::ColsAtCompileTime == 1) { + if constexpr (std::is_same_v) { result = this->getUnitaryMatrix1x1(out); - } else if constexpr (MatrixType::RowsAtCompileTime == 2 && - MatrixType::ColsAtCompileTime == 2) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix2x2(out); - } else if constexpr (MatrixType::RowsAtCompileTime == 4 && - MatrixType::ColsAtCompileTime == 4) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix4x4(out); - } else if constexpr (MatrixType::SizeAtCompileTime == Eigen::Dynamic) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrixDynamic(out); - } else { - // Fallback: Try obtaining dynamic matrix and see if size matches - Eigen::MatrixXcd dynamicOut; - if (this->getUnitaryMatrixDynamic(dynamicOut)) { - if (dynamicOut.rows() == MatrixType::RowsAtCompileTime && - dynamicOut.cols() == MatrixType::ColsAtCompileTime) { - out = dynamicOut; - result = true; - } - } } if (result) { diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index a5bbfb7f51..5a47bc32ad 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -200,7 +200,7 @@ def GPhaseOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "gphase"; } - [[nodiscard]] std::optional, 1, 1>> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix1x1> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "const std::variant&":$theta)>]; @@ -226,7 +226,7 @@ def IdOp : QCOOp<"id", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "id"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -250,7 +250,7 @@ def XOp : QCOOp<"x", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "x"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -274,7 +274,7 @@ def YOp : QCOOp<"y", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "y"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -298,7 +298,7 @@ def ZOp : QCOOp<"z", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "z"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -322,7 +322,7 @@ def HOp : QCOOp<"h", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "h"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -346,7 +346,7 @@ def SOp : QCOOp<"s", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "s"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -371,7 +371,7 @@ def SdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sdg"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -395,7 +395,7 @@ def TOp : QCOOp<"t", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "t"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -420,7 +420,7 @@ def TdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "tdg"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -444,7 +444,7 @@ def SXOp : QCOOp<"sx", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sx"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -469,7 +469,7 @@ def SXdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sxdg"; } - [[nodiscard]] static Eigen::Matrix2cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -494,7 +494,7 @@ def RXOp : QCOOp<"rx", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rx"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -523,7 +523,7 @@ def RYOp : QCOOp<"ry", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ry"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -552,7 +552,7 @@ def RZOp : QCOOp<"rz", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rz"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -581,7 +581,7 @@ def POp : QCOOp<"p", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "p"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -611,7 +611,7 @@ def ROp : QCOOp<"r", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "r"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -641,7 +641,7 @@ def U2Op : QCOOp<"u2", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u2"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -672,7 +672,7 @@ def UOp : QCOOp<"u", traits = [UnitaryOpInterface, OneTargetThreeParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -705,7 +705,7 @@ def SWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "swap"; } - [[nodiscard]] static Eigen::Matrix4cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -733,7 +733,7 @@ def iSWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "iswap"; } - [[nodiscard]] static Eigen::Matrix4cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); }]; } @@ -759,7 +759,7 @@ def DCXOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "dcx"; } - [[nodiscard]] static Eigen::Matrix4cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -787,7 +787,7 @@ def ECROp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ecr"; } - [[nodiscard]] static Eigen::Matrix4cd getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -815,7 +815,7 @@ def RXXOp : QCOOp<"rxx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rxx"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -847,7 +847,7 @@ def RYYOp : QCOOp<"ryy", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ryy"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -879,7 +879,7 @@ def RZXOp : QCOOp<"rzx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzx"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -911,7 +911,7 @@ def RZZOp : QCOOp<"rzz", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzz"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -945,7 +945,7 @@ def XXPlusYYOp : QCOOp<"xx_plus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_plus_yy"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -980,7 +980,7 @@ def XXMinusYYOp : QCOOp<"xx_minus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_minus_yy"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -1124,7 +1124,7 @@ def CtrlOp Value getParameter(size_t i) { return getBodyUnitary().getParameter(i); } ValueRange getParameters() { return getBodyUnitary().getParameters(); } [[nodiscard]] static StringRef getBaseSymbol() { return "ctrl"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::DynamicMatrix> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "ValueRange":$controls, "ValueRange":$targets), @@ -1195,7 +1195,7 @@ def InvOp Value getParameter(size_t i) { return getBodyUnitary().getParameter(i); } ValueRange getParameters() { return getBodyUnitary().getParameters(); } [[nodiscard]] static StringRef getBaseSymbol() { return "inv"; } - [[nodiscard]] std::optional getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::DynamicMatrix> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "ValueRange":$qubits), [{ diff --git a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h new file mode 100644 index 0000000000..679a5db207 --- /dev/null +++ b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +namespace mlir::qco { + +/// Complex scalar type used for unitary matrix entries. +using Complex = std::complex; + +/// Default absolute tolerance for unitary matrix comparisons. +inline constexpr double UNITARY_MATRIX_TOLERANCE = 1e-14; + +/** + * @brief 1x1 unitary matrix for global-phase gates. + * + * Stores a single complex scalar in row-major layout. Used by operations such + * as `GPhaseOp` whose unitary is a global phase factor. + */ +struct Matrix1x1 { + /// Flat storage of the single matrix entry. + std::array data{Complex{1.0, 0.0}}; + + /** + * @brief Constructs a matrix from its single entry. + * @param m00 Element at row 0, column 0. + * @return A new `Matrix1x1` with the given element. + */ + [[nodiscard]] static Matrix1x1 fromElements(Complex m00) { + Matrix1x1 m{}; + m(0, 0) = m00; + return m; + } + + /** + * @brief Mutable element access with `(row, col)` indexing. + * @param row Row index (ignored; always 0). + * @param col Column index (ignored; always 0). + * @return Reference to the sole matrix entry. + */ + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { + (void)row; + (void)col; + return data[0]; + } + + /** + * @brief Const element access with `(row, col)` indexing. + * @param row Row index (ignored; always 0). + * @param col Column index (ignored; always 0). + * @return Copy of the sole matrix entry. + */ + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { + (void)row; + (void)col; + return data[0]; + } + + /** + * @brief Checks approximate equality using an absolute entry-wise tolerance. + * @param other Matrix to compare against. + * @param tol Maximum allowed absolute difference per entry. + * @return True if the absolute difference is within @p tol. + */ + [[nodiscard]] bool isApprox(const Matrix1x1& other, + double tol = UNITARY_MATRIX_TOLERANCE) const { + return std::abs(data[0] - other.data[0]) <= tol; + } +}; + +/** + * @brief Fixed-size 2x2 unitary matrix in row-major layout. + * + * Represents single-qubit gate unitaries. Elements are stored in a flat array + * with index `(row * K_COLS) + col`. + */ +struct Matrix2 { + /// Number of rows. + static constexpr std::size_t K_ROWS = 2; + /// Number of columns. + static constexpr std::size_t K_COLS = 2; + /// Total number of stored elements. + static constexpr std::size_t K_SIZE_AT_COMPILE_TIME = 4; + + /// Flat row-major storage of all matrix entries. + std::array data{}; + + /** + * @brief Constructs a matrix from its four row-major entries. + * @param m00 Element at row 0, column 0. + * @param m01 Element at row 0, column 1. + * @param m10 Element at row 1, column 0. + * @param m11 Element at row 1, column 1. + * @return A new `Matrix2` with the given elements. + */ + [[nodiscard]] static Matrix2 fromElements(Complex m00, Complex m01, + Complex m10, Complex m11) { + Matrix2 m{}; + m.data = {m00, m01, m10, m11}; + return m; + } + + /** + * @brief Returns the 2x2 identity matrix. + * @return Identity matrix `[[1, 0], [0, 1]]`. + */ + [[nodiscard]] static Matrix2 identity() { return fromElements(1, 0, 0, 1); } + + /** + * @brief Mutable element access. + * @param row Row index in `[0, K_ROWS)`. + * @param col Column index in `[0, K_COLS)`. + * @return Reference to the element at `(row, col)`. + */ + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { + return data[(row * K_COLS) + col]; + } + + /** + * @brief Const element access. + * @param row Row index in `[0, K_ROWS)`. + * @param col Column index in `[0, K_COLS)`. + * @return Copy of the element at `(row, col)`. + */ + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { + return data[(row * K_COLS) + col]; + } + + /** + * @brief Matrix product `*this * rhs`. + * @param rhs Right-hand factor. + * @return Product of the two matrices. + */ + [[nodiscard]] Matrix2 operator*(const Matrix2& rhs) const { + Matrix2 out{}; + for (std::size_t i = 0; i < K_ROWS; ++i) { + for (std::size_t j = 0; j < K_COLS; ++j) { + out(i, j) = (*this)(i, 0) * rhs(0, j) + (*this)(i, 1) * rhs(1, j); + } + } + return out; + } + + /** + * @brief Returns the conjugate transpose (adjoint) of this matrix. + * @return Adjoint matrix `A^\dagger`. + */ + [[nodiscard]] Matrix2 adjoint() const { + return fromElements(std::conj((*this)(0, 0)), std::conj((*this)(1, 0)), + std::conj((*this)(0, 1)), std::conj((*this)(1, 1))); + } + + /** + * @brief Returns the trace of this matrix. + * @return Sum of diagonal entries. + */ + [[nodiscard]] Complex trace() const { return (*this)(0, 0) + (*this)(1, 1); } + + /** + * @brief Returns the determinant of this matrix. + * @return Complex determinant `ad - bc`. + */ + [[nodiscard]] Complex determinant() const { + return (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0); + } + + /** + * @brief Checks approximate equality using an absolute entry-wise tolerance. + * + * For each entry `i`, the comparison uses `|a_i - b_i| <= tol`, where the + * absolute value is the complex modulus. + * + * @param other Matrix to compare against. + * @param tol Maximum allowed absolute difference per entry. + * @return True if every entry differs by at most @p tol. + */ + [[nodiscard]] bool isApprox(const Matrix2& other, + double tol = UNITARY_MATRIX_TOLERANCE) const { + for (std::size_t i = 0; i < data.size(); ++i) { + if (std::abs(data[i] - other.data[i]) > tol) { + return false; + } + } + return true; + } +}; + +/** + * @brief Fixed-size 4x4 unitary matrix in row-major layout. + * + * Represents two-qubit gate unitaries. Elements are stored in a flat array with + * index `(row * K_COLS) + col`. + */ +struct Matrix4 { + /// Number of rows. + static constexpr std::size_t K_ROWS = 4; + /// Number of columns. + static constexpr std::size_t K_COLS = 4; + /// Total number of stored elements. + static constexpr std::size_t K_SIZE_AT_COMPILE_TIME = 16; + + /// Flat row-major storage of all matrix entries. + std::array data{}; + + /** + * @brief Constructs a matrix from its sixteen row-major entries. + * @param m00 Element at row 0, column 0. + * @param m01 Element at row 0, column 1. + * @param m02 Element at row 0, column 2. + * @param m03 Element at row 0, column 3. + * @param m10 Element at row 1, column 0. + * @param m11 Element at row 1, column 1. + * @param m12 Element at row 1, column 2. + * @param m13 Element at row 1, column 3. + * @param m20 Element at row 2, column 0. + * @param m21 Element at row 2, column 1. + * @param m22 Element at row 2, column 2. + * @param m23 Element at row 2, column 3. + * @param m30 Element at row 3, column 0. + * @param m31 Element at row 3, column 1. + * @param m32 Element at row 3, column 2. + * @param m33 Element at row 3, column 3. + * @return A new `Matrix4` with the given elements. + */ + [[nodiscard]] static Matrix4 + fromElements(Complex m00, Complex m01, Complex m02, Complex m03, Complex m10, + Complex m11, Complex m12, Complex m13, Complex m20, Complex m21, + Complex m22, Complex m23, Complex m30, Complex m31, Complex m32, + Complex m33) { + Matrix4 m{}; + m.data = {m00, m01, m02, m03, m10, m11, m12, m13, + m20, m21, m22, m23, m30, m31, m32, m33}; + return m; + } + + /** + * @brief Returns the 4x4 identity matrix. + * @return Identity matrix with ones on the diagonal. + */ + [[nodiscard]] static Matrix4 identity() { + Matrix4 m{}; + for (std::size_t i = 0; i < K_ROWS; ++i) { + m(i, i) = 1.0; + } + return m; + } + + /** + * @brief Mutable element access. + * @param row Row index in `[0, K_ROWS)`. + * @param col Column index in `[0, K_COLS)`. + * @return Reference to the element at `(row, col)`. + */ + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { + return data[(row * K_COLS) + col]; + } + + /** + * @brief Const element access. + * @param row Row index in `[0, K_ROWS)`. + * @param col Column index in `[0, K_COLS)`. + * @return Copy of the element at `(row, col)`. + */ + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { + return data[(row * K_COLS) + col]; + } + + /** + * @brief Matrix product `*this * rhs`. + * @param rhs Right-hand factor. + * @return Product of the two matrices. + */ + [[nodiscard]] Matrix4 operator*(const Matrix4& rhs) const { + Matrix4 out{}; + for (std::size_t i = 0; i < K_ROWS; ++i) { + for (std::size_t j = 0; j < K_COLS; ++j) { + Complex sum{0.0, 0.0}; + for (std::size_t k = 0; k < K_COLS; ++k) { + sum += (*this)(i, k) * rhs(k, j); + } + out(i, j) = sum; + } + } + return out; + } + + /** + * @brief Returns the conjugate transpose (adjoint) of this matrix. + * @return Adjoint matrix `A^\dagger`. + */ + [[nodiscard]] Matrix4 adjoint() const { + Matrix4 out{}; + for (std::size_t i = 0; i < K_ROWS; ++i) { + for (std::size_t j = 0; j < K_COLS; ++j) { + out(i, j) = std::conj((*this)(j, i)); + } + } + return out; + } + + /** + * @brief Returns the trace of this matrix. + * @return Sum of diagonal entries. + */ + [[nodiscard]] Complex trace() const { + Complex t{0.0, 0.0}; + for (std::size_t i = 0; i < K_ROWS; ++i) { + t += (*this)(i, i); + } + return t; + } + + /** + * @brief Returns the determinant of this matrix. + * @return Complex determinant computed via Laplace expansion. + */ + [[nodiscard]] Complex determinant() const; + + /** + * @brief Checks approximate equality using an absolute entry-wise tolerance. + * @param other Matrix to compare against. + * @param tol Maximum allowed absolute difference per entry. + * @return True if every entry differs by at most @p tol. + */ + [[nodiscard]] bool isApprox(const Matrix4& other, + double tol = UNITARY_MATRIX_TOLERANCE) const { + for (std::size_t i = 0; i < data.size(); ++i) { + if (std::abs(data[i] - other.data[i]) > tol) { + return false; + } + } + return true; + } +}; + +/** + * @brief Square unitary matrix with runtime dimension. + * + * Used when the Hilbert-space dimension depends on the operation, for example + * in controlled gates (`CtrlOp`) and inverses (`InvOp`). Storage is row-major + * in a `llvm::SmallVector`. + */ +class DynamicMatrix { +public: + /// Creates an empty 0x0 matrix. + DynamicMatrix() = default; + + /** + * @brief Creates a zero-initialized square matrix. + * @param dim Side length of the square matrix. + */ + explicit DynamicMatrix(std::int64_t dim) : dim_(dim), data_(dim * dim) {} + + /** + * @brief Returns a square identity matrix of the given dimension. + * @param dim Side length of the identity matrix. + * @return Identity matrix with ones on the diagonal. + */ + [[nodiscard]] static DynamicMatrix identity(std::int64_t dim) { + DynamicMatrix m(dim); + for (std::int64_t i = 0; i < dim; ++i) { + m(i, i) = 1.0; + } + return m; + } + + /** + * @brief Returns the number of rows. + * @return Matrix dimension. + */ + [[nodiscard]] std::int64_t rows() const { return dim_; } + + /** + * @brief Returns the number of columns. + * @return Matrix dimension. + */ + [[nodiscard]] std::int64_t cols() const { return dim_; } + + /** + * @brief Mutable element access. + * @param row Row index in `[0, dim)`. + * @param col Column index in `[0, dim)`. + * @return Reference to the element at `(row, col)`. + */ + [[nodiscard]] Complex& operator()(std::int64_t row, std::int64_t col) { + return data_[static_cast((row * dim_) + col)]; + } + + /** + * @brief Const element access. + * @param row Row index in `[0, dim)`. + * @param col Column index in `[0, dim)`. + * @return Copy of the element at `(row, col)`. + */ + [[nodiscard]] Complex operator()(std::int64_t row, std::int64_t col) const { + return data_[static_cast((row * dim_) + col)]; + } + + /** + * @brief Copies a 2x2 block into the bottom-right corner. + * @param block Source block placed at indices `(dim-2, dim-2)` through + * `(dim-1, dim-1)`. + */ + void setBottomRightCorner(const Matrix2& block) { + const std::int64_t offset = dim_ - 2; + for (std::int64_t i = 0; i < 2; ++i) { + for (std::int64_t j = 0; j < 2; ++j) { + (*this)(offset + i, offset + j) = + block(static_cast(i), static_cast(j)); + } + } + } + + /** + * @brief Copies a 4x4 block into the bottom-right corner. + * @param block Source block placed at indices `(dim-4, dim-4)` through + * `(dim-1, dim-1)`. + */ + void setBottomRightCorner(const Matrix4& block) { + const std::int64_t offset = dim_ - 4; + for (std::int64_t i = 0; i < 4; ++i) { + for (std::int64_t j = 0; j < 4; ++j) { + (*this)(offset + i, offset + j) = + block(static_cast(i), static_cast(j)); + } + } + } + + /** + * @brief Copies a dynamic block into the bottom-right corner. + * @param block Source block placed at indices `(dim-block.dim, ...)` through + * `(dim-1, dim-1)`. + */ + void setBottomRightCorner(const DynamicMatrix& block) { + const std::int64_t offset = dim_ - block.dim_; + for (std::int64_t i = 0; i < block.dim_; ++i) { + for (std::int64_t j = 0; j < block.dim_; ++j) { + (*this)(offset + i, offset + j) = block(i, j); + } + } + } + + /** + * @brief Replaces this matrix with its conjugate transpose in place. + */ + void adjointInPlace() { + for (std::int64_t i = 0; i < dim_; ++i) { + for (std::int64_t j = i + 1; j < dim_; ++j) { + const Complex tmp = (*this)(i, j); + (*this)(i, j) = std::conj((*this)(j, i)); + (*this)(j, i) = std::conj(tmp); + } + (*this)(i, i) = std::conj((*this)(i, i)); + } + } + + /** + * @brief Checks approximate equality against a fixed 4x4 matrix. + * + * Returns false if this matrix is not 4x4. + * + * @param other Fixed-size matrix to compare against. + * @param tol Maximum allowed absolute difference per entry. + * @return True if dimensions match and every entry differs by at most @p tol. + */ + [[nodiscard]] bool isApprox(const Matrix4& other, + double tol = UNITARY_MATRIX_TOLERANCE) const { + if (dim_ != 4) { + return false; + } + for (std::int64_t i = 0; i < 4; ++i) { + for (std::int64_t j = 0; j < 4; ++j) { + if (std::abs((*this)(i, j) - other(static_cast(i), + static_cast(j))) > + tol) { + return false; + } + } + } + return true; + } + + /** + * @brief Checks approximate equality against another dynamic matrix. + * + * Returns false if the dimensions differ. + * + * @param other Matrix to compare against. + * @param tol Maximum allowed absolute difference per entry. + * @return True if dimensions match and every entry differs by at most @p tol. + */ + [[nodiscard]] bool isApprox(const DynamicMatrix& other, + double tol = UNITARY_MATRIX_TOLERANCE) const { + if (dim_ != other.dim_) { + return false; + } + for (std::size_t idx = 0; idx < data_.size(); ++idx) { + if (std::abs(data_[idx] - other.data_[idx]) > tol) { + return false; + } + } + return true; + } + +private: + /// Side length of the square matrix. + std::int64_t dim_ = 0; + /// Flat row-major storage of all matrix entries. + llvm::SmallVector data_; +}; + +/** + * @brief Returns the determinant of a 4x4 matrix. + * + * Computed via Laplace expansion along the first row. + */ +inline Complex Matrix4::determinant() const { + auto det3 = [](Complex m00, Complex m01, Complex m02, Complex m10, + Complex m11, Complex m12, Complex m20, Complex m21, + Complex m22) { + return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + + m02 * (m10 * m21 - m11 * m20); + }; + return (*this)(0, 0) * det3((*this)(1, 1), (*this)(1, 2), (*this)(1, 3), + (*this)(2, 1), (*this)(2, 2), (*this)(2, 3), + (*this)(3, 1), (*this)(3, 2), (*this)(3, 3)) - + (*this)(0, 1) * det3((*this)(1, 0), (*this)(1, 2), (*this)(1, 3), + (*this)(2, 0), (*this)(2, 2), (*this)(2, 3), + (*this)(3, 0), (*this)(3, 2), (*this)(3, 3)) + + (*this)(0, 2) * det3((*this)(1, 0), (*this)(1, 1), (*this)(1, 3), + (*this)(2, 0), (*this)(2, 1), (*this)(2, 3), + (*this)(3, 0), (*this)(3, 1), (*this)(3, 3)) - + (*this)(0, 3) * det3((*this)(1, 0), (*this)(1, 1), (*this)(1, 2), + (*this)(2, 0), (*this)(2, 1), (*this)(2, 2), + (*this)(3, 0), (*this)(3, 1), (*this)(3, 2)); +} + +/** + * @brief Type trait that identifies supported unitary matrix types. + * @tparam T Candidate type. + */ +template struct IsUnitaryMatrix : std::false_type {}; + +/// @brief Specialization for `Matrix1x1`. +template <> struct IsUnitaryMatrix : std::true_type {}; +/// @brief Specialization for `Matrix2`. +template <> struct IsUnitaryMatrix : std::true_type {}; +/// @brief Specialization for `Matrix4`. +template <> struct IsUnitaryMatrix : std::true_type {}; +/// @brief Specialization for `DynamicMatrix`. +template <> struct IsUnitaryMatrix : std::true_type {}; + +/** + * @brief Convenience variable template for `IsUnitaryMatrix::value`. + * @tparam T Candidate type. + */ +template +inline constexpr bool IS_UNITARY_MATRIX_V = IsUnitaryMatrix::value; + +namespace detail { + +/** + * @brief Copies a 1x1 matrix into a dynamic matrix. + * @param out Destination matrix, resized to 1x1. + * @param src Source matrix. + */ +inline void copyInto(DynamicMatrix& out, const Matrix1x1& src) { + out = DynamicMatrix(1); + out(0, 0) = src(0, 0); +} + +/** + * @brief Copies a 2x2 matrix into a dynamic matrix. + * @param out Destination matrix, resized to 2x2. + * @param src Source matrix. + */ +inline void copyInto(DynamicMatrix& out, const Matrix2& src) { + out = DynamicMatrix(2); + for (std::size_t i = 0; i < Matrix2::K_ROWS; ++i) { + for (std::size_t j = 0; j < Matrix2::K_COLS; ++j) { + out(static_cast(i), static_cast(j)) = + src(i, j); + } + } +} + +/** + * @brief Copies a 4x4 matrix into a dynamic matrix. + * @param out Destination matrix, resized to 4x4. + * @param src Source matrix. + */ +inline void copyInto(DynamicMatrix& out, const Matrix4& src) { + out = DynamicMatrix(4); + for (std::size_t i = 0; i < Matrix4::K_ROWS; ++i) { + for (std::size_t j = 0; j < Matrix4::K_COLS; ++j) { + out(static_cast(i), static_cast(j)) = + src(i, j); + } + } +} + +/** + * @brief Copies a dynamic matrix into another dynamic matrix. + * @param out Destination matrix. + * @param src Source matrix. + */ +inline void copyInto(DynamicMatrix& out, const DynamicMatrix& src) { + out = src; +} + +/** + * @brief Promotes a fixed- or dynamic-size matrix into a dynamic output matrix. + * @tparam Src Source matrix type. + * @param out Destination matrix. + * @param src Source matrix. + * @return Always `true` on success. + */ +template +inline bool assignToDynamic(DynamicMatrix& out, const Src& src) { + copyInto(out, src); + return true; +} + +} // namespace detail + +} // namespace mlir::qco diff --git a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt index f33ece7000..85cadc03a0 100644 --- a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt @@ -28,9 +28,7 @@ add_mlir_dialect_library( MLIRIR MLIRArithDialect MLIRInferTypeOpInterface - MLIRSideEffectInterfaces - PUBLIC - Eigen3::Eigen) + MLIRSideEffectInterfaces) mqt_mlir_target_use_project_options(MLIRQCODialect) diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index 25fc88d084..29aa1cc00a 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -340,12 +340,12 @@ void CtrlOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional CtrlOp::getUnitaryMatrix() { +std::optional CtrlOp::getUnitaryMatrix() { auto&& bodyUnitary = getBodyUnitary(); if (!bodyUnitary) { return std::nullopt; } - auto&& targetMatrix = bodyUnitary.getUnitaryMatrix(); + auto&& targetMatrix = bodyUnitary.getUnitaryMatrix(); if (!targetMatrix) { return std::nullopt; } @@ -359,10 +359,10 @@ std::optional CtrlOp::getUnitaryMatrix() { const auto dim = static_cast((1ULL << getNumControls()) * targetDim); // initialize result with identity - Eigen::MatrixXcd matrix = Eigen::MatrixXcd::Identity(dim, dim); + DynamicMatrix matrix = DynamicMatrix::identity(dim); // apply target matrix - matrix.bottomRightCorner(targetDim, targetDim) = *targetMatrix; + matrix.setBottomRightCorner(*targetMatrix); return matrix; } diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp index d82a64f819..ce8182b276 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include #include #include #include @@ -401,12 +400,12 @@ void InvOp::getCanonicalizationPatterns(RewritePatternSet& results, CancelNestedInv>(context); } -std::optional InvOp::getUnitaryMatrix() { +std::optional InvOp::getUnitaryMatrix() { auto&& bodyUnitary = getBodyUnitary(); if (!bodyUnitary) { return std::nullopt; } - auto&& targetMatrix = bodyUnitary.getUnitaryMatrix(); + auto targetMatrix = bodyUnitary.getUnitaryMatrix(); if (!targetMatrix) { return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp index fc6a3c1e34..b0e5b4270b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -43,9 +42,6 @@ void DCXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix4cd DCXOp::getUnitaryMatrix() { - return Eigen::Matrix4cd{{1, 0, 0, 0}, // row 0 - {0, 0, 1, 0}, // row 1 - {0, 0, 0, 1}, // row 2 - {0, 1, 0, 0}}; // row 3 +Matrix4 DCXOp::getUnitaryMatrix() { + return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp index 676082e68f..6befdca029 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -44,14 +43,12 @@ void ECROp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix4cd ECROp::getUnitaryMatrix() { +Matrix4 ECROp::getUnitaryMatrix() { using namespace std::complex_literals; constexpr auto m0 = 0i; constexpr auto m1 = std::complex{1.0 / std::numbers::sqrt2}; constexpr auto mi = std::complex{0.0, 1.0 / std::numbers::sqrt2}; - return Eigen::Matrix4cd{{m0, m0, m1, mi}, // row 0 - {m0, m0, mi, m1}, // row 1 - {m1, -mi, m0, m0}, // row 2 - {-mi, m1, m0, m0}}; // row 3 + return Matrix4::fromElements(m0, m0, m1, mi, m0, m0, mi, m1, m1, -mi, m0, m0, + -mi, m1, m0, m0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp index aeb8a5c4b9..0cfff5551b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -61,10 +60,9 @@ void GPhaseOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional, 1, 1>> -GPhaseOp::getUnitaryMatrix() { +std::optional GPhaseOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - return Eigen::Matrix, 1, 1>{std::polar(1.0, *theta)}; + return Matrix1x1::fromElements(std::polar(1.0, *theta)); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index 2fe55f5a68..682377a9c7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -43,7 +42,7 @@ void HOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd HOp::getUnitaryMatrix() { +Matrix2 HOp::getUnitaryMatrix() { constexpr auto x = 1.0 / std::numbers::sqrt2; - return Eigen::Matrix2cd{{x, x}, {x, -1.0 * x}}; + return Matrix2::fromElements(x, x, x, -1.0 * x); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp index 4cdf785c07..7b9accebc7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp @@ -10,7 +10,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include #include #include #include @@ -41,6 +40,4 @@ void IdOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd IdOp::getUnitaryMatrix() { - return Eigen::Matrix2cd{{1, 0}, {0, 1}}; -} +Matrix2 IdOp::getUnitaryMatrix() { return Matrix2::fromElements(1, 0, 0, 1); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index 08ee6e068e..92454d8364 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -65,9 +64,9 @@ void POp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional POp::getUnitaryMatrix() { +std::optional POp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - return Eigen::Matrix2cd{{1.0, 0.0}, {0.0, std::polar(1.0, *theta)}}; + return Matrix2::fromElements(1.0, 0.0, 0.0, std::polar(1.0, *theta)); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index 5e7b04b268..75dbfe3d72 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -80,7 +79,7 @@ void ROp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional ROp::getUnitaryMatrix() { +std::optional ROp::getUnitaryMatrix() { const auto theta = valueToDouble(getTheta()); const auto phi = valueToDouble(getPhi()); if (!theta || !phi) { @@ -91,5 +90,5 @@ std::optional ROp::getUnitaryMatrix() { const auto m01 = std::polar(thetaSin, -*phi - (std::numbers::pi / 2)); const auto m10 = std::polar(thetaSin, *phi - (std::numbers::pi / 2)); const std::complex thetaCos = std::cos(*theta / 2.0); - return Eigen::Matrix2cd{{thetaCos, m01}, {m10, thetaCos}}; + return Matrix2::fromElements(thetaCos, m01, m10, thetaCos); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index eef8bf100c..f868246f29 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -65,13 +64,15 @@ void RXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RXOp::getUnitaryMatrix() { +std::optional RXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::cos(*theta / 2.0) + 0i; const auto m01 = -1i * std::sin(*theta / 2.0); - return Eigen::Matrix2cd{{m00, m01}, {m01, m00}}; + const auto m10 = m01; + const auto m11 = m00; + return Matrix2::fromElements(m00, m01, m10, m11); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index 02e3c5d421..bc21cbe383 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -82,17 +81,15 @@ void RXXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RXXOp::getUnitaryMatrix() { +std::optional RXXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::cos(*theta / 2.0) + 0i; const auto ms = -1i * std::sin(*theta / 2.0); - return Eigen::Matrix4cd{{mc, m0, m0, ms}, // row 0 - {m0, mc, ms, m0}, // row 1 - {m0, ms, mc, m0}, // row 2 - {ms, m0, m0, mc}}; // row 3 + return Matrix4::fromElements(mc, m0, m0, ms, m0, mc, ms, m0, m0, ms, mc, m0, + ms, m0, m0, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index 3b9255250a..7441096884 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -65,11 +64,11 @@ void RYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RYOp::getUnitaryMatrix() { +std::optional RYOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::complex{std::cos(*theta / 2.0)}; const auto m01 = std::complex{-std::sin(*theta / 2.0)}; - return Eigen::Matrix2cd{{m00, m01}, {-m01, m00}}; + return Matrix2::fromElements(m00, m01, -m01, m00); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index 2996fdd289..d31b9178f8 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -82,17 +81,15 @@ void RYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RYYOp::getUnitaryMatrix() { +std::optional RYYOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Eigen::Matrix4cd{{mc, m0, m0, ms}, // row 0 - {m0, mc, -ms, m0}, // row 1 - {m0, -ms, mc, m0}, // row 2 - {ms, m0, m0, mc}}; // row 3 + return Matrix4::fromElements(mc, m0, m0, ms, m0, mc, -ms, m0, m0, -ms, mc, + m0, ms, m0, m0, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index cad399846c..bebf8c0c9b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -65,14 +64,15 @@ void RZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZOp::getUnitaryMatrix() { +std::optional RZOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::polar(1.0, -*theta / 2.0); const auto m01 = 0i; + const auto m10 = m01; const auto m11 = std::polar(1.0, *theta / 2.0); - return Eigen::Matrix2cd{{m00, m01}, {m01, m11}}; + return Matrix2::fromElements(m00, m01, m10, m11); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index 9f3ecedfe6..d5972322ca 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -69,17 +68,15 @@ void RZXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZXOp::getUnitaryMatrix() { +std::optional RZXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Eigen::Matrix4cd{{mc, -ms, m0, m0}, // row 0 - {-ms, mc, m0, m0}, // row 1 - {m0, m0, mc, ms}, // row 2 - {m0, m0, ms, mc}}; // row 3 + return Matrix4::fromElements(mc, -ms, m0, m0, -ms, mc, m0, m0, m0, m0, mc, + ms, m0, m0, ms, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index 8a6793475b..f7715a6991 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -12,7 +12,6 @@ #include "mlir/Dialect/QCO/QCOUtils.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -82,17 +81,15 @@ void RZZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZZOp::getUnitaryMatrix() { +std::optional RZZOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mp = std::polar(1.0, *theta / 2.0); const auto mm = std::polar(1.0, -*theta / 2.0); - return Eigen::Matrix4cd{{mm, m0, m0, m0}, // row 0 - {m0, mp, m0, m0}, // row 1 - {m0, m0, mp, m0}, // row 2 - {m0, m0, m0, mm}}; // row 3 + return Matrix4::fromElements(mm, m0, m0, m0, m0, mp, m0, m0, m0, m0, mp, m0, + m0, m0, m0, mm); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index e557053b4b..5cee05ba7b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -55,9 +54,8 @@ void SOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd SOp::getUnitaryMatrix() { +Matrix2 SOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Eigen::Matrix2cd{{1.0, 0.0}, // row 0 - {0.0, 1i}}; // row 1 + return Matrix2::fromElements(1.0, 0.0, 0.0, 1i); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp index b0cb2907e8..81820fdef1 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -55,9 +54,6 @@ void SWAPOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix4cd SWAPOp::getUnitaryMatrix() { - return Eigen::Matrix4cd{{1, 0, 0, 0}, // row 0 - {0, 0, 1, 0}, // row 1 - {0, 1, 0, 0}, // row 2 - {0, 0, 0, 1}}; // row 3 +Matrix4 SWAPOp::getUnitaryMatrix() { + return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index 35a26622a2..0110db7490 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -55,8 +54,10 @@ void SXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd SXOp::getUnitaryMatrix() { +Matrix2 SXOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, 0.5}; constexpr auto m01 = std::complex{0.5, -0.5}; - return Eigen::Matrix2cd{{m00, m01}, {m01, m00}}; + constexpr auto m10 = m01; + constexpr auto m11 = m00; + return Matrix2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index c77e15cbf0..583531eb0e 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -56,8 +55,10 @@ void SXdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd SXdgOp::getUnitaryMatrix() { +Matrix2 SXdgOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, -0.5}; constexpr auto m01 = std::complex{0.5, 0.5}; - return Eigen::Matrix2cd{{m00, m01}, {m01, m00}}; + constexpr auto m10 = m01; + constexpr auto m11 = m00; + return Matrix2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index 8a6cf8606c..f5d472d642 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -55,9 +54,8 @@ void SdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd SdgOp::getUnitaryMatrix() { +Matrix2 SdgOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Eigen::Matrix2cd{{1.0, 0.0}, // row 0 - {0.0, -1i}}; // row 1 + return Matrix2::fromElements(1.0, 0.0, 0.0, -1i); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index 14afd9814a..df2744cf2b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -56,7 +55,7 @@ void TOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd TOp::getUnitaryMatrix() { +Matrix2 TOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, std::numbers::pi / 4.0); - return Eigen::Matrix2cd{{1.0, 0.0}, {0.0, m11}}; + return Matrix2::fromElements(1.0, 0.0, 0.0, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index 21a2a07b23..8c91916180 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -57,7 +56,7 @@ void TdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd TdgOp::getUnitaryMatrix() { +Matrix2 TdgOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, -std::numbers::pi / 4.0); - return Eigen::Matrix2cd{{1.0, 0.0}, {0.0, m11}}; + return Matrix2::fromElements(1.0, 0.0, 0.0, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index 63158dfdb8..cca5a979e7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -105,7 +104,7 @@ void U2Op::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional U2Op::getUnitaryMatrix() { +std::optional U2Op::getUnitaryMatrix() { using namespace std::complex_literals; const auto phi = valueToDouble(getPhi()); @@ -119,5 +118,5 @@ std::optional U2Op::getUnitaryMatrix() { std::polar(1.0 / std::numbers::sqrt2, *lambda + std::numbers::pi); const auto m10 = std::polar(1.0 / std::numbers::sqrt2, *phi); const auto m11 = std::polar(1.0 / std::numbers::sqrt2, *phi + *lambda); - return Eigen::Matrix2cd{{m00, m01}, {m10, m11}}; + return Matrix2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index 3a5e34dddd..ea8c8ba2a3 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -125,7 +124,7 @@ void UOp::getCanonicalizationPatterns(RewritePatternSet& results, context); } -std::optional UOp::getUnitaryMatrix() { +std::optional UOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -141,5 +140,5 @@ std::optional UOp::getUnitaryMatrix() { const auto m01 = std::polar(s, *lambda + std::numbers::pi); const auto m10 = std::polar(s, *phi); const auto m11 = std::polar(c, *phi + *lambda); - return Eigen::Matrix2cd{{m00, m01}, {m10, m11}}; + return Matrix2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp index bd6903685e..d51752e0f1 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -41,6 +40,4 @@ void XOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd XOp::getUnitaryMatrix() { - return Eigen::Matrix2cd{{0, 1}, {1, 0}}; -} +Matrix2 XOp::getUnitaryMatrix() { return Matrix2::fromElements(0, 1, 1, 0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index 6bd93add60..d0db37696f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -101,7 +100,7 @@ void XXMinusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional XXMinusYYOp::getUnitaryMatrix() { +std::optional XXMinusYYOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -116,8 +115,6 @@ std::optional XXMinusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2.)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2.)); - return Eigen::Matrix4cd{{mc, m0, m0, msm}, // row 0 - {m0, m1, m0, m0}, // row 1 - {m0, m0, m1, m0}, // row 2 - {msp, m0, m0, mc}}; // row 3 + return Matrix4::fromElements(mc, m0, m0, msm, m0, m1, m0, m0, m0, m0, m1, m0, + msp, m0, m0, mc); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index 63648cdcf3..c574ea3fd5 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/Utils/Utils.h" -#include #include #include #include @@ -101,7 +100,7 @@ void XXPlusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional XXPlusYYOp::getUnitaryMatrix() { +std::optional XXPlusYYOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -116,8 +115,6 @@ std::optional XXPlusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2)); - return Eigen::Matrix4cd{{m1, m0, m0, m0}, // row 0 - {m0, mc, msp, m0}, // row 1 - {m0, msm, mc, m0}, // row 2 - {m0, m0, m0, m1}}; // row 3 + return Matrix4::fromElements(m1, m0, m0, m0, m0, mc, msp, m0, m0, msm, mc, m0, + m0, m0, m0, m1); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp index c6607fdf25..46c6965169 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -43,8 +42,8 @@ void YOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd YOp::getUnitaryMatrix() { +Matrix2 YOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Eigen::Matrix2cd{{0, -1i}, {1i, 0}}; + return Matrix2::fromElements(0, -1i, 1i, 0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 4049201bbc..2ab2fc4250 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -11,7 +11,6 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include #include #include #include @@ -41,7 +40,6 @@ void ZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Eigen::Matrix2cd ZOp::getUnitaryMatrix() { - return Eigen::Matrix2cd{{1.0, 0.0}, // row 0 - {0.0, -1.0}}; // row 1 +Matrix2 ZOp::getUnitaryMatrix() { + return Matrix2::fromElements(1.0, 0.0, 0.0, -1.0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp index a4642861a4..7e80b2e2e5 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp @@ -10,18 +10,14 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include - #include using namespace mlir; using namespace mlir::qco; -Eigen::Matrix4cd iSWAPOp::getUnitaryMatrix() { +Matrix4 iSWAPOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Eigen::Matrix4cd{{1, 0, 0, 0}, // row 0 - {0, 0, 1i, 0}, // row 1 - {0, 1i, 0, 0}, // row 2 - {0, 0, 0, 1}}; // row 3 + return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1i, 0, 0, 1i, 0, 0, 0, 0, 0, + 1); } diff --git a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp index 24103da18c..fcc012543c 100644 --- a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp @@ -17,9 +17,9 @@ #include "mlir/Dialect/QCO/Builder/QCOProgramBuilder.h" #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "qco_programs.h" -#include #include #include #include @@ -35,6 +35,19 @@ using namespace qco; namespace { +[[nodiscard]] Matrix2 matrix2FromFlat(const dd::GateMatrix& def) { + return Matrix2::fromElements(def[0], def[1], def[2], def[3]); +} + +template +[[nodiscard]] Matrix4 matrix4FromDefinition(const Definition& definition) { + return Matrix4::fromElements( + definition[0][0], definition[0][1], definition[0][2], definition[0][3], + definition[1][0], definition[1][1], definition[1][2], definition[1][3], + definition[2][0], definition[2][1], definition[2][2], definition[2][3], + definition[3][0], definition[3][1], definition[3][2], definition[3][3]); +} + struct QCOMatrixTestCase { std::string name; mqt::test::NamedBuilder programBuilder; @@ -73,16 +86,9 @@ TEST_F(QCOMatrixTest, CXOpMatrix) { const auto cxDD = dd::getDD(cx, *dd); const auto definition = cxDD.getMatrix(2); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix->isApprox(eigenDefinition)); + ASSERT_TRUE(matrix->isApprox(expected)); } /// @} @@ -103,16 +109,9 @@ TEST_F(QCOMatrixTest, InverseIswapOpMatrix) { const auto iswapdgDD = dd::getDD(iswapdg, *dd); const auto definition = iswapdgDD.getMatrix(2); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix->isApprox(eigenDefinition)); + ASSERT_TRUE(matrix->isApprox(expected)); } /// @} @@ -125,16 +124,9 @@ TEST_F(QCOMatrixTest, DCXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::DCX); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -147,16 +139,9 @@ TEST_F(QCOMatrixTest, ECROpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::ECR); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -174,12 +159,9 @@ TEST_F(QCOMatrixTest, GPhaseOpMatrix) { // Get the definition const auto definition = std::polar(1.0, 0.123); // e^(i*0.123) - // Convert it to an Eigen matrix - Eigen::Matrix, 1, 1> eigenDefinition; - eigenDefinition << definition; + const Matrix1x1 expected = Matrix1x1::fromElements(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -192,12 +174,9 @@ TEST_F(QCOMatrixTest, HOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::H); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -210,12 +189,9 @@ TEST_F(QCOMatrixTest, IdOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::I); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -228,16 +204,9 @@ TEST_F(QCOMatrixTest, iSWAPOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::iSWAP); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -255,12 +224,9 @@ TEST_F(QCOMatrixTest, POpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::P, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -278,12 +244,9 @@ TEST_F(QCOMatrixTest, ROpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::R, {0.123, 0.456}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -302,12 +265,9 @@ TEST_F(QCOMatrixTest, RXOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RX, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -325,16 +285,9 @@ TEST_F(QCOMatrixTest, RXXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RXX, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -353,12 +306,9 @@ TEST_F(QCOMatrixTest, RYOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RY, {0.456}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -376,16 +326,9 @@ TEST_F(QCOMatrixTest, RYYOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RYY, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -404,12 +347,9 @@ TEST_F(QCOMatrixTest, RZOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RZ, {0.789}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -427,16 +367,9 @@ TEST_F(QCOMatrixTest, RZXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RZX, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -454,16 +387,9 @@ TEST_F(QCOMatrixTest, RZZOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RZZ, {0.123}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -476,12 +402,9 @@ TEST_F(QCOMatrixTest, SOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::S); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -494,12 +417,9 @@ TEST_F(QCOMatrixTest, SdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Sdg); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -512,16 +432,9 @@ TEST_F(QCOMatrixTest, SWAPOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::SWAP); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -534,12 +447,9 @@ TEST_F(QCOMatrixTest, SXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::SX); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -552,12 +462,9 @@ TEST_F(QCOMatrixTest, SXdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::SXdg); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -570,12 +477,9 @@ TEST_F(QCOMatrixTest, TOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::T); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -588,12 +492,9 @@ TEST_F(QCOMatrixTest, TdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Tdg); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -612,12 +513,9 @@ TEST_F(QCOMatrixTest, U2OpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::U2, {0.234, 0.567}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -636,12 +534,9 @@ TEST_F(QCOMatrixTest, UOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::U, {0.1, 0.2, 0.3}); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -654,12 +549,9 @@ TEST_F(QCOMatrixTest, XOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::X); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -678,16 +570,9 @@ TEST_F(QCOMatrixTest, XXMinusYYOpMatrix) { const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::XXminusYY, {0.123, 0.456}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -706,16 +591,9 @@ TEST_F(QCOMatrixTest, XXPlusYYOp) { const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::XXplusYY, {0.123, 0.456}); - // Convert it to an Eigen matrix - Eigen::Matrix4cd eigenDefinition; - eigenDefinition << definition[0][0], definition[0][1], definition[0][2], - definition[0][3], definition[1][0], definition[1][1], definition[1][2], - definition[1][3], definition[2][0], definition[2][1], definition[2][2], - definition[2][3], definition[3][0], definition[3][1], definition[3][2], - definition[3][3]; + const Matrix4 expected = matrix4FromDefinition(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -728,12 +606,9 @@ TEST_F(QCOMatrixTest, YOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Y); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} @@ -746,11 +621,8 @@ TEST_F(QCOMatrixTest, ZOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Z); - // Convert it to an Eigen matrix - Eigen::Matrix2cd eigenDefinition; - eigenDefinition << definition[0], definition[1], definition[2], definition[3]; + const Matrix2 expected = matrix2FromFlat(definition); - // Check if the matrices are equal - ASSERT_TRUE(matrix.isApprox(eigenDefinition)); + ASSERT_TRUE(matrix.isApprox(expected)); } /// @} From fc1453bb7cd3efc8417dcf232116a82715d88fdf Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 8 Jun 2026 16:19:15 +0200 Subject: [PATCH 02/20] =?UTF-8?q?=F0=9F=9A=A8=20Fix=20linter=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp | 1 + mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp | 1 + .../QCO/IR/Operations/StandardGates/GPhaseOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/HOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/POp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/ROp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/SOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/TOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/UOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/XOp.cpp | 1 + .../QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp | 1 + .../QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/YOp.cpp | 1 + .../Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp | 1 + .../QCO/IR/Operations/StandardGates/iSWAPOp.cpp | 1 + mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp | 10 ++++++---- 32 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index 29aa1cc00a..e4ca57fbaa 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp index ce8182b276..02301368af 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp index b0e5b4270b..84ef783ea7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp index 6befdca029..7d156d3c26 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp index 0cfff5551b..58e536d3ae 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index 682377a9c7..6b94023623 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp index 7b9accebc7..5f21edad1e 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index 92454d8364..4fe6cd320f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index 75dbfe3d72..28ff2786ab 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index f868246f29..005df82b80 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index bc21cbe383..eb615d6244 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index 7441096884..c014d66005 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index d31b9178f8..f44857debb 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index bebf8c0c9b..38aebb75c9 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index d5972322ca..b774d087bb 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index f7715a6991..4fffd2d57a 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index 5cee05ba7b..473dea4d90 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp index 81820fdef1..bc8a0bef23 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index 0110db7490..056fc0a13d 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index 583531eb0e..a1ed2fcb5f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index f5d472d642..bb30c092ef 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index df2744cf2b..ad6fd97db0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index 8c91916180..69d0847835 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index cca5a979e7..957557f884 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index ea8c8ba2a3..fd57ad4526 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp index d51752e0f1..2f004b74df 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index d0db37696f..4062596c81 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index c574ea3fd5..39f811de52 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp index 46c6965169..f48cd7764c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 2ab2fc4250..03a4e799bc 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -10,6 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp index 7e80b2e2e5..a3493b10ac 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp @@ -9,6 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" #include diff --git a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp index fcc012543c..253aacaf9d 100644 --- a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp @@ -9,6 +9,7 @@ */ #include "TestCaseUtils.h" +#include "dd/DDDefinitions.hpp" #include "dd/GateMatrixDefinitions.hpp" #include "dd/Operations.hpp" #include "dd/Package.hpp" @@ -33,14 +34,13 @@ using namespace mlir; using namespace qco; -namespace { - -[[nodiscard]] Matrix2 matrix2FromFlat(const dd::GateMatrix& def) { +[[nodiscard]] static Matrix2 matrix2FromFlat(const dd::GateMatrix& def) { return Matrix2::fromElements(def[0], def[1], def[2], def[3]); } template -[[nodiscard]] Matrix4 matrix4FromDefinition(const Definition& definition) { +[[nodiscard]] static Matrix4 +matrix4FromDefinition(const Definition& definition) { return Matrix4::fromElements( definition[0][0], definition[0][1], definition[0][2], definition[0][3], definition[1][0], definition[1][1], definition[1][2], definition[1][3], @@ -48,6 +48,8 @@ template definition[3][0], definition[3][1], definition[3][2], definition[3][3]); } +namespace { + struct QCOMatrixTestCase { std::string name; mqt::test::NamedBuilder programBuilder; From 504f603938f29cca7112a4f289cab5c85ecb0193 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Mon, 8 Jun 2026 16:35:11 +0200 Subject: [PATCH 03/20] =?UTF-8?q?=F0=9F=8E=A8=20Rename=20Matrix2=20and=20M?= =?UTF-8?q?atrix4=20to=20Matrix2x2=20and=20Matrix4x4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 18 ++--- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 56 +++++++-------- .../mlir/Dialect/QCO/Utils/UnitaryMatrix.h | 70 +++++++++---------- .../QCO/IR/Operations/StandardGates/DCXOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/ECROp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/HOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/IdOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/POp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/ROp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/RXOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/RXXOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RYOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/RYYOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RZOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/RZXOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RZZOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/SOp.cpp | 4 +- .../IR/Operations/StandardGates/SWAPOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/SXOp.cpp | 4 +- .../IR/Operations/StandardGates/SXdgOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/SdgOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/TOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/TdgOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/U2Op.cpp | 4 +- .../QCO/IR/Operations/StandardGates/UOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/XOp.cpp | 4 +- .../Operations/StandardGates/XXMinusYYOp.cpp | 6 +- .../Operations/StandardGates/XXPlusYYOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/YOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/ZOp.cpp | 4 +- .../IR/Operations/StandardGates/iSWAPOp.cpp | 6 +- .../Dialect/QCO/IR/test_qco_ir_matrix.cpp | 68 +++++++++--------- 32 files changed, 174 insertions(+), 168 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 91d9bfac2b..16296b18f4 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -58,7 +58,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { if (auto matrix = $_op.getUnitaryMatrix()) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix2>) { + ::mlir::qco::Matrix2x2>) { out = *matrix; return true; } @@ -67,7 +67,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix2>) { + ::mlir::qco::Matrix2x2>) { out = $_op.getUnitaryMatrix(); return true; } @@ -82,7 +82,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { if (auto matrix = $_op.getUnitaryMatrix()) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix4>) { + ::mlir::qco::Matrix4x4>) { out = *matrix; return true; } @@ -91,7 +91,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix4>) { + ::mlir::qco::Matrix4x4>) { out = $_op.getUnitaryMatrix(); return true; } @@ -178,11 +178,11 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { unitaryMatrix1x1MethodBody>, InterfaceMethod<"Populates the given 2x2 unitary matrix if possible.", "bool", "getUnitaryMatrix2x2", - (ins "::mlir::qco::Matrix2&":$out), + (ins "::mlir::qco::Matrix2x2&":$out), unitaryMatrix2x2MethodBody>, InterfaceMethod<"Populates the given 4x4 unitary matrix if possible.", "bool", "getUnitaryMatrix4x4", - (ins "::mlir::qco::Matrix4&":$out), + (ins "::mlir::qco::Matrix4x4&":$out), unitaryMatrix4x4MethodBody>, InterfaceMethod<"Populates the given dynamic unitary matrix.", "bool", "getUnitaryMatrixDynamic", @@ -203,15 +203,15 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { template std::optional getUnitaryMatrix() { static_assert(::mlir::qco::IS_UNITARY_MATRIX_V, - "MatrixType must be Matrix1x1, Matrix2, Matrix4, or DynamicMatrix"); + "MatrixType must be Matrix1x1, Matrix2x2, Matrix4x4, or DynamicMatrix"); MatrixType out; bool result = false; if constexpr (std::is_same_v) { result = this->getUnitaryMatrix1x1(out); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix2x2(out); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix4x4(out); } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrixDynamic(out); diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index 5a47bc32ad..a923f4e790 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -226,7 +226,7 @@ def IdOp : QCOOp<"id", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "id"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -250,7 +250,7 @@ def XOp : QCOOp<"x", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "x"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -274,7 +274,7 @@ def YOp : QCOOp<"y", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "y"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -298,7 +298,7 @@ def ZOp : QCOOp<"z", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "z"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -322,7 +322,7 @@ def HOp : QCOOp<"h", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "h"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -346,7 +346,7 @@ def SOp : QCOOp<"s", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "s"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -371,7 +371,7 @@ def SdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -395,7 +395,7 @@ def TOp : QCOOp<"t", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "t"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -420,7 +420,7 @@ def TdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "tdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -444,7 +444,7 @@ def SXOp : QCOOp<"sx", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sx"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -469,7 +469,7 @@ def SXdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sxdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -494,7 +494,7 @@ def RXOp : QCOOp<"rx", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -523,7 +523,7 @@ def RYOp : QCOOp<"ry", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ry"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -552,7 +552,7 @@ def RZOp : QCOOp<"rz", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rz"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -581,7 +581,7 @@ def POp : QCOOp<"p", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "p"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -611,7 +611,7 @@ def ROp : QCOOp<"r", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "r"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -641,7 +641,7 @@ def U2Op : QCOOp<"u2", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u2"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -672,7 +672,7 @@ def UOp : QCOOp<"u", traits = [UnitaryOpInterface, OneTargetThreeParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -705,7 +705,7 @@ def SWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "swap"; } - [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -733,7 +733,7 @@ def iSWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "iswap"; } - [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); }]; } @@ -759,7 +759,7 @@ def DCXOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "dcx"; } - [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -787,7 +787,7 @@ def ECROp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ecr"; } - [[nodiscard]] static ::mlir::qco::Matrix4 getUnitaryMatrix(); + [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -815,7 +815,7 @@ def RXXOp : QCOOp<"rxx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rxx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -847,7 +847,7 @@ def RYYOp : QCOOp<"ryy", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ryy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -879,7 +879,7 @@ def RZXOp : QCOOp<"rzx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -911,7 +911,7 @@ def RZZOp : QCOOp<"rzz", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzz"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -945,7 +945,7 @@ def XXPlusYYOp : QCOOp<"xx_plus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_plus_yy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -980,7 +980,7 @@ def XXMinusYYOp : QCOOp<"xx_minus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_minus_yy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4> getUnitaryMatrix(); + [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, diff --git a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h index 679a5db207..c39795fe7a 100644 --- a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h +++ b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h @@ -90,7 +90,7 @@ struct Matrix1x1 { * Represents single-qubit gate unitaries. Elements are stored in a flat array * with index `(row * K_COLS) + col`. */ -struct Matrix2 { +struct Matrix2x2 { /// Number of rows. static constexpr std::size_t K_ROWS = 2; /// Number of columns. @@ -107,11 +107,11 @@ struct Matrix2 { * @param m01 Element at row 0, column 1. * @param m10 Element at row 1, column 0. * @param m11 Element at row 1, column 1. - * @return A new `Matrix2` with the given elements. + * @return A new `Matrix2x2` with the given elements. */ - [[nodiscard]] static Matrix2 fromElements(Complex m00, Complex m01, - Complex m10, Complex m11) { - Matrix2 m{}; + [[nodiscard]] static Matrix2x2 fromElements(Complex m00, Complex m01, + Complex m10, Complex m11) { + Matrix2x2 m{}; m.data = {m00, m01, m10, m11}; return m; } @@ -120,7 +120,7 @@ struct Matrix2 { * @brief Returns the 2x2 identity matrix. * @return Identity matrix `[[1, 0], [0, 1]]`. */ - [[nodiscard]] static Matrix2 identity() { return fromElements(1, 0, 0, 1); } + [[nodiscard]] static Matrix2x2 identity() { return fromElements(1, 0, 0, 1); } /** * @brief Mutable element access. @@ -147,8 +147,8 @@ struct Matrix2 { * @param rhs Right-hand factor. * @return Product of the two matrices. */ - [[nodiscard]] Matrix2 operator*(const Matrix2& rhs) const { - Matrix2 out{}; + [[nodiscard]] Matrix2x2 operator*(const Matrix2x2& rhs) const { + Matrix2x2 out{}; for (std::size_t i = 0; i < K_ROWS; ++i) { for (std::size_t j = 0; j < K_COLS; ++j) { out(i, j) = (*this)(i, 0) * rhs(0, j) + (*this)(i, 1) * rhs(1, j); @@ -161,7 +161,7 @@ struct Matrix2 { * @brief Returns the conjugate transpose (adjoint) of this matrix. * @return Adjoint matrix `A^\dagger`. */ - [[nodiscard]] Matrix2 adjoint() const { + [[nodiscard]] Matrix2x2 adjoint() const { return fromElements(std::conj((*this)(0, 0)), std::conj((*this)(1, 0)), std::conj((*this)(0, 1)), std::conj((*this)(1, 1))); } @@ -190,7 +190,7 @@ struct Matrix2 { * @param tol Maximum allowed absolute difference per entry. * @return True if every entry differs by at most @p tol. */ - [[nodiscard]] bool isApprox(const Matrix2& other, + [[nodiscard]] bool isApprox(const Matrix2x2& other, double tol = UNITARY_MATRIX_TOLERANCE) const { for (std::size_t i = 0; i < data.size(); ++i) { if (std::abs(data[i] - other.data[i]) > tol) { @@ -207,7 +207,7 @@ struct Matrix2 { * Represents two-qubit gate unitaries. Elements are stored in a flat array with * index `(row * K_COLS) + col`. */ -struct Matrix4 { +struct Matrix4x4 { /// Number of rows. static constexpr std::size_t K_ROWS = 4; /// Number of columns. @@ -236,14 +236,14 @@ struct Matrix4 { * @param m31 Element at row 3, column 1. * @param m32 Element at row 3, column 2. * @param m33 Element at row 3, column 3. - * @return A new `Matrix4` with the given elements. + * @return A new `Matrix4x4` with the given elements. */ - [[nodiscard]] static Matrix4 + [[nodiscard]] static Matrix4x4 fromElements(Complex m00, Complex m01, Complex m02, Complex m03, Complex m10, Complex m11, Complex m12, Complex m13, Complex m20, Complex m21, Complex m22, Complex m23, Complex m30, Complex m31, Complex m32, Complex m33) { - Matrix4 m{}; + Matrix4x4 m{}; m.data = {m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33}; return m; @@ -253,8 +253,8 @@ struct Matrix4 { * @brief Returns the 4x4 identity matrix. * @return Identity matrix with ones on the diagonal. */ - [[nodiscard]] static Matrix4 identity() { - Matrix4 m{}; + [[nodiscard]] static Matrix4x4 identity() { + Matrix4x4 m{}; for (std::size_t i = 0; i < K_ROWS; ++i) { m(i, i) = 1.0; } @@ -286,8 +286,8 @@ struct Matrix4 { * @param rhs Right-hand factor. * @return Product of the two matrices. */ - [[nodiscard]] Matrix4 operator*(const Matrix4& rhs) const { - Matrix4 out{}; + [[nodiscard]] Matrix4x4 operator*(const Matrix4x4& rhs) const { + Matrix4x4 out{}; for (std::size_t i = 0; i < K_ROWS; ++i) { for (std::size_t j = 0; j < K_COLS; ++j) { Complex sum{0.0, 0.0}; @@ -304,8 +304,8 @@ struct Matrix4 { * @brief Returns the conjugate transpose (adjoint) of this matrix. * @return Adjoint matrix `A^\dagger`. */ - [[nodiscard]] Matrix4 adjoint() const { - Matrix4 out{}; + [[nodiscard]] Matrix4x4 adjoint() const { + Matrix4x4 out{}; for (std::size_t i = 0; i < K_ROWS; ++i) { for (std::size_t j = 0; j < K_COLS; ++j) { out(i, j) = std::conj((*this)(j, i)); @@ -338,7 +338,7 @@ struct Matrix4 { * @param tol Maximum allowed absolute difference per entry. * @return True if every entry differs by at most @p tol. */ - [[nodiscard]] bool isApprox(const Matrix4& other, + [[nodiscard]] bool isApprox(const Matrix4x4& other, double tol = UNITARY_MATRIX_TOLERANCE) const { for (std::size_t i = 0; i < data.size(); ++i) { if (std::abs(data[i] - other.data[i]) > tol) { @@ -417,7 +417,7 @@ class DynamicMatrix { * @param block Source block placed at indices `(dim-2, dim-2)` through * `(dim-1, dim-1)`. */ - void setBottomRightCorner(const Matrix2& block) { + void setBottomRightCorner(const Matrix2x2& block) { const std::int64_t offset = dim_ - 2; for (std::int64_t i = 0; i < 2; ++i) { for (std::int64_t j = 0; j < 2; ++j) { @@ -432,7 +432,7 @@ class DynamicMatrix { * @param block Source block placed at indices `(dim-4, dim-4)` through * `(dim-1, dim-1)`. */ - void setBottomRightCorner(const Matrix4& block) { + void setBottomRightCorner(const Matrix4x4& block) { const std::int64_t offset = dim_ - 4; for (std::int64_t i = 0; i < 4; ++i) { for (std::int64_t j = 0; j < 4; ++j) { @@ -479,7 +479,7 @@ class DynamicMatrix { * @param tol Maximum allowed absolute difference per entry. * @return True if dimensions match and every entry differs by at most @p tol. */ - [[nodiscard]] bool isApprox(const Matrix4& other, + [[nodiscard]] bool isApprox(const Matrix4x4& other, double tol = UNITARY_MATRIX_TOLERANCE) const { if (dim_ != 4) { return false; @@ -530,7 +530,7 @@ class DynamicMatrix { * * Computed via Laplace expansion along the first row. */ -inline Complex Matrix4::determinant() const { +inline Complex Matrix4x4::determinant() const { auto det3 = [](Complex m00, Complex m01, Complex m02, Complex m10, Complex m11, Complex m12, Complex m20, Complex m21, Complex m22) { @@ -559,10 +559,10 @@ template struct IsUnitaryMatrix : std::false_type {}; /// @brief Specialization for `Matrix1x1`. template <> struct IsUnitaryMatrix : std::true_type {}; -/// @brief Specialization for `Matrix2`. -template <> struct IsUnitaryMatrix : std::true_type {}; -/// @brief Specialization for `Matrix4`. -template <> struct IsUnitaryMatrix : std::true_type {}; +/// @brief Specialization for `Matrix2x2`. +template <> struct IsUnitaryMatrix : std::true_type {}; +/// @brief Specialization for `Matrix4x4`. +template <> struct IsUnitaryMatrix : std::true_type {}; /// @brief Specialization for `DynamicMatrix`. template <> struct IsUnitaryMatrix : std::true_type {}; @@ -590,10 +590,10 @@ inline void copyInto(DynamicMatrix& out, const Matrix1x1& src) { * @param out Destination matrix, resized to 2x2. * @param src Source matrix. */ -inline void copyInto(DynamicMatrix& out, const Matrix2& src) { +inline void copyInto(DynamicMatrix& out, const Matrix2x2& src) { out = DynamicMatrix(2); - for (std::size_t i = 0; i < Matrix2::K_ROWS; ++i) { - for (std::size_t j = 0; j < Matrix2::K_COLS; ++j) { + for (std::size_t i = 0; i < Matrix2x2::K_ROWS; ++i) { + for (std::size_t j = 0; j < Matrix2x2::K_COLS; ++j) { out(static_cast(i), static_cast(j)) = src(i, j); } @@ -605,10 +605,10 @@ inline void copyInto(DynamicMatrix& out, const Matrix2& src) { * @param out Destination matrix, resized to 4x4. * @param src Source matrix. */ -inline void copyInto(DynamicMatrix& out, const Matrix4& src) { +inline void copyInto(DynamicMatrix& out, const Matrix4x4& src) { out = DynamicMatrix(4); - for (std::size_t i = 0; i < Matrix4::K_ROWS; ++i) { - for (std::size_t j = 0; j < Matrix4::K_COLS; ++j) { + for (std::size_t i = 0; i < Matrix4x4::K_ROWS; ++i) { + for (std::size_t j = 0; j < Matrix4x4::K_COLS; ++j) { out(static_cast(i), static_cast(j)) = src(i, j); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp index 84ef783ea7..44e36cd396 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp @@ -43,6 +43,7 @@ void DCXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix4 DCXOp::getUnitaryMatrix() { - return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0); +Matrix4x4 DCXOp::getUnitaryMatrix() { + return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, + 0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp index 7d156d3c26..fd909b1d9f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp @@ -44,12 +44,12 @@ void ECROp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix4 ECROp::getUnitaryMatrix() { +Matrix4x4 ECROp::getUnitaryMatrix() { using namespace std::complex_literals; constexpr auto m0 = 0i; constexpr auto m1 = std::complex{1.0 / std::numbers::sqrt2}; constexpr auto mi = std::complex{0.0, 1.0 / std::numbers::sqrt2}; - return Matrix4::fromElements(m0, m0, m1, mi, m0, m0, mi, m1, m1, -mi, m0, m0, - -mi, m1, m0, m0); + return Matrix4x4::fromElements(m0, m0, m1, mi, m0, m0, mi, m1, m1, -mi, m0, + m0, -mi, m1, m0, m0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index 6b94023623..79d293f8d9 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -43,7 +43,7 @@ void HOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 HOp::getUnitaryMatrix() { +Matrix2x2 HOp::getUnitaryMatrix() { constexpr auto x = 1.0 / std::numbers::sqrt2; - return Matrix2::fromElements(x, x, x, -1.0 * x); + return Matrix2x2::fromElements(x, x, x, -1.0 * x); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp index 5f21edad1e..9190b96961 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp @@ -41,4 +41,6 @@ void IdOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 IdOp::getUnitaryMatrix() { return Matrix2::fromElements(1, 0, 0, 1); } +Matrix2x2 IdOp::getUnitaryMatrix() { + return Matrix2x2::fromElements(1, 0, 0, 1); +} diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index 4fe6cd320f..541be6cc5d 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -65,9 +65,9 @@ void POp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional POp::getUnitaryMatrix() { +std::optional POp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - return Matrix2::fromElements(1.0, 0.0, 0.0, std::polar(1.0, *theta)); + return Matrix2x2::fromElements(1.0, 0.0, 0.0, std::polar(1.0, *theta)); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index 28ff2786ab..330dc19e58 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -80,7 +80,7 @@ void ROp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional ROp::getUnitaryMatrix() { +std::optional ROp::getUnitaryMatrix() { const auto theta = valueToDouble(getTheta()); const auto phi = valueToDouble(getPhi()); if (!theta || !phi) { @@ -91,5 +91,5 @@ std::optional ROp::getUnitaryMatrix() { const auto m01 = std::polar(thetaSin, -*phi - (std::numbers::pi / 2)); const auto m10 = std::polar(thetaSin, *phi - (std::numbers::pi / 2)); const std::complex thetaCos = std::cos(*theta / 2.0); - return Matrix2::fromElements(thetaCos, m01, m10, thetaCos); + return Matrix2x2::fromElements(thetaCos, m01, m10, thetaCos); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index 005df82b80..3eb19fd0e6 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -65,7 +65,7 @@ void RXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RXOp::getUnitaryMatrix() { +std::optional RXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { @@ -73,7 +73,7 @@ std::optional RXOp::getUnitaryMatrix() { const auto m01 = -1i * std::sin(*theta / 2.0); const auto m10 = m01; const auto m11 = m00; - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index eb615d6244..18dc684791 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -82,15 +82,15 @@ void RXXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RXXOp::getUnitaryMatrix() { +std::optional RXXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::cos(*theta / 2.0) + 0i; const auto ms = -1i * std::sin(*theta / 2.0); - return Matrix4::fromElements(mc, m0, m0, ms, m0, mc, ms, m0, m0, ms, mc, m0, - ms, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, ms, m0, mc, ms, m0, m0, ms, mc, + m0, ms, m0, m0, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index c014d66005..954f66820a 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -65,11 +65,11 @@ void RYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RYOp::getUnitaryMatrix() { +std::optional RYOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::complex{std::cos(*theta / 2.0)}; const auto m01 = std::complex{-std::sin(*theta / 2.0)}; - return Matrix2::fromElements(m00, m01, -m01, m00); + return Matrix2x2::fromElements(m00, m01, -m01, m00); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index f44857debb..46eef7717c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -82,15 +82,15 @@ void RYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RYYOp::getUnitaryMatrix() { +std::optional RYYOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4::fromElements(mc, m0, m0, ms, m0, mc, -ms, m0, m0, -ms, mc, - m0, ms, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, ms, m0, mc, -ms, m0, m0, -ms, mc, + m0, ms, m0, m0, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index 38aebb75c9..2e5020c826 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -65,7 +65,7 @@ void RZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZOp::getUnitaryMatrix() { +std::optional RZOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { @@ -73,7 +73,7 @@ std::optional RZOp::getUnitaryMatrix() { const auto m01 = 0i; const auto m10 = m01; const auto m11 = std::polar(1.0, *theta / 2.0); - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index b774d087bb..4254b118de 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -69,15 +69,15 @@ void RZXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZXOp::getUnitaryMatrix() { +std::optional RZXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4::fromElements(mc, -ms, m0, m0, -ms, mc, m0, m0, m0, m0, mc, - ms, m0, m0, ms, mc); + return Matrix4x4::fromElements(mc, -ms, m0, m0, -ms, mc, m0, m0, m0, m0, mc, + ms, m0, m0, ms, mc); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index 4fffd2d57a..f8a49585ac 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -82,15 +82,15 @@ void RZZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional RZZOp::getUnitaryMatrix() { +std::optional RZZOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; const auto mp = std::polar(1.0, *theta / 2.0); const auto mm = std::polar(1.0, -*theta / 2.0); - return Matrix4::fromElements(mm, m0, m0, m0, m0, mp, m0, m0, m0, m0, mp, m0, - m0, m0, m0, mm); + return Matrix4x4::fromElements(mm, m0, m0, m0, m0, mp, m0, m0, m0, m0, mp, + m0, m0, m0, m0, mm); } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index 473dea4d90..03af3a9ba0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -55,8 +55,8 @@ void SOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 SOp::getUnitaryMatrix() { +Matrix2x2 SOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2::fromElements(1.0, 0.0, 0.0, 1i); + return Matrix2x2::fromElements(1.0, 0.0, 0.0, 1i); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp index bc8a0bef23..2ad29e98f7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp @@ -55,6 +55,7 @@ void SWAPOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix4 SWAPOp::getUnitaryMatrix() { - return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1); +Matrix4x4 SWAPOp::getUnitaryMatrix() { + return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, + 1); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index 056fc0a13d..41ac85085f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -55,10 +55,10 @@ void SXOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 SXOp::getUnitaryMatrix() { +Matrix2x2 SXOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, 0.5}; constexpr auto m01 = std::complex{0.5, -0.5}; constexpr auto m10 = m01; constexpr auto m11 = m00; - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index a1ed2fcb5f..4b087bb923 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -56,10 +56,10 @@ void SXdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 SXdgOp::getUnitaryMatrix() { +Matrix2x2 SXdgOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, -0.5}; constexpr auto m01 = std::complex{0.5, 0.5}; constexpr auto m10 = m01; constexpr auto m11 = m00; - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index bb30c092ef..2562d03f71 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -55,8 +55,8 @@ void SdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 SdgOp::getUnitaryMatrix() { +Matrix2x2 SdgOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2::fromElements(1.0, 0.0, 0.0, -1i); + return Matrix2x2::fromElements(1.0, 0.0, 0.0, -1i); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index ad6fd97db0..bebfc45d3c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -56,7 +56,7 @@ void TOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 TOp::getUnitaryMatrix() { +Matrix2x2 TOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, std::numbers::pi / 4.0); - return Matrix2::fromElements(1.0, 0.0, 0.0, m11); + return Matrix2x2::fromElements(1.0, 0.0, 0.0, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index 69d0847835..a4d2c9776a 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -57,7 +57,7 @@ void TdgOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 TdgOp::getUnitaryMatrix() { +Matrix2x2 TdgOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, -std::numbers::pi / 4.0); - return Matrix2::fromElements(1.0, 0.0, 0.0, m11); + return Matrix2x2::fromElements(1.0, 0.0, 0.0, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index 957557f884..4467a1477c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -105,7 +105,7 @@ void U2Op::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional U2Op::getUnitaryMatrix() { +std::optional U2Op::getUnitaryMatrix() { using namespace std::complex_literals; const auto phi = valueToDouble(getPhi()); @@ -119,5 +119,5 @@ std::optional U2Op::getUnitaryMatrix() { std::polar(1.0 / std::numbers::sqrt2, *lambda + std::numbers::pi); const auto m10 = std::polar(1.0 / std::numbers::sqrt2, *phi); const auto m11 = std::polar(1.0 / std::numbers::sqrt2, *phi + *lambda); - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index fd57ad4526..0103d17fcb 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -125,7 +125,7 @@ void UOp::getCanonicalizationPatterns(RewritePatternSet& results, context); } -std::optional UOp::getUnitaryMatrix() { +std::optional UOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -141,5 +141,5 @@ std::optional UOp::getUnitaryMatrix() { const auto m01 = std::polar(s, *lambda + std::numbers::pi); const auto m10 = std::polar(s, *phi); const auto m11 = std::polar(c, *phi + *lambda); - return Matrix2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, m10, m11); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp index 2f004b74df..7096d832ea 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp @@ -41,4 +41,6 @@ void XOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 XOp::getUnitaryMatrix() { return Matrix2::fromElements(0, 1, 1, 0); } +Matrix2x2 XOp::getUnitaryMatrix() { + return Matrix2x2::fromElements(0, 1, 1, 0); +} diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index 4062596c81..f4d894d86f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -101,7 +101,7 @@ void XXMinusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional XXMinusYYOp::getUnitaryMatrix() { +std::optional XXMinusYYOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -116,6 +116,6 @@ std::optional XXMinusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2.)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2.)); - return Matrix4::fromElements(mc, m0, m0, msm, m0, m1, m0, m0, m0, m0, m1, m0, - msp, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, msm, m0, m1, m0, m0, m0, m0, m1, + m0, msp, m0, m0, mc); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index 39f811de52..dd3132553c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -101,7 +101,7 @@ void XXPlusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -std::optional XXPlusYYOp::getUnitaryMatrix() { +std::optional XXPlusYYOp::getUnitaryMatrix() { using namespace std::complex_literals; const auto theta = valueToDouble(getTheta()); @@ -116,6 +116,6 @@ std::optional XXPlusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2)); - return Matrix4::fromElements(m1, m0, m0, m0, m0, mc, msp, m0, m0, msm, mc, m0, - m0, m0, m0, m1); + return Matrix4x4::fromElements(m1, m0, m0, m0, m0, mc, msp, m0, m0, msm, mc, + m0, m0, m0, m0, m1); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp index f48cd7764c..44b5ed4d34 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp @@ -43,8 +43,8 @@ void YOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 YOp::getUnitaryMatrix() { +Matrix2x2 YOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2::fromElements(0, -1i, 1i, 0); + return Matrix2x2::fromElements(0, -1i, 1i, 0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 03a4e799bc..111ceeb5c4 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -41,6 +41,6 @@ void ZOp::getCanonicalizationPatterns(RewritePatternSet& results, results.add(context); } -Matrix2 ZOp::getUnitaryMatrix() { - return Matrix2::fromElements(1.0, 0.0, 0.0, -1.0); +Matrix2x2 ZOp::getUnitaryMatrix() { + return Matrix2x2::fromElements(1.0, 0.0, 0.0, -1.0); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp index a3493b10ac..88015c51f9 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp @@ -16,9 +16,9 @@ using namespace mlir; using namespace mlir::qco; -Matrix4 iSWAPOp::getUnitaryMatrix() { +Matrix4x4 iSWAPOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix4::fromElements(1, 0, 0, 0, 0, 0, 1i, 0, 0, 1i, 0, 0, 0, 0, 0, - 1); + return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1i, 0, 0, 1i, 0, 0, 0, 0, 0, + 1); } diff --git a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp index 253aacaf9d..2d4a81f06b 100644 --- a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp @@ -34,14 +34,14 @@ using namespace mlir; using namespace qco; -[[nodiscard]] static Matrix2 matrix2FromFlat(const dd::GateMatrix& def) { - return Matrix2::fromElements(def[0], def[1], def[2], def[3]); +[[nodiscard]] static Matrix2x2 matrix2FromFlat(const dd::GateMatrix& def) { + return Matrix2x2::fromElements(def[0], def[1], def[2], def[3]); } template -[[nodiscard]] static Matrix4 +[[nodiscard]] static Matrix4x4 matrix4FromDefinition(const Definition& definition) { - return Matrix4::fromElements( + return Matrix4x4::fromElements( definition[0][0], definition[0][1], definition[0][2], definition[0][3], definition[1][0], definition[1][1], definition[1][2], definition[1][3], definition[2][0], definition[2][1], definition[2][2], definition[2][3], @@ -88,7 +88,7 @@ TEST_F(QCOMatrixTest, CXOpMatrix) { const auto cxDD = dd::getDD(cx, *dd); const auto definition = cxDD.getMatrix(2); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix->isApprox(expected)); } @@ -111,7 +111,7 @@ TEST_F(QCOMatrixTest, InverseIswapOpMatrix) { const auto iswapdgDD = dd::getDD(iswapdg, *dd); const auto definition = iswapdgDD.getMatrix(2); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix->isApprox(expected)); } @@ -126,7 +126,7 @@ TEST_F(QCOMatrixTest, DCXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::DCX); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -141,7 +141,7 @@ TEST_F(QCOMatrixTest, ECROpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::ECR); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -176,7 +176,7 @@ TEST_F(QCOMatrixTest, HOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::H); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -191,7 +191,7 @@ TEST_F(QCOMatrixTest, IdOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::I); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -206,7 +206,7 @@ TEST_F(QCOMatrixTest, iSWAPOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::iSWAP); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -226,7 +226,7 @@ TEST_F(QCOMatrixTest, POpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::P, {0.123}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -246,7 +246,7 @@ TEST_F(QCOMatrixTest, ROpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::R, {0.123, 0.456}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -267,7 +267,7 @@ TEST_F(QCOMatrixTest, RXOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RX, {0.123}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -287,7 +287,7 @@ TEST_F(QCOMatrixTest, RXXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RXX, {0.123}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -308,7 +308,7 @@ TEST_F(QCOMatrixTest, RYOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RY, {0.456}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -328,7 +328,7 @@ TEST_F(QCOMatrixTest, RYYOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RYY, {0.123}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -349,7 +349,7 @@ TEST_F(QCOMatrixTest, RZOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::RZ, {0.789}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -369,7 +369,7 @@ TEST_F(QCOMatrixTest, RZXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RZX, {0.123}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -389,7 +389,7 @@ TEST_F(QCOMatrixTest, RZZOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::RZZ, {0.123}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -404,7 +404,7 @@ TEST_F(QCOMatrixTest, SOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::S); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -419,7 +419,7 @@ TEST_F(QCOMatrixTest, SdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Sdg); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -434,7 +434,7 @@ TEST_F(QCOMatrixTest, SWAPOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::SWAP); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -449,7 +449,7 @@ TEST_F(QCOMatrixTest, SXOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::SX); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -464,7 +464,7 @@ TEST_F(QCOMatrixTest, SXdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::SXdg); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -479,7 +479,7 @@ TEST_F(QCOMatrixTest, TOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::T); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -494,7 +494,7 @@ TEST_F(QCOMatrixTest, TdgOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Tdg); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -515,7 +515,7 @@ TEST_F(QCOMatrixTest, U2OpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::U2, {0.234, 0.567}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -536,7 +536,7 @@ TEST_F(QCOMatrixTest, UOpMatrix) { const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::U, {0.1, 0.2, 0.3}); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -551,7 +551,7 @@ TEST_F(QCOMatrixTest, XOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::X); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -572,7 +572,7 @@ TEST_F(QCOMatrixTest, XXMinusYYOpMatrix) { const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::XXminusYY, {0.123, 0.456}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -593,7 +593,7 @@ TEST_F(QCOMatrixTest, XXPlusYYOp) { const auto definition = dd::opToTwoQubitGateMatrix(qc::OpType::XXplusYY, {0.123, 0.456}); - const Matrix4 expected = matrix4FromDefinition(definition); + const Matrix4x4 expected = matrix4FromDefinition(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -608,7 +608,7 @@ TEST_F(QCOMatrixTest, YOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Y); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } @@ -623,7 +623,7 @@ TEST_F(QCOMatrixTest, ZOpMatrix) { // Get the definition of the matrix from the DD library const auto definition = dd::opToSingleQubitGateMatrix(qc::OpType::Z); - const Matrix2 expected = matrix2FromFlat(definition); + const Matrix2x2 expected = matrix2FromFlat(definition); ASSERT_TRUE(matrix.isApprox(expected)); } From 67bcda42b306a8d7a0c349f0cef5e2f0127c1ae9 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 9 Jun 2026 14:21:48 +0200 Subject: [PATCH 04/20] =?UTF-8?q?=F0=9F=8E=A8=20Address=20feedback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 8 +- .../mlir/Dialect/QCO/Utils/UnitaryMatrix.h | 446 +++++------------- mlir/lib/Dialect/QCO/IR/CMakeLists.txt | 2 + mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/DCXOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/ECROp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/HOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/IdOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/POp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/ROp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/RXOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/RXXOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RYOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/RYYOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RZOp.cpp | 4 +- .../QCO/IR/Operations/StandardGates/RZXOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/RZZOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/SOp.cpp | 3 +- .../IR/Operations/StandardGates/SWAPOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/SXOp.cpp | 5 +- .../IR/Operations/StandardGates/SXdgOp.cpp | 5 +- .../QCO/IR/Operations/StandardGates/SdgOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/TOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/TdgOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/U2Op.cpp | 3 +- .../QCO/IR/Operations/StandardGates/UOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/XOp.cpp | 3 +- .../Operations/StandardGates/XXMinusYYOp.cpp | 6 +- .../Operations/StandardGates/XXPlusYYOp.cpp | 6 +- .../QCO/IR/Operations/StandardGates/YOp.cpp | 3 +- .../QCO/IR/Operations/StandardGates/ZOp.cpp | 3 +- .../IR/Operations/StandardGates/iSWAPOp.cpp | 6 +- mlir/lib/Dialect/QCO/Utils/CMakeLists.txt | 12 + mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp | 322 +++++++++++++ .../Dialect/QCO/Utils/CMakeLists.txt | 4 +- .../Dialect/QCO/Utils/test_unitary_matrix.cpp | 238 ++++++++++ 37 files changed, 782 insertions(+), 380 deletions(-) create mode 100644 mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp create mode 100644 mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dde7d6310..b24ffa3f8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel - ✨ Add conversions between `jeff` and QCO ([#1479], [#1548], [#1565], [#1637], [#1676], [#1706]) ([**@denialhaag**], [**@burgholzer**]) - ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568], [#1581], [#1583], [#1588], [#1600], [#1664], [#1709], [#1716], [#1748]) ([**@MatthiasReumann**], [**@burgholzer**]) - ✨ Add initial infrastructure for new QC and QCO MLIR dialects - ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1717], [#1728], [#1730], [#1749], [#1762], [#1765]) + ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1717], [#1728], [#1730], [#1749], [#1762], [#1765], [#1774]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**]) ### Changed @@ -29,7 +29,6 @@ This project adheres to [Semantic Versioning], with the exception that minor rel ### Removed -- 🔥 Remove the Eigen dependency from the QCO MLIR dialect ([#1774]) ([**@simon1hofmann**]) - 🔥 Remove the density matrix support from the MQT Core DD package ([#1466]) ([**@burgholzer**]) - 🔥 Remove `datastructures` (`ds`) (sub)library from MQT Core ([#1458]) ([**@burgholzer**]) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 16296b18f4..8f22872646 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -189,11 +189,13 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { (ins "::mlir::qco::DynamicMatrix&":$out), [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { if (auto matrix = $_op.getUnitaryMatrix()) { - return ::mlir::qco::detail::assignToDynamic(out, *matrix); + out.assignFrom(*matrix); + return true; } return false; } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - return ::mlir::qco::detail::assignToDynamic(out, $_op.getUnitaryMatrix()); + out.assignFrom($_op.getUnitaryMatrix()); + return true; } else { llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); } @@ -202,7 +204,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { let extraClassDeclaration = [{ template std::optional getUnitaryMatrix() { - static_assert(::mlir::qco::IS_UNITARY_MATRIX_V, + static_assert(::mlir::qco::is_unitary_matrix_v, "MatrixType must be Matrix1x1, Matrix2x2, Matrix4x4, or DynamicMatrix"); MatrixType out; bool result = false; diff --git a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h index c39795fe7a..7424faf72b 100644 --- a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h +++ b/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h @@ -10,13 +10,11 @@ #pragma once -#include - #include -#include #include #include #include +#include #include namespace mlir::qco { @@ -30,58 +28,44 @@ inline constexpr double UNITARY_MATRIX_TOLERANCE = 1e-14; /** * @brief 1x1 unitary matrix for global-phase gates. * - * Stores a single complex scalar in row-major layout. Used by operations such - * as `GPhaseOp` whose unitary is a global phase factor. + * Wraps a single complex scalar. Used by operations such as `GPhaseOp` whose + * unitary is a global phase factor. */ struct Matrix1x1 { - /// Flat storage of the single matrix entry. - std::array data{Complex{1.0, 0.0}}; + /// The sole matrix entry. + Complex value{1.0, 0.0}; /** * @brief Constructs a matrix from its single entry. * @param m00 Element at row 0, column 0. * @return A new `Matrix1x1` with the given element. */ - [[nodiscard]] static Matrix1x1 fromElements(Complex m00) { - Matrix1x1 m{}; - m(0, 0) = m00; - return m; - } + [[nodiscard]] static Matrix1x1 fromElements(Complex m00); /** * @brief Mutable element access with `(row, col)` indexing. - * @param row Row index (ignored; always 0). - * @param col Column index (ignored; always 0). + * @param row Row index (must be `0`). + * @param col Column index (must be `0`). * @return Reference to the sole matrix entry. */ - [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { - (void)row; - (void)col; - return data[0]; - } + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col); /** * @brief Const element access with `(row, col)` indexing. - * @param row Row index (ignored; always 0). - * @param col Column index (ignored; always 0). + * @param row Row index (must be `0`). + * @param col Column index (must be `0`). * @return Copy of the sole matrix entry. */ - [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { - (void)row; - (void)col; - return data[0]; - } + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const; /** - * @brief Checks approximate equality using an absolute entry-wise tolerance. + * @brief Checks approximate equality using an absolute tolerance. * @param other Matrix to compare against. - * @param tol Maximum allowed absolute difference per entry. - * @return True if the absolute difference is within @p tol. + * @param tol Maximum allowed complex modulus of the entry difference. + * @return True if the difference is within @p tol. */ [[nodiscard]] bool isApprox(const Matrix1x1& other, - double tol = UNITARY_MATRIX_TOLERANCE) const { - return std::abs(data[0] - other.data[0]) <= tol; - } + double tol = UNITARY_MATRIX_TOLERANCE) const; }; /** @@ -99,7 +83,7 @@ struct Matrix2x2 { static constexpr std::size_t K_SIZE_AT_COMPILE_TIME = 4; /// Flat row-major storage of all matrix entries. - std::array data{}; + std::array data{}; /** * @brief Constructs a matrix from its four row-major entries. @@ -110,17 +94,13 @@ struct Matrix2x2 { * @return A new `Matrix2x2` with the given elements. */ [[nodiscard]] static Matrix2x2 fromElements(Complex m00, Complex m01, - Complex m10, Complex m11) { - Matrix2x2 m{}; - m.data = {m00, m01, m10, m11}; - return m; - } + Complex m10, Complex m11); /** * @brief Returns the 2x2 identity matrix. * @return Identity matrix `[[1, 0], [0, 1]]`. */ - [[nodiscard]] static Matrix2x2 identity() { return fromElements(1, 0, 0, 1); } + [[nodiscard]] static constexpr Matrix2x2 identity() { return {{1, 0, 0, 1}}; } /** * @brief Mutable element access. @@ -128,9 +108,7 @@ struct Matrix2x2 { * @param col Column index in `[0, K_COLS)`. * @return Reference to the element at `(row, col)`. */ - [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { - return data[(row * K_COLS) + col]; - } + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col); /** * @brief Const element access. @@ -138,47 +116,32 @@ struct Matrix2x2 { * @param col Column index in `[0, K_COLS)`. * @return Copy of the element at `(row, col)`. */ - [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { - return data[(row * K_COLS) + col]; - } + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const; /** * @brief Matrix product `*this * rhs`. * @param rhs Right-hand factor. * @return Product of the two matrices. */ - [[nodiscard]] Matrix2x2 operator*(const Matrix2x2& rhs) const { - Matrix2x2 out{}; - for (std::size_t i = 0; i < K_ROWS; ++i) { - for (std::size_t j = 0; j < K_COLS; ++j) { - out(i, j) = (*this)(i, 0) * rhs(0, j) + (*this)(i, 1) * rhs(1, j); - } - } - return out; - } + [[nodiscard]] Matrix2x2 operator*(const Matrix2x2& rhs) const; /** * @brief Returns the conjugate transpose (adjoint) of this matrix. * @return Adjoint matrix `A^\dagger`. */ - [[nodiscard]] Matrix2x2 adjoint() const { - return fromElements(std::conj((*this)(0, 0)), std::conj((*this)(1, 0)), - std::conj((*this)(0, 1)), std::conj((*this)(1, 1))); - } + [[nodiscard]] Matrix2x2 adjoint() const; /** * @brief Returns the trace of this matrix. * @return Sum of diagonal entries. */ - [[nodiscard]] Complex trace() const { return (*this)(0, 0) + (*this)(1, 1); } + [[nodiscard]] Complex trace() const; /** * @brief Returns the determinant of this matrix. * @return Complex determinant `ad - bc`. */ - [[nodiscard]] Complex determinant() const { - return (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0); - } + [[nodiscard]] Complex determinant() const; /** * @brief Checks approximate equality using an absolute entry-wise tolerance. @@ -187,18 +150,11 @@ struct Matrix2x2 { * absolute value is the complex modulus. * * @param other Matrix to compare against. - * @param tol Maximum allowed absolute difference per entry. + * @param tol Maximum allowed complex modulus of each entry difference. * @return True if every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix2x2& other, - double tol = UNITARY_MATRIX_TOLERANCE) const { - for (std::size_t i = 0; i < data.size(); ++i) { - if (std::abs(data[i] - other.data[i]) > tol) { - return false; - } - } - return true; - } + double tol = UNITARY_MATRIX_TOLERANCE) const; }; /** @@ -216,7 +172,7 @@ struct Matrix4x4 { static constexpr std::size_t K_SIZE_AT_COMPILE_TIME = 16; /// Flat row-major storage of all matrix entries. - std::array data{}; + std::array data{}; /** * @brief Constructs a matrix from its sixteen row-major entries. @@ -242,23 +198,17 @@ struct Matrix4x4 { fromElements(Complex m00, Complex m01, Complex m02, Complex m03, Complex m10, Complex m11, Complex m12, Complex m13, Complex m20, Complex m21, Complex m22, Complex m23, Complex m30, Complex m31, Complex m32, - Complex m33) { - Matrix4x4 m{}; - m.data = {m00, m01, m02, m03, m10, m11, m12, m13, - m20, m21, m22, m23, m30, m31, m32, m33}; - return m; - } + Complex m33); /** * @brief Returns the 4x4 identity matrix. * @return Identity matrix with ones on the diagonal. */ - [[nodiscard]] static Matrix4x4 identity() { - Matrix4x4 m{}; - for (std::size_t i = 0; i < K_ROWS; ++i) { - m(i, i) = 1.0; - } - return m; + [[nodiscard]] static constexpr Matrix4x4 identity() { + return {{1, 0, 0, 0, // row 0 + 0, 1, 0, 0, // row 1 + 0, 0, 1, 0, // row 2 + 0, 0, 0, 1}}; // row 3 } /** @@ -267,9 +217,7 @@ struct Matrix4x4 { * @param col Column index in `[0, K_COLS)`. * @return Reference to the element at `(row, col)`. */ - [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col) { - return data[(row * K_COLS) + col]; - } + [[nodiscard]] Complex& operator()(std::size_t row, std::size_t col); /** * @brief Const element access. @@ -277,54 +225,26 @@ struct Matrix4x4 { * @param col Column index in `[0, K_COLS)`. * @return Copy of the element at `(row, col)`. */ - [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const { - return data[(row * K_COLS) + col]; - } + [[nodiscard]] Complex operator()(std::size_t row, std::size_t col) const; /** * @brief Matrix product `*this * rhs`. * @param rhs Right-hand factor. * @return Product of the two matrices. */ - [[nodiscard]] Matrix4x4 operator*(const Matrix4x4& rhs) const { - Matrix4x4 out{}; - for (std::size_t i = 0; i < K_ROWS; ++i) { - for (std::size_t j = 0; j < K_COLS; ++j) { - Complex sum{0.0, 0.0}; - for (std::size_t k = 0; k < K_COLS; ++k) { - sum += (*this)(i, k) * rhs(k, j); - } - out(i, j) = sum; - } - } - return out; - } + [[nodiscard]] Matrix4x4 operator*(const Matrix4x4& rhs) const; /** * @brief Returns the conjugate transpose (adjoint) of this matrix. * @return Adjoint matrix `A^\dagger`. */ - [[nodiscard]] Matrix4x4 adjoint() const { - Matrix4x4 out{}; - for (std::size_t i = 0; i < K_ROWS; ++i) { - for (std::size_t j = 0; j < K_COLS; ++j) { - out(i, j) = std::conj((*this)(j, i)); - } - } - return out; - } + [[nodiscard]] Matrix4x4 adjoint() const; /** * @brief Returns the trace of this matrix. * @return Sum of diagonal entries. */ - [[nodiscard]] Complex trace() const { - Complex t{0.0, 0.0}; - for (std::size_t i = 0; i < K_ROWS; ++i) { - t += (*this)(i, i); - } - return t; - } + [[nodiscard]] Complex trace() const; /** * @brief Returns the determinant of this matrix. @@ -334,19 +254,16 @@ struct Matrix4x4 { /** * @brief Checks approximate equality using an absolute entry-wise tolerance. + * + * For each entry `i`, the comparison uses `|a_i - b_i| <= tol`, where the + * absolute value is the complex modulus. + * * @param other Matrix to compare against. - * @param tol Maximum allowed absolute difference per entry. + * @param tol Maximum allowed complex modulus of each entry difference. * @return True if every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix4x4& other, - double tol = UNITARY_MATRIX_TOLERANCE) const { - for (std::size_t i = 0; i < data.size(); ++i) { - if (std::abs(data[i] - other.data[i]) > tol) { - return false; - } - } - return true; - } + double tol = UNITARY_MATRIX_TOLERANCE) const; }; /** @@ -354,43 +271,48 @@ struct Matrix4x4 { * * Used when the Hilbert-space dimension depends on the operation, for example * in controlled gates (`CtrlOp`) and inverses (`InvOp`). Storage is row-major - * in a `llvm::SmallVector`. + * and held behind a private implementation pointer. */ class DynamicMatrix { public: /// Creates an empty 0x0 matrix. - DynamicMatrix() = default; + DynamicMatrix(); /** * @brief Creates a zero-initialized square matrix. * @param dim Side length of the square matrix. */ - explicit DynamicMatrix(std::int64_t dim) : dim_(dim), data_(dim * dim) {} + explicit DynamicMatrix(std::int64_t dim); + + /// Copy constructor. + DynamicMatrix(const DynamicMatrix& other); + /// Move constructor. + DynamicMatrix(DynamicMatrix&& other) noexcept; + /// Copy assignment. + DynamicMatrix& operator=(const DynamicMatrix& other); + /// Move assignment. + DynamicMatrix& operator=(DynamicMatrix&& other) noexcept; + /// Destructor. + ~DynamicMatrix(); /** * @brief Returns a square identity matrix of the given dimension. * @param dim Side length of the identity matrix. * @return Identity matrix with ones on the diagonal. */ - [[nodiscard]] static DynamicMatrix identity(std::int64_t dim) { - DynamicMatrix m(dim); - for (std::int64_t i = 0; i < dim; ++i) { - m(i, i) = 1.0; - } - return m; - } + [[nodiscard]] static DynamicMatrix identity(std::int64_t dim); /** * @brief Returns the number of rows. * @return Matrix dimension. */ - [[nodiscard]] std::int64_t rows() const { return dim_; } + [[nodiscard]] std::int64_t rows() const; /** * @brief Returns the number of columns. * @return Matrix dimension. */ - [[nodiscard]] std::int64_t cols() const { return dim_; } + [[nodiscard]] std::int64_t cols() const; /** * @brief Mutable element access. @@ -398,9 +320,7 @@ class DynamicMatrix { * @param col Column index in `[0, dim)`. * @return Reference to the element at `(row, col)`. */ - [[nodiscard]] Complex& operator()(std::int64_t row, std::int64_t col) { - return data_[static_cast((row * dim_) + col)]; - } + [[nodiscard]] Complex& operator()(std::int64_t row, std::int64_t col); /** * @brief Const element access. @@ -408,67 +328,71 @@ class DynamicMatrix { * @param col Column index in `[0, dim)`. * @return Copy of the element at `(row, col)`. */ - [[nodiscard]] Complex operator()(std::int64_t row, std::int64_t col) const { - return data_[static_cast((row * dim_) + col)]; - } + [[nodiscard]] Complex operator()(std::int64_t row, std::int64_t col) const; /** * @brief Copies a 2x2 block into the bottom-right corner. * @param block Source block placed at indices `(dim-2, dim-2)` through * `(dim-1, dim-1)`. */ - void setBottomRightCorner(const Matrix2x2& block) { - const std::int64_t offset = dim_ - 2; - for (std::int64_t i = 0; i < 2; ++i) { - for (std::int64_t j = 0; j < 2; ++j) { - (*this)(offset + i, offset + j) = - block(static_cast(i), static_cast(j)); - } - } - } + void setBottomRightCorner(const Matrix2x2& block); /** * @brief Copies a 4x4 block into the bottom-right corner. * @param block Source block placed at indices `(dim-4, dim-4)` through * `(dim-1, dim-1)`. */ - void setBottomRightCorner(const Matrix4x4& block) { - const std::int64_t offset = dim_ - 4; - for (std::int64_t i = 0; i < 4; ++i) { - for (std::int64_t j = 0; j < 4; ++j) { - (*this)(offset + i, offset + j) = - block(static_cast(i), static_cast(j)); - } - } - } + void setBottomRightCorner(const Matrix4x4& block); /** * @brief Copies a dynamic block into the bottom-right corner. - * @param block Source block placed at indices `(dim-block.dim, ...)` through + * @param block Source block placed at indices `(dim - block.rows(), ...)` + * through * `(dim-1, dim-1)`. */ - void setBottomRightCorner(const DynamicMatrix& block) { - const std::int64_t offset = dim_ - block.dim_; - for (std::int64_t i = 0; i < block.dim_; ++i) { - for (std::int64_t j = 0; j < block.dim_; ++j) { - (*this)(offset + i, offset + j) = block(i, j); - } - } - } + void setBottomRightCorner(const DynamicMatrix& block); /** - * @brief Replaces this matrix with its conjugate transpose in place. + * @brief Returns the conjugate transpose (adjoint) of this matrix. + * @return Adjoint matrix `A^\dagger`. */ - void adjointInPlace() { - for (std::int64_t i = 0; i < dim_; ++i) { - for (std::int64_t j = i + 1; j < dim_; ++j) { - const Complex tmp = (*this)(i, j); - (*this)(i, j) = std::conj((*this)(j, i)); - (*this)(j, i) = std::conj(tmp); - } - (*this)(i, i) = std::conj((*this)(i, i)); - } - } + [[nodiscard]] DynamicMatrix adjoint() const; + + /** + * @brief Replaces this matrix with a copy of a 1x1 matrix. + * @param src Source matrix. + */ + void assignFrom(const Matrix1x1& src); + + /** + * @brief Replaces this matrix with a copy of a 2x2 matrix. + * @param src Source matrix. + */ + void assignFrom(const Matrix2x2& src); + + /** + * @brief Replaces this matrix with a copy of a 4x4 matrix. + * @param src Source matrix. + */ + void assignFrom(const Matrix4x4& src); + + /** + * @brief Replaces this matrix with a copy of another dynamic matrix. + * @param src Source matrix. + */ + void assignFrom(const DynamicMatrix& src); + + /** + * @brief Checks approximate equality against a fixed 2x2 matrix. + * + * Returns false if this matrix is not 2x2. + * + * @param other Fixed-size matrix to compare against. + * @param tol Maximum allowed complex modulus of each entry difference. + * @return True if dimensions match and every entry differs by at most @p tol. + */ + [[nodiscard]] bool isApprox(const Matrix2x2& other, + double tol = UNITARY_MATRIX_TOLERANCE) const; /** * @brief Checks approximate equality against a fixed 4x4 matrix. @@ -476,25 +400,11 @@ class DynamicMatrix { * Returns false if this matrix is not 4x4. * * @param other Fixed-size matrix to compare against. - * @param tol Maximum allowed absolute difference per entry. + * @param tol Maximum allowed complex modulus of each entry difference. * @return True if dimensions match and every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix4x4& other, - double tol = UNITARY_MATRIX_TOLERANCE) const { - if (dim_ != 4) { - return false; - } - for (std::int64_t i = 0; i < 4; ++i) { - for (std::int64_t j = 0; j < 4; ++j) { - if (std::abs((*this)(i, j) - other(static_cast(i), - static_cast(j))) > - tol) { - return false; - } - } - } - return true; - } + double tol = UNITARY_MATRIX_TOLERANCE) const; /** * @brief Checks approximate equality against another dynamic matrix. @@ -502,141 +412,29 @@ class DynamicMatrix { * Returns false if the dimensions differ. * * @param other Matrix to compare against. - * @param tol Maximum allowed absolute difference per entry. + * @param tol Maximum allowed complex modulus of each entry difference. * @return True if dimensions match and every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const DynamicMatrix& other, - double tol = UNITARY_MATRIX_TOLERANCE) const { - if (dim_ != other.dim_) { - return false; - } - for (std::size_t idx = 0; idx < data_.size(); ++idx) { - if (std::abs(data_[idx] - other.data_[idx]) > tol) { - return false; - } - } - return true; - } + double tol = UNITARY_MATRIX_TOLERANCE) const; private: - /// Side length of the square matrix. - std::int64_t dim_ = 0; - /// Flat row-major storage of all matrix entries. - llvm::SmallVector data_; + struct Impl; + std::unique_ptr impl_; }; /** - * @brief Returns the determinant of a 4x4 matrix. + * @brief Type trait for the four supported unitary matrix value types. + * + * True for @ref Matrix1x1, @ref Matrix2x2, @ref Matrix4x4, and @ref + * DynamicMatrix. * - * Computed via Laplace expansion along the first row. - */ -inline Complex Matrix4x4::determinant() const { - auto det3 = [](Complex m00, Complex m01, Complex m02, Complex m10, - Complex m11, Complex m12, Complex m20, Complex m21, - Complex m22) { - return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + - m02 * (m10 * m21 - m11 * m20); - }; - return (*this)(0, 0) * det3((*this)(1, 1), (*this)(1, 2), (*this)(1, 3), - (*this)(2, 1), (*this)(2, 2), (*this)(2, 3), - (*this)(3, 1), (*this)(3, 2), (*this)(3, 3)) - - (*this)(0, 1) * det3((*this)(1, 0), (*this)(1, 2), (*this)(1, 3), - (*this)(2, 0), (*this)(2, 2), (*this)(2, 3), - (*this)(3, 0), (*this)(3, 2), (*this)(3, 3)) + - (*this)(0, 2) * det3((*this)(1, 0), (*this)(1, 1), (*this)(1, 3), - (*this)(2, 0), (*this)(2, 1), (*this)(2, 3), - (*this)(3, 0), (*this)(3, 1), (*this)(3, 3)) - - (*this)(0, 3) * det3((*this)(1, 0), (*this)(1, 1), (*this)(1, 2), - (*this)(2, 0), (*this)(2, 1), (*this)(2, 2), - (*this)(3, 0), (*this)(3, 1), (*this)(3, 2)); -} - -/** - * @brief Type trait that identifies supported unitary matrix types. - * @tparam T Candidate type. - */ -template struct IsUnitaryMatrix : std::false_type {}; - -/// @brief Specialization for `Matrix1x1`. -template <> struct IsUnitaryMatrix : std::true_type {}; -/// @brief Specialization for `Matrix2x2`. -template <> struct IsUnitaryMatrix : std::true_type {}; -/// @brief Specialization for `Matrix4x4`. -template <> struct IsUnitaryMatrix : std::true_type {}; -/// @brief Specialization for `DynamicMatrix`. -template <> struct IsUnitaryMatrix : std::true_type {}; - -/** - * @brief Convenience variable template for `IsUnitaryMatrix::value`. * @tparam T Candidate type. */ template -inline constexpr bool IS_UNITARY_MATRIX_V = IsUnitaryMatrix::value; - -namespace detail { - -/** - * @brief Copies a 1x1 matrix into a dynamic matrix. - * @param out Destination matrix, resized to 1x1. - * @param src Source matrix. - */ -inline void copyInto(DynamicMatrix& out, const Matrix1x1& src) { - out = DynamicMatrix(1); - out(0, 0) = src(0, 0); -} - -/** - * @brief Copies a 2x2 matrix into a dynamic matrix. - * @param out Destination matrix, resized to 2x2. - * @param src Source matrix. - */ -inline void copyInto(DynamicMatrix& out, const Matrix2x2& src) { - out = DynamicMatrix(2); - for (std::size_t i = 0; i < Matrix2x2::K_ROWS; ++i) { - for (std::size_t j = 0; j < Matrix2x2::K_COLS; ++j) { - out(static_cast(i), static_cast(j)) = - src(i, j); - } - } -} - -/** - * @brief Copies a 4x4 matrix into a dynamic matrix. - * @param out Destination matrix, resized to 4x4. - * @param src Source matrix. - */ -inline void copyInto(DynamicMatrix& out, const Matrix4x4& src) { - out = DynamicMatrix(4); - for (std::size_t i = 0; i < Matrix4x4::K_ROWS; ++i) { - for (std::size_t j = 0; j < Matrix4x4::K_COLS; ++j) { - out(static_cast(i), static_cast(j)) = - src(i, j); - } - } -} - -/** - * @brief Copies a dynamic matrix into another dynamic matrix. - * @param out Destination matrix. - * @param src Source matrix. - */ -inline void copyInto(DynamicMatrix& out, const DynamicMatrix& src) { - out = src; -} - -/** - * @brief Promotes a fixed- or dynamic-size matrix into a dynamic output matrix. - * @tparam Src Source matrix type. - * @param out Destination matrix. - * @param src Source matrix. - * @return Always `true` on success. - */ -template -inline bool assignToDynamic(DynamicMatrix& out, const Src& src) { - copyInto(out, src); - return true; -} - -} // namespace detail +inline constexpr bool + is_unitary_matrix_v = // NOLINT(readability-identifier-naming) + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; } // namespace mlir::qco diff --git a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt index 85cadc03a0..cba31ac19b 100644 --- a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt @@ -24,6 +24,8 @@ add_mlir_dialect_library( MLIRQCOOpsIncGen MLIRQCOInterfacesIncGen LINK_LIBS + PUBLIC + MLIRQCOUnitaryMatrix PRIVATE MLIRIR MLIRArithDialect diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp index 02301368af..3fe9af123d 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp @@ -406,12 +406,10 @@ std::optional InvOp::getUnitaryMatrix() { if (!bodyUnitary) { return std::nullopt; } - auto targetMatrix = bodyUnitary.getUnitaryMatrix(); + const auto targetMatrix = bodyUnitary.getUnitaryMatrix(); if (!targetMatrix) { return std::nullopt; } - targetMatrix->adjointInPlace(); - - return targetMatrix; + return targetMatrix->adjoint(); } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp index 44e36cd396..0a4ad54605 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp @@ -44,6 +44,8 @@ void DCXOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix4x4 DCXOp::getUnitaryMatrix() { - return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, - 0); + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, 0, 1, 0, // row 1 + 0, 0, 0, 1, // row 2 + 0, 1, 0, 0); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp index fd909b1d9f..48d17a948b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp @@ -50,6 +50,8 @@ Matrix4x4 ECROp::getUnitaryMatrix() { constexpr auto m0 = 0i; constexpr auto m1 = std::complex{1.0 / std::numbers::sqrt2}; constexpr auto mi = std::complex{0.0, 1.0 / std::numbers::sqrt2}; - return Matrix4x4::fromElements(m0, m0, m1, mi, m0, m0, mi, m1, m1, -mi, m0, - m0, -mi, m1, m0, m0); + return Matrix4x4::fromElements(m0, m0, m1, mi, // row 0 + m0, m0, mi, m1, // row 1 + m1, -mi, m0, m0, // row 2 + -mi, m1, m0, m0); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index 79d293f8d9..f9c191ead4 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -45,5 +45,6 @@ void HOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 HOp::getUnitaryMatrix() { constexpr auto x = 1.0 / std::numbers::sqrt2; - return Matrix2x2::fromElements(x, x, x, -1.0 * x); + return Matrix2x2::fromElements(x, x, // row 0 + x, -1.0 * x); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp index 9190b96961..ecbe719c75 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp @@ -42,5 +42,6 @@ void IdOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 IdOp::getUnitaryMatrix() { - return Matrix2x2::fromElements(1, 0, 0, 1); + return Matrix2x2::fromElements(1, 0, // row 0 + 0, 1); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index 541be6cc5d..ca93eb7dc7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -67,7 +67,8 @@ void POp::getCanonicalizationPatterns(RewritePatternSet& results, std::optional POp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - return Matrix2x2::fromElements(1.0, 0.0, 0.0, std::polar(1.0, *theta)); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, std::polar(1.0, *theta)); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index 330dc19e58..86d9231ee5 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -91,5 +91,6 @@ std::optional ROp::getUnitaryMatrix() { const auto m01 = std::polar(thetaSin, -*phi - (std::numbers::pi / 2)); const auto m10 = std::polar(thetaSin, *phi - (std::numbers::pi / 2)); const std::complex thetaCos = std::cos(*theta / 2.0); - return Matrix2x2::fromElements(thetaCos, m01, m10, thetaCos); + return Matrix2x2::fromElements(thetaCos, m01, // row 0 + m10, thetaCos); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index 3eb19fd0e6..6da8a6795b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -71,9 +71,8 @@ std::optional RXOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::cos(*theta / 2.0) + 0i; const auto m01 = -1i * std::sin(*theta / 2.0); - const auto m10 = m01; - const auto m11 = m00; - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m01, m00); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index 18dc684791..a22ecaa53a 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -89,8 +89,10 @@ std::optional RXXOp::getUnitaryMatrix() { const auto m0 = 0i; const auto mc = std::cos(*theta / 2.0) + 0i; const auto ms = -1i * std::sin(*theta / 2.0); - return Matrix4x4::fromElements(mc, m0, m0, ms, m0, mc, ms, m0, m0, ms, mc, - m0, ms, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, ms, // row 0 + m0, mc, ms, m0, // row 1 + m0, ms, mc, m0, // row 2 + ms, m0, m0, mc); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index 954f66820a..d909a897de 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -69,7 +69,8 @@ std::optional RYOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::complex{std::cos(*theta / 2.0)}; const auto m01 = std::complex{-std::sin(*theta / 2.0)}; - return Matrix2x2::fromElements(m00, m01, -m01, m00); + return Matrix2x2::fromElements(m00, m01, // row 0 + -m01, m00); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index 46eef7717c..c356e118c4 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -89,8 +89,10 @@ std::optional RYYOp::getUnitaryMatrix() { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4x4::fromElements(mc, m0, m0, ms, m0, mc, -ms, m0, m0, -ms, mc, - m0, ms, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, ms, // row 0 + m0, mc, -ms, m0, // row 1 + m0, -ms, mc, m0, // row 2 + ms, m0, m0, mc); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index 2e5020c826..b4c8c13ec6 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -71,9 +71,9 @@ std::optional RZOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m00 = std::polar(1.0, -*theta / 2.0); const auto m01 = 0i; - const auto m10 = m01; const auto m11 = std::polar(1.0, *theta / 2.0); - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m01, m11); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index 4254b118de..1273716628 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -76,8 +76,10 @@ std::optional RZXOp::getUnitaryMatrix() { const auto m0 = 0i; const auto mc = std::complex{std::cos(*theta / 2.0)}; const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4x4::fromElements(mc, -ms, m0, m0, -ms, mc, m0, m0, m0, m0, mc, - ms, m0, m0, ms, mc); + return Matrix4x4::fromElements(mc, -ms, m0, m0, // row 0 + -ms, mc, m0, m0, // row 1 + m0, m0, mc, ms, // row 2 + m0, m0, ms, mc); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index f8a49585ac..83e3587dc4 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -89,8 +89,10 @@ std::optional RZZOp::getUnitaryMatrix() { const auto m0 = 0i; const auto mp = std::polar(1.0, *theta / 2.0); const auto mm = std::polar(1.0, -*theta / 2.0); - return Matrix4x4::fromElements(mm, m0, m0, m0, m0, mp, m0, m0, m0, m0, mp, - m0, m0, m0, m0, mm); + return Matrix4x4::fromElements(mm, m0, m0, m0, // row 0 + m0, mp, m0, m0, // row 1 + m0, m0, mp, m0, // row 2 + m0, m0, m0, mm); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index 03af3a9ba0..ebf297f4fe 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -58,5 +58,6 @@ void SOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2x2::fromElements(1.0, 0.0, 0.0, 1i); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, 1i); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp index 2ad29e98f7..f9b3bb7420 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp @@ -56,6 +56,8 @@ void SWAPOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix4x4 SWAPOp::getUnitaryMatrix() { - return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, - 1); + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, 0, 1, 0, // row 1 + 0, 1, 0, 0, // row 2 + 0, 0, 0, 1); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index 41ac85085f..bd25a31c0f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -58,7 +58,6 @@ void SXOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SXOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, 0.5}; constexpr auto m01 = std::complex{0.5, -0.5}; - constexpr auto m10 = m01; - constexpr auto m11 = m00; - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m01, m00); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index 4b087bb923..3d5b5acfb7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -59,7 +59,6 @@ void SXdgOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SXdgOp::getUnitaryMatrix() { constexpr auto m00 = std::complex{0.5, -0.5}; constexpr auto m01 = std::complex{0.5, 0.5}; - constexpr auto m10 = m01; - constexpr auto m11 = m00; - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m01, m00); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index 2562d03f71..711dcb3e80 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -58,5 +58,6 @@ void SdgOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SdgOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2x2::fromElements(1.0, 0.0, 0.0, -1i); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, -1i); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index bebfc45d3c..4517cd70f5 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -58,5 +58,6 @@ void TOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 TOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, std::numbers::pi / 4.0); - return Matrix2x2::fromElements(1.0, 0.0, 0.0, m11); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index a4d2c9776a..87c6976663 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -59,5 +59,6 @@ void TdgOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 TdgOp::getUnitaryMatrix() { const auto m11 = std::polar(1.0, -std::numbers::pi / 4.0); - return Matrix2x2::fromElements(1.0, 0.0, 0.0, m11); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index 4467a1477c..4f59154617 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -119,5 +119,6 @@ std::optional U2Op::getUnitaryMatrix() { std::polar(1.0 / std::numbers::sqrt2, *lambda + std::numbers::pi); const auto m10 = std::polar(1.0 / std::numbers::sqrt2, *phi); const auto m11 = std::polar(1.0 / std::numbers::sqrt2, *phi + *lambda); - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m10, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index 0103d17fcb..7e42d65c19 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -141,5 +141,6 @@ std::optional UOp::getUnitaryMatrix() { const auto m01 = std::polar(s, *lambda + std::numbers::pi); const auto m10 = std::polar(s, *phi); const auto m11 = std::polar(c, *phi + *lambda); - return Matrix2x2::fromElements(m00, m01, m10, m11); + return Matrix2x2::fromElements(m00, m01, // row 0 + m10, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp index 7096d832ea..dab82f98b7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp @@ -42,5 +42,6 @@ void XOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 XOp::getUnitaryMatrix() { - return Matrix2x2::fromElements(0, 1, 1, 0); + return Matrix2x2::fromElements(0, 1, // row 0 + 1, 0); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index f4d894d86f..f4398da177 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -116,6 +116,8 @@ std::optional XXMinusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2.)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2.)); - return Matrix4x4::fromElements(mc, m0, m0, msm, m0, m1, m0, m0, m0, m0, m1, - m0, msp, m0, m0, mc); + return Matrix4x4::fromElements(mc, m0, m0, msm, // row 0 + m0, m1, m0, m0, // row 1 + m0, m0, m1, m0, // row 2 + msp, m0, m0, mc); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index dd3132553c..9f7989ca8c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -116,6 +116,8 @@ std::optional XXPlusYYOp::getUnitaryMatrix() { const auto s = std::sin(*theta / 2.0); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2)); - return Matrix4x4::fromElements(m1, m0, m0, m0, m0, mc, msp, m0, m0, msm, mc, - m0, m0, m0, m0, m1); + return Matrix4x4::fromElements(m1, m0, m0, m0, // row 0 + m0, mc, msp, m0, // row 1 + m0, msm, mc, m0, // row 2 + m0, m0, m0, m1); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp index 44b5ed4d34..122a7fcd75 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp @@ -46,5 +46,6 @@ void YOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 YOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2x2::fromElements(0, -1i, 1i, 0); + return Matrix2x2::fromElements(0, -1i, // row 0 + 1i, 0); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 111ceeb5c4..0d286b7c44 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -42,5 +42,6 @@ void ZOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 ZOp::getUnitaryMatrix() { - return Matrix2x2::fromElements(1.0, 0.0, 0.0, -1.0); + return Matrix2x2::fromElements(1.0, 0.0, // row 0 + 0.0, -1.0); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp index 88015c51f9..104d4d5796 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp @@ -19,6 +19,8 @@ using namespace mlir::qco; Matrix4x4 iSWAPOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix4x4::fromElements(1, 0, 0, 0, 0, 0, 1i, 0, 0, 1i, 0, 0, 0, 0, 0, - 1); + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, 0, 1i, 0, // row 1 + 0, 1i, 0, 0, // row 2 + 0, 0, 0, 1); // row 3 } diff --git a/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt b/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt index 9b94885f1b..4a81c9e640 100644 --- a/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt +++ b/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt @@ -6,10 +6,21 @@ # # Licensed under the MIT License +add_mlir_library(MLIRQCOUnitaryMatrix PARTIAL_SOURCES_INTENDED UnitaryMatrix.cpp LINK_LIBS PUBLIC + MLIRSupport) + +mqt_mlir_target_use_project_options(MLIRQCOUnitaryMatrix) + +target_sources( + MLIRQCOUnitaryMatrix PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_MLIR_SOURCE_INCLUDE_DIR} FILES + ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/UnitaryMatrix.h) + file(GLOB_RECURSE UTILS_CPP "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") +list(FILTER UTILS_CPP EXCLUDE REGEX "UnitaryMatrix\\.cpp$") add_mlir_dialect_library( MLIRQCOUtils + PARTIAL_SOURCES_INTENDED ${UTILS_CPP} ADDITIONAL_HEADER_DIRS ${PROJECT_SOURCE_DIR}/mlir/include/mlir/Dialect/QCO @@ -24,6 +35,7 @@ mqt_mlir_target_use_project_options(MLIRQCOUtils) # collect header files file(GLOB_RECURSE UTILS_HEADERS_SOURCE "${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/*.h") +list(FILTER UTILS_HEADERS_SOURCE EXCLUDE REGEX "UnitaryMatrix\\.h$") file(GLOB_RECURSE UTILS_HEADERS_BUILD "${MQT_MLIR_BUILD_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/*.inc") # add public headers using file sets diff --git a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp new file mode 100644 index 0000000000..18ecd0043d --- /dev/null +++ b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" + +#include +#include + +#include +#include +#include + +namespace mlir::qco { + +struct DynamicMatrix::Impl { + std::int64_t dim = 0; + llvm::SmallVector data; +}; + +namespace { + +/// Returns true if every entry pair differs by at most @p tol (complex +/// modulus). +[[nodiscard]] bool entriesAreApprox(llvm::ArrayRef lhs, + llvm::ArrayRef rhs, double tol) { + if (lhs.size() != rhs.size()) { + return false; + } + return std::equal(lhs.begin(), lhs.end(), rhs.begin(), + [tol](const Complex& lhsEntry, const Complex& rhsEntry) { + return std::abs(lhsEntry - rhsEntry) <= tol; + }); +} + +/// Writes the conjugate transpose of @p in into @p out (square, row-major). +void adjointInto(llvm::ArrayRef in, llvm::MutableArrayRef out, + const std::size_t dim) { + for (std::size_t row = 0; row < dim; ++row) { + for (std::size_t col = 0; col < dim; ++col) { + out[(row * dim) + col] = std::conj(in[(col * dim) + row]); + } + } +} + +template +void assignFixedImpl(std::int64_t& dim, llvm::SmallVector& data, + const std::array& src) { + dim = static_cast(Dim); + data.assign(src.begin(), src.end()); +} + +template +[[nodiscard]] bool +isApproxFixedImpl(const std::int64_t dim, llvm::ArrayRef data, + const std::array& other, const double tol) { + if (dim != static_cast(Dim)) { + return false; + } + return entriesAreApprox(data, other, tol); +} + +/// Copies @p blockData into the bottom-right @p blockDim x @p blockDim corner. +void copyBottomRightCorner(const std::int64_t matrixDim, + llvm::MutableArrayRef matrixData, + const std::int64_t blockDim, + llvm::ArrayRef blockData) { + const std::int64_t offset = matrixDim - blockDim; + for (std::int64_t row = 0; row < blockDim; ++row) { + for (std::int64_t col = 0; col < blockDim; ++col) { + matrixData[static_cast(((offset + row) * matrixDim) + + offset + col)] = + blockData[static_cast((row * blockDim) + col)]; + } + } +} + +} // namespace + +Matrix1x1 Matrix1x1::fromElements(const Complex m00) { return {m00}; } + +Complex& Matrix1x1::operator()(const std::size_t row, const std::size_t col) { + assert(row == 0 && col == 0); + return value; +} + +Complex Matrix1x1::operator()(const std::size_t row, + const std::size_t col) const { + assert(row == 0 && col == 0); + return value; +} + +bool Matrix1x1::isApprox(const Matrix1x1& other, const double tol) const { + return std::abs(value - other.value) <= tol; +} + +Matrix2x2 Matrix2x2::fromElements(const Complex m00, const Complex m01, + const Complex m10, const Complex m11) { + return {{m00, m01, m10, m11}}; +} + +Complex& Matrix2x2::operator()(const std::size_t row, const std::size_t col) { + return data[(row * K_COLS) + col]; +} + +Complex Matrix2x2::operator()(const std::size_t row, + const std::size_t col) const { + return data[(row * K_COLS) + col]; +} + +Matrix2x2 Matrix2x2::operator*(const Matrix2x2& rhs) const { + return fromElements(data[0] * rhs.data[0] + data[1] * rhs.data[2], + data[0] * rhs.data[1] + data[1] * rhs.data[3], + data[2] * rhs.data[0] + data[3] * rhs.data[2], + data[2] * rhs.data[1] + data[3] * rhs.data[3]); +} + +Matrix2x2 Matrix2x2::adjoint() const { + return fromElements(std::conj(data[0]), std::conj(data[2]), + std::conj(data[1]), std::conj(data[3])); +} + +Complex Matrix2x2::trace() const { return data[0] + data[3]; } + +Complex Matrix2x2::determinant() const { + return data[0] * data[3] - data[1] * data[2]; +} + +bool Matrix2x2::isApprox(const Matrix2x2& other, const double tol) const { + return entriesAreApprox(data, other.data, tol); +} + +Matrix4x4 Matrix4x4::fromElements(const Complex m00, const Complex m01, + const Complex m02, const Complex m03, + const Complex m10, const Complex m11, + const Complex m12, const Complex m13, + const Complex m20, const Complex m21, + const Complex m22, const Complex m23, + const Complex m30, const Complex m31, + const Complex m32, const Complex m33) { + return {{m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, + m32, m33}}; +} + +Complex& Matrix4x4::operator()(const std::size_t row, const std::size_t col) { + return data[(row * K_COLS) + col]; +} + +Complex Matrix4x4::operator()(const std::size_t row, + const std::size_t col) const { + return data[(row * K_COLS) + col]; +} + +Matrix4x4 Matrix4x4::operator*(const Matrix4x4& rhs) const { + Matrix4x4 out{}; + for (std::size_t row = 0; row < K_ROWS; ++row) { + const std::size_t rowBase = row * K_COLS; + const Complex a0 = data[rowBase + 0]; + const Complex a1 = data[rowBase + 1]; + const Complex a2 = data[rowBase + 2]; + const Complex a3 = data[rowBase + 3]; + out.data[rowBase + 0] = a0 * rhs.data[0] + a1 * rhs.data[4] + + a2 * rhs.data[8] + a3 * rhs.data[12]; + out.data[rowBase + 1] = a0 * rhs.data[1] + a1 * rhs.data[5] + + a2 * rhs.data[9] + a3 * rhs.data[13]; + out.data[rowBase + 2] = a0 * rhs.data[2] + a1 * rhs.data[6] + + a2 * rhs.data[10] + a3 * rhs.data[14]; + out.data[rowBase + 3] = a0 * rhs.data[3] + a1 * rhs.data[7] + + a2 * rhs.data[11] + a3 * rhs.data[15]; + } + return out; +} + +Matrix4x4 Matrix4x4::adjoint() const { + Matrix4x4 out{}; + adjointInto(data, out.data, K_ROWS); + return out; +} + +Complex Matrix4x4::trace() const { + return data[0] + data[5] + data[10] + data[15]; +} + +Complex Matrix4x4::determinant() const { + auto det3 = [](const Complex m00, const Complex m01, const Complex m02, + const Complex m10, const Complex m11, const Complex m12, + const Complex m20, const Complex m21, const Complex m22) { + return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + + m02 * (m10 * m21 - m11 * m20); + }; + return data[0] * det3(data[5], data[6], data[7], data[9], data[10], data[11], + data[13], data[14], data[15]) - + data[1] * det3(data[4], data[6], data[7], data[8], data[10], data[11], + data[12], data[14], data[15]) + + data[2] * det3(data[4], data[5], data[7], data[8], data[9], data[11], + data[12], data[13], data[15]) - + data[3] * det3(data[4], data[5], data[6], data[8], data[9], data[10], + data[12], data[13], data[14]); +} + +bool Matrix4x4::isApprox(const Matrix4x4& other, const double tol) const { + return entriesAreApprox(data, other.data, tol); +} + +DynamicMatrix::DynamicMatrix() : impl_(std::make_unique()) {} + +DynamicMatrix::DynamicMatrix(const std::int64_t dim) + : impl_(std::make_unique()) { + impl_->dim = dim; + impl_->data.assign(static_cast(dim * dim), Complex{}); +} + +DynamicMatrix::DynamicMatrix(const DynamicMatrix& other) + : impl_(std::make_unique(*other.impl_)) {} + +DynamicMatrix::DynamicMatrix(DynamicMatrix&& other) noexcept = default; + +DynamicMatrix& DynamicMatrix::operator=(const DynamicMatrix& other) { + if (this != &other) { + *impl_ = *other.impl_; + } + return *this; +} + +DynamicMatrix& +DynamicMatrix::operator=(DynamicMatrix&& other) noexcept = default; + +DynamicMatrix::~DynamicMatrix() = default; + +std::int64_t DynamicMatrix::rows() const { return impl_->dim; } + +std::int64_t DynamicMatrix::cols() const { return impl_->dim; } + +DynamicMatrix DynamicMatrix::identity(const std::int64_t dim) { + DynamicMatrix matrix(dim); + const auto udim = static_cast(dim); + for (std::size_t i = 0; i < udim; ++i) { + matrix.impl_->data[(i * udim) + i] = 1.0; + } + return matrix; +} + +Complex& DynamicMatrix::operator()(const std::int64_t row, + const std::int64_t col) { + return impl_->data[static_cast((row * impl_->dim) + col)]; +} + +Complex DynamicMatrix::operator()(const std::int64_t row, + const std::int64_t col) const { + return impl_->data[static_cast((row * impl_->dim) + col)]; +} + +void DynamicMatrix::setBottomRightCorner(const Matrix2x2& block) { + copyBottomRightCorner(impl_->dim, impl_->data, + static_cast(Matrix2x2::K_ROWS), + block.data); +} + +void DynamicMatrix::setBottomRightCorner(const Matrix4x4& block) { + copyBottomRightCorner(impl_->dim, impl_->data, + static_cast(Matrix4x4::K_ROWS), + block.data); +} + +void DynamicMatrix::setBottomRightCorner(const DynamicMatrix& block) { + copyBottomRightCorner(impl_->dim, impl_->data, block.impl_->dim, + block.impl_->data); +} + +DynamicMatrix DynamicMatrix::adjoint() const { + DynamicMatrix out(impl_->dim); + adjointInto(impl_->data, out.impl_->data, + static_cast(impl_->dim)); + return out; +} + +void DynamicMatrix::assignFrom(const Matrix1x1& src) { + impl_->dim = 1; + impl_->data.assign({src.value}); +} + +void DynamicMatrix::assignFrom(const Matrix2x2& src) { + assignFixedImpl( + impl_->dim, impl_->data, src.data); +} + +void DynamicMatrix::assignFrom(const Matrix4x4& src) { + assignFixedImpl( + impl_->dim, impl_->data, src.data); +} + +void DynamicMatrix::assignFrom(const DynamicMatrix& src) { + *impl_ = *src.impl_; +} + +bool DynamicMatrix::isApprox(const Matrix2x2& other, const double tol) const { + return isApproxFixedImpl( + impl_->dim, impl_->data, other.data, tol); +} + +bool DynamicMatrix::isApprox(const Matrix4x4& other, const double tol) const { + return isApproxFixedImpl( + impl_->dim, impl_->data, other.data, tol); +} + +bool DynamicMatrix::isApprox(const DynamicMatrix& other, + const double tol) const { + if (impl_->dim != other.impl_->dim) { + return false; + } + return entriesAreApprox(impl_->data, other.impl_->data, tol); +} + +} // namespace mlir::qco diff --git a/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt b/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt index e5815170b6..12372120ff 100644 --- a/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt +++ b/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt @@ -7,9 +7,9 @@ # Licensed under the MIT License set(qco_utils_target mqt-core-mlir-unittest-qco-utils) -add_executable(${qco_utils_target} test_drivers.cpp test_wireiterator.cpp) +add_executable(${qco_utils_target} test_drivers.cpp test_unitary_matrix.cpp test_wireiterator.cpp) target_link_libraries(${qco_utils_target} PRIVATE GTest::gtest_main MLIRQCOUtils - MLIRQCOProgramBuilder) + MLIRQCOProgramBuilder MLIRQCOUnitaryMatrix) mqt_mlir_configure_unittest_target(${qco_utils_target}) gtest_discover_tests(${qco_utils_target} PROPERTIES LABELS mqt-mlir-unittests DISCOVERY_TIMEOUT 60) diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp new file mode 100644 index 0000000000..f86ddfed90 --- /dev/null +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM + * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH + * All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * Licensed under the MIT License + */ + +#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" + +#include + +#include + +using namespace mlir::qco; + +namespace { + +using namespace std::complex_literals; + +[[nodiscard]] Matrix2x2 pauliX() { return Matrix2x2::fromElements(0, 1, 1, 0); } + +[[nodiscard]] Matrix4x4 swapMatrix() { + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, 0, 1, 0, // row 1 + 0, 1, 0, 0, // row 2 + 0, 0, 0, 1); // row 3 +} + +static_assert(is_unitary_matrix_v); +static_assert(is_unitary_matrix_v); +static_assert(is_unitary_matrix_v); +static_assert(is_unitary_matrix_v); +static_assert(!is_unitary_matrix_v); + +} // namespace + +TEST(UnitaryMatrix1x1, FromElementsAndAccess) { + Matrix1x1 matrix = Matrix1x1::fromElements(0.5 + 0.5i); + EXPECT_EQ(matrix(0, 0), 0.5 + 0.5i); + matrix(0, 0) = -1i; + EXPECT_EQ(matrix.value, -1i); +} + +TEST(UnitaryMatrix1x1, IsApprox) { + const Matrix1x1 a = Matrix1x1::fromElements(1.0); + const Matrix1x1 b = Matrix1x1::fromElements(1.0 + 1e-16i); + EXPECT_TRUE(a.isApprox(b)); + EXPECT_FALSE(a.isApprox(Matrix1x1::fromElements(2.0))); + EXPECT_TRUE(a.isApprox(Matrix1x1::fromElements(1.1), 0.2)); +} + +TEST(UnitaryMatrix2x2, IdentityAndAccess) { + const Matrix2x2 identity = Matrix2x2::identity(); + EXPECT_TRUE(identity.isApprox(Matrix2x2::fromElements(1, 0, 0, 1))); + EXPECT_EQ(identity(0, 1), 0.0); + Matrix2x2 mutableMatrix = identity; + mutableMatrix(1, 1) = 2.0; + EXPECT_EQ(mutableMatrix(1, 1), 2.0); +} + +TEST(UnitaryMatrix2x2, MultiplyAdjointTraceDeterminant) { + const Matrix2x2 x = pauliX(); + const Matrix2x2 identity = Matrix2x2::identity(); + + EXPECT_TRUE((x * x).isApprox(identity)); + EXPECT_TRUE((identity * x).isApprox(x)); + EXPECT_TRUE(x.adjoint().isApprox(x)); + EXPECT_EQ(x.trace(), Complex(0.0, 0.0)); + EXPECT_EQ(identity.trace(), Complex(2.0, 0.0)); + EXPECT_EQ(x.determinant(), Complex(-1.0, 0.0)); + EXPECT_EQ(identity.determinant(), Complex(1.0, 0.0)); +} + +TEST(UnitaryMatrix2x2, IsApprox) { + const Matrix2x2 a = Matrix2x2::identity(); + Matrix2x2 b = a; + b(0, 0) += 1e-15; + EXPECT_TRUE(a.isApprox(b)); + EXPECT_FALSE(a.isApprox(pauliX())); +} + +TEST(UnitaryMatrix4x4, IdentityAndAccess) { + const Matrix4x4 identity = Matrix4x4::identity(); + EXPECT_TRUE(identity.isApprox( + Matrix4x4::fromElements(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1))); + EXPECT_EQ(identity(2, 2), 1.0); +} + +TEST(UnitaryMatrix4x4, MultiplyAdjointTraceDeterminant) { + const Matrix4x4 swap = swapMatrix(); + const Matrix4x4 identity = Matrix4x4::identity(); + + EXPECT_TRUE((swap * swap).isApprox(identity)); + EXPECT_TRUE(swap.adjoint().isApprox(swap)); + EXPECT_EQ(identity.trace(), Complex(4.0, 0.0)); + EXPECT_EQ(identity.determinant(), Complex(1.0, 0.0)); +} + +TEST(UnitaryMatrix4x4, IsApprox) { + const Matrix4x4 a = Matrix4x4::identity(); + Matrix4x4 b = a; + b(3, 3) += 1e-15; + EXPECT_TRUE(a.isApprox(b)); + EXPECT_FALSE(a.isApprox(swapMatrix())); +} + +TEST(DynamicMatrix, DefaultAndSizedConstruction) { + const DynamicMatrix empty; + EXPECT_EQ(empty.rows(), 0); + EXPECT_EQ(empty.cols(), 0); + + const DynamicMatrix sized(2); + EXPECT_EQ(sized.rows(), 2); + EXPECT_EQ(sized(0, 0), 0.0); + EXPECT_EQ(sized(1, 1), 0.0); +} + +TEST(DynamicMatrix, CopyMoveAssign) { + DynamicMatrix original(2); + original(0, 0) = 1.0; + original(1, 1) = 1.0; + + const DynamicMatrix copied(original); + EXPECT_TRUE(copied.isApprox(original)); + + DynamicMatrix moved(copied); + EXPECT_TRUE(moved.isApprox(original)); + + DynamicMatrix assigned; + assigned = original; + EXPECT_TRUE(assigned.isApprox(original)); + + DynamicMatrix moveAssigned(1); + moveAssigned = std::move(moved); + EXPECT_TRUE(moveAssigned.isApprox(original)); +} + +TEST(DynamicMatrix, IdentityAndElementAccess) { + const DynamicMatrix identity = DynamicMatrix::identity(3); + EXPECT_EQ(identity.rows(), 3); + EXPECT_EQ(identity.cols(), 3); + EXPECT_EQ(identity(0, 0), 1.0); + EXPECT_EQ(identity(1, 2), 0.0); + EXPECT_EQ(identity(2, 2), 1.0); + + DynamicMatrix mutableMatrix = identity; + mutableMatrix(1, 1) = 0.5; + EXPECT_EQ(mutableMatrix(1, 1), 0.5); +} + +TEST(DynamicMatrix, AssignFrom) { + DynamicMatrix dynamic; + + dynamic.assignFrom(Matrix1x1::fromElements(0.25)); + EXPECT_EQ(dynamic.rows(), 1); + EXPECT_EQ(dynamic(0, 0), 0.25); + + dynamic.assignFrom(pauliX()); + EXPECT_TRUE(dynamic.isApprox(pauliX())); + + dynamic.assignFrom(swapMatrix()); + EXPECT_TRUE(dynamic.isApprox(swapMatrix())); + + const DynamicMatrix source = DynamicMatrix::identity(2); + dynamic.assignFrom(source); + EXPECT_TRUE(dynamic.isApprox(source)); +} + +TEST(DynamicMatrix, SetBottomRightCorner) { + const Matrix2x2 x = pauliX(); + const Matrix4x4 swap = swapMatrix(); + + DynamicMatrix with2x2 = DynamicMatrix::identity(4); + with2x2.setBottomRightCorner(x); + EXPECT_EQ(with2x2(0, 0), 1.0); + EXPECT_EQ(with2x2(2, 2), 0.0); + EXPECT_EQ(with2x2(2, 3), 1.0); + EXPECT_EQ(with2x2(3, 2), 1.0); + + DynamicMatrix with4x4 = DynamicMatrix::identity(6); + with4x4.setBottomRightCorner(swap); + EXPECT_EQ(with4x4(0, 0), 1.0); + EXPECT_EQ(with4x4(1, 1), 1.0); + EXPECT_EQ(with4x4(2, 2), 1.0); + EXPECT_EQ(with4x4(3, 4), 1.0); + EXPECT_EQ(with4x4(4, 3), 1.0); + EXPECT_EQ(with4x4(5, 5), 1.0); + + DynamicMatrix block = DynamicMatrix::identity(2); + block(0, 1) = 1i; + DynamicMatrix withDynamic = DynamicMatrix::identity(3); + withDynamic.setBottomRightCorner(block); + EXPECT_EQ(withDynamic(1, 1), 1.0); + EXPECT_EQ(withDynamic(1, 2), 1i); + EXPECT_EQ(withDynamic(2, 1), 0.0); +} + +TEST(DynamicMatrix, Adjoint) { + DynamicMatrix matrix(2); + matrix(0, 0) = 1.0; + matrix(0, 1) = 1i; + matrix(1, 0) = 0.0; + matrix(1, 1) = 1.0; + + const DynamicMatrix adjoint = matrix.adjoint(); + EXPECT_EQ(adjoint(0, 0), 1.0); + EXPECT_EQ(adjoint(0, 1), 0.0); + EXPECT_EQ(adjoint(1, 0), -1i); + EXPECT_EQ(adjoint(1, 1), 1.0); +} + +TEST(DynamicMatrix, IsApproxOverloads) { + const Matrix2x2 x = pauliX(); + const Matrix4x4 swap = swapMatrix(); + + DynamicMatrix as2x2; + as2x2.assignFrom(x); + EXPECT_TRUE(as2x2.isApprox(x)); + EXPECT_FALSE(as2x2.isApprox(Matrix2x2::identity())); + + DynamicMatrix as4x4; + as4x4.assignFrom(swap); + EXPECT_TRUE(as4x4.isApprox(swap)); + EXPECT_FALSE(as4x4.isApprox(Matrix4x4::identity())); + + DynamicMatrix wrongDim = DynamicMatrix::identity(3); + EXPECT_FALSE(wrongDim.isApprox(x)); + EXPECT_FALSE(wrongDim.isApprox(swap)); + + const DynamicMatrix a = DynamicMatrix::identity(2); + DynamicMatrix b = a; + b(1, 0) += 1e-15; + EXPECT_TRUE(a.isApprox(b)); + EXPECT_FALSE(a.isApprox(DynamicMatrix::identity(3))); +} From d0e7bae73c84ecca3e460058559f508384cf2677 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 9 Jun 2026 14:58:55 +0200 Subject: [PATCH 05/20] =?UTF-8?q?=F0=9F=9A=A8=20Fix=20linter=20warnings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp | 47 ++++++++++--------- .../Dialect/QCO/Utils/test_unitary_matrix.cpp | 37 +++++++++------ 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp index 18ecd0043d..0bf96663a1 100644 --- a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp @@ -14,22 +14,22 @@ #include #include +#include #include #include +#include +#include +#include +#include +#include namespace mlir::qco { -struct DynamicMatrix::Impl { - std::int64_t dim = 0; - llvm::SmallVector data; -}; - -namespace { - /// Returns true if every entry pair differs by at most @p tol (complex /// modulus). -[[nodiscard]] bool entriesAreApprox(llvm::ArrayRef lhs, - llvm::ArrayRef rhs, double tol) { +[[nodiscard]] static bool entriesAreApprox(llvm::ArrayRef lhs, + llvm::ArrayRef rhs, + double tol) { if (lhs.size() != rhs.size()) { return false; } @@ -40,8 +40,9 @@ namespace { } /// Writes the conjugate transpose of @p in into @p out (square, row-major). -void adjointInto(llvm::ArrayRef in, llvm::MutableArrayRef out, - const std::size_t dim) { +static void adjointInto(llvm::ArrayRef in, + llvm::MutableArrayRef out, + const std::size_t dim) { for (std::size_t row = 0; row < dim; ++row) { for (std::size_t col = 0; col < dim; ++col) { out[(row * dim) + col] = std::conj(in[(col * dim) + row]); @@ -50,27 +51,27 @@ void adjointInto(llvm::ArrayRef in, llvm::MutableArrayRef out, } template -void assignFixedImpl(std::int64_t& dim, llvm::SmallVector& data, - const std::array& src) { +static void assignFixedImpl(std::int64_t& dim, llvm::SmallVector& data, + const std::array& src) { dim = static_cast(Dim); data.assign(src.begin(), src.end()); } template -[[nodiscard]] bool +[[nodiscard]] static bool isApproxFixedImpl(const std::int64_t dim, llvm::ArrayRef data, const std::array& other, const double tol) { - if (dim != static_cast(Dim)) { + if (std::cmp_not_equal(dim, static_cast(Dim))) { return false; } return entriesAreApprox(data, other, tol); } /// Copies @p blockData into the bottom-right @p blockDim x @p blockDim corner. -void copyBottomRightCorner(const std::int64_t matrixDim, - llvm::MutableArrayRef matrixData, - const std::int64_t blockDim, - llvm::ArrayRef blockData) { +static void copyBottomRightCorner(const std::int64_t matrixDim, + llvm::MutableArrayRef matrixData, + const std::int64_t blockDim, + llvm::ArrayRef blockData) { const std::int64_t offset = matrixDim - blockDim; for (std::int64_t row = 0; row < blockDim; ++row) { for (std::int64_t col = 0; col < blockDim; ++col) { @@ -81,7 +82,10 @@ void copyBottomRightCorner(const std::int64_t matrixDim, } } -} // namespace +struct DynamicMatrix::Impl { + std::int64_t dim = 0; + llvm::SmallVector data; +}; Matrix1x1 Matrix1x1::fromElements(const Complex m00) { return {m00}; } @@ -313,9 +317,6 @@ bool DynamicMatrix::isApprox(const Matrix4x4& other, const double tol) const { bool DynamicMatrix::isApprox(const DynamicMatrix& other, const double tol) const { - if (impl_->dim != other.impl_->dim) { - return false; - } return entriesAreApprox(impl_->data, other.impl_->data, tol); } diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp index f86ddfed90..ec113638b7 100644 --- a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -13,40 +13,43 @@ #include #include +#include using namespace mlir::qco; - -namespace { - using namespace std::complex_literals; -[[nodiscard]] Matrix2x2 pauliX() { return Matrix2x2::fromElements(0, 1, 1, 0); } - -[[nodiscard]] Matrix4x4 swapMatrix() { - return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 - 0, 0, 1, 0, // row 1 - 0, 1, 0, 0, // row 2 - 0, 0, 0, 1); // row 3 -} - static_assert(is_unitary_matrix_v); static_assert(is_unitary_matrix_v); static_assert(is_unitary_matrix_v); static_assert(is_unitary_matrix_v); static_assert(!is_unitary_matrix_v); -} // namespace +[[nodiscard]] static Matrix2x2 pauliX() { + return Matrix2x2::fromElements(0, 1, 1, 0); +} + +[[nodiscard]] static Matrix4x4 swapMatrix() { + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, 0, 1, 0, // row 1 + 0, 1, 0, 0, // row 2 + 0, 0, 0, 1); // row 3 +} TEST(UnitaryMatrix1x1, FromElementsAndAccess) { - Matrix1x1 matrix = Matrix1x1::fromElements(0.5 + 0.5i); + Matrix1x1 matrix = Matrix1x1::fromElements(Complex{0.5, 0.5}); EXPECT_EQ(matrix(0, 0), 0.5 + 0.5i); matrix(0, 0) = -1i; EXPECT_EQ(matrix.value, -1i); } +TEST(UnitaryMatrix1x1, ConstElementAccess) { + const Matrix1x1 matrix = Matrix1x1::fromElements(Complex{0.25, 0.5}); + EXPECT_EQ(matrix(0, 0), Complex{0.25, 0.5}); +} + TEST(UnitaryMatrix1x1, IsApprox) { const Matrix1x1 a = Matrix1x1::fromElements(1.0); - const Matrix1x1 b = Matrix1x1::fromElements(1.0 + 1e-16i); + const Matrix1x1 b = Matrix1x1::fromElements(Complex{1.0, 1e-16}); EXPECT_TRUE(a.isApprox(b)); EXPECT_FALSE(a.isApprox(Matrix1x1::fromElements(2.0))); EXPECT_TRUE(a.isApprox(Matrix1x1::fromElements(1.1), 0.2)); @@ -212,6 +215,10 @@ TEST(DynamicMatrix, Adjoint) { EXPECT_EQ(adjoint(1, 1), 1.0); } +TEST(DynamicMatrix, IsApproxRejectsMismatchedExtents) { + EXPECT_FALSE(DynamicMatrix::identity(1).isApprox(DynamicMatrix::identity(2))); +} + TEST(DynamicMatrix, IsApproxOverloads) { const Matrix2x2 x = pauliX(); const Matrix4x4 swap = swapMatrix(); From 7dc510f8fc03681f69befc662bd277e672429a9e Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 9 Jun 2026 15:09:57 +0200 Subject: [PATCH 06/20] =?UTF-8?q?=F0=9F=94=A7=20Fix=20element=20access=20i?= =?UTF-8?q?n=20UnitMatrix1x1=20test=20to=20ensure=20proper=20comparison=20?= =?UTF-8?q?with=20Complex=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp index ec113638b7..792d660671 100644 --- a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -44,7 +44,7 @@ TEST(UnitaryMatrix1x1, FromElementsAndAccess) { TEST(UnitaryMatrix1x1, ConstElementAccess) { const Matrix1x1 matrix = Matrix1x1::fromElements(Complex{0.25, 0.5}); - EXPECT_EQ(matrix(0, 0), Complex{0.25, 0.5}); + EXPECT_EQ(matrix(0, 0), (Complex{0.25, 0.5})); } TEST(UnitaryMatrix1x1, IsApprox) { From 2b95d091de2a9564bf03e29f2b6d28d09fb95240 Mon Sep 17 00:00:00 2001 From: Simon Hofmann Date: Tue, 9 Jun 2026 16:03:40 +0200 Subject: [PATCH 07/20] =?UTF-8?q?=E2=9C=A8=20Enhance=20DynamicMatrix=20wit?= =?UTF-8?q?h=20dimension=20validation=20and=20storage=20size=20checks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp | 31 ++++++++++++++++--- .../Dialect/QCO/Utils/test_unitary_matrix.cpp | 4 +-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp index 0bf96663a1..a1f46c0921 100644 --- a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -67,11 +68,34 @@ isApproxFixedImpl(const std::int64_t dim, llvm::ArrayRef data, return entriesAreApprox(data, other, tol); } +/// Returns @p dim as `size_t` after asserting it is non-negative and squarable. +[[nodiscard]] static std::size_t checkedDim(const std::int64_t dim) { + assert(dim >= 0 && "DynamicMatrix dimension must be non-negative"); + const auto udim = static_cast(dim); + assert(udim == 0 || udim <= std::numeric_limits::max() / udim); + return udim; +} + +[[nodiscard]] static std::size_t checkedStorageSize(const std::int64_t dim) { + const auto udim = checkedDim(dim); + return udim * udim; +} + +static void validateCornerDims(const std::int64_t matrixDim, + const std::int64_t blockDim) { + assert(matrixDim >= 0 && blockDim >= 0 && blockDim <= matrixDim && + "block must fit in the bottom-right corner of the matrix"); + checkedDim(matrixDim); +} + /// Copies @p blockData into the bottom-right @p blockDim x @p blockDim corner. static void copyBottomRightCorner(const std::int64_t matrixDim, llvm::MutableArrayRef matrixData, const std::int64_t blockDim, llvm::ArrayRef blockData) { + validateCornerDims(matrixDim, blockDim); + assert(matrixData.size() >= checkedStorageSize(matrixDim)); + assert(blockData.size() >= checkedStorageSize(blockDim)); const std::int64_t offset = matrixDim - blockDim; for (std::int64_t row = 0; row < blockDim; ++row) { for (std::int64_t col = 0; col < blockDim; ++col) { @@ -217,7 +241,7 @@ DynamicMatrix::DynamicMatrix() : impl_(std::make_unique()) {} DynamicMatrix::DynamicMatrix(const std::int64_t dim) : impl_(std::make_unique()) { impl_->dim = dim; - impl_->data.assign(static_cast(dim * dim), Complex{}); + impl_->data.assign(checkedStorageSize(dim), Complex{}); } DynamicMatrix::DynamicMatrix(const DynamicMatrix& other) @@ -243,7 +267,7 @@ std::int64_t DynamicMatrix::cols() const { return impl_->dim; } DynamicMatrix DynamicMatrix::identity(const std::int64_t dim) { DynamicMatrix matrix(dim); - const auto udim = static_cast(dim); + const auto udim = checkedDim(dim); for (std::size_t i = 0; i < udim; ++i) { matrix.impl_->data[(i * udim) + i] = 1.0; } @@ -279,8 +303,7 @@ void DynamicMatrix::setBottomRightCorner(const DynamicMatrix& block) { DynamicMatrix DynamicMatrix::adjoint() const { DynamicMatrix out(impl_->dim); - adjointInto(impl_->data, out.impl_->data, - static_cast(impl_->dim)); + adjointInto(impl_->data, out.impl_->data, checkedDim(impl_->dim)); return out; } diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp index 792d660671..3177dcf412 100644 --- a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -126,10 +126,10 @@ TEST(DynamicMatrix, CopyMoveAssign) { original(0, 0) = 1.0; original(1, 1) = 1.0; - const DynamicMatrix copied(original); + DynamicMatrix copied(original); EXPECT_TRUE(copied.isApprox(original)); - DynamicMatrix moved(copied); + DynamicMatrix moved(std::move(copied)); EXPECT_TRUE(moved.isApprox(original)); DynamicMatrix assigned; From 4ea56f7c76c9cb0feeb5fdb2fe001f3dd1c3ab06 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 16:54:26 +0200 Subject: [PATCH 08/20] :adhesive_bandage: fix missing link library in MLIRQTensorUtils Signed-off-by: burgholzer --- mlir/lib/Dialect/QTensor/Utils/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mlir/lib/Dialect/QTensor/Utils/CMakeLists.txt b/mlir/lib/Dialect/QTensor/Utils/CMakeLists.txt index 59cbc69bec..2014cafbe6 100644 --- a/mlir/lib/Dialect/QTensor/Utils/CMakeLists.txt +++ b/mlir/lib/Dialect/QTensor/Utils/CMakeLists.txt @@ -17,7 +17,9 @@ add_mlir_dialect_library( MLIRQTensorOpsIncGen LINK_LIBS PUBLIC - MLIRQCODialect) + MLIRQCODialect + PRIVATE + MLIRSCFDialect) mqt_mlir_target_use_project_options(MLIRQTensorUtils) From 0042db0d45a5e29b44094938cbcddfee56ef92ec Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 17:00:15 +0200 Subject: [PATCH 09/20] :art: remove redundant namespace qualifiers Signed-off-by: burgholzer --- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 35 ++++---- mlir/include/mlir/Dialect/QCO/IR/QCOOps.td | 86 +++++++++---------- 2 files changed, 57 insertions(+), 64 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 8f22872646..283f8d0b56 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -34,7 +34,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { if (auto matrix = $_op.getUnitaryMatrix()) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix1x1>) { + Matrix1x1>) { out = *matrix; return true; } @@ -43,7 +43,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix1x1>) { + Matrix1x1>) { out = $_op.getUnitaryMatrix(); return true; } @@ -58,7 +58,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { if (auto matrix = $_op.getUnitaryMatrix()) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix2x2>) { + Matrix2x2>) { out = *matrix; return true; } @@ -67,7 +67,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix2x2>) { + Matrix2x2>) { out = $_op.getUnitaryMatrix(); return true; } @@ -82,7 +82,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { if (auto matrix = $_op.getUnitaryMatrix()) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix4x4>) { + Matrix4x4>) { out = *matrix; return true; } @@ -91,7 +91,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { if constexpr (std::is_same_v< std::remove_cvref_t, - ::mlir::qco::Matrix4x4>) { + Matrix4x4>) { out = $_op.getUnitaryMatrix(); return true; } @@ -173,20 +173,17 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { // Unitary matrix helpers InterfaceMethod<"Populates the given 1x1 unitary matrix if possible.", - "bool", "getUnitaryMatrix1x1", - (ins "::mlir::qco::Matrix1x1&":$out), + "bool", "getUnitaryMatrix1x1", (ins "Matrix1x1&":$out), unitaryMatrix1x1MethodBody>, InterfaceMethod<"Populates the given 2x2 unitary matrix if possible.", - "bool", "getUnitaryMatrix2x2", - (ins "::mlir::qco::Matrix2x2&":$out), + "bool", "getUnitaryMatrix2x2", (ins "Matrix2x2&":$out), unitaryMatrix2x2MethodBody>, InterfaceMethod<"Populates the given 4x4 unitary matrix if possible.", - "bool", "getUnitaryMatrix4x4", - (ins "::mlir::qco::Matrix4x4&":$out), + "bool", "getUnitaryMatrix4x4", (ins "Matrix4x4&":$out), unitaryMatrix4x4MethodBody>, InterfaceMethod<"Populates the given dynamic unitary matrix.", "bool", - "getUnitaryMatrixDynamic", - (ins "::mlir::qco::DynamicMatrix&":$out), [{ + "getUnitaryMatrixDynamic", (ins "DynamicMatrix&":$out), + [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { if (auto matrix = $_op.getUnitaryMatrix()) { out.assignFrom(*matrix); @@ -204,18 +201,18 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { let extraClassDeclaration = [{ template std::optional getUnitaryMatrix() { - static_assert(::mlir::qco::is_unitary_matrix_v, + static_assert(is_unitary_matrix_v, "MatrixType must be Matrix1x1, Matrix2x2, Matrix4x4, or DynamicMatrix"); MatrixType out; bool result = false; - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { result = this->getUnitaryMatrix1x1(out); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix2x2(out); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrix4x4(out); - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v) { result = this->getUnitaryMatrixDynamic(out); } diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td index a923f4e790..8bdaaa668a 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOOps.td @@ -200,7 +200,7 @@ def GPhaseOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "gphase"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix1x1> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "const std::variant&":$theta)>]; @@ -226,7 +226,7 @@ def IdOp : QCOOp<"id", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "id"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -250,7 +250,7 @@ def XOp : QCOOp<"x", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "x"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -274,7 +274,7 @@ def YOp : QCOOp<"y", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "y"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -298,7 +298,7 @@ def ZOp : QCOOp<"z", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "z"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -322,7 +322,7 @@ def HOp : QCOOp<"h", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "h"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -346,7 +346,7 @@ def SOp : QCOOp<"s", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "s"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -371,7 +371,7 @@ def SdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -395,7 +395,7 @@ def TOp : QCOOp<"t", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "t"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -420,7 +420,7 @@ def TdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "tdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -444,7 +444,7 @@ def SXOp : QCOOp<"sx", traits = [UnitaryOpInterface, OneTargetZeroParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sx"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -469,7 +469,7 @@ def SXdgOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "sxdg"; } - [[nodiscard]] static ::mlir::qco::Matrix2x2 getUnitaryMatrix(); + [[nodiscard]] static Matrix2x2 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -494,7 +494,7 @@ def RXOp : QCOOp<"rx", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -523,7 +523,7 @@ def RYOp : QCOOp<"ry", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ry"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -552,7 +552,7 @@ def RZOp : QCOOp<"rz", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rz"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -581,7 +581,7 @@ def POp : QCOOp<"p", traits = [UnitaryOpInterface, OneTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "p"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -611,7 +611,7 @@ def ROp : QCOOp<"r", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "r"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -641,7 +641,7 @@ def U2Op : QCOOp<"u2", traits = [UnitaryOpInterface, OneTargetTwoParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u2"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -672,7 +672,7 @@ def UOp : QCOOp<"u", traits = [UnitaryOpInterface, OneTargetThreeParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "u"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix2x2> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit_in, @@ -705,7 +705,7 @@ def SWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "swap"; } - [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); + [[nodiscard]] static Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -733,7 +733,7 @@ def iSWAPOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "iswap"; } - [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); + [[nodiscard]] static Matrix4x4 getUnitaryMatrix(); }]; } @@ -759,7 +759,7 @@ def DCXOp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "dcx"; } - [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); + [[nodiscard]] static Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -787,7 +787,7 @@ def ECROp let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ecr"; } - [[nodiscard]] static ::mlir::qco::Matrix4x4 getUnitaryMatrix(); + [[nodiscard]] static Matrix4x4 getUnitaryMatrix(); }]; let hasCanonicalizer = 1; @@ -815,7 +815,7 @@ def RXXOp : QCOOp<"rxx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rxx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -847,7 +847,7 @@ def RYYOp : QCOOp<"ryy", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "ryy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -879,7 +879,7 @@ def RZXOp : QCOOp<"rzx", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzx"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -911,7 +911,7 @@ def RZZOp : QCOOp<"rzz", traits = [UnitaryOpInterface, TwoTargetOneParameter]> { let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "rzz"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -945,7 +945,7 @@ def XXPlusYYOp : QCOOp<"xx_plus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_plus_yy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -980,7 +980,7 @@ def XXMinusYYOp : QCOOp<"xx_minus_yy", let extraClassDeclaration = [{ [[nodiscard]] static StringRef getBaseSymbol() { return "xx_minus_yy"; } - [[nodiscard]] std::optional<::mlir::qco::Matrix4x4> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "Value":$qubit0_in, "Value":$qubit1_in, @@ -1060,13 +1060,12 @@ def YieldOp : QCOOp<"yield", traits = [Terminator, ReturnLike]> { let assemblyFormat = "attr-dict ($targets^ `:` type($targets))?"; } -def CtrlOp - : QCOOp<"ctrl", - traits = [UnitaryOpInterface, AttrSizedOperandSegments, - AttrSizedResultSegments, SameOperandsAndResultType, - SameOperandsAndResultShape, - SingleBlockImplicitTerminator<"::mlir::qco::YieldOp">, - RecursiveMemoryEffects]> { +def CtrlOp : QCOOp<"ctrl", + traits = [UnitaryOpInterface, AttrSizedOperandSegments, + AttrSizedResultSegments, SameOperandsAndResultType, + SameOperandsAndResultShape, + SingleBlockImplicitTerminator<"YieldOp">, + RecursiveMemoryEffects]> { let summary = "Add control qubits to a unitary operation"; let description = [{ A modifier operation that adds control qubits to the unitary operation @@ -1124,7 +1123,7 @@ def CtrlOp Value getParameter(size_t i) { return getBodyUnitary().getParameter(i); } ValueRange getParameters() { return getBodyUnitary().getParameters(); } [[nodiscard]] static StringRef getBaseSymbol() { return "ctrl"; } - [[nodiscard]] std::optional<::mlir::qco::DynamicMatrix> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "ValueRange":$controls, "ValueRange":$targets), @@ -1139,11 +1138,9 @@ def CtrlOp let hasVerifier = 1; } -def InvOp - : QCOOp<"inv", - traits = [UnitaryOpInterface, - SingleBlockImplicitTerminator<"::mlir::qco::YieldOp">, - RecursiveMemoryEffects]> { +def InvOp : QCOOp<"inv", traits = [UnitaryOpInterface, + SingleBlockImplicitTerminator<"YieldOp">, + RecursiveMemoryEffects]> { let summary = "Invert a unitary operation"; let description = [{ A modifier operation that inverts the unitary operation defined in its body @@ -1195,7 +1192,7 @@ def InvOp Value getParameter(size_t i) { return getBodyUnitary().getParameter(i); } ValueRange getParameters() { return getBodyUnitary().getParameters(); } [[nodiscard]] static StringRef getBaseSymbol() { return "inv"; } - [[nodiscard]] std::optional<::mlir::qco::DynamicMatrix> getUnitaryMatrix(); + [[nodiscard]] std::optional getUnitaryMatrix(); }]; let builders = [OpBuilder<(ins "ValueRange":$qubits), [{ @@ -1220,8 +1217,7 @@ def IfOp RegionBranchOpInterface, ["getNumRegionInvocations", "getRegionInvocationBounds", "getEntrySuccessorRegions"]>, - SingleBlock, - SingleBlockImplicitTerminator<"::mlir::qco::YieldOp">, + SingleBlock, SingleBlockImplicitTerminator<"YieldOp">, RecursiveMemoryEffects]> { let summary = "If-then-else operation for linear (qubit) types"; From 28063ce4922f4d412a0c78a646d24eb6c5a4e8a4 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 17:25:00 +0200 Subject: [PATCH 10/20] :zap: Slightly optimize the optional case for the matrix getter bodies Calls getUnitaryMatrix only when the type check is successful Signed-off-by: burgholzer --- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 283f8d0b56..84593694ff 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -31,19 +31,19 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { // Size-specific bodies: each helper only accepts the matching matrix type. defvar unitaryMatrix1x1MethodBody = [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { - if (auto matrix = $_op.getUnitaryMatrix()) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix1x1>) { + using ValueT = std::remove_cvref_t())>; + if constexpr (std::is_same_v) { + if (auto matrix = $_op.getUnitaryMatrix()) { out = *matrix; return true; } + return false; + } else { + return false; } - return false; } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix1x1>) { + using ValueT = std::remove_cvref_t; + if constexpr (std::is_same_v) { out = $_op.getUnitaryMatrix(); return true; } @@ -55,19 +55,19 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { defvar unitaryMatrix2x2MethodBody = [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { - if (auto matrix = $_op.getUnitaryMatrix()) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix2x2>) { + using ValueT = std::remove_cvref_t())>; + if constexpr (std::is_same_v) { + if (auto matrix = $_op.getUnitaryMatrix()) { out = *matrix; return true; } + return false; + } else { + return false; } - return false; } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix2x2>) { + using ValueT = std::remove_cvref_t; + if constexpr (std::is_same_v) { out = $_op.getUnitaryMatrix(); return true; } @@ -79,19 +79,19 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { defvar unitaryMatrix4x4MethodBody = [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { - if (auto matrix = $_op.getUnitaryMatrix()) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix4x4>) { + using ValueT = std::remove_cvref_t())>; + if constexpr (std::is_same_v) { + if (auto matrix = $_op.getUnitaryMatrix()) { out = *matrix; return true; } + return false; + } else { + return false; } - return false; } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - if constexpr (std::is_same_v< - std::remove_cvref_t, - Matrix4x4>) { + using ValueT = std::remove_cvref_t; + if constexpr (std::is_same_v) { out = $_op.getUnitaryMatrix(); return true; } From 46571ae2bf5b62c2b9b173026fc74a17081bc890 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 17:32:19 +0200 Subject: [PATCH 11/20] :recycle: Turn assert in CtrlOp to a runtime error with an appropriate error message Signed-off-by: burgholzer --- mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index e4ca57fbaa..e73fdcd9d6 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -355,12 +355,17 @@ std::optional CtrlOp::getUnitaryMatrix() { const auto targetDim = targetMatrix->cols(); assert(targetMatrix->cols() == targetMatrix->rows()); + if (getNumControls() >= 32) { + llvm::reportFatalUsageError( + "Creating the unitary matrix for a CtrlOp with more than 31 controls " + "is not supported due to memory constraints."); + } + // define dimensions and type of output matrix - assert(getNumControls() < sizeof(unsigned long long) * 8); const auto dim = static_cast((1ULL << getNumControls()) * targetDim); // initialize result with identity - DynamicMatrix matrix = DynamicMatrix::identity(dim); + auto matrix = DynamicMatrix::identity(dim); // apply target matrix matrix.setBottomRightCorner(*targetMatrix); From 15823553aa1aa6d22a47e73fab4d214afe95c92d Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 17:55:46 +0200 Subject: [PATCH 12/20] :art: Cleanup and streamline unitary matrix definitions Signed-off-by: burgholzer --- .../QCO/IR/Operations/StandardGates/HOp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/POp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/ROp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/RXOp.cpp | 8 ++++---- .../QCO/IR/Operations/StandardGates/RXXOp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/RYOp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/RYYOp.cpp | 13 ++++++------ .../QCO/IR/Operations/StandardGates/RZOp.cpp | 11 ++++------ .../QCO/IR/Operations/StandardGates/RZXOp.cpp | 13 ++++++------ .../QCO/IR/Operations/StandardGates/RZZOp.cpp | 15 ++++++-------- .../QCO/IR/Operations/StandardGates/SOp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/SXOp.cpp | 8 ++++---- .../IR/Operations/StandardGates/SXdgOp.cpp | 8 ++++---- .../QCO/IR/Operations/StandardGates/SdgOp.cpp | 4 ++-- .../QCO/IR/Operations/StandardGates/TOp.cpp | 6 +++--- .../QCO/IR/Operations/StandardGates/TdgOp.cpp | 6 +++--- .../QCO/IR/Operations/StandardGates/U2Op.cpp | 11 ++++------ .../QCO/IR/Operations/StandardGates/UOp.cpp | 10 ++++------ .../Operations/StandardGates/XXMinusYYOp.cpp | 20 ++++++++----------- .../Operations/StandardGates/XXPlusYYOp.cpp | 16 ++++++--------- .../QCO/IR/Operations/StandardGates/ZOp.cpp | 4 ++-- 21 files changed, 78 insertions(+), 99 deletions(-) diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index f9c191ead4..b30687a991 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -45,6 +45,6 @@ void HOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 HOp::getUnitaryMatrix() { constexpr auto x = 1.0 / std::numbers::sqrt2; - return Matrix2x2::fromElements(x, x, // row 0 - x, -1.0 * x); // row 1 + return Matrix2x2::fromElements(x, x, // row 0 + x, -x); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index ca93eb7dc7..0c18fa3eac 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -67,8 +67,8 @@ void POp::getCanonicalizationPatterns(RewritePatternSet& results, std::optional POp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, std::polar(1.0, *theta)); // row 1 + return Matrix2x2::fromElements(1, 0, // row 0 + 0, std::polar(1.0, *theta)); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index 86d9231ee5..eea83574dc 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -87,10 +87,10 @@ std::optional ROp::getUnitaryMatrix() { return std::nullopt; } - const auto thetaSin = std::sin(*theta / 2.0); + const auto thetaSin = std::sin(*theta / 2); const auto m01 = std::polar(thetaSin, -*phi - (std::numbers::pi / 2)); const auto m10 = std::polar(thetaSin, *phi - (std::numbers::pi / 2)); - const std::complex thetaCos = std::cos(*theta / 2.0); + const auto thetaCos = std::cos(*theta / 2); return Matrix2x2::fromElements(thetaCos, m01, // row 0 m10, thetaCos); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index 6da8a6795b..82a697b313 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -69,10 +69,10 @@ std::optional RXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { - const auto m00 = std::cos(*theta / 2.0) + 0i; - const auto m01 = -1i * std::sin(*theta / 2.0); - return Matrix2x2::fromElements(m00, m01, // row 0 - m01, m00); // row 1 + const auto diag = std::cos(*theta / 2); + const auto offDiag = -1i * std::sin(*theta / 2); + return Matrix2x2::fromElements(diag, offDiag, // row 0 + offDiag, diag); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index a22ecaa53a..fb92d6d942 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -87,8 +87,8 @@ std::optional RXXOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { const auto m0 = 0i; - const auto mc = std::cos(*theta / 2.0) + 0i; - const auto ms = -1i * std::sin(*theta / 2.0); + const auto mc = std::cos(*theta / 2); + const auto ms = -1i * std::sin(*theta / 2); return Matrix4x4::fromElements(mc, m0, m0, ms, // row 0 m0, mc, ms, m0, // row 1 m0, ms, mc, m0, // row 2 diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index d909a897de..08a56618f3 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -67,8 +67,8 @@ void RYOp::getCanonicalizationPatterns(RewritePatternSet& results, std::optional RYOp::getUnitaryMatrix() { if (const auto theta = valueToDouble(getTheta())) { - const auto m00 = std::complex{std::cos(*theta / 2.0)}; - const auto m01 = std::complex{-std::sin(*theta / 2.0)}; + const auto m00 = std::cos(*theta / 2); + const auto m01 = -std::sin(*theta / 2); return Matrix2x2::fromElements(m00, m01, // row 0 -m01, m00); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index c356e118c4..f300e5ff14 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -86,13 +86,12 @@ std::optional RYYOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { - const auto m0 = 0i; - const auto mc = std::complex{std::cos(*theta / 2.0)}; - const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4x4::fromElements(mc, m0, m0, ms, // row 0 - m0, mc, -ms, m0, // row 1 - m0, -ms, mc, m0, // row 2 - ms, m0, m0, mc); // row 3 + const auto mc = std::cos(*theta / 2); + const auto ms = 1i * std::sin(*theta / 2); + return Matrix4x4::fromElements(mc, 0, 0, ms, // row 0 + 0, mc, -ms, 0, // row 1 + 0, -ms, mc, 0, // row 2 + ms, 0, 0, mc); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index b4c8c13ec6..99fa8e8701 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -66,14 +66,11 @@ void RZOp::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional RZOp::getUnitaryMatrix() { - using namespace std::complex_literals; - if (const auto theta = valueToDouble(getTheta())) { - const auto m00 = std::polar(1.0, -*theta / 2.0); - const auto m01 = 0i; - const auto m11 = std::polar(1.0, *theta / 2.0); - return Matrix2x2::fromElements(m00, m01, // row 0 - m01, m11); // row 1 + const auto m00 = std::polar(1.0, -*theta / 2); + const auto m11 = std::polar(1.0, *theta / 2); + return Matrix2x2::fromElements(m00, 0, // row 0 + 0, m11); // row 1 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index 1273716628..0b9fb1a715 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -73,13 +73,12 @@ std::optional RZXOp::getUnitaryMatrix() { using namespace std::complex_literals; if (const auto theta = valueToDouble(getTheta())) { - const auto m0 = 0i; - const auto mc = std::complex{std::cos(*theta / 2.0)}; - const auto ms = std::complex{0.0, std::sin(*theta / 2.0)}; - return Matrix4x4::fromElements(mc, -ms, m0, m0, // row 0 - -ms, mc, m0, m0, // row 1 - m0, m0, mc, ms, // row 2 - m0, m0, ms, mc); // row 3 + const auto mc = std::cos(*theta / 2); + const auto ms = 1i * std::sin(*theta / 2); + return Matrix4x4::fromElements(mc, -ms, 0, 0, // row 0 + -ms, mc, 0, 0, // row 1 + 0, 0, mc, ms, // row 2 + 0, 0, ms, mc); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index 83e3587dc4..93f748b081 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -83,16 +83,13 @@ void RZZOp::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional RZZOp::getUnitaryMatrix() { - using namespace std::complex_literals; - if (const auto theta = valueToDouble(getTheta())) { - const auto m0 = 0i; - const auto mp = std::polar(1.0, *theta / 2.0); - const auto mm = std::polar(1.0, -*theta / 2.0); - return Matrix4x4::fromElements(mm, m0, m0, m0, // row 0 - m0, mp, m0, m0, // row 1 - m0, m0, mp, m0, // row 2 - m0, m0, m0, mm); // row 3 + const auto mp = std::polar(1.0, *theta / 2); + const auto mm = std::polar(1.0, -*theta / 2); + return Matrix4x4::fromElements(mm, 0, 0, 0, // row 0 + 0, mp, 0, 0, // row 1 + 0, 0, mp, 0, // row 2 + 0, 0, 0, mm); // row 3 } return std::nullopt; } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index ebf297f4fe..aa86942b5d 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -58,6 +58,6 @@ void SOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, 1i); // row 1 + return Matrix2x2::fromElements(1, 0, // row 0 + 0, 1i); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index bd25a31c0f..ef573093f1 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -56,8 +56,8 @@ void SXOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 SXOp::getUnitaryMatrix() { - constexpr auto m00 = std::complex{0.5, 0.5}; - constexpr auto m01 = std::complex{0.5, -0.5}; - return Matrix2x2::fromElements(m00, m01, // row 0 - m01, m00); // row 1 + constexpr auto diag = std::complex{0.5, 0.5}; + constexpr auto offDiag = std::complex{0.5, -0.5}; + return Matrix2x2::fromElements(diag, offDiag, // row 0 + offDiag, diag); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index 3d5b5acfb7..69aa211d27 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -57,8 +57,8 @@ void SXdgOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 SXdgOp::getUnitaryMatrix() { - constexpr auto m00 = std::complex{0.5, -0.5}; - constexpr auto m01 = std::complex{0.5, 0.5}; - return Matrix2x2::fromElements(m00, m01, // row 0 - m01, m00); // row 1 + constexpr auto diag = std::complex{0.5, -0.5}; + constexpr auto offDiag = std::complex{0.5, 0.5}; + return Matrix2x2::fromElements(diag, offDiag, // row 0 + offDiag, diag); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index 711dcb3e80..4dbcf21f58 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -58,6 +58,6 @@ void SdgOp::getCanonicalizationPatterns(RewritePatternSet& results, Matrix2x2 SdgOp::getUnitaryMatrix() { using namespace std::complex_literals; - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, -1i); // row 1 + return Matrix2x2::fromElements(1, 0, // row 0 + 0, -1i); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index 4517cd70f5..2dd2a2865c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -57,7 +57,7 @@ void TOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 TOp::getUnitaryMatrix() { - const auto m11 = std::polar(1.0, std::numbers::pi / 4.0); - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, m11); // row 1 + const auto m11 = std::polar(1.0, std::numbers::pi / 4); + return Matrix2x2::fromElements(1, 0, // row 0 + 0, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index 87c6976663..778eea2f7f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -58,7 +58,7 @@ void TdgOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 TdgOp::getUnitaryMatrix() { - const auto m11 = std::polar(1.0, -std::numbers::pi / 4.0); - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, m11); // row 1 + const auto m11 = std::polar(1.0, -std::numbers::pi / 4); + return Matrix2x2::fromElements(1, 0, // row 0 + 0, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index 4f59154617..77d7155c26 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -106,19 +106,16 @@ void U2Op::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional U2Op::getUnitaryMatrix() { - using namespace std::complex_literals; - const auto phi = valueToDouble(getPhi()); const auto lambda = valueToDouble(getLambda()); if (!phi || !lambda) { return std::nullopt; } - const auto m00 = 1.0 / std::numbers::sqrt2 + 0i; - const auto m01 = - std::polar(1.0 / std::numbers::sqrt2, *lambda + std::numbers::pi); - const auto m10 = std::polar(1.0 / std::numbers::sqrt2, *phi); - const auto m11 = std::polar(1.0 / std::numbers::sqrt2, *phi + *lambda); + constexpr auto m00 = 1 / std::numbers::sqrt2; + const auto m01 = std::polar(m00, *lambda + std::numbers::pi); + const auto m10 = std::polar(m00, *phi); + const auto m11 = std::polar(m00, *phi + *lambda); return Matrix2x2::fromElements(m00, m01, // row 0 m10, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index 7e42d65c19..281b4c279b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -126,8 +126,6 @@ void UOp::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional UOp::getUnitaryMatrix() { - using namespace std::complex_literals; - const auto theta = valueToDouble(getTheta()); const auto phi = valueToDouble(getPhi()); const auto lambda = valueToDouble(getLambda()); @@ -135,12 +133,12 @@ std::optional UOp::getUnitaryMatrix() { return std::nullopt; } - const auto c = std::cos(*theta / 2.0); - const auto s = std::sin(*theta / 2.0); - const auto m00 = c + 0i; + const auto c = std::cos(*theta / 2); + const auto s = std::sin(*theta / 2); + const auto m01 = std::polar(s, *lambda + std::numbers::pi); const auto m10 = std::polar(s, *phi); const auto m11 = std::polar(c, *phi + *lambda); - return Matrix2x2::fromElements(m00, m01, // row 0 + return Matrix2x2::fromElements(c, m01, // row 0 m10, m11); // row 1 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index f4398da177..7dea7eac68 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -102,22 +102,18 @@ void XXMinusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional XXMinusYYOp::getUnitaryMatrix() { - using namespace std::complex_literals; - const auto theta = valueToDouble(getTheta()); const auto beta = valueToDouble(getBeta()); if (!theta || !beta) { return std::nullopt; } - const auto m0 = 0.0 + 0i; - const auto m1 = 1.0 + 0i; - const auto mc = std::cos(*theta / 2.0) + 0i; - const auto s = std::sin(*theta / 2.0); - const auto msp = std::polar(s, *beta - (std::numbers::pi / 2.)); - const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2.)); - return Matrix4x4::fromElements(mc, m0, m0, msm, // row 0 - m0, m1, m0, m0, // row 1 - m0, m0, m1, m0, // row 2 - msp, m0, m0, mc); // row 3 + const auto mc = std::cos(*theta / 2); + const auto s = std::sin(*theta / 2); + const auto msp = std::polar(s, *beta - (std::numbers::pi / 2)); + const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2)); + return Matrix4x4::fromElements(mc, 0, 0, msm, // row 0 + 0, 1, 0, 0, // row 1 + 0, 0, 1, 0, // row 2 + msp, 0, 0, mc); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index 9f7989ca8c..53b01d8908 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -102,22 +102,18 @@ void XXPlusYYOp::getCanonicalizationPatterns(RewritePatternSet& results, } std::optional XXPlusYYOp::getUnitaryMatrix() { - using namespace std::complex_literals; - const auto theta = valueToDouble(getTheta()); const auto beta = valueToDouble(getBeta()); if (!theta || !beta) { return std::nullopt; } - const auto m0 = 0.0 + 0i; - const auto m1 = 1.0 + 0i; - const auto mc = std::cos(*theta / 2.0) + 0i; - const auto s = std::sin(*theta / 2.0); + const auto mc = std::cos(*theta / 2); + const auto s = std::sin(*theta / 2); const auto msp = std::polar(s, *beta - (std::numbers::pi / 2)); const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2)); - return Matrix4x4::fromElements(m1, m0, m0, m0, // row 0 - m0, mc, msp, m0, // row 1 - m0, msm, mc, m0, // row 2 - m0, m0, m0, m1); // row 3 + return Matrix4x4::fromElements(1, 0, 0, 0, // row 0 + 0, mc, msp, 0, // row 1 + 0, msm, mc, 0, // row 2 + 0, 0, 0, 1); // row 3 } diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 0d286b7c44..5b000f26d6 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -42,6 +42,6 @@ void ZOp::getCanonicalizationPatterns(RewritePatternSet& results, } Matrix2x2 ZOp::getUnitaryMatrix() { - return Matrix2x2::fromElements(1.0, 0.0, // row 0 - 0.0, -1.0); // row 1 + return Matrix2x2::fromElements(1, 0, // row 0 + 0, -1); // row 1 } From f3c7adfe6c018cc0cc28335faf45e93b8254f4f4 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 17:58:21 +0200 Subject: [PATCH 13/20] :rotating_light: Fix local clang-tidy warning in test Signed-off-by: burgholzer --- mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp index 3177dcf412..ac239718e4 100644 --- a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -132,8 +132,7 @@ TEST(DynamicMatrix, CopyMoveAssign) { DynamicMatrix moved(std::move(copied)); EXPECT_TRUE(moved.isApprox(original)); - DynamicMatrix assigned; - assigned = original; + const DynamicMatrix assigned = original; EXPECT_TRUE(assigned.isApprox(original)); DynamicMatrix moveAssigned(1); From 43dc4cfedf7ec1a33a0d69d403871773ec2de261 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 18:19:20 +0200 Subject: [PATCH 14/20] :truck: Generalize matrix utils to not refer to unitary In the end, the respective functionality is general enough Signed-off-by: burgholzer --- .../mlir/Dialect/QCO/IR/QCOInterfaces.h | 2 +- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 2 +- .../QCO/Utils/{UnitaryMatrix.h => Matrix.h} | 46 +++++++++---------- mlir/lib/Dialect/QCO/IR/CMakeLists.txt | 2 +- mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp | 2 +- mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/DCXOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/ECROp.cpp | 2 +- .../IR/Operations/StandardGates/GPhaseOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/HOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/IdOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/POp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/ROp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RXOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RXXOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RYOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RYYOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RZOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RZXOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/RZZOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/SOp.cpp | 2 +- .../IR/Operations/StandardGates/SWAPOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/SXOp.cpp | 2 +- .../IR/Operations/StandardGates/SXdgOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/SdgOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/TOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/TdgOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/U2Op.cpp | 2 +- .../QCO/IR/Operations/StandardGates/UOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/XOp.cpp | 2 +- .../Operations/StandardGates/XXMinusYYOp.cpp | 2 +- .../Operations/StandardGates/XXPlusYYOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/YOp.cpp | 2 +- .../QCO/IR/Operations/StandardGates/ZOp.cpp | 2 +- .../IR/Operations/StandardGates/iSWAPOp.cpp | 2 +- mlir/lib/Dialect/QCO/Utils/CMakeLists.txt | 14 +++--- .../Utils/{UnitaryMatrix.cpp => Matrix.cpp} | 2 +- .../Dialect/QCO/IR/test_qco_ir_matrix.cpp | 2 +- .../Dialect/QCO/Utils/CMakeLists.txt | 2 +- .../Dialect/QCO/Utils/test_unitary_matrix.cpp | 12 ++--- 40 files changed, 72 insertions(+), 74 deletions(-) rename mlir/include/mlir/Dialect/QCO/Utils/{UnitaryMatrix.h => Matrix.h} (90%) rename mlir/lib/Dialect/QCO/Utils/{UnitaryMatrix.cpp => Matrix.cpp} (99%) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h index 9104d196a1..0940cea2af 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.h @@ -10,7 +10,7 @@ #pragma once -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index 84593694ff..f97d7ec4ce 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -201,7 +201,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { let extraClassDeclaration = [{ template std::optional getUnitaryMatrix() { - static_assert(is_unitary_matrix_v, + static_assert(is_supported_matrix_v, "MatrixType must be Matrix1x1, Matrix2x2, Matrix4x4, or DynamicMatrix"); MatrixType out; bool result = false; diff --git a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h b/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h similarity index 90% rename from mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h rename to mlir/include/mlir/Dialect/QCO/Utils/Matrix.h index 7424faf72b..11e15755eb 100644 --- a/mlir/include/mlir/Dialect/QCO/Utils/UnitaryMatrix.h +++ b/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h @@ -19,21 +19,21 @@ namespace mlir::qco { -/// Complex scalar type used for unitary matrix entries. +/// Complex scalar type used for matrix entries. using Complex = std::complex; -/// Default absolute tolerance for unitary matrix comparisons. -inline constexpr double UNITARY_MATRIX_TOLERANCE = 1e-14; +/// Default absolute tolerance for matrix comparisons. +inline constexpr double MATRIX_TOLERANCE = 1e-14; /** - * @brief 1x1 unitary matrix for global-phase gates. + * @brief 1x1 matrix for global-phase gates. * * Wraps a single complex scalar. Used by operations such as `GPhaseOp` whose * unitary is a global phase factor. */ struct Matrix1x1 { /// The sole matrix entry. - Complex value{1.0, 0.0}; + Complex value{0.0, 0.0}; /** * @brief Constructs a matrix from its single entry. @@ -65,13 +65,13 @@ struct Matrix1x1 { * @return True if the difference is within @p tol. */ [[nodiscard]] bool isApprox(const Matrix1x1& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; }; /** - * @brief Fixed-size 2x2 unitary matrix in row-major layout. + * @brief Fixed-size 2x2 matrix in row-major layout. * - * Represents single-qubit gate unitaries. Elements are stored in a flat array + * Used to represent single-qubit unitaries. Elements are stored in a flat array * with index `(row * K_COLS) + col`. */ struct Matrix2x2 { @@ -154,14 +154,14 @@ struct Matrix2x2 { * @return True if every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix2x2& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; }; /** - * @brief Fixed-size 4x4 unitary matrix in row-major layout. + * @brief Fixed-size 4x4 matrix in row-major layout. * - * Represents two-qubit gate unitaries. Elements are stored in a flat array with - * index `(row * K_COLS) + col`. + * Used to represent two-qubit gate unitaries. Elements are stored in a flat + * array with index `(row * K_COLS) + col`. */ struct Matrix4x4 { /// Number of rows. @@ -263,13 +263,13 @@ struct Matrix4x4 { * @return True if every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix4x4& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; }; /** - * @brief Square unitary matrix with runtime dimension. + * @brief Square matrix with runtime dimension. * - * Used when the Hilbert-space dimension depends on the operation, for example + * Used when the Hilbert-space dimension depends on the operation, for example, * in controlled gates (`CtrlOp`) and inverses (`InvOp`). Storage is row-major * and held behind a private implementation pointer. */ @@ -392,7 +392,7 @@ class DynamicMatrix { * @return True if dimensions match and every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix2x2& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; /** * @brief Checks approximate equality against a fixed 4x4 matrix. @@ -404,7 +404,7 @@ class DynamicMatrix { * @return True if dimensions match and every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const Matrix4x4& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; /** * @brief Checks approximate equality against another dynamic matrix. @@ -416,7 +416,7 @@ class DynamicMatrix { * @return True if dimensions match and every entry differs by at most @p tol. */ [[nodiscard]] bool isApprox(const DynamicMatrix& other, - double tol = UNITARY_MATRIX_TOLERANCE) const; + double tol = MATRIX_TOLERANCE) const; private: struct Impl; @@ -424,7 +424,7 @@ class DynamicMatrix { }; /** - * @brief Type trait for the four supported unitary matrix value types. + * @brief Type trait for the four supported matrix types. * * True for @ref Matrix1x1, @ref Matrix2x2, @ref Matrix4x4, and @ref * DynamicMatrix. @@ -433,8 +433,8 @@ class DynamicMatrix { */ template inline constexpr bool - is_unitary_matrix_v = // NOLINT(readability-identifier-naming) - std::is_same_v || std::is_same_v || - std::is_same_v || std::is_same_v; - + is_supported_matrix_v = // NOLINT(readability-identifier-naming) + std::disjunction_v, std::is_same, + std::is_same, + std::is_same>; } // namespace mlir::qco diff --git a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt index cba31ac19b..cb7c30a4ee 100644 --- a/mlir/lib/Dialect/QCO/IR/CMakeLists.txt +++ b/mlir/lib/Dialect/QCO/IR/CMakeLists.txt @@ -25,7 +25,7 @@ add_mlir_dialect_library( MLIRQCOInterfacesIncGen LINK_LIBS PUBLIC - MLIRQCOUnitaryMatrix + MLIRQCOMatrix PRIVATE MLIRIR MLIRArithDialect diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp index e73fdcd9d6..ccfb9b6093 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/CtrlOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp index 3fe9af123d..02a9204941 100644 --- a/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Modifiers/InvOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp index 0a4ad54605..60cb98c196 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/DCXOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp index 48d17a948b..9223bbe11c 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ECROp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp index 58e536d3ae..c25cbbb344 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/GPhaseOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp index b30687a991..602acff7d8 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/HOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp index ecbe719c75..adbe47c592 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/IdOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp index 0c18fa3eac..fa7c5c8e22 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/POp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp index eea83574dc..1eca6542b0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp index 82a697b313..5a81d94797 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp index fb92d6d942..c55edc7f8a 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RXXOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index 08a56618f3..dc38b2fa6d 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp index f300e5ff14..9f59ca471e 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYYOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp index 99fa8e8701..288e9f0d0f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp index 0b9fb1a715..e182a0327b 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZXOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp index 93f748b081..c290dc69b0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RZZOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp index aa86942b5d..768bddfcc0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp index f9b3bb7420..673ffffdee 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SWAPOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp index ef573093f1..e42d30f234 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp index 69aa211d27..73b36fcf33 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SXdgOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp index 4dbcf21f58..1a9110d312 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/SdgOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp index 2dd2a2865c..8e9a90e582 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp index 778eea2f7f..ca093fd81d 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/TdgOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp index 77d7155c26..92face4e40 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/U2Op.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp index 281b4c279b..f504ba3a49 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp index dab82f98b7..7d53d6f83f 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp index 7dea7eac68..26d5966d11 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp index 53b01d8908..6b4c5f0b9e 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "mlir/Dialect/Utils/Utils.h" #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp index 122a7fcd75..e6921dc9f7 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/YOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp index 5b000f26d6..0e938206f0 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ZOp.cpp @@ -10,7 +10,7 @@ #include "mlir/Dialect/QCO/IR/QCOOps.h" #include "mlir/Dialect/QCO/QCOUtils.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp index 104d4d5796..0f9f189821 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/iSWAPOp.cpp @@ -9,7 +9,7 @@ */ #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include diff --git a/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt b/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt index 4a81c9e640..6e0d1eed9c 100644 --- a/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt +++ b/mlir/lib/Dialect/QCO/Utils/CMakeLists.txt @@ -6,17 +6,15 @@ # # Licensed under the MIT License -add_mlir_library(MLIRQCOUnitaryMatrix PARTIAL_SOURCES_INTENDED UnitaryMatrix.cpp LINK_LIBS PUBLIC - MLIRSupport) +add_mlir_library(MLIRQCOMatrix PARTIAL_SOURCES_INTENDED Matrix.cpp LINK_LIBS PUBLIC MLIRSupport) -mqt_mlir_target_use_project_options(MLIRQCOUnitaryMatrix) +mqt_mlir_target_use_project_options(MLIRQCOMatrix) -target_sources( - MLIRQCOUnitaryMatrix PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_MLIR_SOURCE_INCLUDE_DIR} FILES - ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/UnitaryMatrix.h) +target_sources(MLIRQCOMatrix PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_MLIR_SOURCE_INCLUDE_DIR} FILES + ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/Matrix.h) file(GLOB_RECURSE UTILS_CPP "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") -list(FILTER UTILS_CPP EXCLUDE REGEX "UnitaryMatrix\\.cpp$") +list(FILTER UTILS_CPP EXCLUDE REGEX "Matrix\\.cpp$") add_mlir_dialect_library( MLIRQCOUtils @@ -35,7 +33,7 @@ mqt_mlir_target_use_project_options(MLIRQCOUtils) # collect header files file(GLOB_RECURSE UTILS_HEADERS_SOURCE "${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/*.h") -list(FILTER UTILS_HEADERS_SOURCE EXCLUDE REGEX "UnitaryMatrix\\.h$") +list(FILTER UTILS_HEADERS_SOURCE EXCLUDE REGEX "Matrix\\.h$") file(GLOB_RECURSE UTILS_HEADERS_BUILD "${MQT_MLIR_BUILD_INCLUDE_DIR}/mlir/Dialect/QCO/Utils/*.inc") # add public headers using file sets diff --git a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp similarity index 99% rename from mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp rename to mlir/lib/Dialect/QCO/Utils/Matrix.cpp index a1f46c0921..9c05ec4a83 100644 --- a/mlir/lib/Dialect/QCO/Utils/UnitaryMatrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp @@ -8,7 +8,7 @@ * Licensed under the MIT License */ -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include #include diff --git a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp index 2d4a81f06b..91c31f9899 100644 --- a/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/IR/test_qco_ir_matrix.cpp @@ -18,7 +18,7 @@ #include "mlir/Dialect/QCO/Builder/QCOProgramBuilder.h" #include "mlir/Dialect/QCO/IR/QCODialect.h" #include "mlir/Dialect/QCO/IR/QCOOps.h" -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include "qco_programs.h" #include diff --git a/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt b/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt index 12372120ff..ac92f4e9aa 100644 --- a/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt +++ b/mlir/unittests/Dialect/QCO/Utils/CMakeLists.txt @@ -9,7 +9,7 @@ set(qco_utils_target mqt-core-mlir-unittest-qco-utils) add_executable(${qco_utils_target} test_drivers.cpp test_unitary_matrix.cpp test_wireiterator.cpp) target_link_libraries(${qco_utils_target} PRIVATE GTest::gtest_main MLIRQCOUtils - MLIRQCOProgramBuilder MLIRQCOUnitaryMatrix) + MLIRQCOProgramBuilder MLIRQCOMatrix) mqt_mlir_configure_unittest_target(${qco_utils_target}) gtest_discover_tests(${qco_utils_target} PROPERTIES LABELS mqt-mlir-unittests DISCOVERY_TIMEOUT 60) diff --git a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp index ac239718e4..8008dc7561 100644 --- a/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp +++ b/mlir/unittests/Dialect/QCO/Utils/test_unitary_matrix.cpp @@ -8,7 +8,7 @@ * Licensed under the MIT License */ -#include "mlir/Dialect/QCO/Utils/UnitaryMatrix.h" +#include "mlir/Dialect/QCO/Utils/Matrix.h" #include @@ -18,11 +18,11 @@ using namespace mlir::qco; using namespace std::complex_literals; -static_assert(is_unitary_matrix_v); -static_assert(is_unitary_matrix_v); -static_assert(is_unitary_matrix_v); -static_assert(is_unitary_matrix_v); -static_assert(!is_unitary_matrix_v); +static_assert(is_supported_matrix_v); +static_assert(is_supported_matrix_v); +static_assert(is_supported_matrix_v); +static_assert(is_supported_matrix_v); +static_assert(!is_supported_matrix_v); [[nodiscard]] static Matrix2x2 pauliX() { return Matrix2x2::fromElements(0, 1, 1, 0); From 0264720faeac7ecdfcc0fc7fde9ecad175b35dde Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 18:50:53 +0200 Subject: [PATCH 15/20] :zap: Pass complex numbers by const reference to avoid copies Signed-off-by: burgholzer --- mlir/include/mlir/Dialect/QCO/Utils/Matrix.h | 16 +++++---- mlir/lib/Dialect/QCO/Utils/Matrix.cpp | 34 ++++++++++---------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h b/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h index 11e15755eb..2305a06346 100644 --- a/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h +++ b/mlir/include/mlir/Dialect/QCO/Utils/Matrix.h @@ -93,8 +93,10 @@ struct Matrix2x2 { * @param m11 Element at row 1, column 1. * @return A new `Matrix2x2` with the given elements. */ - [[nodiscard]] static Matrix2x2 fromElements(Complex m00, Complex m01, - Complex m10, Complex m11); + [[nodiscard]] static Matrix2x2 fromElements(const Complex& m00, + const Complex& m01, + const Complex& m10, + const Complex& m11); /** * @brief Returns the 2x2 identity matrix. @@ -195,10 +197,12 @@ struct Matrix4x4 { * @return A new `Matrix4x4` with the given elements. */ [[nodiscard]] static Matrix4x4 - fromElements(Complex m00, Complex m01, Complex m02, Complex m03, Complex m10, - Complex m11, Complex m12, Complex m13, Complex m20, Complex m21, - Complex m22, Complex m23, Complex m30, Complex m31, Complex m32, - Complex m33); + fromElements(const Complex& m00, const Complex& m01, const Complex& m02, + const Complex& m03, const Complex& m10, const Complex& m11, + const Complex& m12, const Complex& m13, const Complex& m20, + const Complex& m21, const Complex& m22, const Complex& m23, + const Complex& m30, const Complex& m31, const Complex& m32, + const Complex& m33); /** * @brief Returns the 4x4 identity matrix. diff --git a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp index 9c05ec4a83..b057f41175 100644 --- a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp @@ -128,8 +128,8 @@ bool Matrix1x1::isApprox(const Matrix1x1& other, const double tol) const { return std::abs(value - other.value) <= tol; } -Matrix2x2 Matrix2x2::fromElements(const Complex m00, const Complex m01, - const Complex m10, const Complex m11) { +Matrix2x2 Matrix2x2::fromElements(const Complex& m00, const Complex& m01, + const Complex& m10, const Complex& m11) { return {{m00, m01, m10, m11}}; } @@ -164,14 +164,14 @@ bool Matrix2x2::isApprox(const Matrix2x2& other, const double tol) const { return entriesAreApprox(data, other.data, tol); } -Matrix4x4 Matrix4x4::fromElements(const Complex m00, const Complex m01, - const Complex m02, const Complex m03, - const Complex m10, const Complex m11, - const Complex m12, const Complex m13, - const Complex m20, const Complex m21, - const Complex m22, const Complex m23, - const Complex m30, const Complex m31, - const Complex m32, const Complex m33) { +Matrix4x4 Matrix4x4::fromElements(const Complex& m00, const Complex& m01, + const Complex& m02, const Complex& m03, + const Complex& m10, const Complex& m11, + const Complex& m12, const Complex& m13, + const Complex& m20, const Complex& m21, + const Complex& m22, const Complex& m23, + const Complex& m30, const Complex& m31, + const Complex& m32, const Complex& m33) { return {{m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33}}; } @@ -189,10 +189,10 @@ Matrix4x4 Matrix4x4::operator*(const Matrix4x4& rhs) const { Matrix4x4 out{}; for (std::size_t row = 0; row < K_ROWS; ++row) { const std::size_t rowBase = row * K_COLS; - const Complex a0 = data[rowBase + 0]; - const Complex a1 = data[rowBase + 1]; - const Complex a2 = data[rowBase + 2]; - const Complex a3 = data[rowBase + 3]; + const Complex& a0 = data[rowBase + 0]; + const Complex& a1 = data[rowBase + 1]; + const Complex& a2 = data[rowBase + 2]; + const Complex& a3 = data[rowBase + 3]; out.data[rowBase + 0] = a0 * rhs.data[0] + a1 * rhs.data[4] + a2 * rhs.data[8] + a3 * rhs.data[12]; out.data[rowBase + 1] = a0 * rhs.data[1] + a1 * rhs.data[5] + @@ -216,9 +216,9 @@ Complex Matrix4x4::trace() const { } Complex Matrix4x4::determinant() const { - auto det3 = [](const Complex m00, const Complex m01, const Complex m02, - const Complex m10, const Complex m11, const Complex m12, - const Complex m20, const Complex m21, const Complex m22) { + auto det3 = [](const Complex& m00, const Complex& m01, const Complex& m02, + const Complex& m10, const Complex& m11, const Complex& m12, + const Complex& m20, const Complex& m21, const Complex& m22) { return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20); }; From a6de65c8abce89bf550c53f70436ca8221e5d682 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 18:52:42 +0200 Subject: [PATCH 16/20] :art: Drop namespace qualifiers Signed-off-by: burgholzer --- mlir/lib/Dialect/QCO/Utils/Matrix.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp index b057f41175..a2e0e44a6a 100644 --- a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp @@ -11,7 +11,7 @@ #include "mlir/Dialect/QCO/Utils/Matrix.h" #include -#include +#include #include #include @@ -41,8 +41,7 @@ namespace mlir::qco { } /// Writes the conjugate transpose of @p in into @p out (square, row-major). -static void adjointInto(llvm::ArrayRef in, - llvm::MutableArrayRef out, +static void adjointInto(ArrayRef in, MutableArrayRef out, const std::size_t dim) { for (std::size_t row = 0; row < dim; ++row) { for (std::size_t col = 0; col < dim; ++col) { @@ -52,7 +51,7 @@ static void adjointInto(llvm::ArrayRef in, } template -static void assignFixedImpl(std::int64_t& dim, llvm::SmallVector& data, +static void assignFixedImpl(std::int64_t& dim, SmallVector& data, const std::array& src) { dim = static_cast(Dim); data.assign(src.begin(), src.end()); @@ -60,9 +59,9 @@ static void assignFixedImpl(std::int64_t& dim, llvm::SmallVector& data, template [[nodiscard]] static bool -isApproxFixedImpl(const std::int64_t dim, llvm::ArrayRef data, +isApproxFixedImpl(const std::int64_t dim, ArrayRef data, const std::array& other, const double tol) { - if (std::cmp_not_equal(dim, static_cast(Dim))) { + if (std::cmp_not_equal(dim, Dim)) { return false; } return entriesAreApprox(data, other, tol); @@ -85,14 +84,14 @@ static void validateCornerDims(const std::int64_t matrixDim, const std::int64_t blockDim) { assert(matrixDim >= 0 && blockDim >= 0 && blockDim <= matrixDim && "block must fit in the bottom-right corner of the matrix"); - checkedDim(matrixDim); + std::ignore = checkedDim(matrixDim); } /// Copies @p blockData into the bottom-right @p blockDim x @p blockDim corner. static void copyBottomRightCorner(const std::int64_t matrixDim, - llvm::MutableArrayRef matrixData, + MutableArrayRef matrixData, const std::int64_t blockDim, - llvm::ArrayRef blockData) { + ArrayRef blockData) { validateCornerDims(matrixDim, blockDim); assert(matrixData.size() >= checkedStorageSize(matrixDim)); assert(blockData.size() >= checkedStorageSize(blockDim)); @@ -108,7 +107,7 @@ static void copyBottomRightCorner(const std::int64_t matrixDim, struct DynamicMatrix::Impl { std::int64_t dim = 0; - llvm::SmallVector data; + SmallVector data; }; Matrix1x1 Matrix1x1::fromElements(const Complex m00) { return {m00}; } From 7695d54583fe1e8711eedf3052e1180c63fdf1d8 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 18:53:20 +0200 Subject: [PATCH 17/20] :art: optimize approximate equality check Signed-off-by: burgholzer --- mlir/lib/Dialect/QCO/Utils/Matrix.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp index a2e0e44a6a..01d1b35ea4 100644 --- a/mlir/lib/Dialect/QCO/Utils/Matrix.cpp +++ b/mlir/lib/Dialect/QCO/Utils/Matrix.cpp @@ -28,16 +28,12 @@ namespace mlir::qco { /// Returns true if every entry pair differs by at most @p tol (complex /// modulus). -[[nodiscard]] static bool entriesAreApprox(llvm::ArrayRef lhs, - llvm::ArrayRef rhs, - double tol) { - if (lhs.size() != rhs.size()) { - return false; - } - return std::equal(lhs.begin(), lhs.end(), rhs.begin(), - [tol](const Complex& lhsEntry, const Complex& rhsEntry) { - return std::abs(lhsEntry - rhsEntry) <= tol; - }); +[[nodiscard]] static bool entriesAreApprox(ArrayRef lhs, + ArrayRef rhs, double tol) { + return std::ranges::equal(lhs, rhs, + [tol](const Complex& a, const Complex& b) { + return std::abs(a - b) <= tol; + }); } /// Writes the conjugate transpose of @p in into @p out (square, row-major). From 7882534795980d68cfb348e0e5fec410b547dde0 Mon Sep 17 00:00:00 2001 From: burgholzer Date: Tue, 9 Jun 2026 19:03:07 +0200 Subject: [PATCH 18/20] :rotating_light: fix clang-tidy warning Signed-off-by: burgholzer --- mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp index dc38b2fa6d..7c58ee3cbd 100644 --- a/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp +++ b/mlir/lib/Dialect/QCO/IR/Operations/StandardGates/RYOp.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include From e14e76f092541b5357dc2f280ada1ccfa1460cad Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 9 Jun 2026 21:21:04 +0200 Subject: [PATCH 19/20] Simplify .clang-format --- .clang-format | 2 -- 1 file changed, 2 deletions(-) diff --git a/.clang-format b/.clang-format index 11d0a4ab06..c862c60400 100644 --- a/.clang-format +++ b/.clang-format @@ -5,8 +5,6 @@ IncludeCategories: Priority: 1 - Regex: '^<.*\.(h|hpp)>' Priority: 2 - - Regex: "^" - Priority: 2 - Regex: "^<.*>" Priority: 3 PointerAlignment: Left From 8a494529949c1aeee2f3ce69038d0fbcf9a8cf02 Mon Sep 17 00:00:00 2001 From: Daniel Haag <121057143+denialhaag@users.noreply.github.com> Date: Tue, 9 Jun 2026 21:44:28 +0200 Subject: [PATCH 20/20] Define unitaryMatrixDynamicMethodBody --- .../mlir/Dialect/QCO/IR/QCOInterfaces.td | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td index f97d7ec4ce..3384d7a048 100644 --- a/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td +++ b/mlir/include/mlir/Dialect/QCO/IR/QCOInterfaces.td @@ -28,7 +28,8 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { let cppNamespace = "::mlir::qco"; - // Size-specific bodies: each helper only accepts the matching matrix type. + // Size-specific bodies + // Each helper only accepts the matching matrix type. defvar unitaryMatrix1x1MethodBody = [{ if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { using ValueT = std::remove_cvref_t())>; @@ -101,6 +102,21 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { } }]; + defvar unitaryMatrixDynamicMethodBody = [{ + if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { + if (auto matrix = $_op.getUnitaryMatrix()) { + out.assignFrom(*matrix); + return true; + } + return false; + } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { + out.assignFrom($_op.getUnitaryMatrix()); + return true; + } else { + llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); + } + }]; + let methods = [ // Qubit accessors InterfaceMethod< @@ -183,20 +199,7 @@ def UnitaryOpInterface : OpInterface<"UnitaryOpInterface"> { unitaryMatrix4x4MethodBody>, InterfaceMethod<"Populates the given dynamic unitary matrix.", "bool", "getUnitaryMatrixDynamic", (ins "DynamicMatrix&":$out), - [{ - if constexpr (requires { $_op.getUnitaryMatrix().has_value(); }) { - if (auto matrix = $_op.getUnitaryMatrix()) { - out.assignFrom(*matrix); - return true; - } - return false; - } else if constexpr (requires { $_op.getUnitaryMatrix(); }) { - out.assignFrom($_op.getUnitaryMatrix()); - return true; - } else { - llvm::reportFatalUsageError("Operation '" + $_op.getBaseSymbol() + "' has no unitary matrix definition!"); - } - }]>]; + unitaryMatrixDynamicMethodBody>]; let extraClassDeclaration = [{ template