Program Listing for File StateVectorBase.hpp

Return to documentation for file (pennylane_lightning/core/src/simulators/base/StateVectorBase.hpp)

// Copyright 2018-2023 Xanadu Quantum Technologies Inc.

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once

// Required for compilation with MSVC
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES // for C++
#endif

#include <complex>

namespace Pennylane {
template <class PrecisionT, class Derived> class StateVectorBase {
  protected:
    std::size_t num_qubits_{0};

  public:
    using ComplexT = std::complex<PrecisionT>;

    explicit StateVectorBase(size_t num_qubits) : num_qubits_{num_qubits} {}

    [[nodiscard]] auto getNumQubits() const -> std::size_t {
        return num_qubits_;
    }

    [[nodiscard]] auto getTotalNumQubits() const -> std::size_t {
        return num_qubits_;
    }

    [[nodiscard]] std::size_t getLength() const {
        return static_cast<std::size_t>(exp2(num_qubits_));
    }

    [[nodiscard]] inline auto getData() -> decltype(auto) {
        return static_cast<Derived *>(this)->getData();
    }

    [[nodiscard]] inline auto getData() const -> decltype(auto) {
        return static_cast<const Derived *>(this)->getData();
    }

    inline void applyOperation(const std::string &opName,
                               const std::vector<std::size_t> &wires,
                               bool adjoint = false,
                               const std::vector<PrecisionT> &params = {}) {
        return static_cast<Derived *>(this)->applyOperation(opName, wires,
                                                            adjoint, params);
    }

    void
    applyOperations(const std::vector<std::string> &ops,
                    const std::vector<std::vector<std::size_t>> &ops_wires,
                    const std::vector<bool> &ops_adjoint,
                    const std::vector<std::vector<PrecisionT>> &ops_params) {
        const std::size_t numOperations = ops.size();
        PL_ABORT_IF(
            numOperations != ops_wires.size(),
            "Invalid arguments: number of operations, wires, inverses, and "
            "parameters must all be equal");
        PL_ABORT_IF(
            numOperations != ops_adjoint.size(),
            "Invalid arguments: number of operations, wires, inverses, and "
            "parameters must all be equal");
        PL_ABORT_IF(
            numOperations != ops_params.size(),
            "Invalid arguments: number of operations, wires, inverses, and "
            "parameters must all be equal");
        for (size_t i = 0; i < numOperations; i++) {
            this->applyOperation(ops[i], ops_wires[i], ops_adjoint[i],
                                 ops_params[i]);
        }
    }

    void applyOperations(const std::vector<std::string> &ops,
                         const std::vector<std::vector<std::size_t>> &ops_wires,
                         const std::vector<bool> &ops_adjoint) {
        const std::size_t numOperations = ops.size();
        PL_ABORT_IF_NOT(
            numOperations == ops_wires.size(),
            "Invalid arguments: number of operations, wires, and inverses "
            "must all be equal");
        PL_ABORT_IF_NOT(
            numOperations == ops_adjoint.size(),
            "Invalid arguments: number of operations, wires and inverses"
            "must all be equal");
        for (size_t i = 0; i < numOperations; i++) {
            this->applyOperation(ops[i], ops_wires[i], ops_adjoint[i], {});
        }
    }

    inline auto applyGenerator(const std::string &opName,
                               const std::vector<std::size_t> &wires,
                               bool adjoint = false) -> PrecisionT {
        return static_cast<Derived *>(this)->applyGenerator(opName, wires,
                                                            adjoint);
    }

    inline void applyMatrix(const ComplexT *matrix,
                            const std::vector<std::size_t> &wires,
                            bool inverse = false) {
        return static_cast<Derived *>(this)->applyMatrix(matrix, wires,
                                                         inverse);
    }
};

} // namespace Pennylane