blob: f453ebd1399a13f5b2296bfc742ea15f43919b0b [file] [log] [blame] [edit]
//
// Copyright 2024 Google LLC
//
// 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.
//
#ifndef DIFFERENTIAL_PRIVACY_CPP_ALGORITHMS_APPROX_BOUNDS_AS_BOUNDS_PROVIDER_H_
#define DIFFERENTIAL_PRIVACY_CPP_ALGORITHMS_APPROX_BOUNDS_AS_BOUNDS_PROVIDER_H_
#include <cstdint>
#include <memory>
#include <utility>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "algorithms/approx-bounds.h"
#include "algorithms/bounds-provider.h"
#include "algorithms/internal/clamped-calculation-without-bounds.h"
#include "base/status_macros.h"
namespace differential_privacy {
// Adapter to use ApproxBounds as a BoundsProvider. Wraps an ApproxBounds
// object.
template <typename T>
class ApproxBoundsAsBoundsProvider final : public BoundsProvider<T> {
public:
explicit ApproxBoundsAsBoundsProvider(
std::unique_ptr<ApproxBounds<T>> approx_bounds)
: approx_bounds_(std::move(approx_bounds)) {}
void AddEntry(const T& entry) override { approx_bounds_->AddEntry(entry); }
virtual absl::StatusOr<BoundsResult<T>> FinalizeAndCalculateBounds()
override {
ASSIGN_OR_RETURN(Output output, approx_bounds_->PartialResult());
BoundsResult<T> result;
result.lower_bound = GetValue<T>(output.elements(0).value());
result.upper_bound = GetValue<T>(output.elements(1).value());
return result;
}
BoundingReport GetBoundingReport(
const BoundsResult<T>& bounds_result) override {
return approx_bounds_->GetBoundingReport(bounds_result.lower_bound,
bounds_result.upper_bound);
}
void Reset() override { approx_bounds_->Reset(); }
int64_t MemoryUsed() const override {
return sizeof(*this) + approx_bounds_->MemoryUsed();
}
double GetEpsilon() const override { return approx_bounds_->GetEpsilon(); }
double GetDelta() const override { return approx_bounds_->GetDelta(); }
BoundsSummary Serialize() const override {
Summary summary = approx_bounds_->Serialize();
BoundsSummary bounds_summary;
summary.data().UnpackTo(bounds_summary.mutable_approx_bounds_summary());
return bounds_summary;
}
absl::Status Merge(const BoundsSummary& bounds_summary) {
if (!bounds_summary.has_approx_bounds_summary()) {
return absl::InternalError("approx_bounds_summary must be set");
}
Summary summary;
const bool pack_successful = summary.mutable_data()->PackFrom(
bounds_summary.approx_bounds_summary());
if (!pack_successful) {
return absl::InternalError("Cannot pack bounds summary");
}
return approx_bounds_->Merge(summary);
}
std::unique_ptr<internal::ClampedCalculationWithoutBounds<T>>
CreateClampedCalculationWithoutBounds() const override {
return approx_bounds_->CreateClampedCalculationWithoutBounds();
}
// Returns a pointer to the wrapped ApproxBounds object. Does not transfer
// ownership. Only use for testing.
ApproxBounds<T>* GetApproxBoundsForTesting() { return approx_bounds_.get(); }
private:
std::unique_ptr<ApproxBounds<T>> approx_bounds_;
};
} // namespace differential_privacy
#endif // DIFFERENTIAL_PRIVACY_CPP_ALGORITHMS_APPROX_BOUNDS_AS_BOUNDS_PROVIDER_H_