Program Listing for File ConstantUtil.hpp

Return to documentation for file (pennylane_lightning/core/src/utils/ConstantUtil.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>
#include <array>
#include <compare>
#include <cstdlib>
#include <stdexcept>
#include <tuple>
#include <unordered_map>

#if __has_include(<version>)
#include <version>
#endif

#include "Error.hpp"
#include "TypeTraits.hpp"
#include "Util.hpp"

namespace Pennylane::Util {
template <typename Key, typename Value, std::size_t size>
constexpr auto lookup(const std::array<std::pair<Key, Value>, size> &arr,
                      const Key &key) -> Value {
    for (size_t idx = 0; idx < size; idx++) {
        if (std::get<0>(arr[idx]) == key) {
            return std::get<1>(arr[idx]);
        }
    }
    PL_ABORT("The given key does not exist.");
}

template <typename Key, typename Value, std::size_t size>
constexpr auto
reverse_lookup(const std::array<std::pair<Key, Value>, size> &arr,
               const Value &value) -> Key {
    for (size_t idx = 0; idx < size; idx++) {
        if (std::get<1>(arr[idx]) == value) {
            return std::get<0>(arr[idx]);
        }
    }
    PL_ABORT("The given value does not exist.");
}

template <typename U, std::size_t size>
constexpr auto array_has_elem(const std::array<U, size> &arr, const U &elem)
    -> bool {
    for (size_t idx = 0; idx < size; idx++) {
        if (arr[idx] == elem) {
            return true;
        }
    }
    return false;
}

template <typename Key, typename Value, std::size_t size>
constexpr auto
array_contains(const std::array<std::pair<Key, Value>, size> &arr,
               const Value &value) -> bool {
    for (size_t idx = 0; idx < size; idx++) {
        if (std::get<1>(arr[idx]) == value) {
            return true;
        }
    }
    return false;
}

namespace Internal {
template <class T, class Tuple, std::size_t... I>
constexpr auto
prepend_to_tuple_helper(T &&elem, Tuple &&t,
                        [[maybe_unused]] std::index_sequence<I...> dummy) {
    return std::make_tuple(elem, std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace Internal

template <class T, class Tuple>
constexpr auto prepend_to_tuple(T &&elem, Tuple &&t) {
    return Internal::prepend_to_tuple_helper(
        std::forward<T>(elem), std::forward<Tuple>(t),
        std::make_index_sequence<
            std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}

template <class Tuple> constexpr auto tuple_to_array(Tuple &&tuple) {
    using T = std::tuple_element_t<0, std::remove_cvref_t<Tuple>>;
    return std::apply(
        [](auto... n) { return std::array<T, sizeof...(n)>{n...}; },
        std::forward<Tuple>(tuple));
}

namespace Internal {
template <class T, class U, std::size_t size, std::size_t... I>
constexpr auto
reverse_pairs_helper(const std::array<std::pair<T, U>, size> &arr,
                     [[maybe_unused]] std::index_sequence<I...> dummy) {
    return std::array{std::pair{arr[I].second, arr[I].first}...};
}
} // namespace Internal

template <class T, class U, std::size_t size>
constexpr auto reverse_pairs(const std::array<std::pair<T, U>, size> &arr)
    -> std::array<std::pair<U, T>, size> {
    return Internal::reverse_pairs_helper(arr,
                                          std::make_index_sequence<size>{});
}

} // namespace Pennylane::Util