Program Listing for File BitUtil.hpp

Return to documentation for file (pennylane_lightning/core/src/utils/BitUtil.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
#include <algorithm> // sort
#include <array>
#include <bit>     // countr_zero, popcount, has_single_bit
#include <climits> // CHAR_BIT
#include <cstddef> // size_t
#include <vector>

namespace Pennylane::Util {
inline auto constexpr log2PerfectPower(size_t val) -> size_t {
    return static_cast<size_t>(std::countr_zero(val));
}

inline auto constexpr isPerfectPowerOf2(size_t value) -> bool {
    return std::has_single_bit(value);
}

template <class IntegerType = size_t>
inline auto constexpr fillTrailingOnes(size_t nbits) -> IntegerType {
    static_assert(std::is_integral_v<IntegerType> &&
                  std::is_unsigned_v<IntegerType>);

    return (nbits == 0) ? 0
                        : static_cast<IntegerType>(~IntegerType(0)) >>
                              static_cast<IntegerType>(
                                  CHAR_BIT * sizeof(IntegerType) - nbits);
}
template <class IntegerType = size_t>
inline auto constexpr fillLeadingOnes(size_t pos) -> size_t {
    static_assert(std::is_integral_v<IntegerType> &&
                  std::is_unsigned_v<IntegerType>);

    return (~IntegerType{0}) << pos;
}

inline auto constexpr bitswap(size_t bits, const size_t i, const size_t j)
    -> size_t {
    size_t x = ((bits >> i) ^ (bits >> j)) & 1U;
    return bits ^ ((x << i) | (x << j));
}

inline auto revWireParity(const std::vector<std::size_t> &wire_list)
    -> std::vector<std::size_t> {
    const std::size_t wire_size = wire_list.size();
    auto rev_wire = wire_list;
    std::sort(rev_wire.begin(), rev_wire.end());
    std::vector<std::size_t> parity(wire_size + 1);
    parity[0] = fillTrailingOnes(rev_wire[0]);
    for (std::size_t i = 1; i < wire_size; i++) {
        parity[i] = fillLeadingOnes(rev_wire[i - 1] + 1) &
                    fillTrailingOnes(rev_wire[i]);
    }
    parity[wire_size] = fillLeadingOnes(rev_wire[wire_size - 1] + 1);
    return parity;
}

template <std::size_t wire_size>
inline auto revWireParity(const std::array<std::size_t, wire_size> &wire_list)
    -> std::array<std::size_t, wire_size + 1> {
    auto rev_wire = wire_list;
    std::sort(rev_wire.begin(), rev_wire.end());
    std::array<std::size_t, wire_size + 1> parity{};
    parity[0] = fillTrailingOnes(rev_wire[0]);
    for (std::size_t i = 1; i < wire_size; i++) {
        parity[i] = fillLeadingOnes(rev_wire[i - 1] + 1) &
                    fillTrailingOnes(rev_wire[i]);
    }
    parity[wire_size] = fillLeadingOnes(rev_wire[wire_size - 1] + 1);
    return parity;
}

} // namespace Pennylane::Util