<commit_before>// Copyright (c) 2011, 2012, 2013 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "libmv/simple_pipeline/bundle.h"

#include <map>

#include "ceres/ceres.h"
#include "ceres/rotation.h"
#include "libmv/base/scoped_ptr.h"
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/fundamental.h"
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"

#ifdef _OPENMP
#  include <omp.h>
#endif

namespace libmv {

// The intrinsics need to get combined into a single parameter block; use these
// enums to index instead of numeric constants.
enum {
  OFFSET_FOCAL_LENGTH,
  OFFSET_PRINCIPAL_POINT_X,
  OFFSET_PRINCIPAL_POINT_Y,
  OFFSET_K1,
  OFFSET_K2,
  OFFSET_K3,
  OFFSET_P1,
  OFFSET_P2,
};

namespace {

struct OpenCVReprojectionError {
  OpenCVReprojectionError(double observed_x, double observed_y)
      : observed_x(observed_x), observed_y(observed_y) {}

  template <typename T>
  bool operator()(const T* const intrinsics,
                  const T* const R,  // Rotation 3x3 column-major.
                  const T* const t,  // Translation 3x1.
                  const T* const X,  // Point coordinates 3x1.
                  T* residuals) const {
    // Unpack the intrinsics.
    const T& focal_length      = intrinsics[OFFSET_FOCAL_LENGTH];
    const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
    const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
    const T& k1                = intrinsics[OFFSET_K1];
    const T& k2                = intrinsics[OFFSET_K2];
    const T& k3                = intrinsics[OFFSET_K3];
    const T& p1                = intrinsics[OFFSET_P1];
    const T& p2                = intrinsics[OFFSET_P2];

    // Compute projective coordinates: x = RX + t.
    T x[3];
    x[0] = R[0]*X[0] + R[3]*X[1] + R[6]*X[2] + t[0];
    x[1] = R[1]*X[0] + R[4]*X[1] + R[7]*X[2] + t[1];
    x[2] = R[2]*X[0] + R[5]*X[1] + R[8]*X[2] + t[2];

    // Compute normalized coordinates: x /= x[2].
    T xn = x[0] / x[2];
    T yn = x[1] / x[2];

    T predicted_x, predicted_y;

    // EuclideanBundle uses empty intrinsics, which breaks undistortion code;
    // so use an implied focal length of 1.0 if the focal length is exactly
    // zero.
    // TODO(keir): Figure out a better way to do this.
    if (focal_length != T(0)) {
      // Apply distortion to the normalized points to get (xd, yd).
      // TODO(keir): Do early bailouts for zero distortion; these are expensive
      // jet operations.

      ApplyRadialDistortionCameraIntrinsics(focal_length,
                                            focal_length,
                                            principal_point_x,
                                            principal_point_y,
                                            k1, k2, k3,
                                            p1, p2,
                                            xn, yn,
                                            &predicted_x,
                                            &predicted_y);
    } else {
      predicted_x = xn;
      predicted_y = yn;
    }

    // The error is the difference between the predicted and observed position.
    residuals[0] = predicted_x - T(observed_x);
    residuals[1] = predicted_y - T(observed_y);

    return true;
  }

  double observed_x;
  double observed_y;
};

// TODO(keir): Get rid of the parameterization! Ceres will work much faster if
// the rotation block is angle-axis and also the translation is merged into a
// single parameter block.
struct RotationMatrixPlus {
  template<typename T>
  bool operator()(const T* R_array,  // Rotation 3x3 col-major.
                  const T* delta,    // Angle-axis delta
                  T* R_plus_delta_array) const {
    T angle_axis[3];

    ceres::RotationMatrixToAngleAxis(R_array, angle_axis);

    angle_axis[0] += delta[0];
    angle_axis[1] += delta[1];
    angle_axis[2] += delta[2];

    ceres::AngleAxisToRotationMatrix(angle_axis, R_plus_delta_array);

    return true;
  }
};

// TODO(sergey): would be nice to have this in Ceres upstream
template<typename PlusFunctor, int kGlobalSize, int kLocalSize>
class AutodiffParameterization : public ceres::LocalParameterization {
 public:
  AutodiffParameterization(const PlusFunctor &plus_functor)
    : plus_functor_(plus_functor) {}

  virtual ~AutodiffParameterization() {}

  virtual bool Plus(const double* x,
                    const double* delta,
                    double* x_plus_delta) const {
    return plus_functor_(x, delta, x_plus_delta);
  }

  virtual bool ComputeJacobian(const double* x, double* jacobian) const {
    double zero_delta[kLocalSize] = { 0.0 };
    double x_plus_delta[kGlobalSize];
    const double* parameters[2] = { x, zero_delta };
    double* jacobians_array[2] = { NULL, jacobian };

    Plus(x, zero_delta, x_plus_delta);

    return ceres::internal::AutoDiff<PlusFunctor,
                              double,
                              kGlobalSize, kLocalSize>
        ::Differentiate(plus_functor_,
                        parameters,
                        kGlobalSize,
                        x_plus_delta,
                        jacobians_array);

    return true;
  }

  virtual int GlobalSize() const { return kGlobalSize; }
  virtual int LocalSize() const { return kLocalSize; }

 private:
  const PlusFunctor &plus_functor_;
};

void BundleIntrinsicsLogMessage(int bundle_intrinsics) {
  if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
    LG << "Bundling only camera positions.";
  } else if (bundle_intrinsics == BUNDLE_FOCAL_LENGTH) {
    LG << "Bundling f.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT)) {
    LG << "Bundling f, px, py.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT |
                                   BUNDLE_RADIAL)) {
    LG << "Bundling f, px, py, k1, k2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT |
                                   BUNDLE_RADIAL |
                                   BUNDLE_TANGENTIAL)) {
    LG << "Bundling f, px, py, k1, k2, p1, p2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL |
                                   BUNDLE_TANGENTIAL)) {
    LG << "Bundling f, px, py, k1, k2, p1, p2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL)) {
    LG << "Bundling f, k1, k2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL_K1)) {
    LG << "Bundling f, k1.";
  } else if (bundle_intrinsics == (BUNDLE_RADIAL_K1 |
                                   BUNDLE_RADIAL_K2)) {
    LG << "Bundling k1, k2.";
  } else {
    LOG(FATAL) << "Unsupported bundle combination.";
  }
}

}  // namespace

void EuclideanBundle(const Tracks &tracks,
                     EuclideanReconstruction *reconstruction) {
  CameraIntrinsics intrinsics;
  EuclideanBundleCommonIntrinsics(tracks,
                                  BUNDLE_NO_INTRINSICS,
                                  reconstruction,
                                  &intrinsics);
}

void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
                                     int bundle_intrinsics,
                                     EuclideanReconstruction *reconstruction,
                                     CameraIntrinsics *intrinsics,
                                     int bundle_constraints) {
  LG << "Original intrinsics: " << *intrinsics;
  vector<Marker> markers = tracks.AllMarkers();

  ceres::Problem::Options problem_options;
  problem_options.local_parameterization_ownership =
    ceres::DO_NOT_TAKE_OWNERSHIP;

  ceres::Problem problem(problem_options);

  // Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
  // intrinsics into a single block and rely on local parameterizations to
  // control which intrinsics are allowed to vary.
  double ceres_intrinsics[8];
  ceres_intrinsics[OFFSET_FOCAL_LENGTH]       = intrinsics->focal_length();
  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X]  = intrinsics->principal_point_x();
  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]  = intrinsics->principal_point_y();
  ceres_intrinsics[OFFSET_K1]                 = intrinsics->k1();
  ceres_intrinsics[OFFSET_K2]                 = intrinsics->k2();
  ceres_intrinsics[OFFSET_K3]                 = intrinsics->k3();
  ceres_intrinsics[OFFSET_P1]                 = intrinsics->p1();
  ceres_intrinsics[OFFSET_P2]                 = intrinsics->p2();

  RotationMatrixPlus rotation_matrix_plus;
  AutodiffParameterization<RotationMatrixPlus, 9, 3>
      rotation_parameterization(rotation_matrix_plus);

  int num_residuals = 0;
  for (int i = 0; i < markers.size(); ++i) {
    const Marker &marker = markers[i];
    EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
    EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
    if (!camera || !point) {
      continue;
    }

    problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
        OpenCVReprojectionError, 2, 8, 9, 3, 3>(
            new OpenCVReprojectionError(
                marker.x,
                marker.y)),
        NULL,
        ceres_intrinsics,
        &camera->R(0, 0),
        &camera->t(0),
        &point->X(0));

    // It's fine if the parameterization for one camera is set repeatedly.
    problem.SetParameterization(&camera->R(0, 0),
                                &rotation_parameterization);

    if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
      problem.SetParameterBlockConstant(&camera->t(0));
    }

    num_residuals++;
  }
  LG << "Number of residuals: " << num_residuals;

  if (!num_residuals) {
    LG << "Skipping running minimizer with zero residuals";
    return;
  }

  BundleIntrinsicsLogMessage(bundle_intrinsics);

  scoped_ptr<ceres::SubsetParameterization>
      subset_parameterization(NULL);

  if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
    // No camera intrinsics are refining,
    // set the whole parameter block as constant for best performance
    problem.SetParameterBlockConstant(ceres_intrinsics);
  } else {
    // Set intrinsics not being bundles as constant

    std::vector<int> constant_intrinsics;
#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
    if (!(bundle_intrinsics & bundle_enum)) { \
      constant_intrinsics.push_back(offset); \
    }
    MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH,    OFFSET_FOCAL_LENGTH);
    MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_X);
    MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_Y);
    MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1,       OFFSET_K1);
    MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2,       OFFSET_K2);
    MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1,   OFFSET_P1);
    MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2,   OFFSET_P2);
#undef MAYBE_SET_CONSTANT

    // Always set K3 constant, it's not used at the moment.
    constant_intrinsics.push_back(OFFSET_K3);

    subset_parameterization.reset(
        new ceres::SubsetParameterization(8, constant_intrinsics));

    problem.SetParameterization(ceres_intrinsics, subset_parameterization.get());
  }

  ceres::Solver::Options options;
  options.use_nonmonotonic_steps = true;
  options.preconditioner_type = ceres::SCHUR_JACOBI;
  options.linear_solver_type = ceres::ITERATIVE_SCHUR;
  options.use_inner_iterations = true;
  options.max_num_iterations = 100;

#ifdef _OPENMP
  options.num_threads = omp_get_max_threads();
  options.num_linear_solver_threads = omp_get_max_threads();
#endif

  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  LG << "Final report:\n" << summary.FullReport();

  // Copy intrinsics back.
  if (bundle_intrinsics != BUNDLE_NO_INTRINSICS) {
    intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
                               ceres_intrinsics[OFFSET_FOCAL_LENGTH]);

    intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
                                  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);

    intrinsics->SetRadialDistortion(ceres_intrinsics[OFFSET_K1],
                                    ceres_intrinsics[OFFSET_K2],
                                    ceres_intrinsics[OFFSET_K3]);

    intrinsics->SetTangentialDistortion(ceres_intrinsics[OFFSET_P1],
                                        ceres_intrinsics[OFFSET_P2]);
  }

  LG << "Final intrinsics: " << *intrinsics;
}

void ProjectiveBundle(const Tracks & /*tracks*/,
                      ProjectiveReconstruction * /*reconstruction*/) {
  // TODO(keir): Implement this! This can't work until we have a better bundler
  // than SSBA, since SSBA has no support for projective bundling.
}

}  // namespace libmv
<commit_msg> Bundle adjustment improvements<commit_after>// Copyright (c) 2011, 2012, 2013 libmv authors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "libmv/simple_pipeline/bundle.h"

#include <map>

#include "ceres/ceres.h"
#include "ceres/rotation.h"
#include "libmv/base/scoped_ptr.h"
#include "libmv/base/vector.h"
#include "libmv/logging/logging.h"
#include "libmv/multiview/fundamental.h"
#include "libmv/multiview/projection.h"
#include "libmv/numeric/numeric.h"
#include "libmv/simple_pipeline/camera_intrinsics.h"
#include "libmv/simple_pipeline/reconstruction.h"
#include "libmv/simple_pipeline/tracks.h"

#ifdef _OPENMP
#  include <omp.h>
#endif

namespace libmv {

// The intrinsics need to get combined into a single parameter block; use these
// enums to index instead of numeric constants.
enum {
  OFFSET_FOCAL_LENGTH,
  OFFSET_PRINCIPAL_POINT_X,
  OFFSET_PRINCIPAL_POINT_Y,
  OFFSET_K1,
  OFFSET_K2,
  OFFSET_K3,
  OFFSET_P1,
  OFFSET_P2,
};

namespace {

struct OpenCVReprojectionError {
  OpenCVReprojectionError(double observed_x, double observed_y)
      : observed_x(observed_x), observed_y(observed_y) {}

  template <typename T>
  bool operator()(const T* const intrinsics,
                  const T* const R_t,  // Rotation denoted by angle axis
                                       // followed with translation
                  const T* const X,  // Point coordinates 3x1.
                  T* residuals) const {
    // Unpack the intrinsics.
    const T& focal_length      = intrinsics[OFFSET_FOCAL_LENGTH];
    const T& principal_point_x = intrinsics[OFFSET_PRINCIPAL_POINT_X];
    const T& principal_point_y = intrinsics[OFFSET_PRINCIPAL_POINT_Y];
    const T& k1                = intrinsics[OFFSET_K1];
    const T& k2                = intrinsics[OFFSET_K2];
    const T& k3                = intrinsics[OFFSET_K3];
    const T& p1                = intrinsics[OFFSET_P1];
    const T& p2                = intrinsics[OFFSET_P2];

    // Compute projective coordinates: x = RX + t.
    T x[3];

    ceres::AngleAxisRotatePoint(R_t, X, x);
    x[0] += R_t[3];
    x[1] += R_t[4];
    x[2] += R_t[5];

    // Compute normalized coordinates: x /= x[2].
    T xn = x[0] / x[2];
    T yn = x[1] / x[2];

    T predicted_x, predicted_y;

    // EuclideanBundle uses empty intrinsics, which breaks undistortion code;
    // so use an implied focal length of 1.0 if the focal length is exactly
    // zero.
    // TODO(keir): Figure out a better way to do this.
    if (focal_length != T(0)) {
      // Apply distortion to the normalized points to get (xd, yd).
      // TODO(keir): Do early bailouts for zero distortion; these are expensive
      // jet operations.

      ApplyRadialDistortionCameraIntrinsics(focal_length,
                                            focal_length,
                                            principal_point_x,
                                            principal_point_y,
                                            k1, k2, k3,
                                            p1, p2,
                                            xn, yn,
                                            &predicted_x,
                                            &predicted_y);
    } else {
      predicted_x = xn;
      predicted_y = yn;
    }

    // The error is the difference between the predicted and observed position.
    residuals[0] = predicted_x - T(observed_x);
    residuals[1] = predicted_y - T(observed_y);

    return true;
  }

  double observed_x;
  double observed_y;
};

void BundleIntrinsicsLogMessage(int bundle_intrinsics) {
  if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
    LG << "Bundling only camera positions.";
  } else if (bundle_intrinsics == BUNDLE_FOCAL_LENGTH) {
    LG << "Bundling f.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT)) {
    LG << "Bundling f, px, py.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT |
                                   BUNDLE_RADIAL)) {
    LG << "Bundling f, px, py, k1, k2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_PRINCIPAL_POINT |
                                   BUNDLE_RADIAL |
                                   BUNDLE_TANGENTIAL)) {
    LG << "Bundling f, px, py, k1, k2, p1, p2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL |
                                   BUNDLE_TANGENTIAL)) {
    LG << "Bundling f, px, py, k1, k2, p1, p2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL)) {
    LG << "Bundling f, k1, k2.";
  } else if (bundle_intrinsics == (BUNDLE_FOCAL_LENGTH |
                                   BUNDLE_RADIAL_K1)) {
    LG << "Bundling f, k1.";
  } else if (bundle_intrinsics == (BUNDLE_RADIAL_K1 |
                                   BUNDLE_RADIAL_K2)) {
    LG << "Bundling k1, k2.";
  } else {
    LOG(FATAL) << "Unsupported bundle combination.";
  }
}

// Pack intrinsics from object to an array for easier
// and faster minimization
void PackIntrinisicsIntoArray(CameraIntrinsics *intrinsics,
                              double ceres_intrinsics[8]) {
  ceres_intrinsics[OFFSET_FOCAL_LENGTH]       = intrinsics->focal_length();
  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X]  = intrinsics->principal_point_x();
  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]  = intrinsics->principal_point_y();
  ceres_intrinsics[OFFSET_K1]                 = intrinsics->k1();
  ceres_intrinsics[OFFSET_K2]                 = intrinsics->k2();
  ceres_intrinsics[OFFSET_K3]                 = intrinsics->k3();
  ceres_intrinsics[OFFSET_P1]                 = intrinsics->p1();
  ceres_intrinsics[OFFSET_P2]                 = intrinsics->p2();
}

// Unpack intrinsics back from an array to an object
void UnpackIntrinsicsFromArray(CameraIntrinsics *intrinsics,
                               double ceres_intrinsics[8]) {
    intrinsics->SetFocalLength(ceres_intrinsics[OFFSET_FOCAL_LENGTH],
                               ceres_intrinsics[OFFSET_FOCAL_LENGTH]);

    intrinsics->SetPrincipalPoint(ceres_intrinsics[OFFSET_PRINCIPAL_POINT_X],
                                  ceres_intrinsics[OFFSET_PRINCIPAL_POINT_Y]);

    intrinsics->SetRadialDistortion(ceres_intrinsics[OFFSET_K1],
                                    ceres_intrinsics[OFFSET_K2],
                                    ceres_intrinsics[OFFSET_K3]);

    intrinsics->SetTangentialDistortion(ceres_intrinsics[OFFSET_P1],
                                        ceres_intrinsics[OFFSET_P2]);
}

// Get a vector of camera's rotations denoted by angle axis
// conjuncted with translations into single block
//
// Element with index i matches to a rotation+translation for
// camera at image i.
vector<Vec6> PackCamerasRotationAndTranslation(
                                 const Tracks &tracks,
                                 EuclideanReconstruction *reconstruction) {
  vector<Vec6> cameras_R_t;
  int max_image = tracks.MaxImage();

  cameras_R_t.resize(max_image + 1);

  for (int i = 0; i <= max_image; i++) {
    EuclideanCamera *camera = reconstruction->CameraForImage(i);

    if (!camera)
      continue;

    ceres::RotationMatrixToAngleAxis(&camera->R(0, 0),
                                     &cameras_R_t[i](0));
    cameras_R_t[i].tail<3>() = camera->t;
  }

  return cameras_R_t;
}

// Convert cameras rotations fro mangle axis back to rotation matrix
void UnpackCamerasRotationAndTranslation(
                                  const Tracks &tracks,
                                  EuclideanReconstruction *reconstruction,
                                  vector<Vec6> cameras_R_t) {
  int max_image = tracks.MaxImage();

  for (int i = 0; i <= max_image; i++) {
    EuclideanCamera *camera = reconstruction->CameraForImage(i);

    if (!camera)
      continue;

    ceres::AngleAxisToRotationMatrix(&cameras_R_t[i](0),
                                     &camera->R(0, 0));
    camera->t = cameras_R_t[i].tail<3>();
  }
}

}  // namespace

void EuclideanBundle(const Tracks &tracks,
                     EuclideanReconstruction *reconstruction) {
  CameraIntrinsics intrinsics;
  EuclideanBundleCommonIntrinsics(tracks,
                                  BUNDLE_NO_INTRINSICS,
                                  reconstruction,
                                  &intrinsics);
}

void EuclideanBundleCommonIntrinsics(const Tracks &tracks,
                                     int bundle_intrinsics,
                                     EuclideanReconstruction *reconstruction,
                                     CameraIntrinsics *intrinsics,
                                     int bundle_constraints) {
  LG << "Original intrinsics: " << *intrinsics;
  vector<Marker> markers = tracks.AllMarkers();

  ceres::Problem::Options problem_options;
  ceres::Problem problem(problem_options);

  // Residual blocks with 10 parameters are unwieldly with Ceres, so pack the
  // intrinsics into a single block and rely on local parameterizations to
  // control which intrinsics are allowed to vary.
  double ceres_intrinsics[8];
  PackIntrinisicsIntoArray(intrinsics, ceres_intrinsics);

  // Convert cameras rotations to angle axis and merge with translation
  // into single parameter block for maximal minimization speed
  //
  // Block for minimization has got the following structure:
  //   <3 elements for angle-axis> <3 elements for translation>
  vector<Vec6> cameras_R_t =
    PackCamerasRotationAndTranslation(tracks, reconstruction);

  int num_residuals = 0;
  bool have_locked_camera = false;
  for (int i = 0; i < markers.size(); ++i) {
    const Marker &marker = markers[i];
    EuclideanCamera *camera = reconstruction->CameraForImage(marker.image);
    EuclideanPoint *point = reconstruction->PointForTrack(marker.track);
    if (!camera || !point) {
      continue;
    }

    // Rotation of camera denoted in angle axis
    double *camera_R_t = &cameras_R_t[camera->image] (0);

    problem.AddResidualBlock(new ceres::AutoDiffCostFunction<
        OpenCVReprojectionError, 2, 8, 6, 3>(
            new OpenCVReprojectionError(
                marker.x,
                marker.y)),
        NULL,
        ceres_intrinsics,
        camera_R_t,
        &point->X(0));

    // We lock first camera for better deal with
    // scene orientation ambiguity
    if (!have_locked_camera) {
      problem.SetParameterBlockConstant(camera_R_t);
      have_locked_camera = true;
    }

    if (bundle_constraints & BUNDLE_NO_TRANSLATION)
      problem.SetParameterBlockConstant(&camera->t(0));

    num_residuals++;
  }
  LG << "Number of residuals: " << num_residuals;

  if (!num_residuals) {
    LG << "Skipping running minimizer with zero residuals";
    return;
  }

  BundleIntrinsicsLogMessage(bundle_intrinsics);

  if (bundle_intrinsics == BUNDLE_NO_INTRINSICS) {
    // No camera intrinsics are refining,
    // set the whole parameter block as constant for best performance
    problem.SetParameterBlockConstant(ceres_intrinsics);
  } else {
    // Set intrinsics not being bundles as constant

    std::vector<int> constant_intrinsics;
#define MAYBE_SET_CONSTANT(bundle_enum, offset) \
    if (!(bundle_intrinsics & bundle_enum)) { \
      constant_intrinsics.push_back(offset); \
    }
    MAYBE_SET_CONSTANT(BUNDLE_FOCAL_LENGTH,    OFFSET_FOCAL_LENGTH);
    MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_X);
    MAYBE_SET_CONSTANT(BUNDLE_PRINCIPAL_POINT, OFFSET_PRINCIPAL_POINT_Y);
    MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K1,       OFFSET_K1);
    MAYBE_SET_CONSTANT(BUNDLE_RADIAL_K2,       OFFSET_K2);
    MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P1,   OFFSET_P1);
    MAYBE_SET_CONSTANT(BUNDLE_TANGENTIAL_P2,   OFFSET_P2);
#undef MAYBE_SET_CONSTANT

    // Always set K3 constant, it's not used at the moment.
    constant_intrinsics.push_back(OFFSET_K3);

    ceres::SubsetParameterization *subset_parameterization =
      new ceres::SubsetParameterization(8, constant_intrinsics);

    problem.SetParameterization(ceres_intrinsics, subset_parameterization);
  }

  // Configure the solver
  ceres::Solver::Options options;
  options.use_nonmonotonic_steps = true;
  options.preconditioner_type = ceres::SCHUR_JACOBI;
  options.linear_solver_type = ceres::ITERATIVE_SCHUR;
  options.use_inner_iterations = true;
  options.max_num_iterations = 100;

#ifdef _OPENMP
  options.num_threads = omp_get_max_threads();
  options.num_linear_solver_threads = omp_get_max_threads();
#endif

  // Solve!
  ceres::Solver::Summary summary;
  ceres::Solve(options, &problem, &summary);

  LG << "Final report:\n" << summary.FullReport();

  // Copy rotations and translations back.
  UnpackCamerasRotationAndTranslation(tracks,
                                      reconstruction,
                                      cameras_R_t);

  // Copy intrinsics back.
  if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
    UnpackIntrinsicsFromArray(intrinsics, ceres_intrinsics);

  LG << "Final intrinsics: " << *intrinsics;
}

void ProjectiveBundle(const Tracks & /*tracks*/,
                      ProjectiveReconstruction * /*reconstruction*/) {
  // TODO(keir): Implement this! This can't work until we have a better bundler
  // than SSBA, since SSBA has no support for projective bundling.
}

}  // namespace libmv
<|endoftext|>


<commit_before>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2014, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ----------------------------------------------------------------------
 */

/** @file
 * Implementation of Connections
 */

#include <climits>
#include <nta/algorithms/Connections.hpp>

using namespace std;
using namespace nta;
using namespace nta::algorithms::connections;

Connections::Connections(CellIdx numCells) : cells_(numCells) {}

Segment Connections::createSegment(const Cell& cell)
{
  vector<SegmentData>& segments = cells_[cell.idx].segments;
  if (segments.size() == UCHAR_MAX) {
    throw runtime_error("Cannot create segment: cell has reached maximum number of segments.");
  }
  Segment segment(segments.size(), cell);

  SegmentData segmentData;
  segments.push_back(segmentData);

  return segment;
}

Synapse Connections::createSynapse(const Segment& segment,
                                   const Cell& presynapticCell,
                                   Permanence permanence)
{
  vector<SynapseData>& synapses = cells_[segment.cell.idx].segments[segment.idx].synapses;
  if (synapses.size() == UCHAR_MAX) {
    throw runtime_error("Cannot create synapse: segment has reached maximum number of synapses.");
  }
  Synapse synapse(synapses.size(), segment);

  SynapseData synapseData = {presynapticCell, permanence};
  synapses.push_back(synapseData);

  synapsesForPresynapticCell_[presynapticCell].push_back(synapse);

  return synapse;
}

void Connections::updateSynapsePermanence(const Synapse& synapse,
                                          Permanence permanence)
{
  const Segment& segment = synapse.segment;
  const Cell& cell = segment.cell;

  cells_[cell.idx].segments[segment.idx].synapses[synapse.idx].permanence = permanence;
}

vector<Segment> Connections::segmentsForCell(const Cell& cell)
{
  vector<Segment> segments;
  Segment segment;

  for (SegmentIdx i = 0; i < cells_[cell.idx].segments.size(); i++) {
    segment.idx = i;
    segment.cell = cell;
    segments.push_back(segment);
  }

  return segments;
}

vector<Synapse> Connections::synapsesForSegment(const Segment& segment)
{
  const Cell& cell = segment.cell;
  vector<Synapse> synapses;
  Synapse synapse;

  for (SynapseIdx i = 0; i < cells_[cell.idx].segments[segment.idx].synapses.size(); i++) {
    synapse.idx = i;
    synapse.segment = segment;
    synapses.push_back(synapse);
  }

  return synapses;
}

SynapseData Connections::dataForSynapse(const Synapse& synapse) const
{
  const Segment& segment = synapse.segment;
  const Cell& cell = segment.cell;

  return cells_[cell.idx].segments[segment.idx].synapses[synapse.idx];
}

bool Connections::mostActiveSegmentForCells(const vector<Cell>& cells,
                                            vector<Cell> input,
                                            UInt synapseThreshold,
                                            Segment& retSegment) const
{
  UInt numSynapses, maxSynapses = synapseThreshold;
  vector<SegmentData> segments;
  vector<SynapseData> synapses;
  SegmentIdx segmentIdx = 0;
  bool found = false;

  sort(input.begin(), input.end());  // for binary search

  for (auto cell : cells) {
    segments = cells_[cell.idx].segments;
    segmentIdx = 0;

    for (auto segment : segments) {
      synapses = segment.synapses;
      numSynapses = 0;

      for (auto synapse : synapses) {
        if (binary_search(input.begin(), input.end(), synapse.presynapticCell)) {
          numSynapses++;
        }
      }

      if (numSynapses >= maxSynapses) {
        maxSynapses = numSynapses;
        retSegment.idx = segmentIdx;
        retSegment.cell = cell;
        found = true;
      }

      segmentIdx++;
    }
  }

  return found;
}

Activity Connections::computeActivity(const vector<Cell>& input,
                                      Permanence permanenceThreshold,
                                      UInt synapseThreshold) const
{
  Activity activity;
  vector<Synapse> synapses;
  SynapseData synapseData;

  for (auto cell : input) {
    if (!synapsesForPresynapticCell_.count(cell)) continue;
    synapses = synapsesForPresynapticCell_.at(cell);

    for (auto synapse : synapses) {
      synapseData = dataForSynapse(synapse);

      if (synapseData.permanence >= permanenceThreshold) {
        activity.numActiveSynapsesForSegment[synapse.segment] += 1;

        if (activity.numActiveSynapsesForSegment[synapse.segment] == synapseThreshold) {
          activity.activeSegmentsForCell[synapse.segment.cell].push_back(synapse.segment);
        }
      }
    }
  }

  return activity;
}

vector<Segment> Connections::activeSegments(const Activity& activity)
{
  vector<Segment> segments;

  for (auto i : activity.activeSegmentsForCell) {
    segments.insert(segments.end(), i.second.begin(), i.second.end());
  }

  return segments;
}

vector<Cell> Connections::activeCells(const Activity& activity)
{
  vector<Cell> cells;

  for (auto i : activity.activeSegmentsForCell) {
    cells.push_back(i.first);
  }

  return cells;
}

UInt Connections::numSegments() const
{
  UInt num = 0;

  for (auto cell : cells_) {
    num += cell.segments.size();
  }

  return num;
}

UInt Connections::numSynapses() const
{
  UInt num = 0;

  for (auto cell : cells_) {
    for (auto segment : cell.segments) {
      num += segment.synapses.size();
    }
  }

  return num;
}

bool Cell::operator==(const Cell &other) const {
  return idx == other.idx;
}

bool Cell::operator<=(const Cell &other) const
{
  return idx <= other.idx;
}

bool Cell::operator<(const Cell &other) const
{
  return idx < other.idx;
}

bool Cell::operator>=(const Cell &other) const
{
  return idx >= other.idx;
}

bool Cell::operator>(const Cell &other) const
{
  return idx > other.idx;
}

bool Segment::operator==(const Segment &other) const
{
  return idx == other.idx && cell == other.cell;
}

bool Segment::operator<=(const Segment &other) const
{
  return idx == other.idx ? cell <= other.cell : idx <= other.idx;
}

bool Segment::operator<(const Segment &other) const
{
  return idx == other.idx ? cell < other.cell : idx < other.idx;
}

bool Segment::operator>=(const Segment &other) const
{
  return idx == other.idx ? cell >= other.cell : idx >= other.idx;
}

bool Segment::operator>(const Segment &other) const
{
  return idx == other.idx ? cell > other.cell : idx > other.idx;
}

bool Synapse::operator==(const Synapse &other) const {
  return idx == other.idx && segment == other.segment;
}
<commit_msg>Reluctantly following code convention<commit_after>/* ---------------------------------------------------------------------
 * Numenta Platform for Intelligent Computing (NuPIC)
 * Copyright (C) 2014, Numenta, Inc.  Unless you have an agreement
 * with Numenta, Inc., for a separate license for this software code, the
 * following terms and conditions apply:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses.
 *
 * http://numenta.org/licenses/
 * ----------------------------------------------------------------------
 */

/** @file
 * Implementation of Connections
 */

#include <climits>
#include <nta/algorithms/Connections.hpp>

using namespace std;
using namespace nta;
using namespace nta::algorithms::connections;

Connections::Connections(CellIdx numCells) : cells_(numCells) {}

Segment Connections::createSegment(const Cell& cell)
{
  vector<SegmentData>& segments = cells_[cell.idx].segments;
  if (segments.size() == UCHAR_MAX)
  {
    throw runtime_error("Cannot create segment: cell has reached maximum number of segments.");
  }
  Segment segment(segments.size(), cell);

  SegmentData segmentData;
  segments.push_back(segmentData);

  return segment;
}

Synapse Connections::createSynapse(const Segment& segment,
                                   const Cell& presynapticCell,
                                   Permanence permanence)
{
  vector<SynapseData>& synapses = cells_[segment.cell.idx].segments[segment.idx].synapses;
  if (synapses.size() == UCHAR_MAX)
  {
    throw runtime_error("Cannot create synapse: segment has reached maximum number of synapses.");
  }
  Synapse synapse(synapses.size(), segment);

  SynapseData synapseData = {presynapticCell, permanence};
  synapses.push_back(synapseData);

  synapsesForPresynapticCell_[presynapticCell].push_back(synapse);

  return synapse;
}

void Connections::updateSynapsePermanence(const Synapse& synapse,
                                          Permanence permanence)
{
  const Segment& segment = synapse.segment;
  const Cell& cell = segment.cell;

  cells_[cell.idx].segments[segment.idx].synapses[synapse.idx].permanence = permanence;
}

vector<Segment> Connections::segmentsForCell(const Cell& cell)
{
  vector<Segment> segments;
  Segment segment;

  for (SegmentIdx i = 0; i < cells_[cell.idx].segments.size(); i++)
  {
    segment.idx = i;
    segment.cell = cell;
    segments.push_back(segment);
  }

  return segments;
}

vector<Synapse> Connections::synapsesForSegment(const Segment& segment)
{
  const Cell& cell = segment.cell;
  vector<Synapse> synapses;
  Synapse synapse;

  for (SynapseIdx i = 0; i < cells_[cell.idx].segments[segment.idx].synapses.size(); i++)
  {
    synapse.idx = i;
    synapse.segment = segment;
    synapses.push_back(synapse);
  }

  return synapses;
}

SynapseData Connections::dataForSynapse(const Synapse& synapse) const
{
  const Segment& segment = synapse.segment;
  const Cell& cell = segment.cell;

  return cells_[cell.idx].segments[segment.idx].synapses[synapse.idx];
}

bool Connections::mostActiveSegmentForCells(const vector<Cell>& cells,
                                            vector<Cell> input,
                                            UInt synapseThreshold,
                                            Segment& retSegment) const
{
  UInt numSynapses, maxSynapses = synapseThreshold;
  vector<SegmentData> segments;
  vector<SynapseData> synapses;
  SegmentIdx segmentIdx = 0;
  bool found = false;

  sort(input.begin(), input.end());  // for binary search

  for (auto cell : cells)
  {
    segments = cells_[cell.idx].segments;
    segmentIdx = 0;

    for (auto segment : segments)
    {
      synapses = segment.synapses;
      numSynapses = 0;

      for (auto synapse : synapses)
      {
        if (binary_search(input.begin(), input.end(), synapse.presynapticCell))
        {
          numSynapses++;
        }
      }

      if (numSynapses >= maxSynapses)
      {
        maxSynapses = numSynapses;
        retSegment.idx = segmentIdx;
        retSegment.cell = cell;
        found = true;
      }

      segmentIdx++;
    }
  }

  return found;
}

Activity Connections::computeActivity(const vector<Cell>& input,
                                      Permanence permanenceThreshold,
                                      UInt synapseThreshold) const
{
  Activity activity;
  vector<Synapse> synapses;
  SynapseData synapseData;

  for (auto cell : input)
  {
    if (!synapsesForPresynapticCell_.count(cell)) continue;
    synapses = synapsesForPresynapticCell_.at(cell);

    for (auto synapse : synapses)
    {
      synapseData = dataForSynapse(synapse);

      if (synapseData.permanence >= permanenceThreshold)
      {
        activity.numActiveSynapsesForSegment[synapse.segment] += 1;

        if (activity.numActiveSynapsesForSegment[synapse.segment] == synapseThreshold)
        {
          activity.activeSegmentsForCell[synapse.segment.cell].push_back(synapse.segment);
        }
      }
    }
  }

  return activity;
}

vector<Segment> Connections::activeSegments(const Activity& activity)
{
  vector<Segment> segments;

  for (auto i : activity.activeSegmentsForCell)
  {
    segments.insert(segments.end(), i.second.begin(), i.second.end());
  }

  return segments;
}

vector<Cell> Connections::activeCells(const Activity& activity)
{
  vector<Cell> cells;

  for (auto i : activity.activeSegmentsForCell)
  {
    cells.push_back(i.first);
  }

  return cells;
}

UInt Connections::numSegments() const
{
  UInt num = 0;

  for (auto cell : cells_)
  {
    num += cell.segments.size();
  }

  return num;
}

UInt Connections::numSynapses() const
{
  UInt num = 0;

  for (auto cell : cells_)
  {
    for (auto segment : cell.segments)
    {
      num += segment.synapses.size();
    }
  }

  return num;
}

bool Cell::operator==(const Cell &other) const
{
  return idx == other.idx;
}

bool Cell::operator<=(const Cell &other) const
{
  return idx <= other.idx;
}

bool Cell::operator<(const Cell &other) const
{
  return idx < other.idx;
}

bool Cell::operator>=(const Cell &other) const
{
  return idx >= other.idx;
}

bool Cell::operator>(const Cell &other) const
{
  return idx > other.idx;
}

bool Segment::operator==(const Segment &other) const
{
  return idx == other.idx && cell == other.cell;
}

bool Segment::operator<=(const Segment &other) const
{
  return idx == other.idx ? cell <= other.cell : idx <= other.idx;
}

bool Segment::operator<(const Segment &other) const
{
  return idx == other.idx ? cell < other.cell : idx < other.idx;
}

bool Segment::operator>=(const Segment &other) const
{
  return idx == other.idx ? cell >= other.cell : idx >= other.idx;
}

bool Segment::operator>(const Segment &other) const
{
  return idx == other.idx ? cell > other.cell : idx > other.idx;
}

bool Synapse::operator==(const Synapse &other) const
{
  return idx == other.idx && segment == other.segment;
}
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)
//
// Given string A representative a positive integer which has N digits,
// remove any k digits of the number, the remaining digits are arranged
// according to the original order to become a new positive integer.
// Make this new positive integers as small as possible.
//
// N <= 240 and k <= N,
//
// Example
// Given an integer A="178542", k=4
//
// return a string "12"
//
class Solution {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        const auto len = A.size();

        // Handle boundary case
        if (len == k) {
            return "0";
        }

        // If a digit is greater than next one, delete it.
        stack<char> s;
        for (auto i = 0; i < len; ++i) {
            while (k > 0 && !s.empty() && s.top() > A[i]) {
                s.pop();
                --k;
            }
            s.emplace(A[i]);
        }

        // If all digits are increasingly sorted, delete last.
        while (k > 0) {
            s.pop();
            --k;
        }

        // Assemble the answer in reverse order
        string ans;
        while (!s.empty()) {
            ans.push_back(s.top());
            s.pop();
        }
        reverse(ans.begin(), ans.end());

        // Strip all leading '0'
        auto i = 0;
        for (; i < ans.length() && ans[i] == '0'; ++i);
        ans = ans.substr(i);

        // Handle boundary case
        if (ans.length() == 0) {
            return "0";
        }

        return ans;
    }
};

// Time:  O(k * n)
// Space: O(1)
// Greedy method
class Solution2 {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        const auto len = A.size();

        // Handle boundary case
        if (len == k) {
            return "0";
        }

        // If a digit is greater than next one, delete it.
        int i = 0;
        while (i + 1 <= len && k > 0) {
            if (A[i] > A[i + 1]) {
                A.erase(A.begin() + i); // Not efficient, linear time
                i = max(0, i - 1);
                --k;
            } else {
                ++i;
            }
        }

        // If all digits are increasingly sorted, delete last.
        if (k > 0) {
            A = A.substr(0, A.length() - k);
        }

        // Strip all leading '0'
        if (A.length() > 0 && A[0] == '0') {
            size_t pos = A.find_first_not_of("0");
            if (pos != string::npos) {
                A = A.substr(A.find_first_not_of("0"));
            }
        }

        // Handle boundary case
        if (A.length() == 0) {
            return "0";
        }

        return A;
    }
};

<commit_msg>Update delete-digits.cpp<commit_after>// Time:  O(n)
// Space: O(n)
//
// Given string A representative a positive integer which has N digits,
// remove any k digits of the number, the remaining digits are arranged
// according to the original order to become a new positive integer.
// Make this new positive integers as small as possible.
//
// N <= 240 and k <= N,
//
// Example
// Given an integer A="178542", k=4
//
// return a string "12"
//

class Solution {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        string s;
        for (auto i = 0; i < A.size(); ++i) {
            while (k > 0 && !s.empty() && s.back() > A[i]) {
                s.pop_back();
                --k;
            }
            s.push_back(A[i]);
        }

        // If all digits are increasingly sorted, delete last.
        while (k > 0) {
            s.pop_back();
            --k;
        }

        // Strip all leading '0'
        return s.empty() ? "0" : s.substr(s.find_first_not_of("0"));
    }
};

// Time:  O(k * n)
// Space: O(1)
// Greedy method
class Solution2 {
public:
    /**
     *@param A: A positive integer which has N digits, A is a string.
     *@param k: Remove k digits.
     *@return: A string
     */
    string DeleteDigits(string A, int k) {
        // If a digit is greater than next one, delete it.
        for (int i = 0; i + 1 <= A.size() && k > 0;) {
            if (A[i] > A[i + 1]) {
                A.erase(A.begin() + i); // Not efficient, linear time
                i = max(0, i - 1);
                --k;
            } else {
                ++i;
            }
        }

        // If all digits are increasingly sorted, delete last.
        A.resize(A.length() - k);

        // Strip all leading '0'
        return A.empty() ? "0" : A.substr(A.find_first_not_of("0"));
    }
};

<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2008 George Goldberg <grundleborg@googlemail.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License version 2 as
 *   published by the Free Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "presence.h"

#include <TelepathyQt4/Client/Account>
#include <TelepathyQt4/Client/AccountManager>

#include <KDebug>
#include <KLocale>
#include <KUrl>

#include <QtCore/QDateTime>
#include <QtCore/QTimer>

class PresenceEngine::PresenceEnginePrivate
{
	PresenceEngine *parent;
public:
	PresenceEnginePrivate(PresenceEngine *p) : parent(p) {}

	Telepathy::Client::AccountManager * m_accountManager;

	void createAccountDataSource(const QDBusObjectPath &path)
	{
		// \todo: FIXME
		kDebug() << "createAccountDataSource called";
		kDebug() << path.path();
	    Telepathy::Client::Account *account = accountFromObjectPath(path);

	    QString source;
	    // \todo: FIXME
	    // source = account.uniqueIdentifier();
	    Telepathy::SimplePresence sp = account->currentPresence();
	    QVariant vsp;
	    vsp.setValue(sp);
	    parent->setData(source, "current_presence", vsp);

		// emit parent->sourceAdded(account->uniqueIdentifier());

		// \todo: remove
/*
			QString source;
		    source.setNum(handle);
		    QVariantMap accountData = m_accountManager->queryAccount(handle);
		    QMap<QString, QVariant>::const_iterator end( accountData.constEnd() );
		    for(QMap<QString, QVariant>::const_iterator itr(accountData.constBegin()); itr != end; ++itr)
		    {
		        if(itr.key() == Decibel::name_current_presence)
		        {
		            QtTapioca::PresenceState ps = qdbus_cast<QtTapioca::PresenceState>(itr.value().value<QDBusArgument>());
		            QVariant psv;
		            psv.setValue(ps);
		            setData(source, "current_presence", psv);
		            continue;
		        }
		        else if(itr.key() == Decibel::name_presence_parameters)
		        {
		            setData(source, "status_message", itr.value().toMap().value("status_message").toString());
		        }
		    }

		emit parent->sourceAdded(account->uniqueIdentifier());
*/
	}

	void removeAccountDataSource(const QDBusObjectPath &path)
	{
		kDebug() << "removeAccountDataSource called";
		kDebug() << path.path();

		Telepathy::Client::Account *account = accountFromObjectPath(path);

		// \todo: FIXME
/*
		QString identifier = account->uniqueIdentifier();
		parent->removeSource(identifier);
		emit parent->sourceRemoved(identifier);
*/
	}

	Telepathy::Client::Account *accountFromObjectPath(const QDBusObjectPath &path)
	{
		return m_accountManager->accountForPath(path);
	}
};

PresenceEngine::PresenceEngine(QObject * parent, const QVariantList & args)
  : Plasma::DataEngine(parent, args),
  d(new PresenceEnginePrivate(this))
{
    // Register custom types:
    Telepathy::registerTypes();
}

PresenceEngine::~PresenceEngine()
{
	delete d->m_accountManager;
	delete d;
}

void
PresenceEngine::init()
{
    kDebug() << "init() started";
    /*
     * check that we are connected to the session
     * bus OK.
     */
    if (!QDBusConnection::sessionBus().isConnected())
    {
        kDebug() << "PresenceEngine::init(): cannot connect to session bus.";
    }

   /*
    * set up the dbus accountmanager object
    * which will provide all the data to this
    * data engine.
    */
    d->m_accountManager =
    	new Telepathy::Client::AccountManager(QDBusConnection::sessionBus());

    /*
     * get a list of all the accounts that
     * are all ready there
     */
    QList<Telepathy::Client::Account *> accounts = d->m_accountManager->allAccounts();
    kDebug() << "accounts: " << accounts.size();

    Telepathy::ObjectPathList objectPathList = d->m_accountManager->allAccountPaths();
    /*
     * connect signals from the account manager
     * to slots within this data engine.
     *
     * we intentionally do this before processing
     * the accounts that are already created so
     * that if another is created while we are
     * processing them, we don't miss out on it.
     */
    connect(d->m_accountManager, SIGNAL(accountCreated(const QDBusObjectPath &)),
            this, SLOT(accountCreated(const QDBusObjectPath &)));
    connect(d->m_accountManager, SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)),
            this, SLOT(accountValidityChanged(const QDBusObjectPath &, bool)));
    connect(d->m_accountManager, SIGNAL(accountRemoved(const QDBusObjectPath &)),
            this, SLOT(accountRemoved(const QDBusObjectPath &)));

    /*
     * create a datasource for each
     * of the accounts we got in the list.
     */
    foreach(const QDBusObjectPath &path, objectPathList)
    {
        d->createAccountDataSource(path);
    }
}

bool
PresenceEngine::sourceRequestEvent(const QString & name)
{
    /*
     * if the visualisation requests a
     * source that is not already there
     * then it doesn't exist, so return
     * false
     */
    Q_UNUSED(name);
    return false;
}

void
PresenceEngine::accountCreated(const QDBusObjectPath &path)
{
    kDebug() << "accountCreated() called";
    // Load the data for the new account. To avoid duplicating code, we treat
    // this just as if an account was updated, and call the method to handle
    // that.
    d->createAccountDataSource(path);
}

void
PresenceEngine::accountValidityChanged(const QDBusObjectPath &path, bool valid)
{
	Q_UNUSED(valid);
    kDebug() << "accountValidityChanged() called";
    /*
     * slot called when an account has
     * been updated.
     */
    d->createAccountDataSource(path);
}

void
PresenceEngine::accountRemoved(const QDBusObjectPath &path)
{
    kDebug() << "uint handle() called";
    /*
     * slot called when an account has been deleted
     *
     * remove that source.
     */
    d->removeAccountDataSource(path);
}

#include "presence.moc"

<commit_msg>update documentation<commit_after>/*
 *   Copyright (C) 2008 George Goldberg <grundleborg@googlemail.com>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Library General Public License version 2 as
 *   published by the Free Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Library General Public License for more details
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "presence.h"

#include <TelepathyQt4/Client/Account>
#include <TelepathyQt4/Client/AccountManager>

#include <KDebug>
#include <KLocale>
#include <KUrl>

#include <QtCore/QDateTime>
#include <QtCore/QTimer>

class PresenceEngine::PresenceEnginePrivate
{
	PresenceEngine *parent;
public:
	PresenceEnginePrivate(PresenceEngine *p) : parent(p) {}

	Telepathy::Client::AccountManager * m_accountManager;

	void createAccountDataSource(const QDBusObjectPath &path)
	{
		// \todo: FIXME
		kDebug() << "createAccountDataSource called";
		kDebug() << path.path();
	    Telepathy::Client::Account *account = accountFromObjectPath(path);

	    QString source;
	    // \todo: FIXME
	    // source = account.uniqueIdentifier();
	    Telepathy::SimplePresence sp = account->currentPresence();
	    QVariant vsp;
	    vsp.setValue(sp);
	    parent->setData(source, "current_presence", vsp);

		// emit parent->sourceAdded(account->uniqueIdentifier());

		// \todo: remove
/*
			QString source;
		    source.setNum(handle);
		    QVariantMap accountData = m_accountManager->queryAccount(handle);
		    QMap<QString, QVariant>::const_iterator end( accountData.constEnd() );
		    for(QMap<QString, QVariant>::const_iterator itr(accountData.constBegin()); itr != end; ++itr)
		    {
		        if(itr.key() == Decibel::name_current_presence)
		        {
		            QtTapioca::PresenceState ps = qdbus_cast<QtTapioca::PresenceState>(itr.value().value<QDBusArgument>());
		            QVariant psv;
		            psv.setValue(ps);
		            setData(source, "current_presence", psv);
		            continue;
		        }
		        else if(itr.key() == Decibel::name_presence_parameters)
		        {
		            setData(source, "status_message", itr.value().toMap().value("status_message").toString());
		        }
		    }

		emit parent->sourceAdded(account->uniqueIdentifier());
*/
	}

	void removeAccountDataSource(const QDBusObjectPath &path)
	{
		kDebug() << "removeAccountDataSource called";
		kDebug() << path.path();

		Telepathy::Client::Account *account = accountFromObjectPath(path);

		// \todo: FIXME
/*
		QString identifier = account->uniqueIdentifier();
		parent->removeSource(identifier);
		emit parent->sourceRemoved(identifier);
*/
	}

	Telepathy::Client::Account *accountFromObjectPath(const QDBusObjectPath &path)
	{
		return m_accountManager->accountForPath(path);
	}
};

/**
 * \class PresenceEngine
 * \ingroup presence
 * \headerfile <presence.h>
 *
 * Object representing a Presence data source.
 */

/**
 * Construct a new PresenceEngine object.
 *
 * \param parent Object parent.
 * \param args QVariantList arguments.
 */
PresenceEngine::PresenceEngine(QObject * parent, const QVariantList & args)
  : Plasma::DataEngine(parent, args),
  d(new PresenceEnginePrivate(this))
{
    // Register custom types:
    Telepathy::registerTypes();
}

/**
 * Class destructor
 */
PresenceEngine::~PresenceEngine()
{
	delete d->m_accountManager;
	delete d;
}

/**
 * Initialize Presence.
 */
void PresenceEngine::init()
{
    kDebug() << "init() started";
    /*
     * check that we are connected to the session
     * bus OK.
     */
    if (!QDBusConnection::sessionBus().isConnected())
    {
        kDebug() << "PresenceEngine::init(): cannot connect to session bus.";
    }

   /*
    * set up the dbus accountmanager object
    * which will provide all the data to this
    * data engine.
    */
    d->m_accountManager =
    	new Telepathy::Client::AccountManager(QDBusConnection::sessionBus());

    /*
     * get a list of all the accounts that
     * are all ready there
     */
    QList<Telepathy::Client::Account *> accounts = d->m_accountManager->allAccounts();
    kDebug() << "accounts: " << accounts.size();

    Telepathy::ObjectPathList objectPathList = d->m_accountManager->allAccountPaths();
    /*
     * connect signals from the account manager
     * to slots within this data engine.
     *
     * we intentionally do this before processing
     * the accounts that are already created so
     * that if another is created while we are
     * processing them, we don't miss out on it.
     */
    connect(d->m_accountManager, SIGNAL(accountCreated(const QDBusObjectPath &)),
            this, SLOT(accountCreated(const QDBusObjectPath &)));
    connect(d->m_accountManager, SIGNAL(accountValidityChanged(const QDBusObjectPath &, bool)),
            this, SLOT(accountValidityChanged(const QDBusObjectPath &, bool)));
    connect(d->m_accountManager, SIGNAL(accountRemoved(const QDBusObjectPath &)),
            this, SLOT(accountRemoved(const QDBusObjectPath &)));

    /*
     * create a datasource for each
     * of the accounts we got in the list.
     */
    foreach(const QDBusObjectPath &path, objectPathList)
    {
        d->createAccountDataSource(path);
    }
}

/**
 * Return whether source exist.
 *
 * \return \c true if source exists.
 */
bool PresenceEngine::sourceRequestEvent(const QString & name)
{
    /*
     * if the visualisation requests a
     * source that is not already there
     * then it doesn't exist, so return
     * false
     */
    Q_UNUSED(name);
    return false;
}

/**
 *  Slot for new account.
 *
 * \param path QDBusObjectPath to created account.
 */
void PresenceEngine::accountCreated(const QDBusObjectPath &path)
{
    kDebug() << "accountCreated() called";
    // Load the data for the new account. To avoid duplicating code, we treat
    // this just as if an account was updated, and call the method to handle
    // that.
    d->createAccountDataSource(path);
}

/**
 * Slot for account data changed.
 *
 * \param QDBusObjectPath Name of the account path.
 * \param valid true if the account is valid.
 */
void PresenceEngine::accountValidityChanged(const QDBusObjectPath &path, bool valid)
{
	Q_UNUSED(valid);
    kDebug() << "accountValidityChanged() called";
    /*
     * slot called when an account has
     * been updated.
     */
    d->createAccountDataSource(path);
}

/**
 * Slot for account removed.
 *
 * \param QDBusObjectPath Name of the account path.
 */
void PresenceEngine::accountRemoved(const QDBusObjectPath &path)
{
    kDebug() << "uint handle() called";
    /*
     * slot called when an account has been deleted
     *
     * remove that source.
     */
    d->removeAccountDataSource(path);
}

#include "presence.moc"

<|endoftext|>


<commit_before><commit_msg>android: Stopgap: _exit() is better than a hang<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: oemjob.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: vg $ $Date: 2003-05-22 08:54:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SOCOMP_OEMJOB_HXX_
#define _SOCOMP_OEMJOB_HXX_

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_EXCEPTION_HPP_
#include <com/sun/star/uno/Exception.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_TASK_XJOB_HPP_
#include <com/sun/star/task/XJob.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <osl/mutex.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::task;

namespace desktop{

class OEMPreloadJob : public ::cppu::WeakImplHelper3< XJob, XComponent, XServiceInfo >
{

private:
    ::osl::Mutex                        m_aMutex;
    ::cppu::OInterfaceContainerHelper   m_aListeners;
    Reference< XMultiServiceFactory >   m_xServiceManager;

    sal_Bool checkOEMPreloadFlag();
    void disableOEMPreloadFlag();

public:
    OEMPreloadJob( const Reference < XMultiServiceFactory >& xFactory );
    virtual ~OEMPreloadJob();

    static ::rtl::OUString                      GetImplementationName();
    static Sequence< rtl::OUString >            GetSupportedServiceNames();

    // XComponent
    virtual void SAL_CALL dispose() throw ( RuntimeException );
    virtual void SAL_CALL addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException );
    virtual void SAL_CALL removeEventListener(const Reference< XEventListener > & aListener) throw ( RuntimeException );

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL    getImplementationName() throw ( RuntimeException );
    virtual sal_Bool SAL_CALL           supportsService( const ::rtl::OUString& rServiceName ) throw ( RuntimeException );
    virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( RuntimeException );

    //XJob
    virtual Any SAL_CALL execute(const Sequence<NamedValue>& args)throw ( RuntimeException );

    static const char* interfaces[];
    static const char* implementationName;
    static const char* serviceName;
    static Reference<XInterface> SAL_CALL CreateInstance(
        const Reference< XMultiServiceFactory >&);

};
}

#endif // _SOCOMP_OEMJOB_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.2.590); FILE MERGED 2005/09/05 17:50:59 rt 1.2.590.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: oemjob.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 17:48:12 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _SOCOMP_OEMJOB_HXX_
#define _SOCOMP_OEMJOB_HXX_

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_EXCEPTION_HPP_
#include <com/sun/star/uno/Exception.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_LANG_XCOMPONENT_HPP_
#include <com/sun/star/lang/XComponent.hpp>
#endif
#ifndef _COM_SUN_STAR_TASK_XJOB_HPP_
#include <com/sun/star/task/XJob.hpp>
#endif
#ifndef _CPPUHELPER_IMPLBASE3_HXX_
#include <cppuhelper/implbase3.hxx>
#endif
#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <osl/mutex.hxx>

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::task;

namespace desktop{

class OEMPreloadJob : public ::cppu::WeakImplHelper3< XJob, XComponent, XServiceInfo >
{

private:
    ::osl::Mutex                        m_aMutex;
    ::cppu::OInterfaceContainerHelper   m_aListeners;
    Reference< XMultiServiceFactory >   m_xServiceManager;

    sal_Bool checkOEMPreloadFlag();
    void disableOEMPreloadFlag();

public:
    OEMPreloadJob( const Reference < XMultiServiceFactory >& xFactory );
    virtual ~OEMPreloadJob();

    static ::rtl::OUString                      GetImplementationName();
    static Sequence< rtl::OUString >            GetSupportedServiceNames();

    // XComponent
    virtual void SAL_CALL dispose() throw ( RuntimeException );
    virtual void SAL_CALL addEventListener( const Reference< XEventListener > & aListener) throw ( RuntimeException );
    virtual void SAL_CALL removeEventListener(const Reference< XEventListener > & aListener) throw ( RuntimeException );

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL    getImplementationName() throw ( RuntimeException );
    virtual sal_Bool SAL_CALL           supportsService( const ::rtl::OUString& rServiceName ) throw ( RuntimeException );
    virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw ( RuntimeException );

    //XJob
    virtual Any SAL_CALL execute(const Sequence<NamedValue>& args)throw ( RuntimeException );

    static const char* interfaces[];
    static const char* implementationName;
    static const char* serviceName;
    static Reference<XInterface> SAL_CALL CreateInstance(
        const Reference< XMultiServiceFactory >&);

};
}

#endif // _SOCOMP_OEMJOB_HXX_
<|endoftext|>


<commit_before>// Copyright (c) Facebook, Inc. and its affiliates.

#include <torch/extension.h>
#include "ROIAlignRotated/ROIAlignRotated.h"
#include "box_iou_rotated/box_iou_rotated.h"
#include "cocoeval/cocoeval.h"
#include "deformable/deform_conv.h"
#include "nms_rotated/nms_rotated.h"

namespace detectron2 {

#if defined(WITH_CUDA) || defined(WITH_HIP)
extern int get_cudart_version();
#endif

std::string get_cuda_version() {
#if defined(WITH_CUDA) || defined(WITH_HIP)
  std::ostringstream oss;

#if defined(WITH_CUDA)
  oss << "CUDA ";
#else
  oss << "HIP ";
#endif

  // copied from
  // https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/cuda/detail/CUDAHooks.cpp#L231
  auto printCudaStyleVersion = [&](int v) {
    oss << (v / 1000) << "." << (v / 10 % 100);
    if (v % 10 != 0) {
      oss << "." << (v % 10);
    }
  };
  printCudaStyleVersion(get_cudart_version());
  return oss.str();
#else // neither CUDA nor HIP
  return std::string("not available");
#endif
}

bool has_cuda() {
#if defined(WITH_CUDA)
  return true;
#else
  return false;
#endif
}

// similar to
// https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/Version.cpp
std::string get_compiler_version() {
  std::ostringstream ss;
#if defined(__GNUC__)
#ifndef __clang__

#if ((__GNUC__ <= 4) && (__GNUC_MINOR__ <= 8))
#error "GCC >= 4.9 is required!"
#endif

  { ss << "GCC " << __GNUC__ << "." << __GNUC_MINOR__; }
#endif
#endif

#if defined(__clang_major__)
  {
    ss << "clang " << __clang_major__ << "." << __clang_minor__ << "."
       << __clang_patchlevel__;
  }
#endif

#if defined(_MSC_VER)
  { ss << "MSVC " << _MSC_FULL_VER; }
#endif
  return ss.str();
}

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
  m.def("get_compiler_version", &get_compiler_version, "get_compiler_version");
  m.def("get_cuda_version", &get_cuda_version, "get_cuda_version");
  m.def("has_cuda", &has_cuda, "has_cuda");

  m.def("deform_conv_forward", &deform_conv_forward, "deform_conv_forward");
  m.def(
      "deform_conv_backward_input",
      &deform_conv_backward_input,
      "deform_conv_backward_input");
  m.def(
      "deform_conv_backward_filter",
      &deform_conv_backward_filter,
      "deform_conv_backward_filter");
  m.def(
      "modulated_deform_conv_forward",
      &modulated_deform_conv_forward,
      "modulated_deform_conv_forward");
  m.def(
      "modulated_deform_conv_backward",
      &modulated_deform_conv_backward,
      "modulated_deform_conv_backward");

  m.def("COCOevalAccumulate", &COCOeval::Accumulate, "COCOeval::Accumulate");
  m.def(
      "COCOevalEvaluateImages",
      &COCOeval::EvaluateImages,
      "COCOeval::EvaluateImages");
  pybind11::class_<COCOeval::InstanceAnnotation>(m, "InstanceAnnotation")
      .def(pybind11::init<uint64_t, double, double, bool, bool>());
  pybind11::class_<COCOeval::ImageEvaluation>(m, "ImageEvaluation")
      .def(pybind11::init<>());
}

TORCH_LIBRARY(detectron2, m) {
  m.def("nms_rotated", &nms_rotated);
  m.def("box_iou_rotated", &box_iou_rotated);
  m.def("roi_align_rotated_forward", &ROIAlignRotated_forward);
  m.def("roi_align_rotated_backward", &ROIAlignRotated_backward);
}
} // namespace detectron2
<commit_msg>Revert D32612862: Daily `arc lint --take CLANGFORMAT`<commit_after>// Copyright (c) Facebook, Inc. and its affiliates.

#include <torch/extension.h>
#include "ROIAlignRotated/ROIAlignRotated.h"
#include "box_iou_rotated/box_iou_rotated.h"
#include "cocoeval/cocoeval.h"
#include "deformable/deform_conv.h"
#include "nms_rotated/nms_rotated.h"

namespace detectron2 {

#if defined(WITH_CUDA) || defined(WITH_HIP)
extern int get_cudart_version();
#endif

std::string get_cuda_version() {
#if defined(WITH_CUDA) || defined(WITH_HIP)
  std::ostringstream oss;

#if defined(WITH_CUDA)
  oss << "CUDA ";
#else
  oss << "HIP ";
#endif

  // copied from
  // https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/cuda/detail/CUDAHooks.cpp#L231
  auto printCudaStyleVersion = [&](int v) {
    oss << (v / 1000) << "." << (v / 10 % 100);
    if (v % 10 != 0) {
      oss << "." << (v % 10);
    }
  };
  printCudaStyleVersion(get_cudart_version());
  return oss.str();
#else // neither CUDA nor HIP
  return std::string("not available");
#endif
}

bool has_cuda() {
#if defined(WITH_CUDA)
  return true;
#else
  return false;
#endif
}

// similar to
// https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/Version.cpp
std::string get_compiler_version() {
  std::ostringstream ss;
#if defined(__GNUC__)
#ifndef __clang__

#if ((__GNUC__ <= 4) && (__GNUC_MINOR__ <= 8))
#error "GCC >= 4.9 is required!"
#endif

  { ss << "GCC " << __GNUC__ << "." << __GNUC_MINOR__; }
#endif
#endif

#if defined(__clang_major__)
  {
    ss << "clang " << __clang_major__ << "." << __clang_minor__ << "."
       << __clang_patchlevel__;
  }
#endif

#if defined(_MSC_VER)
  { ss << "MSVC " << _MSC_FULL_VER; }
#endif
  return ss.str();
}

PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
  m.def("get_compiler_version", &get_compiler_version, "get_compiler_version");
  m.def("get_cuda_version", &get_cuda_version, "get_cuda_version");
  m.def("has_cuda", &has_cuda, "has_cuda");

  m.def("deform_conv_forward", &deform_conv_forward, "deform_conv_forward");
  m.def(
      "deform_conv_backward_input",
      &deform_conv_backward_input,
      "deform_conv_backward_input");
  m.def(
      "deform_conv_backward_filter",
      &deform_conv_backward_filter,
      "deform_conv_backward_filter");
  m.def(
      "modulated_deform_conv_forward",
      &modulated_deform_conv_forward,
      "modulated_deform_conv_forward");
  m.def(
      "modulated_deform_conv_backward",
      &modulated_deform_conv_backward,
      "modulated_deform_conv_backward");

  m.def("COCOevalAccumulate", &COCOeval::Accumulate, "COCOeval::Accumulate");
  m.def(
      "COCOevalEvaluateImages",
      &COCOeval::EvaluateImages,
      "COCOeval::EvaluateImages");
  pybind11::class_<COCOeval::InstanceAnnotation>(m, "InstanceAnnotation")
      .def(pybind11::init<uint64_t, double, double, bool, bool>());
  pybind11::class_<COCOeval::ImageEvaluation>(m, "ImageEvaluation")
      .def(pybind11::init<>());
}

TORCH_LIBRARY(detectron2, m) {
  m.def("nms_rotated", &nms_rotated);
  m.def("box_iou_rotated", &box_iou_rotated);
  m.def("roi_align_rotated_forward", &ROIAlignRotated_forward);
  m.def("roi_align_rotated_backward", &ROIAlignRotated_backward);
}
} // namespace detectron2
<|endoftext|>


<commit_before><commit_msg>Fix checkbox value<commit_after><|endoftext|>


<commit_before><commit_msg>Refactor<commit_after><|endoftext|>