<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "storagecomponent.h"
#include <vespa/storage/storageserver/prioritymapper.h>

#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vdslib/distribution/distribution.h>

namespace storage {

// Defined in cpp file to allow unique pointers of unknown type in header.
StorageComponent::~StorageComponent()
{
}

void
StorageComponent::setNodeInfo(vespalib::stringref clusterName,
                              const lib::NodeType& nodeType,
                              uint16_t index)
{
    // Assumed to not be set dynamically.
    _clusterName = clusterName;
    _nodeType = &nodeType;
    _index = index;
}

void
StorageComponent::setDocumentTypeRepo(DocumentTypeRepoSP repo)
{
    std::lock_guard<std::mutex> guard(_lock);
    _docTypeRepo = repo;
}

void
StorageComponent::setLoadTypes(LoadTypeSetSP loadTypes)
{
    std::lock_guard<std::mutex> guard(_lock);
    _loadTypes = loadTypes;
}

void
StorageComponent::setPriorityConfig(const PriorityConfig& c)
{
    // Priority mapper is already thread safe.
    _priorityMapper->setConfig(c);
}

void
StorageComponent::setBucketIdFactory(const document::BucketIdFactory& factory)
{
    // Assumed to not be set dynamically.
    _bucketIdFactory = factory;
}

void
StorageComponent::setDistribution(DistributionSP distribution)
{
    std::lock_guard<std::mutex> guard(_lock);
    _distribution = distribution;
}

void
StorageComponent::enableMultipleBucketSpaces(bool value)
{
    std::lock_guard<std::mutex> guard(_lock);
    _enableMultipleBucketSpaces = value;
}

void
StorageComponent::setNodeStateUpdater(NodeStateUpdater& updater)
{
    std::lock_guard<std::mutex> guard(_lock);
    if (_nodeStateUpdater != 0) {
        throw vespalib::IllegalStateException(
                "Node state updater is already set", VESPA_STRLOC);
    }
    _nodeStateUpdater = &updater;
}

StorageComponent::StorageComponent(StorageComponentRegister& compReg,
                                   vespalib::stringref name)
    : Component(compReg, name),
      _clusterName(),
      _nodeType(nullptr),
      _index(0),
      _docTypeRepo(),
      _loadTypes(),
      _priorityMapper(new PriorityMapper),
      _bucketIdFactory(),
      _distribution(),
      _nodeStateUpdater(nullptr),
      _lock(),
      _enableMultipleBucketSpaces(false)
{
    compReg.registerStorageComponent(*this);
}

NodeStateUpdater&
StorageComponent::getStateUpdater() const
{
    std::lock_guard<std::mutex> guard(_lock);
    if (_nodeStateUpdater == 0) {
        throw vespalib::IllegalStateException(
                "Component need node state updater at this time, but it has "
                "not been initialized.", VESPA_STRLOC);
   }
    return *_nodeStateUpdater;
}

vespalib::string
StorageComponent::getIdentity() const
{
    vespalib::asciistream name;
    name << "storage/cluster." << _clusterName << "/"
         << _nodeType->serialize() << "/" << _index;
    return name.str();
}

uint8_t
StorageComponent::getPriority(const documentapi::LoadType& lt) const
{
    return _priorityMapper->getPriority(lt);
}

StorageComponent::DocumentTypeRepoSP
StorageComponent::getTypeRepo() const
{
    std::lock_guard<std::mutex> guard(_lock);
    return _docTypeRepo;
}

StorageComponent::LoadTypeSetSP
StorageComponent::getLoadTypes() const
{
    std::lock_guard<std::mutex> guard(_lock);
    return _loadTypes;
}

StorageComponent::DistributionSP
StorageComponent::getDistribution() const
{
    std::lock_guard<std::mutex> guard(_lock);
    return _distribution;
}

bool
StorageComponent::enableMultipleBucketSpaces() const
{
    std::lock_guard<std::mutex> guard(_lock);
    return _enableMultipleBucketSpaces;
}

} // storage
<commit_msg>Utilize class template argument deduction (in C++17).<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "storagecomponent.h"
#include <vespa/storage/storageserver/prioritymapper.h>

#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vdslib/distribution/distribution.h>

namespace storage {

// Defined in cpp file to allow unique pointers of unknown type in header.
StorageComponent::~StorageComponent()
{
}

void
StorageComponent::setNodeInfo(vespalib::stringref clusterName,
                              const lib::NodeType& nodeType,
                              uint16_t index)
{
    // Assumed to not be set dynamically.
    _clusterName = clusterName;
    _nodeType = &nodeType;
    _index = index;
}

void
StorageComponent::setDocumentTypeRepo(DocumentTypeRepoSP repo)
{
    std::lock_guard guard(_lock);
    _docTypeRepo = repo;
}

void
StorageComponent::setLoadTypes(LoadTypeSetSP loadTypes)
{
    std::lock_guard guard(_lock);
    _loadTypes = loadTypes;
}

void
StorageComponent::setPriorityConfig(const PriorityConfig& c)
{
    // Priority mapper is already thread safe.
    _priorityMapper->setConfig(c);
}

void
StorageComponent::setBucketIdFactory(const document::BucketIdFactory& factory)
{
    // Assumed to not be set dynamically.
    _bucketIdFactory = factory;
}

void
StorageComponent::setDistribution(DistributionSP distribution)
{
    std::lock_guard guard(_lock);
    _distribution = distribution;
}

void
StorageComponent::enableMultipleBucketSpaces(bool value)
{
    std::lock_guard guard(_lock);
    _enableMultipleBucketSpaces = value;
}

void
StorageComponent::setNodeStateUpdater(NodeStateUpdater& updater)
{
    std::lock_guard guard(_lock);
    if (_nodeStateUpdater != 0) {
        throw vespalib::IllegalStateException(
                "Node state updater is already set", VESPA_STRLOC);
    }
    _nodeStateUpdater = &updater;
}

StorageComponent::StorageComponent(StorageComponentRegister& compReg,
                                   vespalib::stringref name)
    : Component(compReg, name),
      _clusterName(),
      _nodeType(nullptr),
      _index(0),
      _docTypeRepo(),
      _loadTypes(),
      _priorityMapper(new PriorityMapper),
      _bucketIdFactory(),
      _distribution(),
      _nodeStateUpdater(nullptr),
      _lock(),
      _enableMultipleBucketSpaces(false)
{
    compReg.registerStorageComponent(*this);
}

NodeStateUpdater&
StorageComponent::getStateUpdater() const
{
    std::lock_guard guard(_lock);
    if (_nodeStateUpdater == 0) {
        throw vespalib::IllegalStateException(
                "Component need node state updater at this time, but it has "
                "not been initialized.", VESPA_STRLOC);
   }
    return *_nodeStateUpdater;
}

vespalib::string
StorageComponent::getIdentity() const
{
    vespalib::asciistream name;
    name << "storage/cluster." << _clusterName << "/"
         << _nodeType->serialize() << "/" << _index;
    return name.str();
}

uint8_t
StorageComponent::getPriority(const documentapi::LoadType& lt) const
{
    return _priorityMapper->getPriority(lt);
}

StorageComponent::DocumentTypeRepoSP
StorageComponent::getTypeRepo() const
{
    std::lock_guard guard(_lock);
    return _docTypeRepo;
}

StorageComponent::LoadTypeSetSP
StorageComponent::getLoadTypes() const
{
    std::lock_guard guard(_lock);
    return _loadTypes;
}

StorageComponent::DistributionSP
StorageComponent::getDistribution() const
{
    std::lock_guard guard(_lock);
    return _distribution;
}

bool
StorageComponent::enableMultipleBucketSpaces() const
{
    std::lock_guard guard(_lock);
    return _enableMultipleBucketSpaces;
}

} // storage
<|endoftext|>


<commit_before>#include <polar/core/log.h>
#include <polar/fs/local.h>
#include <polar/util/sdl.h>

namespace polar::core {
	std::shared_ptr<logger> logger::instance;

	void logger::msgbox(std::string title, std::string msg) {
#if defined(_WIN32)
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.data(), msg.data(), NULL);
#endif
		std::cerr << title << ": " << msg << std::endl;
	}

	logger::logger(priority_t priority)
	  : file((fs::local::app_dir() / "log.txt").str(), std::ios::out | std::ios::binary | std::ios::trunc),
	    priority(priority) {}
}
<commit_msg>Throw exception on fatal error<commit_after>#include <polar/core/log.h>
#include <polar/fs/local.h>
#include <polar/util/sdl.h>

namespace polar::core {
	std::shared_ptr<logger> logger::instance;

	void logger::msgbox(std::string title, std::string msg) {
#if defined(_WIN32)
		SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title.data(), msg.data(), NULL);
#endif
		std::cerr << title << ": " << msg << std::endl;
		throw std::runtime_error("fatal error");
	}

	logger::logger(priority_t priority)
	  : file((fs::local::app_dir() / "log.txt").str(), std::ios::out | std::ios::binary | std::ios::trunc),
	    priority(priority) {}
}
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2006-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NASA Vision Workbench is 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.
// __END_LICENSE__

#include <vw/Image/ImageView.h>
#include <vw/Image/PixelMask.h>
#include <vw/Image/PixelMath.h>
#include <vw/Image/PixelTypeInfo.h>
#include <vw/Image/PixelTypes.h>
#include <vw/Math/Vector.h>
#include <vw/Math/LevenbergMarquardt.h>
#include <vw/Camera/CameraModel.h>
#include <vw/Stereo/StereoModel.h>

namespace vw {
namespace stereo {
  namespace detail {
    class PointLMA : public math::LeastSquaresModelBase<PointLMA> {
      const camera::CameraModel *m_camera1, *m_camera2;

    public:
      typedef Vector<double,4> result_type;
      typedef Vector<double,3> domain_type;
      typedef Matrix<double> jacobian_type;

      PointLMA( camera::CameraModel const* cam1,
                camera::CameraModel const* cam2 ) :
        m_camera1(cam1), m_camera2(cam2) {}

      inline result_type operator()( domain_type const& x ) const {
        Vector4 output;
        subvector(output,0,2) = m_camera1->point_to_pixel( x );
        subvector(output,2,2) = m_camera2->point_to_pixel( x );
        return output;
      }
    };
  }

StereoModel::StereoModel(camera::CameraModel const* camera_model1,
                         camera::CameraModel const* camera_model2,
                         bool least_squares_refine ) :
  m_camera1(camera_model1), m_camera2(camera_model2),
  m_least_squares(least_squares_refine) {}

ImageView<Vector3>
StereoModel::operator()(ImageView<PixelMask<Vector2f> > const& disparity_map,
                        ImageView<double> &error) const {

  // Error analysis
  double mean_error = 0.0;
  double max_error = 0.0;
  int32 point_count = 0;
  int32 divergent = 0;

  // Allocate xyz image and get pointer to buffer
  ImageView<Vector3> xyz(disparity_map.cols(), disparity_map.rows());
  error.set_size(disparity_map.cols(), disparity_map.rows());

  // Compute 3D position for each pixel in the disparity map
  vw_out() << "StereoModel: Applying camera models\n";
  for (int32 y = 0; y < disparity_map.rows(); y++) {
    if (y % 100 == 0) {
      printf("\tStereoModel computing points: %0.2f%% complete.\r", 100.0f*float(y)/disparity_map.rows());
      fflush(stdout);
    }
    for (int32 x = 0; x < disparity_map.cols(); x++) {
      if ( is_valid(disparity_map(x,y)) ) {
        xyz(x,y) = (*this)(Vector2( x, y),
                           Vector2( x+disparity_map(x,y)[0], y+disparity_map(x,y)[1]),
                           error(x,y) );

        if (error(x,y) >= 0) {
          // Keep track of error statistics
          if (error(x,y) > max_error)
            max_error = error(x,y);
          mean_error += error(x,y);
            ++point_count;
        } else {
          // rays diverge or are parallel
          xyz(x,y) = Vector3();
          divergent++;
        }
      } else {
        xyz(x,y) = Vector3();
        error(x,y) = 0;
      }
      }
  }

  if (divergent != 0)
    vw_out() << "WARNING in StereoModel: " << divergent
             << " rays diverged or were parallel!\n";

  vw_out() << "\tStereoModel computing points: Done.                  \n";
  vw_out() << "\tMean error = " << mean_error/double(point_count)
           << ",  Max error = " << max_error << std::endl;
    return xyz;
}

bool StereoModel::are_nearly_parallel(Vector3 const& vec1, Vector3 const& vec2) const{
  // If vec1 and vec2 are nearly parallel, there will be
  // very large numerical uncertainty about where to place the
  // point.  We set a threshold here to reject points that are
  // on nearly parallel rays.  The threshold of 1e-4 corresponds
  // to a convergence of less than theta = 0.81 degrees, so if
  // the two rays are within 0.81 degrees of being parallel, we
  // reject this point.
  //
  // This threshold was chosen empirically for now, but should
  // probably be revisited once a more rigorous analysis has
  // been completed. -mbroxton (11-MAR-07)
  return ( (1-dot_prod(vec1, vec2) < 1e-4 && !m_least_squares) ||
           (1-dot_prod(vec1, vec2) < 1e-5 && m_least_squares) );
}

Vector3 StereoModel::operator()(Vector2 const& pix1,
                                Vector2 const& pix2, Vector3& errorVec) const {

  // Note: Class RPCStereoModel inherits from this class and re-implements this function.

  errorVec = Vector3();

  // Check for NaN values
  if (pix1 != pix1 || pix2 != pix2) return Vector3();

  try {
    // Determine range by triangulation
    Vector3 vec1 = m_camera1->pixel_to_vector(pix1);
    Vector3 vec2 = m_camera2->pixel_to_vector(pix2);

    if (are_nearly_parallel(vec1, vec2)){
      return Vector3();
    }

    Vector3 origin1 = m_camera1->camera_center(pix1);
    Vector3 origin2 = m_camera2->camera_center(pix2);
    Vector3 result  = triangulate_point(origin1, vec1,
                                        origin2, vec2,
                                        errorVec);

    if ( m_least_squares )
      refine_point(pix1, pix2, result);

    // Reflect points that fall behind one of the two cameras
    if ( dot_prod(result - origin1, vec1) < 0 ||
         dot_prod(result - origin2, vec2) < 0 ) {
      result = -result + 2*origin1;
    }

    return result;

  } catch (const camera::PixelToRayErr& /*e*/) {
    return Vector3();
  }
}

  Vector3 StereoModel::operator()(Vector2 const& pix1, Vector2 const& pix2,
                                  double& error ) const {
  Vector3 errorVec;
  Vector3 result = operator()(pix1, pix2, errorVec);
  error = norm_2(errorVec);
  return result;
}

double StereoModel::convergence_angle(Vector2 const& pix1, Vector2 const& pix2) const {
  return acos(dot_prod(m_camera1->pixel_to_vector(pix1),
                       m_camera2->pixel_to_vector(pix2)));
}

Vector3 StereoModel::triangulate_point(Vector3 const& point1,
                                       Vector3 const& vec1,
                                       Vector3 const& point2,
                                       Vector3 const& vec2,
                                       Vector3& errorVec) const {

  // Triangulate the point by finding the midpoint of the segment
  // joining the closest points on the two rays emanating
  // from the camera.

  Vector3 v12 = cross_prod(vec1, vec2);
  Vector3 v1 = cross_prod(v12, vec1);
  Vector3 v2 = cross_prod(v12, vec2);

  Vector3 closestPoint1 = point1 + dot_prod(v2, point2-point1)/dot_prod(v2, vec1)*vec1;
  Vector3 closestPoint2 = point2 + dot_prod(v1, point1-point2)/dot_prod(v1, vec2)*vec2;

  errorVec = closestPoint1 - closestPoint2;

  return 0.5 * (closestPoint1 + closestPoint2);
}

void StereoModel::refine_point(Vector2 const& pix1,
                               Vector2 const& pix2,
                               Vector3& point) const {

  // Refine the point by minimizing the least squares error in pixel domain.

  detail::PointLMA model( m_camera1, m_camera2 );
  Vector4 objective( pix1[0], pix1[1], pix2[0], pix2[1] );
  int status = 0;
  Vector3 npoint = levenberg_marquardt( model, point,
                                        objective, status, 1e-3, 1e-6, 10 );
  if ( status > 0 )
    point = npoint;
}

}} // vw::stereo
<commit_msg>StereoModel: Catch all exceptions<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2006-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NASA Vision Workbench is 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.
// __END_LICENSE__

#include <vw/Image/ImageView.h>
#include <vw/Image/PixelMask.h>
#include <vw/Image/PixelMath.h>
#include <vw/Image/PixelTypeInfo.h>
#include <vw/Image/PixelTypes.h>
#include <vw/Math/Vector.h>
#include <vw/Math/LevenbergMarquardt.h>
#include <vw/Camera/CameraModel.h>
#include <vw/Stereo/StereoModel.h>

namespace vw {
namespace stereo {
  namespace detail {
    class PointLMA : public math::LeastSquaresModelBase<PointLMA> {
      const camera::CameraModel *m_camera1, *m_camera2;

    public:
      typedef Vector<double,4> result_type;
      typedef Vector<double,3> domain_type;
      typedef Matrix<double> jacobian_type;

      PointLMA( camera::CameraModel const* cam1,
                camera::CameraModel const* cam2 ) :
        m_camera1(cam1), m_camera2(cam2) {}

      inline result_type operator()( domain_type const& x ) const {
        Vector4 output;
        subvector(output,0,2) = m_camera1->point_to_pixel( x );
        subvector(output,2,2) = m_camera2->point_to_pixel( x );
        return output;
      }
    };
  }

StereoModel::StereoModel(camera::CameraModel const* camera_model1,
                         camera::CameraModel const* camera_model2,
                         bool least_squares_refine ) :
  m_camera1(camera_model1), m_camera2(camera_model2),
  m_least_squares(least_squares_refine) {}

ImageView<Vector3>
StereoModel::operator()(ImageView<PixelMask<Vector2f> > const& disparity_map,
                        ImageView<double> &error) const {

  // Error analysis
  double mean_error = 0.0;
  double max_error = 0.0;
  int32 point_count = 0;
  int32 divergent = 0;

  // Allocate xyz image and get pointer to buffer
  ImageView<Vector3> xyz(disparity_map.cols(), disparity_map.rows());
  error.set_size(disparity_map.cols(), disparity_map.rows());

  // Compute 3D position for each pixel in the disparity map
  vw_out() << "StereoModel: Applying camera models\n";
  for (int32 y = 0; y < disparity_map.rows(); y++) {
    if (y % 100 == 0) {
      printf("\tStereoModel computing points: %0.2f%% complete.\r", 100.0f*float(y)/disparity_map.rows());
      fflush(stdout);
    }
    for (int32 x = 0; x < disparity_map.cols(); x++) {
      if ( is_valid(disparity_map(x,y)) ) {
        xyz(x,y) = (*this)(Vector2( x, y),
                           Vector2( x+disparity_map(x,y)[0], y+disparity_map(x,y)[1]),
                           error(x,y) );

        if (error(x,y) >= 0) {
          // Keep track of error statistics
          if (error(x,y) > max_error)
            max_error = error(x,y);
          mean_error += error(x,y);
            ++point_count;
        } else {
          // rays diverge or are parallel
          xyz(x,y) = Vector3();
          divergent++;
        }
      } else {
        xyz(x,y) = Vector3();
        error(x,y) = 0;
      }
      }
  }

  if (divergent != 0)
    vw_out() << "WARNING in StereoModel: " << divergent
             << " rays diverged or were parallel!\n";

  vw_out() << "\tStereoModel computing points: Done.                  \n";
  vw_out() << "\tMean error = " << mean_error/double(point_count)
           << ",  Max error = " << max_error << std::endl;
    return xyz;
}

bool StereoModel::are_nearly_parallel(Vector3 const& vec1, Vector3 const& vec2) const{
  // If vec1 and vec2 are nearly parallel, there will be
  // very large numerical uncertainty about where to place the
  // point.  We set a threshold here to reject points that are
  // on nearly parallel rays.  The threshold of 1e-4 corresponds
  // to a convergence of less than theta = 0.81 degrees, so if
  // the two rays are within 0.81 degrees of being parallel, we
  // reject this point.
  //
  // This threshold was chosen empirically for now, but should
  // probably be revisited once a more rigorous analysis has
  // been completed. -mbroxton (11-MAR-07)
  return ( (1-dot_prod(vec1, vec2) < 1e-4 && !m_least_squares) ||
           (1-dot_prod(vec1, vec2) < 1e-5 && m_least_squares) );
}

Vector3 StereoModel::operator()(Vector2 const& pix1,
                                Vector2 const& pix2, Vector3& errorVec) const {

  // Note: Class RPCStereoModel inherits from this class and re-implements this function.

  errorVec = Vector3();

  // Check for NaN values
  if (pix1 != pix1 || pix2 != pix2) return Vector3();

  try {
    // Determine range by triangulation
    Vector3 vec1 = m_camera1->pixel_to_vector(pix1);
    Vector3 vec2 = m_camera2->pixel_to_vector(pix2);

    if (are_nearly_parallel(vec1, vec2)){
      return Vector3();
    }

    Vector3 origin1 = m_camera1->camera_center(pix1);
    Vector3 origin2 = m_camera2->camera_center(pix2);
    Vector3 result  = triangulate_point(origin1, vec1,
                                        origin2, vec2,
                                        errorVec);

    if ( m_least_squares )
      refine_point(pix1, pix2, result);

    // Reflect points that fall behind one of the two cameras
    if ( dot_prod(result - origin1, vec1) < 0 ||
         dot_prod(result - origin2, vec2) < 0 ) {
      result = -result + 2*origin1;
    }

    return result;

  } catch (...) {
    return Vector3();
  }
}

  Vector3 StereoModel::operator()(Vector2 const& pix1, Vector2 const& pix2,
                                  double& error ) const {
  Vector3 errorVec;
  Vector3 result = operator()(pix1, pix2, errorVec);
  error = norm_2(errorVec);
  return result;
}

double StereoModel::convergence_angle(Vector2 const& pix1, Vector2 const& pix2) const {
  return acos(dot_prod(m_camera1->pixel_to_vector(pix1),
                       m_camera2->pixel_to_vector(pix2)));
}

Vector3 StereoModel::triangulate_point(Vector3 const& point1,
                                       Vector3 const& vec1,
                                       Vector3 const& point2,
                                       Vector3 const& vec2,
                                       Vector3& errorVec) const {

  // Triangulate the point by finding the midpoint of the segment
  // joining the closest points on the two rays emanating
  // from the camera.

  Vector3 v12 = cross_prod(vec1, vec2);
  Vector3 v1 = cross_prod(v12, vec1);
  Vector3 v2 = cross_prod(v12, vec2);

  Vector3 closestPoint1 = point1 + dot_prod(v2, point2-point1)/dot_prod(v2, vec1)*vec1;
  Vector3 closestPoint2 = point2 + dot_prod(v1, point1-point2)/dot_prod(v1, vec2)*vec2;

  errorVec = closestPoint1 - closestPoint2;

  return 0.5 * (closestPoint1 + closestPoint2);
}

void StereoModel::refine_point(Vector2 const& pix1,
                               Vector2 const& pix2,
                               Vector3& point) const {

  // Refine the point by minimizing the least squares error in pixel domain.

  detail::PointLMA model( m_camera1, m_camera2 );
  Vector4 objective( pix1[0], pix1[1], pix2[0], pix2[1] );
  int status = 0;
  Vector3 npoint = levenberg_marquardt( model, point,
                                        objective, status, 1e-3, 1e-6, 10 );
  if ( status > 0 )
    point = npoint;
}

}} // vw::stereo
<|endoftext|>


<commit_before>// Copyright 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following disclaimer
//     in the documentation and/or other materials provided with the
//     distribution.
//   * Neither the name of Google Inc. nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
//
// Tool to view protocol buffer files generated by the ReFr toolkit.
// Author: kbhall@google.com (Keith Hall)
//
// Example usage:
//  protoview -i training_data_file
//  protoview -M -i model_file
//  protoview -S -i symbol_table_file
//  protoview -F -i feature_message_file
//

#include <fstream>
#include <iostream>
#include <string>
#include <getopt.h>
#include <math.h>
#include "../proto/data.pb.h"
#include "../proto/dataio.h"
#include "../utils/kdebug.h"
#include "../proto/model.pb.h"

using namespace std;

int main(int argc, char* argv[]) {
  bool compressed = true;
  bool base64 = true;
  int option_char;
  bool decode_model = false;
  bool decode_features = false;
  bool decode_symbols = false;
  string input_file;

  // Invokes member function `int operator ()(void);'
  while ((option_char = getopt(argc, argv, "RUi:MFS")) != EOF) {
    switch (option_char) {
    case 'S':
      decode_symbols = true;
      break;
    case 'M':
      decode_model = true;
      break;
    case 'F':
      decode_features = true;
      break;
    case 'U':
      compressed = false;
      break;
    case 'R':
      base64 = false;
      break;
    case 'i':
      input_file = optarg;
      break;
    case '?':
      cerr << "usage: [-R] [-U] [-M] [-F] [-S] [-i file]" << endl;
      cerr << "-R - view raw encoded file (non-base64)" << endl;
      cerr << "-U - uncompressed input file" << endl;
      cerr << "-i - if empty, uses stdin" << endl;
      cerr << "-M - output model messages" << endl;
      cerr << "-F - output feature messages" << endl;
      cerr << "-S - output symbol messages" << endl;
      return -1;
      break;
    }
  }
  ConfusionProtoIO* reader;
  if (!input_file.empty()) {
    reader = new ConfusionProtoIO(input_file, ConfusionProtoIO::READ,
                                  compressed, base64);
  } else {
    reader = new ConfusionProtoIO("", ConfusionProtoIO::READSTD,
                                  false, base64);
  }
  bool reader_valid = true;
  bool first_message = true;
  while (reader_valid) {
    google::protobuf::Message* tmp_msg;
    if (decode_model) {
      if (first_message) {
        tmp_msg = new confusion_learning::ModelMessage;
        first_message = false;
      } else {
        tmp_msg = new confusion_learning::FeatureMessage;
      }
    } else if (decode_features) {
      tmp_msg = new confusion_learning::FeatureMessage;
    } else if (decode_symbols) {
      tmp_msg = new confusion_learning::SymbolMessage;
    } else {
      // Default is to decode candidate-set messages
      tmp_msg = new confusion_learning::CandidateSetMessage;
    }
    reader_valid = reader->Read(tmp_msg);
    if (reader_valid) {
      cout << "Data: " << tmp_msg->Utf8DebugString();
    }
  }
  reader->Close();
  delete reader;
  google::protobuf::ShutdownProtobufLibrary();
}
<commit_msg>Fixed memory leak.<commit_after>// Copyright 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//   * Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//   * Redistributions in binary form must reproduce the above
//     copyright notice, this list of conditions and the following disclaimer
//     in the documentation and/or other materials provided with the
//     distribution.
//   * Neither the name of Google Inc. nor the names of its
//     contributors may be used to endorse or promote products derived from
//     this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
//
// Tool to view protocol buffer files generated by the ReFr toolkit.
// Author: kbhall@google.com (Keith Hall)
//
// Example usage:
//  protoview -i training_data_file
//  protoview -M -i model_file
//  protoview -S -i symbol_table_file
//  protoview -F -i feature_message_file
//

#include <fstream>
#include <iostream>
#include <string>
#include <getopt.h>
#include <math.h>
#include "../proto/data.pb.h"
#include "../proto/dataio.h"
#include "../utils/kdebug.h"
#include "../proto/model.pb.h"

using namespace std;

int main(int argc, char* argv[]) {
  bool compressed = true;
  bool base64 = true;
  int option_char;
  bool decode_model = false;
  bool decode_features = false;
  bool decode_symbols = false;
  string input_file;

  // Invokes member function `int operator ()(void);'
  while ((option_char = getopt(argc, argv, "RUi:MFS")) != EOF) {
    switch (option_char) {
    case 'S':
      decode_symbols = true;
      break;
    case 'M':
      decode_model = true;
      break;
    case 'F':
      decode_features = true;
      break;
    case 'U':
      compressed = false;
      break;
    case 'R':
      base64 = false;
      break;
    case 'i':
      input_file = optarg;
      break;
    case '?':
      cerr << "usage: [-R] [-U] [-M] [-F] [-S] [-i file]" << endl;
      cerr << "-R - view raw encoded file (non-base64)" << endl;
      cerr << "-U - uncompressed input file" << endl;
      cerr << "-i - if empty, uses stdin" << endl;
      cerr << "-M - output model messages" << endl;
      cerr << "-F - output feature messages" << endl;
      cerr << "-S - output symbol messages" << endl;
      return -1;
      break;
    }
  }
  ConfusionProtoIO* reader;
  if (!input_file.empty()) {
    reader = new ConfusionProtoIO(input_file, ConfusionProtoIO::READ,
                                  compressed, base64);
  } else {
    reader = new ConfusionProtoIO("", ConfusionProtoIO::READSTD,
                                  false, base64);
  }
  bool reader_valid = true;
  bool first_message = true;
  while (reader_valid) {
    google::protobuf::Message* tmp_msg;
    if (decode_model) {
      if (first_message) {
        tmp_msg = new confusion_learning::ModelMessage;
        first_message = false;
      } else {
        tmp_msg = new confusion_learning::FeatureMessage;
      }
    } else if (decode_features) {
      tmp_msg = new confusion_learning::FeatureMessage;
    } else if (decode_symbols) {
      tmp_msg = new confusion_learning::SymbolMessage;
    } else {
      // Default is to decode candidate-set messages
      tmp_msg = new confusion_learning::CandidateSetMessage;
    }
    if (tmp_msg == NULL) {
      continue
    }
    reader_valid = reader->Read(tmp_msg);
    if (reader_valid) {
      cout << "Data: " << tmp_msg->Utf8DebugString();
    }
    delete tmp_msg;
  }
  reader->Close();
  delete reader;
  google::protobuf::ShutdownProtobufLibrary();
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#define EIGEN_USE_THREADS

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define EIGEN_USE_GPU
#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

#include "tensorflow/core/kernels/quantize_and_dequantize_op.h"

#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/type_traits.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

// Simulate quantization precision loss in a float tensor by:
// 1. Quantize the tensor to fixed point numbers, which should match the target
//    quantization method when it is used in inference.
// 2. Dequantize it back to floating point numbers for the following ops, most
//    likely matmul.
template <typename Device, typename T>
class QuantizeAndDequantizeV2Op : public OpKernel {
 public:
  explicit QuantizeAndDequantizeV2Op(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("num_bits", &num_bits_));
    OP_REQUIRES(ctx, num_bits_ > 0 && num_bits_ < (signed_input_ ? 62 : 63),
                errors::InvalidArgument("num_bits is out of range: ", num_bits_,
                                        " with signed_input_ ", signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));

    string round_mode_string;
    OP_REQUIRES_OK(ctx, ctx->GetAttr("round_mode", &round_mode_string));
    OP_REQUIRES(
        ctx,
        (round_mode_string == "HALF_UP" || round_mode_string == "HALF_TO_EVEN"),
        errors::InvalidArgument("Round mode string must be "
                                "'HALF_UP' or "
                                "'HALF_TO_EVEN', is '" +
                                round_mode_string + "'"));
    if (round_mode_string == "HALF_UP") {
      round_mode_ = ROUND_HALF_UP;
    } else if (round_mode_string == "HALF_TO_EVEN") {
      round_mode_ = ROUND_HALF_TO_EVEN;
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    Tensor input_min_tensor;
    Tensor input_max_tensor;
    if (range_given_) {
      input_min_tensor = ctx->input(1);
      input_max_tensor = ctx->input(2);
      auto min_val = input_min_tensor.scalar<T>()();
      auto max_val = input_max_tensor.scalar<T>()();
      OP_REQUIRES(ctx, min_val <= max_val,
                  errors::InvalidArgument("Invalid range: input_min ", min_val,
                                          " > input_max ", max_val));
    } else {
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_min_tensor));
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_max_tensor));
    }

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> f;
    f(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_, num_bits_,
      range_given_, &input_min_tensor, &input_max_tensor, round_mode_,
      output->flat<T>());
  }

 private:
  bool signed_input_;
  int num_bits_;
  bool range_given_;
  QuantizerRoundMode round_mode_;
};

// Simulate quantization precision loss in a float tensor by:
// 1. Quantize the tensor to fixed point numbers, which should match the target
//    quantization method when it is used in inference.
// 2. Dequantize it back to floating point numbers for the following ops, most
//    likely matmul.
// Almost identical to QuantizeAndDequantizeV2Op, except that num_bits is a
// tensor.
template <typename Device, typename T>
class QuantizeAndDequantizeV3Op : public OpKernel {
 public:
  explicit QuantizeAndDequantizeV3Op(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    Tensor num_bits_tensor;
    num_bits_tensor = ctx->input(3);
    int num_bits_val = num_bits_tensor.scalar<int32>()();

    OP_REQUIRES(
        ctx, num_bits_val > 0 && num_bits_val < (signed_input_ ? 62 : 63),
        errors::InvalidArgument("num_bits is out of range: ", num_bits_val,
                                " with signed_input_ ", signed_input_));

    Tensor input_min_tensor;
    Tensor input_max_tensor;
    if (range_given_) {
      input_min_tensor = ctx->input(1);
      input_max_tensor = ctx->input(2);
      auto min_val = input_min_tensor.scalar<T>()();
      auto max_val = input_max_tensor.scalar<T>()();
      OP_REQUIRES(ctx, min_val <= max_val,
                  errors::InvalidArgument("Invalid range: input_min ", min_val,
                                          " > input_max ", max_val));
    } else {
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_min_tensor));
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_max_tensor));
    }

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> f;
    f(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_, num_bits_val,
      range_given_, &input_min_tensor, &input_max_tensor, ROUND_HALF_TO_EVEN,
      output->flat<T>());
  }

 private:
  bool signed_input_;
  bool range_given_;
};

// DEPRECATED: Use QuantizeAndDequantizeV2Op.
template <typename Device, typename T>
class QuantizeAndDequantizeOp : public OpKernel {
 public:
  explicit QuantizeAndDequantizeOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("num_bits", &num_bits_));
    OP_REQUIRES(ctx, num_bits_ > 0 && num_bits_ < (signed_input_ ? 62 : 63),
                errors::InvalidArgument("num_bits is out of range: ", num_bits_,
                                        " with signed_input_ ", signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("input_min", &input_min_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("input_max", &input_max_));
    if (range_given_) {
      OP_REQUIRES(
          ctx, input_min_ <= input_max_,
          errors::InvalidArgument("Invalid range: input_min ", input_min_,
                                  " > input_max ", input_max_));
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    // One global scale.
    Tensor input_min_tensor(DataTypeToEnum<T>::value, TensorShape());
    Tensor input_max_tensor(DataTypeToEnum<T>::value, TensorShape());
    // Initialize the tensors with the values in the Attrs.
    input_min_tensor.template scalar<T>()() = static_cast<T>(input_min_);
    input_max_tensor.template scalar<T>()() = static_cast<T>(input_max_);

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> functor;
    functor(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_,
            num_bits_, range_given_, &input_min_tensor, &input_max_tensor,
            ROUND_HALF_TO_EVEN, output->flat<T>());
  }

 private:
  bool signed_input_;
  int num_bits_;
  bool range_given_;
  float input_min_;
  float input_max_;
};

// Specialization for CPUDevice.
namespace functor {
template <typename T>
struct QuantizeAndDequantizeOneScaleFunctor<CPUDevice, T> {
  void operator()(const CPUDevice& d, typename TTypes<T>::ConstVec input,
                  const bool signed_input, const int num_bits,
                  const bool range_given, Tensor* input_min_tensor,
                  Tensor* input_max_tensor, QuantizerRoundMode round_mode,
                  typename TTypes<T>::Vec out) {
    QuantizeAndDequantizeOneScaleImpl<CPUDevice, T>::Compute(
        d, input, signed_input, num_bits, range_given, input_min_tensor,
        input_max_tensor, round_mode, out);
  }
};
}  // namespace functor

#define REGISTER_CPU_KERNEL(T)                                                 \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV2")                      \
                              .Device(DEVICE_CPU)                              \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV2Op<CPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV3")                      \
                              .Device(DEVICE_CPU)                              \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV3Op<CPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("QuantizeAndDequantize").Device(DEVICE_CPU).TypeConstraint<T>("T"), \
      QuantizeAndDequantizeOp<CPUDevice, T>);
TF_CALL_float(REGISTER_CPU_KERNEL);
TF_CALL_double(REGISTER_CPU_KERNEL);
#undef REGISTER_CPU_KERNEL

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define REGISTER_GPU_KERNEL(T)                                                 \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV2")                      \
                              .Device(DEVICE_GPU)                              \
                              .HostMemory("input_max")                         \
                              .HostMemory("input_min")                         \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV2Op<GPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV3")                      \
                              .Device(DEVICE_GPU)                              \
                              .HostMemory("input_max")                         \
                              .HostMemory("input_min")                         \
                              .HostMemory("num_bits")                          \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV3Op<GPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("QuantizeAndDequantize").Device(DEVICE_GPU).TypeConstraint<T>("T"), \
      QuantizeAndDequantizeOp<GPUDevice, T>);
TF_CALL_float(REGISTER_GPU_KERNEL);
TF_CALL_double(REGISTER_GPU_KERNEL);
#undef REGISTER_GPU_KERNEL
#endif
}  // namespace tensorflow
<commit_msg>Added comment to endif<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

#define EIGEN_USE_THREADS

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define EIGEN_USE_GPU
#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM

#include "tensorflow/core/kernels/quantize_and_dequantize_op.h"

#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/framework/type_traits.h"
#include "tensorflow/core/framework/types.h"
#include "tensorflow/core/lib/core/errors.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;

// Simulate quantization precision loss in a float tensor by:
// 1. Quantize the tensor to fixed point numbers, which should match the target
//    quantization method when it is used in inference.
// 2. Dequantize it back to floating point numbers for the following ops, most
//    likely matmul.
template <typename Device, typename T>
class QuantizeAndDequantizeV2Op : public OpKernel {
 public:
  explicit QuantizeAndDequantizeV2Op(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("num_bits", &num_bits_));
    OP_REQUIRES(ctx, num_bits_ > 0 && num_bits_ < (signed_input_ ? 62 : 63),
                errors::InvalidArgument("num_bits is out of range: ", num_bits_,
                                        " with signed_input_ ", signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));

    string round_mode_string;
    OP_REQUIRES_OK(ctx, ctx->GetAttr("round_mode", &round_mode_string));
    OP_REQUIRES(
        ctx,
        (round_mode_string == "HALF_UP" || round_mode_string == "HALF_TO_EVEN"),
        errors::InvalidArgument("Round mode string must be "
                                "'HALF_UP' or "
                                "'HALF_TO_EVEN', is '" +
                                round_mode_string + "'"));
    if (round_mode_string == "HALF_UP") {
      round_mode_ = ROUND_HALF_UP;
    } else if (round_mode_string == "HALF_TO_EVEN") {
      round_mode_ = ROUND_HALF_TO_EVEN;
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    Tensor input_min_tensor;
    Tensor input_max_tensor;
    if (range_given_) {
      input_min_tensor = ctx->input(1);
      input_max_tensor = ctx->input(2);
      auto min_val = input_min_tensor.scalar<T>()();
      auto max_val = input_max_tensor.scalar<T>()();
      OP_REQUIRES(ctx, min_val <= max_val,
                  errors::InvalidArgument("Invalid range: input_min ", min_val,
                                          " > input_max ", max_val));
    } else {
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_min_tensor));
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_max_tensor));
    }

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> f;
    f(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_, num_bits_,
      range_given_, &input_min_tensor, &input_max_tensor, round_mode_,
      output->flat<T>());
  }

 private:
  bool signed_input_;
  int num_bits_;
  bool range_given_;
  QuantizerRoundMode round_mode_;
};

// Simulate quantization precision loss in a float tensor by:
// 1. Quantize the tensor to fixed point numbers, which should match the target
//    quantization method when it is used in inference.
// 2. Dequantize it back to floating point numbers for the following ops, most
//    likely matmul.
// Almost identical to QuantizeAndDequantizeV2Op, except that num_bits is a
// tensor.
template <typename Device, typename T>
class QuantizeAndDequantizeV3Op : public OpKernel {
 public:
  explicit QuantizeAndDequantizeV3Op(OpKernelConstruction* ctx)
      : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    Tensor num_bits_tensor;
    num_bits_tensor = ctx->input(3);
    int num_bits_val = num_bits_tensor.scalar<int32>()();

    OP_REQUIRES(
        ctx, num_bits_val > 0 && num_bits_val < (signed_input_ ? 62 : 63),
        errors::InvalidArgument("num_bits is out of range: ", num_bits_val,
                                " with signed_input_ ", signed_input_));

    Tensor input_min_tensor;
    Tensor input_max_tensor;
    if (range_given_) {
      input_min_tensor = ctx->input(1);
      input_max_tensor = ctx->input(2);
      auto min_val = input_min_tensor.scalar<T>()();
      auto max_val = input_max_tensor.scalar<T>()();
      OP_REQUIRES(ctx, min_val <= max_val,
                  errors::InvalidArgument("Invalid range: input_min ", min_val,
                                          " > input_max ", max_val));
    } else {
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_min_tensor));
      OP_REQUIRES_OK(ctx, ctx->allocate_temp(DataTypeToEnum<T>::value,
                                             TensorShape(), &input_max_tensor));
    }

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> f;
    f(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_, num_bits_val,
      range_given_, &input_min_tensor, &input_max_tensor, ROUND_HALF_TO_EVEN,
      output->flat<T>());
  }

 private:
  bool signed_input_;
  bool range_given_;
};

// DEPRECATED: Use QuantizeAndDequantizeV2Op.
template <typename Device, typename T>
class QuantizeAndDequantizeOp : public OpKernel {
 public:
  explicit QuantizeAndDequantizeOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
    OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("num_bits", &num_bits_));
    OP_REQUIRES(ctx, num_bits_ > 0 && num_bits_ < (signed_input_ ? 62 : 63),
                errors::InvalidArgument("num_bits is out of range: ", num_bits_,
                                        " with signed_input_ ", signed_input_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("input_min", &input_min_));
    OP_REQUIRES_OK(ctx, ctx->GetAttr("input_max", &input_max_));
    if (range_given_) {
      OP_REQUIRES(
          ctx, input_min_ <= input_max_,
          errors::InvalidArgument("Invalid range: input_min ", input_min_,
                                  " > input_max ", input_max_));
    }
  }

  void Compute(OpKernelContext* ctx) override {
    const Tensor& input = ctx->input(0);

    Tensor* output = nullptr;
    OP_REQUIRES_OK(ctx, ctx->allocate_output(0, input.shape(), &output));

    // One global scale.
    Tensor input_min_tensor(DataTypeToEnum<T>::value, TensorShape());
    Tensor input_max_tensor(DataTypeToEnum<T>::value, TensorShape());
    // Initialize the tensors with the values in the Attrs.
    input_min_tensor.template scalar<T>()() = static_cast<T>(input_min_);
    input_max_tensor.template scalar<T>()() = static_cast<T>(input_max_);

    functor::QuantizeAndDequantizeOneScaleFunctor<Device, T> functor;
    functor(ctx->eigen_device<Device>(), input.flat<T>(), signed_input_,
            num_bits_, range_given_, &input_min_tensor, &input_max_tensor,
            ROUND_HALF_TO_EVEN, output->flat<T>());
  }

 private:
  bool signed_input_;
  int num_bits_;
  bool range_given_;
  float input_min_;
  float input_max_;
};

// Specialization for CPUDevice.
namespace functor {
template <typename T>
struct QuantizeAndDequantizeOneScaleFunctor<CPUDevice, T> {
  void operator()(const CPUDevice& d, typename TTypes<T>::ConstVec input,
                  const bool signed_input, const int num_bits,
                  const bool range_given, Tensor* input_min_tensor,
                  Tensor* input_max_tensor, QuantizerRoundMode round_mode,
                  typename TTypes<T>::Vec out) {
    QuantizeAndDequantizeOneScaleImpl<CPUDevice, T>::Compute(
        d, input, signed_input, num_bits, range_given, input_min_tensor,
        input_max_tensor, round_mode, out);
  }
};
}  // namespace functor

#define REGISTER_CPU_KERNEL(T)                                                 \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV2")                      \
                              .Device(DEVICE_CPU)                              \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV2Op<CPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV3")                      \
                              .Device(DEVICE_CPU)                              \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV3Op<CPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("QuantizeAndDequantize").Device(DEVICE_CPU).TypeConstraint<T>("T"), \
      QuantizeAndDequantizeOp<CPUDevice, T>);
TF_CALL_float(REGISTER_CPU_KERNEL);
TF_CALL_double(REGISTER_CPU_KERNEL);
#undef REGISTER_CPU_KERNEL

#if GOOGLE_CUDA || TENSORFLOW_USE_ROCM
#define REGISTER_GPU_KERNEL(T)                                                 \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV2")                      \
                              .Device(DEVICE_GPU)                              \
                              .HostMemory("input_max")                         \
                              .HostMemory("input_min")                         \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV2Op<GPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(Name("QuantizeAndDequantizeV3")                      \
                              .Device(DEVICE_GPU)                              \
                              .HostMemory("input_max")                         \
                              .HostMemory("input_min")                         \
                              .HostMemory("num_bits")                          \
                              .TypeConstraint<T>("T"),                         \
                          QuantizeAndDequantizeV3Op<GPUDevice, T>);            \
  REGISTER_KERNEL_BUILDER(                                                     \
      Name("QuantizeAndDequantize").Device(DEVICE_GPU).TypeConstraint<T>("T"), \
      QuantizeAndDequantizeOp<GPUDevice, T>);
TF_CALL_float(REGISTER_GPU_KERNEL);
TF_CALL_double(REGISTER_GPU_KERNEL);
#undef REGISTER_GPU_KERNEL
#endif  // GOOGLE_CUDA || TENSORFLOW_USE_ROCM
}  // namespace tensorflow
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <memory>

using namespace std;

static void test_unique() {
    unique_ptr<string> films[5] = {
        unique_ptr<string> (new string("Fowl Balls")),
        unique_ptr<string> (new string("Duck Walks")),
        unique_ptr<string> (new string("Chicken Runs")),
        unique_ptr<string> (new string("Turkey  Errors")),
        unique_ptr<string> (new string("Goose Eggs"))
    };

    cout << "The nominees for best avian baseball file are\n";
    for (int i = 0; i < 5; i++) {
        cout << *films[i] << endl;
    }
    unique_ptr<string> pwin = std::move(films[2]);

    cout << "The winner is " << *pwin << endl;
}

static void test_shared() {
    shared_ptr<string> films[5] = {
        shared_ptr<string> (new string("Fowl Balls")),
        shared_ptr<string> (new string("Duck Walks")),
        shared_ptr<string> (new string("Chicken Runs")),
        shared_ptr<string> (new string("Turkey  Errors")),
        shared_ptr<string> (new string("Goose Eggs"))
    };

    shared_ptr<string> pwin = films[2];
    cout << "The nominees for best avian baseball file are\n";
    for (int i = 0; i < 5; i++) {
        cout << *films[i] << endl;
    }

    cout << "The winner is " << *pwin << endl;
}

class A : public std::enable_shared_from_this<A> {
public:
    A() { cout << "A::A() constructor" << endl; }
    ~A() { cout << "A::~A() destructor" << endl; }

    std::shared_ptr<A> GetSelf() {
        return shared_from_this();
    }
};

int main() {
    test_unique();
    test_shared();

    std::shared_ptr<A> pA(new A);
    std::shared_ptr<A> pB = pA->GetSelf();
    std::shared_ptr<A> pC = std::make_shared<A>();

    return 0;
}

<commit_msg>modify on languages/program_on_cpp/In_Depth_C++_11/chapter4-smartpointer/shared_ptr.cpp<commit_after>#include <iostream>
#include <string>
#include <memory>

using namespace std;

static void test_unique() {
    unique_ptr<string> films[5] = {
        unique_ptr<string> (new string("Fowl Balls")),
        unique_ptr<string> (new string("Duck Walks")),
        unique_ptr<string> (new string("Chicken Runs")),
        unique_ptr<string> (new string("Turkey  Errors")),
        unique_ptr<string> (new string("Goose Eggs"))
    };

    cout << "The nominees for best avian baseball file are\n";
    for (int i = 0; i < 5; i++) {
        cout << *films[i] << endl;
    }
    unique_ptr<string> pwin = std::move(films[2]);

    cout << "The winner is " << *pwin << endl;
}

static void test_shared() {
    shared_ptr<string> films[5] = {
        shared_ptr<string> (new string("Fowl Balls")),
        shared_ptr<string> (new string("Duck Walks")),
        shared_ptr<string> (new string("Chicken Runs")),
        shared_ptr<string> (new string("Turkey  Errors")),
        shared_ptr<string> (new string("Goose Eggs"))
    };

    shared_ptr<string> pwin = films[2];
    cout << "The nominees for best avian baseball file are\n";
    for (int i = 0; i < 5; i++) {
        cout << *films[i] << endl;
    }

    cout << "The winner is " << *pwin << endl;
}

class A : public std::enable_shared_from_this<A> {
public:
    A() { cout << "A::A() constructor" << endl; }
    ~A() { cout << "A::~A() destructor" << endl; }

    std::shared_ptr<A> GetSelf() {
        return shared_from_this();
    }
};

void test_reset() {
    int *p = new int(1);
    std::shared_ptr<int> pInt = nullptr;
    pInt.reset(p);

    printf("i = %d\n", *pInt);
}

int main() {
    test_unique();
    test_shared();

    std::shared_ptr<A> pA(new A);
    std::shared_ptr<A> pB = pA->GetSelf();
    std::shared_ptr<A> pC = std::make_shared<A>();

    test_reset();

    return 0;
}

<|endoftext|>


<commit_before>#include "tiramisu/tiramisu.h"

// This code is the Tiramisu implementation of the following Matlab code
// https://www.mathworks.com/examples/computer-vision/community/35625-lucas-kanade-method-example-2?s_tid=examples_p1_BOTH

using namespace tiramisu;

int main(int argc, char* argv[])
{
    // Declare the function name
    tiramisu::init("optical_flow_tiramisu");

    // TODO: input should be a gray image.
    // TODO: check data types.
    // TODO: isolate ludcmp and compare it separately.
    // TODO: compare correctness (partial results) to Matlab.
    // TODO: compare results and performance to OpenCV (one pyramid).

    // Declare input sizes
    // TODO: "input" dimension sizes should be expressions not variables.
    input SIZES("SIZES", {var("S", 0, 2)}, p_int32);

    constant N0("N0", SIZES(0));
    constant N1("N1", SIZES(1));
    constant NC("NC", 20); // Number of corners
    constant w("w", 10); // Window size

    // Loop iterators
    var x("x", 0, N1), y("y", 0, N0), k("k", 0, NC);

    // input images
    input im1("im1", {y, x}, p_uint8);
    input im2("im2", {y, x}, p_uint8);
    // Corners
    input C1("C1", {k}, p_int32);
    input C2("C2", {k}, p_int32);

    // First convolution (partial on x)
    expr e1 = cast(p_uint8, (cast(p_float32,	im1(y,     x) - im1(y,     x + 1) +
						im1(y + 1, x) - im1(y + 1, x + 1))));
    computation Ix_m("Ix_m", {y, x}, e1);

    // Second convolution  (partial on y)
    expr e2 = cast(p_uint8, (cast(p_float32,    im1(y,     x)     + im1(y,     x + 1)
					      - im1(y + 1, x + 1) - im1(y + 1, x    ))));
    computation Iy_m("Iy_m", {y, x}, e2);

    // Third convolution
    expr e3 = cast(p_uint8, (cast(p_float32,    im1(y,     x)  + im1(y,     x + 1)
					      + im1(y + 1, x)  + im1(y + 1, x + 1))));
    expr e4 = cast(p_uint8, (cast(p_float32, (- im2(y,     x)) - im2(y,     x + 1)
					      - im2(y + 1, x)  - im2(y + 1, x + 1))));
    computation It_m("It_m", {y, x}, e3 + e4);

    // Second part of the algorithm
    // Compute "u" and "v" for each corner "k"
    computation i({k}, C2(k));
    computation j({k}, C1(k));

    // Ix = Ix_m(i-w:i+w, j-w:j+w);
    // Iy = Iy_m(i-w:i+w, j-w:j+w);
    // It = It_m(i-w:i+w, j-w:j+w);
    // Ix = Ix(:); % flatten the IX 2D array into a vector
    // Iy = Iy(:);
    // A = [Ix Iy];
    // b = -It(:); % get b here
    var x1("x1", 0, 2*w);
    var y1("y1", 0, 2*w);
    computation        A("A",        {k, y1, x1},   Ix_m(i(0)+y1-w, j(0)+x1-w));  //TODO: use i(k) and j(k) instead of i(0) and j(0)
    computation A_right("A_right",   {k, y1, x1},   Iy_m(i(0)+y1-w, j(0)+x1-w));  //i(k), j(k)
    computation        b("b",        {k, y1, x1}, (-It_m(i(0)+y1-w, j(0)+x1-w))); //i(k), j(k)

    // Compute pinv(A):
    //	    tA = transpose(A)
    //	    mul1 = tA * A
    //	    X = inv(mul1)
    //	    pinv(A) = X * tA
    var x2("x2", 0, 4*w);
    var y2("y2", 0, 4*w);
    var l1("l1", 0, 2*w);
    computation tA("tA", {k, x2, y1}, A(k, y1, x2));

    computation mul1("mul1", {k, x2, y2}, expr((uint8_t) 0));
    computation mul1_update("mul1_update", {k, x2, y2, l1}, mul1(k, x2, y2) + tA(k, x2, l1) * A(k, l1, y2));

    // Compute the inverse of mul1 using LU decomposition.
    // We use the following reference implementation (lines 95 to 126)
    // https://github.com/Meinersbur/polybench/blob/master/polybench-code/linear-algebra/solvers/ludcmp/ludcmp.c
    //	    1)- Compute the LU decomposition of mul1: LU = mul1
    //	    2)- Use LU to compute X, the inverse of mul1 by solving the following
    //	    system:
    //		    LU*X=I
    //	    where I is the identity matrix.
    var i1("i1", 0, 4*w);
    var j1("j1", 0, i1);
    var l2("l2", 0, j1);

    // LU decomposition of A
    computation        w1("w1",        {k, i1, j1},     mul1(k, i1, j1));
    computation w1_update("w1_update", {k, i1, j1, l2},   w1(k, i1, j1) - mul1(k, i1, l2)*mul1(k, l2, j1));
    computation      temp("temp",      {k, i1, j1},       w1(k, i1, j1)/mul1(k, j1, j1));

    var j2("j2", i1, 4*w);
    var l3("l3",  0,  i1);

    computation        w2("w2",        {k, i1, j2},     temp(k, i1, j2));
    computation w2_update("w2_update", {k, i1, j2, l3}, w2(k, i1, j2) - temp(k, i1, l3)*temp(k, l3, j2));
    computation        LU("LU",        {k, i1, j2},     w2(k, i1, j2));

    // Finding the inverse of A.
    // The inverse will be stored in X.
    var r("r", 0, 4*w);
    var r2("r2", r, r+1);
    computation     Y("Y", {k, r, i1}, p_uint8);
    computation     bp("bp", {k, r, i1}, expr((uint8_t) 0));
    computation     bp_update("bp_update", {k, r, r2}, expr((uint8_t) 1));
    computation     w3("w3", {k, r, i1}, bp(k, r, i1));
    computation     w3_update("w3_update", {k, r, i1, j1}, w3(k, r, i1) - LU(k, i1, j1)*Y(k, r, j1));
    Y.set_expression(w3(k, r, i1));

    // TODO: support reverse order loops.
    var j3("j3", i1+1, 4*w);
    computation     X("X", {k, r, i1}, p_uint8);
    computation     w4("w4", {k, r, i1}, Y(k, r, 4-w-1-i1));
    computation     w4_update("w4_update", {k, r, i1, j3}, w4(k, r, i1) - LU(k, 4-w-1-i1, j3)*X(k, r, j3));
    X.set_expression(w4(k, r, i1)/LU(k, 4-w-1-i1, 4-w-1-i1));

    // Computing pinv(A)=X*tA
    var j4("j4", 0, 4*w);
    computation    pinvA("pinvA", {k, i1, y1}, expr((uint8_t) 0));
    computation    pinvA_update("pinvA_update", {k, i1, y1, j4}, pinvA(k, i1, y1) + X(k, i1, j4)*tA(k, j4, y1));

    // Compute nu = pinv(A)*b
    computation nu("nu", {k, i1, x1}, expr((uint8_t) 0));
    computation nu_update("nu_update", {k, i1, x1, y1}, nu(k, i1, x1) + pinvA(k, i1, y1)*b(k, y1, x1));

    // Results
    // u(k) = nu(0)
    // v(k) = nu(1)

    Ix_m.then(Iy_m, x)
	.then(It_m, x)
	.then(i, computation::root)
	.then(j, k)
	.then(A, y1)
	.then(A_right, y1)
	.then(b, y1)
	.then(tA, computation::root)
	.then(mul1, computation::root)
	.then(mul1_update, y2)
	.then(w1, computation::root)
	.then(w1_update, j1)
	.then(temp, j1)
	.then(w2, computation::root)
	.then(w2_update, j2)
	.then(LU, j2)
	.then(bp, computation::root)
	.then(bp_update, r)
	.then(w3, r)
	.then(w3_update, i1)
	.then(Y, i1)
	.then(w4, computation::root)
	.then(w4_update, i1)
	.then(X, i1)
	.then(pinvA, computation::root)
	.then(pinvA_update, y1)
	.then(nu, computation::root)
	.then(nu_update, x1);

    // Buffer allocation and mapping computations to buffers
    buffer b_SIZES("b_SIZES", {2}, p_int32, a_input);
    buffer b_im1("b_im1", {N0, N1}, p_uint8, a_input);
    buffer b_im2("b_im2", {N0, N1}, p_uint8, a_input);
    buffer b_Ix_m("b_Ix_m", {N0, N1}, p_float32, a_output);
    buffer b_Iy_m("b_Iy_m", {N0, N1}, p_float32, a_output);
    buffer b_It_m("b_It_m", {N0, N1}, p_float32, a_output);
    buffer b_C1("b_C1", {NC}, p_int32, a_input);
    buffer b_C2("b_C2", {NC}, p_int32, a_input);
    buffer b_i("b_i", {1}, p_int32, a_temporary);
    buffer b_j("b_j", {1}, p_int32, a_temporary);
    buffer b_A("b_A", {2*w, 4*w}, p_float32, a_temporary);
    buffer b_b("b_b", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_tA("b_tA", {4*w, 2*w}, p_float32, a_temporary);
    buffer b_mul("b_mul", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_w1("b_w1", {1}, p_float32, a_temporary);
    buffer b_temp("b_temp", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_w2("b_w2", {1}, p_float32, a_temporary);
    buffer b_LU("b_LU", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_y("b_y", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_bp("b_bp", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_w3("b_w3", {1}, p_float32, a_temporary);
    buffer b_x("b_x", {2*w, 2*w}, p_float32, a_temporary);
    buffer b_w4("b_w4", {1}, p_float32, a_temporary);
    buffer b_pinvA("b_pinvA", {4*w, 2*w}, p_float32, a_temporary);
    buffer b_nu("b_nu", {4*w, 2*w}, p_float32, a_temporary);

    SIZES.store_in(&b_SIZES);
    im1.store_in(&b_im1);
    im2.store_in(&b_im2);
    Ix_m.store_in(&b_Ix_m);
    Iy_m.store_in(&b_Iy_m);
    It_m.store_in(&b_It_m);
    C1.store_in(&b_C1);
    C2.store_in(&b_C2);
    i.store_in(&b_i, {0});
    j.store_in(&b_j, {0});
    A.store_in(&b_A, {x1, y1});
    A_right.store_in(&b_A, {x1+2*10, y1});  //2*w
    b.store_in(&b_b, {x1, y1});
    tA.store_in(&b_tA, {x2, y1});
    mul1.store_in(&b_mul, {x2, y2});
    mul1_update.store_in(&b_mul, {x2, y2});
    w1.store_in(&b_w1, {0});
    w1_update.store_in(&b_w1, {0});
    temp.store_in(&b_temp, {i1, j1});
    w2.store_in(&b_w2, {0});
    w2_update.store_in(&b_w2, {0});
    LU.store_in(&b_LU, {i1, j2});
    Y.store_in(&b_y, {r, i1});
    bp.store_in(&b_bp, {r, i1});
    bp_update.store_in(&b_bp, {r, r2});
    w3.store_in(&b_w3, {0});
    w3_update.store_in(&b_w3, {0});
    X.store_in(&b_x, {r, i1});
    w4.store_in(&b_w4, {0});
    w4_update.store_in(&b_w4, {0});
    pinvA.store_in(&b_pinvA, {i1, y1});
    pinvA_update.store_in(&b_pinvA, {i1, y1});
    nu.store_in(&b_nu, {i1, x1});
    nu_update.store_in(&b_nu, {i1, x1});

    tiramisu::codegen({&b_SIZES, &b_im1, &b_im2, &b_Ix_m, &b_Iy_m, &b_It_m, &b_C1, &b_C2}, "build/generated_fct_optical_flow.o");

    return 0;
}
<commit_msg>Update optical flow<commit_after>#include "tiramisu/tiramisu.h"

// This code is the Tiramisu implementation of the following Matlab code
// https://www.mathworks.com/examples/computer-vision/community/35625-lucas-kanade-method-example-2?s_tid=examples_p1_BOTH

using namespace tiramisu;

int main(int argc, char* argv[])
{
    // Declare the function name
    tiramisu::init("optical_flow_tiramisu");

    // TODO: input should be a gray image.
    // TODO: check data types.
    // TODO: isolate ludcmp and compare it separately.
    // TODO: compare correctness (partial results) to Matlab.
    // TODO: compare results and performance to OpenCV (one pyramid).

    // Declare input sizes
    // TODO: "input" dimension sizes should be expressions not variables.
    input SIZES("SIZES", {var("S", 0, 2)}, p_int32);

    constant N0("N0", SIZES(0));
    constant N1("N1", SIZES(1));
    constant NC("NC", 20); // Number of corners

    // Window size
    #define w 10

    // Loop iterators
    var x("x", 0, N1), y("y", 0, N0), k("k", 0, NC);

    // input images
    input im1("im1", {y, x}, p_uint8);
    input im2("im2", {y, x}, p_uint8);
    // Corners
    input C1("C1", {k}, p_int32);
    input C2("C2", {k}, p_int32);

    // First convolution (partial on x)
    expr e1 = (cast(p_float32,	im1(y,     x) - im1(y,     x + 1) +
				im1(y + 1, x) - im1(y + 1, x + 1)));
    computation Ix_m("Ix_m", {y, x}, e1);

    // Second convolution  (partial on y)
    expr e2 = (cast(p_float32,    im1(y,     x)     + im1(y,     x + 1)
			        - im1(y + 1, x + 1) - im1(y + 1, x    )));
    computation Iy_m("Iy_m", {y, x}, e2);

    // Third convolution
    expr e3 = (cast(p_float32,    im1(y,     x)  + im1(y,     x + 1)
				+ im1(y + 1, x)  + im1(y + 1, x + 1)));
    expr e4 = (cast(p_float32, (- im2(y,     x)) - im2(y,     x + 1)
			        - im2(y + 1, x)  - im2(y + 1, x + 1)));
    computation It_m("It_m", {y, x}, e3 + e4);

    // Second part of the algorithm
    // Compute "u" and "v" for each corner "k"
    computation i("i", {k}, C2(k));
    computation j("j", {k}, C1(k));

    // Ix = Ix_m(i-w:i+w, j-w:j+w);
    // Iy = Iy_m(i-w:i+w, j-w:j+w);
    // It = It_m(i-w:i+w, j-w:j+w);
    // Ix = Ix(:); % flatten the IX 2D array into a vector
    // Iy = Iy(:);
    // A = [Ix Iy];
    // b = -It(:); % get b here
    var xp("xp", 0, 2*w);
    var yp("yp", 0, 2*w);
    computation        A1("A1",        {k, yp, xp},   Ix_m(i(0)+yp-w, j(0)+xp-w));  //TODO: use i(k) and j(k) instead of i(0) and j(0)
    computation  A1_right("A1_right",  {k, yp, xp},   Iy_m(i(0)+yp-w, j(0)+xp-w));  //i(k), j(k)
    computation        b1("b1",        {k, yp, xp}, (-It_m(i(0)+yp-w, j(0)+xp-w))); //i(k), j(k)

    // Reshape A1 to A
    var x1("x1", 0, 2);
    var y1("y1", 0, 4*w*w);
    input        A("A",        {k, y1, x1}, p_float32); // Use A to reshape A1 and A1_right
    input        b("b",        {k, y1}, p_float32);     // Use b to reshape b1

    // Compute pinv(A):
    // 1)    tA = transpose(A)
    // 2)    tAA = tA * A
    // 3)    X = inv(tAA)
    // 4)    pinv(A) = X * tA

    // 1) Computing tA = transpose(A)
    computation tA("tA", {k, x1, y1}, A(k, y1, x1));

    // 2) Computing tAA = tA * A
    var y2("y2", 0, 2);
    var l1("l1", 0, 4*w*w);
    computation tAA("tAA", {k, x1, y2}, expr((float) 0));
    computation tAA_update("tAA_update", {k, x1, y2, l1}, tAA(k, x1, y2) + (tA(k, x1, l1) * A(k, l1, y2)));

    // 3) Computing X = inv(tAA)
    computation determinant("determinant", {k}, (tAA(k,0,0)*tAA(k,1,1)) - (tAA(k,0,1)*tAA(k,1,0)));
    computation tAAp_00("tAAp_00", {k},  tAA(k,1,1)/determinant(k));
    computation tAAp_11("tAAp_11", {k},  tAA(k,0,0)/determinant(k));
    computation tAAp_01("tAAp_01", {k}, -tAA(k,0,1)/determinant(k));
    computation tAAp_10("tAAp_10", {k}, -tAA(k,1,0)/determinant(k));
    input X("X", {k, x1, y2}, p_float32);

    // 4) Computing pinv(A) = X*tA
    var l2("l2", 0, 2);
    computation    pinvA("pinvA", {k, x1, y1}, expr((float) 0));
    computation    pinvA_update("pinvA_update", {k, x1, y1, l2}, pinvA(k, x1, y1) + X(k, x1, l2)*tA(k, l2, y1));

    // Compute nu = pinv(A)*b
    computation nu("nu", {k, x1}, expr((float) 0));
    computation nu_update("nu_update", {k, x1, y1}, nu(k, x1) + pinvA(k, x1, y1)*b(k, y1));

    // Results
    // u(k) = nu(0)
    // v(k) = nu(1)

    Ix_m.then(Iy_m, x)
	.then(It_m, x)
	.then(i, computation::root)
	.then(j, k)
	.then(A1, k)
	.then(A1_right, k)
	.then(b1, k)
	.then(tA, k)
	.then(tAA, k)
	.then(tAA_update, y2)
	.then(determinant, k)
	.then(tAAp_00, k)
	.then(tAAp_11, k)
	.then(tAAp_01, k)
	.then(tAAp_10, k)
	.then(X, k)
	.then(pinvA, k)
	.then(pinvA_update, y1)
	.then(nu, k)
	.then(nu_update, x1);

    // Buffer allocation and mapping computations to buffers
    buffer b_SIZES("b_SIZES", {2}, p_int32, a_input);
    buffer b_im1("b_im1", {N0, N1}, p_uint8, a_input);
    buffer b_im2("b_im2", {N0, N1}, p_uint8, a_input);
    buffer b_Ix_m("b_Ix_m", {N0, N1}, p_float32, a_output);
    buffer b_Iy_m("b_Iy_m", {N0, N1}, p_float32, a_output);
    buffer b_It_m("b_It_m", {N0, N1}, p_float32, a_output);
    buffer b_C1("b_C1", {NC}, p_int32, a_input);
    buffer b_C2("b_C2", {NC}, p_int32, a_input);
    buffer b_i("b_i", {1}, p_int32, a_temporary);
    buffer b_j("b_j", {1}, p_int32, a_temporary);
    buffer b_A("b_A", {4*w*w, 2}, p_float32, a_temporary);
    buffer b_b("b_b", {4*w*w}, p_float32, a_temporary);
    buffer b_tA("b_tA", {2, 4*w*w}, p_float32, a_temporary);
    buffer b_tAA("b_tAA", {2, 2}, p_float32, a_temporary);
    buffer b_determinant("b_determinant", {1}, p_float32, a_temporary);
    buffer b_X("b_X", {2, 2}, p_float32, a_temporary);
    buffer b_pinvA("b_pinvA", {2, 4*w*w}, p_float32, a_temporary);
    buffer b_nu("b_nu", {2}, p_float32, a_temporary);

    SIZES.store_in(&b_SIZES);
    im1.store_in(&b_im1);
    im2.store_in(&b_im2);
    Ix_m.store_in(&b_Ix_m);
    Iy_m.store_in(&b_Iy_m);
    It_m.store_in(&b_It_m);
    C1.store_in(&b_C1);
    C2.store_in(&b_C2);
    i.store_in(&b_i, {0});
    j.store_in(&b_j, {0});
    A1.store_in(&b_A, {xp+yp*2*w, 0});
    A1_right.store_in(&b_A, {xp+yp*2*w, 1});
    b1.store_in(&b_b, {xp+yp*2*w});
    A.store_in(&b_A, {y1, x1});
    b.store_in(&b_b, {y1});
    tA.store_in(&b_tA, {x1, y1});
    tAA.store_in(&b_tAA, {x1, y2});
    tAA_update.store_in(&b_tAA, {x1, y2});
    determinant.store_in(&b_determinant, {0});
    tAAp_00.store_in(&b_X, {0, 0});
    tAAp_01.store_in(&b_X, {0, 1});
    tAAp_10.store_in(&b_X, {1, 0});
    tAAp_11.store_in(&b_X, {1, 1});
    X.store_in(&b_X, {x1, y2});
    pinvA.store_in(&b_pinvA, {x1, y1});
    pinvA_update.store_in(&b_pinvA, {x1, y1});
    nu.store_in(&b_nu, {x1});
    nu_update.store_in(&b_nu, {x1});

    tiramisu::codegen({&b_SIZES, &b_im1, &b_im2, &b_Ix_m, &b_Iy_m, &b_It_m, &b_C1, &b_C2}, "build/generated_fct_optical_flow.o");

    return 0;
}
<|endoftext|>


<commit_before>//
// Bareflank Hypervisor
//
// Copyright (C) 2015 Assured Information Security, Inc.
// Author: Rian Quinn        <quinnr@ainfosec.com>
// Author: Brendan Kerrigan  <kerriganb@ainfosec.com>
// Author: Connor Davis      <davisc@ainfosec.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#include <test.h>
#include <vmcs/vmcs_intel_x64.h>
#include <memory_manager/memory_manager.h>

static std::map<uint32_t, uint64_t> g_msrs;
static std::map<uint64_t, uint64_t> g_vmcs_fields;

static uint64_t
read_msr(uint32_t msr)
{
    return g_msrs[msr];
}

static void
write_msr(uint32_t msr, uint64_t val)
{
    g_msrs[msr] = val;
}

static bool
vmread(uint64_t field, uint64_t *val)
{
    *val = g_vmcs_fields[field];
    return true;
}

static bool
vmwrite(uint64_t field, uint64_t val)
{
    g_vmcs_fields[field] = val;
    return true;
}

static uint16_t
get_16bit_state()
{
    return 0;
}

static uint32_t
get_32bit_state()
{
    return 0;
}

static uint64_t
get_64bit_state()
{
    return 0;
}

static void
dump()
{
}

static uintptr_t
virt_to_phys_ptr(void *ptr)
{
    (void) ptr;

    return 0x0000000ABCDEF0000;
}

static void
setup_vmcs_x64_state_intrinsics(MockRepository &mocks, vmcs_intel_x64_state *state_in)
{
    // Setup 16 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::es).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gdt_limit).Do(get_16bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::idt_limit).Do(get_16bit_state);

    // Setup 32 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::es_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_limit).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_limit).Do(get_32bit_state);

    mocks.OnCall(state_in, vmcs_intel_x64_state::es_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_access_rights).Do(get_32bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_access_rights).Do(get_32bit_state);

    // Setup 64 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr0).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr3).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr4).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::dr7).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::rflags).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gdt_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::idt_base).Do(get_64bit_state);

    mocks.OnCall(state_in, vmcs_intel_x64_state::es_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_base).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_base).Do(get_64bit_state);

    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_debugctl_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_pat_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_efer_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_perf_global_ctrl_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_cs_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_esp_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_eip_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_fs_base_msr).Do(get_64bit_state);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_gs_base_msr).Do(get_64bit_state);

    mocks.OnCall(state_in, vmcs_intel_x64_state::dump).Do(dump);
}

static void
setup_vmcs_intrinsics(MockRepository &mocks, memory_manager *mm, intrinsics_intel_x64 *in)
{
    // Emulate the memory manager
    mocks.OnCallFunc(memory_manager::instance).Return(mm);
    mocks.OnCallOverload(mm, (uintptr_t(memory_manager::*)(void *))&memory_manager::virt_to_phys).Do(virt_to_phys_ptr);

    // Setup MSR and vmread returns to mock a successful vmcs_intel_x64::filter_unsupported
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_BASIC_MSR).Return(0x7fffFFFF);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_PINBASED_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_PROCBASED_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_PROCBASED_CTLS2_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_EXIT_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_ENTRY_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::vmread).Return(0x5555555555555555);

    mocks.OnCall(in, intrinsics_intel_x64::read_msr).Do(read_msr);
    mocks.OnCall(in, intrinsics_intel_x64::write_msr).Do(write_msr);
    mocks.OnCall(in, intrinsics_intel_x64::vmread).Do(vmread);
    mocks.OnCall(in, intrinsics_intel_x64::vmwrite).Do(vmwrite);

    // Make the default return of the vm* calls true
    mocks.OnCall(in, intrinsics_intel_x64::vmclear).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmptrld).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmwrite).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmlaunch).Return(true);
}

void
vmcs_ut::test_launch_success()
{
    MockRepository mocks;
    auto mm = mocks.Mock<memory_manager>();
    auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks);
    auto host_state = bfn::mock_shared<vmcs_intel_x64_state>(mocks);
    auto guest_state = bfn::mock_shared<vmcs_intel_x64_state>(mocks);

    setup_vmcs_intrinsics(mocks, mm, in.get());
    setup_vmcs_x64_state_intrinsics(mocks, host_state.get());
    setup_vmcs_x64_state_intrinsics(mocks, guest_state.get());

    RUN_UNITTEST_WITH_MOCKS(mocks, [&]
    {
        vmcs_intel_x64 vmcs(in);

        EXPECT_NO_EXCEPTION(vmcs.launch(host_state, guest_state));
    });
}
<commit_msg>Add vmcs_intel_x64_state mocked functions<commit_after>//
// Bareflank Hypervisor
//
// Copyright (C) 2015 Assured Information Security, Inc.
// Author: Rian Quinn        <quinnr@ainfosec.com>
// Author: Brendan Kerrigan  <kerriganb@ainfosec.com>
// Author: Connor Davis      <davisc@ainfosec.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

#include <test.h>
#include <vmcs/vmcs_intel_x64.h>
#include <memory_manager/memory_manager.h>

static std::map<uint32_t, uint64_t> g_msrs;
static std::map<uint64_t, uint64_t> g_vmcs_fields;

static uint64_t
read_msr(uint32_t msr)
{
    return g_msrs[msr];
}

static void
write_msr(uint32_t msr, uint64_t val)
{
    g_msrs[msr] = val;
}

static bool
vmread(uint64_t field, uint64_t *val)
{
    *val = g_vmcs_fields[field];
    return true;
}

static bool
vmwrite(uint64_t field, uint64_t val)
{
    g_vmcs_fields[field] = val;
    return true;
}

static uint16_t es() { return 0; }
static uint16_t cs() { return 0; }
static uint16_t ss() { return 0; }
static uint16_t ds() { return 0; }
static uint16_t fs() { return 0; }
static uint16_t gs() { return 0; }
static uint16_t ldtr() { return 0; }
static uint16_t tr() { return 0; }

static uint64_t cr0() { return 0; }
static uint64_t cr3() { return 0; }
static uint64_t cr4() { return 0; }
static uint64_t dr7() { return 0; }

static uint64_t rflags() { return 0; }

static uint64_t gdt_base() { return 0; }
static uint64_t idt_base() { return 0; }

static uint16_t gdt_limit() { return 0; }
static uint16_t idt_limit() { return 0; }

static uint32_t es_limit() { return 0; }
static uint32_t cs_limit() { return 0; }
static uint32_t ss_limit() { return 0; }
static uint32_t ds_limit() { return 0; }
static uint32_t fs_limit() { return 0; }
static uint32_t gs_limit() { return 0; }
static uint32_t ldtr_limit() { return 0; }
static uint32_t tr_limit() { return 0; }

static uint32_t es_access_rights() { return 0x10000; }
static uint32_t cs_access_rights() { return 0x10000; }
static uint32_t ss_access_rights() { return 0x10000; }
static uint32_t ds_access_rights() { return 0x10000; }
static uint32_t fs_access_rights() { return 0x10000; }
static uint32_t gs_access_rights() { return 0x10000; }
static uint32_t ldtr_access_rights() { return 0x10000; }
static uint32_t tr_access_rights() { return 0x10000; }

static uint64_t es_base() { return 0; }
static uint64_t cs_base() { return 0; }
static uint64_t ss_base() { return 0; }
static uint64_t ds_base() { return 0; }
static uint64_t fs_base() { return 0; }
static uint64_t gs_base() { return 0; }
static uint64_t ldtr_base() { return 0; }
static uint64_t tr_base() { return 0; }

static uint64_t ia32_debugctl_msr() { return 0; }
static uint64_t ia32_pat_msr() { return 0; }
static uint64_t ia32_efer_msr() { return 0; }
static uint64_t ia32_perf_global_ctrl_msr() { return 0; }
static uint64_t ia32_sysenter_cs_msr() { return 0; }
static uint64_t ia32_sysenter_esp_msr() { return 0; }
static uint64_t ia32_sysenter_eip_msr() { return 0; }
static uint64_t ia32_fs_base_msr() { return 0; }
static uint64_t ia32_gs_base_msr() { return 0; }

static void dump() {}

static uintptr_t
virt_to_phys_ptr(void *ptr)
{
    (void) ptr;

    return 0x0000000ABCDEF0000;
}

static void
setup_vmcs_x64_state_intrinsics(MockRepository &mocks, vmcs_intel_x64_state *state_in)
{
    // Setup 16 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::es).Do(es);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs).Do(cs);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss).Do(ss);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds).Do(ds);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs).Do(fs);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs).Do(gs);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr).Do(ldtr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr).Do(tr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gdt_limit).Do(gdt_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::idt_limit).Do(idt_limit);

    // Setup 32 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::es_limit).Do(es_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_limit).Do(cs_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_limit).Do(ss_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_limit).Do(ds_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_limit).Do(ds_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_limit).Do(fs_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_limit).Do(gs_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_limit).Do(ldtr_limit);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_limit).Do(tr_limit);

    mocks.OnCall(state_in, vmcs_intel_x64_state::es_access_rights).Do(es_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_access_rights).Do(cs_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_access_rights).Do(ss_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_access_rights).Do(ds_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_access_rights).Do(ds_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_access_rights).Do(fs_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_access_rights).Do(gs_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_access_rights).Do(ldtr_access_rights);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_access_rights).Do(tr_access_rights);

    // Setup 64 bit state functions
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr0).Do(cr0);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr3).Do(cr3);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cr4).Do(cr4);
    mocks.OnCall(state_in, vmcs_intel_x64_state::dr7).Do(dr7);
    mocks.OnCall(state_in, vmcs_intel_x64_state::rflags).Do(rflags);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gdt_base).Do(gdt_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::idt_base).Do(idt_base);

    mocks.OnCall(state_in, vmcs_intel_x64_state::es_base).Do(es_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::cs_base).Do(cs_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ss_base).Do(ss_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_base).Do(ds_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ds_base).Do(ds_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::fs_base).Do(fs_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::gs_base).Do(gs_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ldtr_base).Do(ldtr_base);
    mocks.OnCall(state_in, vmcs_intel_x64_state::tr_base).Do(tr_base);

    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_debugctl_msr).Do(ia32_debugctl_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_pat_msr).Do(ia32_pat_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_efer_msr).Do(ia32_efer_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_perf_global_ctrl_msr).Do(ia32_perf_global_ctrl_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_cs_msr).Do(ia32_sysenter_cs_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_esp_msr).Do(ia32_sysenter_esp_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_sysenter_eip_msr).Do(ia32_sysenter_eip_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_fs_base_msr).Do(ia32_fs_base_msr);
    mocks.OnCall(state_in, vmcs_intel_x64_state::ia32_gs_base_msr).Do(ia32_gs_base_msr);

    mocks.OnCall(state_in, vmcs_intel_x64_state::dump).Do(dump);
}

static void
setup_vmcs_intrinsics(MockRepository &mocks, memory_manager *mm, intrinsics_intel_x64 *in)
{
    // Emulate the memory manager
    mocks.OnCallFunc(memory_manager::instance).Return(mm);
    mocks.OnCallOverload(mm, (uintptr_t(memory_manager::*)(void *))&memory_manager::virt_to_phys).Do(virt_to_phys_ptr);

    // Setup MSR and vmread returns to mock a successful vmcs_intel_x64::filter_unsupported
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_BASIC_MSR).Return(0x7fffFFFF);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_PINBASED_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_PROCBASED_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_PROCBASED_CTLS2_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_EXIT_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::read_msr).With(IA32_VMX_TRUE_ENTRY_CTLS_MSR).Return(0x55555555aaaaAAAA);
    mocks.OnCall(in, intrinsics_intel_x64::vmread).Return(0x5555555555555555);

    mocks.OnCall(in, intrinsics_intel_x64::read_msr).Do(read_msr);
    mocks.OnCall(in, intrinsics_intel_x64::write_msr).Do(write_msr);
    mocks.OnCall(in, intrinsics_intel_x64::vmread).Do(vmread);
    mocks.OnCall(in, intrinsics_intel_x64::vmwrite).Do(vmwrite);

    // Make the default return of the vm* calls true
    mocks.OnCall(in, intrinsics_intel_x64::vmclear).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmptrld).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmwrite).Return(true);
    mocks.OnCall(in, intrinsics_intel_x64::vmlaunch).Return(true);
}

void
vmcs_ut::test_launch_success()
{
    MockRepository mocks;
    auto mm = mocks.Mock<memory_manager>();
    auto in = bfn::mock_shared<intrinsics_intel_x64>(mocks);
    auto host_state = bfn::mock_shared<vmcs_intel_x64_state>(mocks);
    auto guest_state = bfn::mock_shared<vmcs_intel_x64_state>(mocks);

    setup_vmcs_intrinsics(mocks, mm, in.get());
    setup_vmcs_x64_state_intrinsics(mocks, host_state.get());
    setup_vmcs_x64_state_intrinsics(mocks, guest_state.get());

    RUN_UNITTEST_WITH_MOCKS(mocks, [&]
    {
        vmcs_intel_x64 vmcs(in);

        EXPECT_NO_EXCEPTION(vmcs.launch(host_state, guest_state));
    });
}
<|endoftext|>