void OutputMetrics::calculateValue()

in fbpcs/emp_games/lift/calculator/OutputMetrics.hpp [696:778]


void OutputMetrics<MY_ROLE>::calculateValue(
    const OutputMetrics::GroupType& groupType,
    const std::vector<std::vector<emp::Integer>>& purchaseValueArrays,
    const std::vector<std::vector<emp::Bit>>& eventArrays,
    const std::vector<emp::Bit>& reachedArray) {
  XLOG(INFO) << "Calculate " << getGroupTypeStr(groupType) << " value";
  std::vector<std::vector<emp::Integer>> valueArrays =
      private_measurement::functional::zip_apply(
          [](std::vector<emp::Bit> testEvents,
             std::vector<emp::Integer> purchaseValues)
              -> std::vector<emp::Integer> {
            std::vector<emp::Integer> vec;
            if (testEvents.size() != purchaseValues.size()) {
              XLOG(FATAL) << "Numbers of test event bits and/or purchase "
                             "values are inconsistent.";
            }
            for (size_t i = 0; i < testEvents.size(); ++i) {
              const emp::Integer zero = emp::Integer{
                  static_cast<int>(purchaseValues.at(i).size()),
                  0,
                  emp::PUBLIC};
              vec.emplace_back(
                  emp::If(testEvents.at(i), purchaseValues.at(i), zero));
            }
            return vec;
          },
          eventArrays.begin(),
          eventArrays.end(),
          purchaseValueArrays.begin());

  std::vector<std::vector<emp::Integer>> reachedValue;
  if (groupType == GroupType::TEST) {
    reachedValue = private_measurement::functional::zip_apply(
        [](std::vector<emp::Integer> validValues,
           emp::Bit reached) -> std::vector<emp::Integer> {
          std::vector<emp::Integer> vec;
          for (const auto& validValue : validValues) {
            const emp::Integer zero = emp::Integer{
                static_cast<int>(validValue.size()), 0, emp::PUBLIC};
            vec.emplace_back(emp::If(reached, validValue, zero));
          }
          return vec;
        },
        valueArrays.begin(),
        valueArrays.end(),
        reachedArray.begin());

    metrics_.testValue = sum(valueArrays);
    metrics_.reachedValue = sum(reachedValue);
  } else {
    metrics_.controlValue = sum(valueArrays);
  }

  // And compute for breakdowns + cohorts
  // TODO: These could be abstracted into a common function
  for (size_t i = 0; i < numPublisherBreakdowns_; ++i) {
    auto groupInts = private_measurement::secret_sharing::multiplyBitmask(
        valueArrays, publisherBitmasks_.at(i));
    if (groupType == GroupType::TEST) {
      publisherBreakdowns_[i].testValue = sum(groupInts);
      auto reachedGroupInts =
          private_measurement::secret_sharing::multiplyBitmask(
              reachedValue, publisherBitmasks_.at(i));
      publisherBreakdowns_[i].reachedValue = sum(reachedGroupInts);
    } else {
      publisherBreakdowns_[i].controlValue = sum(groupInts);
    }
  }

  for (size_t i = 0; i < numPartnerCohorts_; ++i) {
    auto groupInts = private_measurement::secret_sharing::multiplyBitmask(
        valueArrays, partnerBitmasks_.at(i));
    if (groupType == GroupType::TEST) {
      cohortMetrics_[i].testValue = sum(groupInts);
      auto reachedGroupInts =
          private_measurement::secret_sharing::multiplyBitmask(
              reachedValue, partnerBitmasks_.at(i));
      cohortMetrics_[i].reachedValue = sum(reachedGroupInts);
    } else {
      cohortMetrics_[i].controlValue = sum(groupInts);
    }
  }
}