/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ #include #include #ifndef _TUPLE_POLICY_HPP_ #define _TUPLE_POLICY_HPP_ namespace py = pybind11; namespace datasketches { /** * @brief tuple_policy provides the underlying base class from * which native Python policies ultimately inherit. The actual * policies implement TuplePolicy, as shown in TuplePolicy.py */ struct tuple_policy { virtual py::object create_summary() const = 0; virtual py::object update_summary(py::object& summary, const py::object& update) const = 0; virtual py::object operator()(py::object& summary, const py::object& update) const = 0; virtual ~tuple_policy() = default; }; /** * @brief TuplePolicy provides the "trampoline" class for pybind11 * that allows for a native Python implementation of tuple * sketch policies. */ struct TuplePolicy : public tuple_policy { using tuple_policy::tuple_policy; /** * @brief Create a summary object * * @return py::object representing a new summary */ py::object create_summary() const override { PYBIND11_OVERRIDE_PURE( py::object, // Return type tuple_policy, // Parent class create_summary, // Name of function in C++ (must match Python name) // Argument(s) -- if any ); } /** * @brief Update a summary object using this policy * * @param summary The current summary to update * @param update The new value with which to update the summary * @return py::object The updated summary */ py::object update_summary(py::object& summary, const py::object& update) const override { PYBIND11_OVERRIDE_PURE( py::object, // Return type tuple_policy, // Parent class update_summary, // Name of function in C++ (must match Python name) summary, update // Arguments ); } /** * @brief Applies this policy to summary with the provided update * * @param summary The current summary on which to apply the policy * @param update An update to apply to the current summary * @return py::object The potentially modified summary */ py::object operator()(py::object& summary, const py::object& update) const override { PYBIND11_OVERRIDE_PURE_NAME( py::object, // Return type tuple_policy, // Parent class "__call__", // Name of function in python operator(), // Name of function in C++ summary, update // Arguemnts ); } }; /* The tuple_policy_holder provides a concrete class that dispatches calls * from the sketch to the tuple_policy. This class is needed to provide a * concrete object to produce a compiled library, but library users should * never need to use this directly. */ struct tuple_policy_holder { explicit tuple_policy_holder(std::shared_ptr policy) : _policy(policy) {} tuple_policy_holder(const tuple_policy_holder& other) : _policy(other._policy) {} tuple_policy_holder(tuple_policy_holder&& other) : _policy(std::move(other._policy)) {} tuple_policy_holder& operator=(const tuple_policy_holder& other) { _policy = other._policy; return *this; } tuple_policy_holder& operator=(tuple_policy_holder&& other) { std::swap(_policy, other._policy); return *this; } py::object create() const { return _policy->create_summary(); } void update(py::object& summary, const py::object& update) const { summary = _policy->update_summary(summary, update); } void operator()(py::object& summary, const py::object& update) const { summary = _policy->operator()(summary, update); } private: std::shared_ptr _policy; }; /* A degenerate policy used to enable Jaccard Similarity on tuple sketches, * where the computation requires a union and intersection over the keys but * does not need to observe the summaries. */ struct dummy_jaccard_policy { void operator()(py::object&, const py::object&) const { return; } }; } #endif // _TUPLE_POLICY_HPP_