<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo 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.
 *****************************************************************************/

/*
 * spiral_reference_line_smoother.cc
 */

#include "modules/planning/reference_line/spiral_reference_line_smoother.h"

#include <algorithm>
#include <iomanip>
#include <utility>

#include "IpIpoptApplication.hpp"
#include "IpSolveStatistics.hpp"
#include "glog/logging.h"

#include "modules/common/time/time.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/curve1d/quintic_spiral_path.h"
#include "modules/planning/reference_line/spiral_problem_interface.h"

namespace apollo {
namespace planning {

using apollo::common::time::Clock;

SpiralReferenceLineSmoother::SpiralReferenceLineSmoother(
    const double max_point_deviation)
    : default_max_point_deviation_(max_point_deviation) {
  CHECK(max_point_deviation >= 0.0);
}

bool SpiralReferenceLineSmoother::Smooth(
    const ReferenceLine& raw_reference_line,
    ReferenceLine* const smoothed_reference_line) {
  const double start_timestamp = Clock::NowInSecond();
  std::vector<double> opt_x;
  std::vector<double> opt_y;
  std::vector<double> opt_theta;
  std::vector<double> opt_kappa;
  std::vector<double> opt_dkappa;
  std::vector<double> opt_s;

  if (anchor_points_.empty()) {
    const double piecewise_length = FLAGS_spiral_smoother_piecewise_length;
    const double length = raw_reference_line.Length();
    ADEBUG << "Length = " << length;
    uint32_t num_of_pieces =
        std::max(1u, static_cast<uint32_t>(length / piecewise_length));

    const double delta_s = length / num_of_pieces;
    double s = 0.0;

    std::vector<Eigen::Vector2d> raw_point2d;
    for (std::uint32_t i = 0; i <= num_of_pieces;
         ++i, s = std::fmin(s + delta_s, length)) {
      ReferencePoint rlp = raw_reference_line.GetReferencePoint(s);
      raw_point2d.emplace_back(rlp.x(), rlp.y());
    }

    Smooth(raw_point2d, &opt_theta, &opt_kappa, &opt_dkappa, &opt_s, &opt_x,
           &opt_y);
  } else {
    std::size_t start_index = 0;
    for (const auto& anchor_point : anchor_points_) {
      if (anchor_point.enforced) {
        start_index++;
      }
    }

    std::vector<Eigen::Vector2d> raw_point2d;
    if (start_index == 0) {
      for (const auto& anchor_point : anchor_points_) {
        raw_point2d.emplace_back(anchor_point.path_point.x(),
                                 anchor_point.path_point.y());
      }
    } else {
      std::vector<double> overhead_s;
      for (std::size_t i = 0; i + 1 < start_index; ++i) {
        const auto& p0 = anchor_points_[i];
        const auto& p1 = anchor_points_[i + 1];
        overhead_s.push_back(p1.path_point.s() - p0.path_point.s());
      }

      std::vector<double> overhead_theta;
      std::vector<double> overhead_kappa;
      std::vector<double> overhead_dkappa;
      std::vector<double> overhead_x;
      std::vector<double> overhead_y;
      for (std::size_t i = 0; i < anchor_points_.size(); ++i) {
        const auto& p = anchor_points_[i];
        if (i + 1 < start_index) {
          overhead_theta.push_back(p.path_point.theta());
          overhead_kappa.push_back(p.path_point.kappa());
          overhead_dkappa.push_back(p.path_point.dkappa());
          overhead_x.push_back(p.path_point.x());
          overhead_y.push_back(p.path_point.y());
        } else {
          raw_point2d.emplace_back(p.path_point.x(), p.path_point.y());
        }
      }

      fixed_start_point_ = true;
      fixed_start_x_ = anchor_points_[start_index - 1].path_point.x();
      fixed_start_y_ = anchor_points_[start_index - 1].path_point.y();
      fixed_start_theta_ = common::math::NormalizeAngle(
          anchor_points_[start_index - 1].path_point.theta());
      fixed_start_kappa_ = anchor_points_[start_index - 1].path_point.kappa();
      fixed_start_dkappa_ = anchor_points_[start_index - 1].path_point.dkappa();

      Smooth(raw_point2d, &opt_theta, &opt_kappa, &opt_dkappa, &opt_s, &opt_x,
             &opt_y);

      opt_theta.insert(opt_theta.begin(), overhead_theta.begin(),
                       overhead_theta.end());
      opt_kappa.insert(opt_kappa.begin(), overhead_kappa.begin(),
                       overhead_kappa.end());
      opt_dkappa.insert(opt_dkappa.begin(), overhead_dkappa.begin(),
                        overhead_dkappa.end());
      opt_s.insert(opt_s.begin(), overhead_s.begin(), overhead_s.end());
      opt_x.insert(opt_x.begin(), overhead_x.begin(), overhead_x.end());
      opt_y.insert(opt_y.begin(), overhead_y.begin(), overhead_y.end());

      std::for_each(opt_x.begin(), opt_x.end(), [this](double& x){
        x += zero_x_;
      });

      std::for_each(opt_y.begin(), opt_y.end(), [this](double& y){
        y += zero_y_;
      });
    }
  }

  std::vector<common::PathPoint> smoothed_point2d =
      Interpolate(opt_theta, opt_kappa, opt_dkappa, opt_s, opt_x, opt_y,
                  FLAGS_spiral_reference_line_resolution);

  std::vector<ReferencePoint> ref_points;
  for (const auto& p : smoothed_point2d) {
    const double heading = p.theta();
    const double kappa = p.kappa();
    const double dkappa = p.dkappa();

    common::SLPoint ref_sl_point;
    if (!raw_reference_line.XYToSL({p.x(), p.y()}, &ref_sl_point)) {
      return false;
    }
    if (ref_sl_point.s() < 0 ||
        ref_sl_point.s() > raw_reference_line.Length()) {
      continue;
    }

    ReferencePoint rlp = raw_reference_line.GetReferencePoint(ref_sl_point.s());
    ref_points.emplace_back(
        ReferencePoint(hdmap::MapPathPoint(common::math::Vec2d(p.x(), p.y()),
                                           heading, rlp.lane_waypoints()),
                       kappa, dkappa, 0.0, 0.0));
  }

  ReferencePoint::RemoveDuplicates(&ref_points);
  if (ref_points.size() < 2) {
    AERROR << "Fail to generate smoothed reference line.";
    return false;
  }
  *smoothed_reference_line = ReferenceLine(ref_points);
  const double end_timestamp = Clock::NowInSecond();
  ADEBUG << "Spiral reference line smoother time: "
         << (end_timestamp - start_timestamp) * 1000 << " ms.";
  return true;
}

bool SpiralReferenceLineSmoother::Smooth(std::vector<Eigen::Vector2d> point2d,
                                         std::vector<double>* ptr_theta,
                                         std::vector<double>* ptr_kappa,
                                         std::vector<double>* ptr_dkappa,
                                         std::vector<double>* ptr_s,
                                         std::vector<double>* ptr_x,
                                         std::vector<double>* ptr_y) const {
  CHECK_GT(point2d.size(), 1);

  SpiralProblemInterface* ptop = new SpiralProblemInterface(point2d);
  ptop->set_default_max_point_deviation(default_max_point_deviation_);
  if (fixed_start_point_) {
    ptop->set_start_point(fixed_start_x_, fixed_start_y_, fixed_start_theta_,
                          fixed_start_kappa_, fixed_start_dkappa_);
  }

  Ipopt::SmartPtr<Ipopt::TNLP> problem = ptop;

  // Create an instance of the IpoptApplication
  Ipopt::SmartPtr<Ipopt::IpoptApplication> app = IpoptApplicationFactory();

  //  app->Options()->SetStringValue("jacobian_approximation",
  //  "finite-difference-values");
  app->Options()->SetStringValue("hessian_approximation", "limited-memory");
  //  app->Options()->SetStringValue("derivative_test", "first-order");
  //  app->Options()->SetNumericValue("derivative_test_perturbation", 1.0e-7);
  //  app->Options()->SetStringValue("derivative_test", "second-order");
  app->Options()->SetIntegerValue("print_level", 0);
  int num_iterations = FLAGS_spiral_smoother_num_iteration;
  app->Options()->SetIntegerValue("max_iter", num_iterations);

  //  app->Options()->SetNumericValue("acceptable_tol", 0.5);
  //  app->Options()->SetNumericValue("acceptable_obj_change_tol", 0.5);
  //  app->Options()->SetNumericValue("constr_viol_tol", 0.01);
  //  app->Options()->SetIntegerValue("acceptable_iter", 10);
  //  app->Options()->SetIntegerValue("print_level", 0);
  //  app->Options()->SetStringValue("fast_step_computation", "yes");

  Ipopt::ApplicationReturnStatus status = app->Initialize();
  if (status != Ipopt::Solve_Succeeded) {
    ADEBUG << "*** Error during initialization!";
    return static_cast<int>(status);
  }

  status = app->OptimizeTNLP(problem);

  if (status == Ipopt::Solve_Succeeded ||
      status == Ipopt::Solved_To_Acceptable_Level) {
    // Retrieve some statistics about the solve
    Ipopt::Index iter_count = app->Statistics()->IterationCount();
    ADEBUG << "*** The problem solved in " << iter_count << " iterations!";

    Ipopt::Number final_obj = app->Statistics()->FinalObjective();
    ADEBUG << "*** The final value of the objective function is " << final_obj
           << '.';
  } else {
    ADEBUG << "Return status: " << int(status);
  }

  ptop->get_optimization_results(ptr_theta, ptr_kappa, ptr_dkappa, ptr_s, ptr_x,
                                 ptr_y);

  return status == Ipopt::Solve_Succeeded ||
         status == Ipopt::Solved_To_Acceptable_Level;
}

std::vector<common::PathPoint> SpiralReferenceLineSmoother::Interpolate(
    const std::vector<double>& theta, const std::vector<double>& kappa,
    const std::vector<double>& dkappa, const std::vector<double>& s,
    const std::vector<double>& x, const std::vector<double>& y,
    const double resolution) const {
  std::vector<common::PathPoint> smoothed_point2d;
  double start_s = 0.0;
  common::PathPoint first_point =
      to_path_point(x.front(), y.front(), start_s, theta.front(), kappa.front(),
                    dkappa.front());
  smoothed_point2d.push_back(first_point);

  for (std::size_t i = 0; i + 1 < theta.size(); ++i) {
    double start_x = x[i];
    double start_y = y[i];

    auto path_point_seg = Interpolate(
        start_x, start_y, start_s, theta[i], kappa[i], dkappa[i], theta[i + 1],
        kappa[i + 1], dkappa[i + 1], s[i], resolution);

    smoothed_point2d.insert(smoothed_point2d.end(), path_point_seg.begin(),
                            path_point_seg.end());

    start_s = smoothed_point2d.back().s();
  }
  return smoothed_point2d;
}

std::vector<common::PathPoint> SpiralReferenceLineSmoother::Interpolate(
    const double start_x, const double start_y, const double start_s,
    const double theta0, const double kappa0, const double dkappa0,
    const double theta1, const double kappa1, const double dkappa1,
    const double delta_s, const double resolution) const {
  std::vector<common::PathPoint> path_points;

  QuinticSpiralPath spiral_curve(theta0, kappa0, dkappa0, theta1, kappa1,
                                 dkappa1, delta_s);
  std::size_t num_of_points = std::ceil(delta_s / resolution) + 1;
  for (std::size_t i = 1; i <= num_of_points; ++i) {
    const double inter_s = delta_s / num_of_points * i;
    const double dx = spiral_curve.ComputeCartesianDeviationX<10>(inter_s);
    const double dy = spiral_curve.ComputeCartesianDeviationY<10>(inter_s);

    const double theta =
        common::math::NormalizeAngle(spiral_curve.Evaluate(0, inter_s));
    const double kappa = spiral_curve.Evaluate(1, inter_s);
    const double dkappa = spiral_curve.Evaluate(2, inter_s);

    auto path_point = to_path_point(start_x + dx, start_y + dy,
                                    start_s + inter_s, theta, kappa, dkappa);
    path_points.push_back(std::move(path_point));
  }
  return path_points;
}

common::PathPoint SpiralReferenceLineSmoother::to_path_point(
    const double x, const double y, const double s, const double theta,
    const double kappa, const double dkappa) const {
  common::PathPoint point;
  point.set_x(x);
  point.set_y(y);
  point.set_s(s);
  point.set_theta(theta);
  point.set_kappa(kappa);
  point.set_dkappa(dkappa);
  return point;
}

void SpiralReferenceLineSmoother::SetAnchorPoints(
    const std::vector<AnchorPoint>& anchor_points) {
  anchor_points_ = std::move(anchor_points);

  CHECK_GT(anchor_points_.size(), 1);
  zero_x_ = anchor_points_.front().path_point.x();
  zero_y_ = anchor_points_.front().path_point.y();

  std::for_each(anchor_points_.begin(), anchor_points_.end(),
      [this](AnchorPoint& p) {
        auto curr_x = p.path_point.x();
        auto curr_y = p.path_point.y();
        p.path_point.set_x(curr_x - zero_x_);
        p.path_point.set_y(curr_y - zero_y_);});
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: bug fix for spiral reference line smoother to determine starting constrained anchor point<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo 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.
 *****************************************************************************/

/*
 * spiral_reference_line_smoother.cc
 */

#include "modules/planning/reference_line/spiral_reference_line_smoother.h"

#include <algorithm>
#include <iomanip>
#include <utility>

#include "IpIpoptApplication.hpp"
#include "IpSolveStatistics.hpp"
#include "glog/logging.h"

#include "modules/common/time/time.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/curve1d/quintic_spiral_path.h"
#include "modules/planning/reference_line/spiral_problem_interface.h"

namespace apollo {
namespace planning {

using apollo::common::time::Clock;

SpiralReferenceLineSmoother::SpiralReferenceLineSmoother(
    const double max_point_deviation)
    : default_max_point_deviation_(max_point_deviation) {
  CHECK(max_point_deviation >= 0.0);
}

bool SpiralReferenceLineSmoother::Smooth(
    const ReferenceLine& raw_reference_line,
    ReferenceLine* const smoothed_reference_line) {
  const double start_timestamp = Clock::NowInSecond();
  std::vector<double> opt_x;
  std::vector<double> opt_y;
  std::vector<double> opt_theta;
  std::vector<double> opt_kappa;
  std::vector<double> opt_dkappa;
  std::vector<double> opt_s;

  if (anchor_points_.empty()) {
    const double piecewise_length = FLAGS_spiral_smoother_piecewise_length;
    const double length = raw_reference_line.Length();
    ADEBUG << "Length = " << length;
    uint32_t num_of_pieces =
        std::max(1u, static_cast<uint32_t>(length / piecewise_length));

    const double delta_s = length / num_of_pieces;
    double s = 0.0;

    std::vector<Eigen::Vector2d> raw_point2d;
    for (std::uint32_t i = 0; i <= num_of_pieces;
         ++i, s = std::fmin(s + delta_s, length)) {
      ReferencePoint rlp = raw_reference_line.GetReferencePoint(s);
      raw_point2d.emplace_back(rlp.x(), rlp.y());
    }

    Smooth(raw_point2d, &opt_theta, &opt_kappa, &opt_dkappa, &opt_s, &opt_x,
           &opt_y);
  } else {
    std::size_t start_index = 0;
    for (const auto& anchor_point : anchor_points_) {
      if (anchor_point.enforced) {
        start_index++;
      } else {
        break;
      }
    }

    std::vector<Eigen::Vector2d> raw_point2d;
    if (start_index == 0) {
      for (const auto& anchor_point : anchor_points_) {
        raw_point2d.emplace_back(anchor_point.path_point.x(),
                                 anchor_point.path_point.y());
      }
    } else {
      std::vector<double> overhead_s;
      for (std::size_t i = 0; i + 1 < start_index; ++i) {
        const auto& p0 = anchor_points_[i];
        const auto& p1 = anchor_points_[i + 1];
        overhead_s.push_back(p1.path_point.s() - p0.path_point.s());
      }

      std::vector<double> overhead_theta;
      std::vector<double> overhead_kappa;
      std::vector<double> overhead_dkappa;
      std::vector<double> overhead_x;
      std::vector<double> overhead_y;
      for (std::size_t i = 0; i < anchor_points_.size(); ++i) {
        const auto& p = anchor_points_[i];
        if (i + 1 < start_index) {
          overhead_theta.push_back(p.path_point.theta());
          overhead_kappa.push_back(p.path_point.kappa());
          overhead_dkappa.push_back(p.path_point.dkappa());
          overhead_x.push_back(p.path_point.x());
          overhead_y.push_back(p.path_point.y());
        } else {
          raw_point2d.emplace_back(p.path_point.x(), p.path_point.y());
        }
      }

      fixed_start_point_ = true;
      fixed_start_x_ = anchor_points_[start_index - 1].path_point.x();
      fixed_start_y_ = anchor_points_[start_index - 1].path_point.y();
      fixed_start_theta_ = common::math::NormalizeAngle(
          anchor_points_[start_index - 1].path_point.theta());
      fixed_start_kappa_ = anchor_points_[start_index - 1].path_point.kappa();
      fixed_start_dkappa_ = anchor_points_[start_index - 1].path_point.dkappa();

      Smooth(raw_point2d, &opt_theta, &opt_kappa, &opt_dkappa, &opt_s, &opt_x,
             &opt_y);

      opt_theta.insert(opt_theta.begin(), overhead_theta.begin(),
                       overhead_theta.end());
      opt_kappa.insert(opt_kappa.begin(), overhead_kappa.begin(),
                       overhead_kappa.end());
      opt_dkappa.insert(opt_dkappa.begin(), overhead_dkappa.begin(),
                        overhead_dkappa.end());
      opt_s.insert(opt_s.begin(), overhead_s.begin(), overhead_s.end());
      opt_x.insert(opt_x.begin(), overhead_x.begin(), overhead_x.end());
      opt_y.insert(opt_y.begin(), overhead_y.begin(), overhead_y.end());

      std::for_each(opt_x.begin(), opt_x.end(), [this](double& x){
        x += zero_x_;
      });

      std::for_each(opt_y.begin(), opt_y.end(), [this](double& y){
        y += zero_y_;
      });
    }
  }

  std::vector<common::PathPoint> smoothed_point2d =
      Interpolate(opt_theta, opt_kappa, opt_dkappa, opt_s, opt_x, opt_y,
                  FLAGS_spiral_reference_line_resolution);

  std::vector<ReferencePoint> ref_points;
  for (const auto& p : smoothed_point2d) {
    const double heading = p.theta();
    const double kappa = p.kappa();
    const double dkappa = p.dkappa();

    common::SLPoint ref_sl_point;
    if (!raw_reference_line.XYToSL({p.x(), p.y()}, &ref_sl_point)) {
      return false;
    }
    if (ref_sl_point.s() < 0 ||
        ref_sl_point.s() > raw_reference_line.Length()) {
      continue;
    }

    ReferencePoint rlp = raw_reference_line.GetReferencePoint(ref_sl_point.s());
    ref_points.emplace_back(
        ReferencePoint(hdmap::MapPathPoint(common::math::Vec2d(p.x(), p.y()),
                                           heading, rlp.lane_waypoints()),
                       kappa, dkappa, 0.0, 0.0));
  }

  ReferencePoint::RemoveDuplicates(&ref_points);
  if (ref_points.size() < 2) {
    AERROR << "Fail to generate smoothed reference line.";
    return false;
  }
  *smoothed_reference_line = ReferenceLine(ref_points);
  const double end_timestamp = Clock::NowInSecond();
  ADEBUG << "Spiral reference line smoother time: "
         << (end_timestamp - start_timestamp) * 1000 << " ms.";
  return true;
}

bool SpiralReferenceLineSmoother::Smooth(std::vector<Eigen::Vector2d> point2d,
                                         std::vector<double>* ptr_theta,
                                         std::vector<double>* ptr_kappa,
                                         std::vector<double>* ptr_dkappa,
                                         std::vector<double>* ptr_s,
                                         std::vector<double>* ptr_x,
                                         std::vector<double>* ptr_y) const {
  CHECK_GT(point2d.size(), 1);

  SpiralProblemInterface* ptop = new SpiralProblemInterface(point2d);
  ptop->set_default_max_point_deviation(default_max_point_deviation_);
  if (fixed_start_point_) {
    ptop->set_start_point(fixed_start_x_, fixed_start_y_, fixed_start_theta_,
                          fixed_start_kappa_, fixed_start_dkappa_);
  }

  Ipopt::SmartPtr<Ipopt::TNLP> problem = ptop;

  // Create an instance of the IpoptApplication
  Ipopt::SmartPtr<Ipopt::IpoptApplication> app = IpoptApplicationFactory();

  //  app->Options()->SetStringValue("jacobian_approximation",
  //  "finite-difference-values");
  app->Options()->SetStringValue("hessian_approximation", "limited-memory");
  //  app->Options()->SetStringValue("derivative_test", "first-order");
  //  app->Options()->SetNumericValue("derivative_test_perturbation", 1.0e-7);
  //  app->Options()->SetStringValue("derivative_test", "second-order");
  app->Options()->SetIntegerValue("print_level", 0);
  int num_iterations = FLAGS_spiral_smoother_num_iteration;
  app->Options()->SetIntegerValue("max_iter", num_iterations);

  //  app->Options()->SetNumericValue("acceptable_tol", 0.5);
  //  app->Options()->SetNumericValue("acceptable_obj_change_tol", 0.5);
  //  app->Options()->SetNumericValue("constr_viol_tol", 0.01);
  //  app->Options()->SetIntegerValue("acceptable_iter", 10);
  //  app->Options()->SetIntegerValue("print_level", 0);
  //  app->Options()->SetStringValue("fast_step_computation", "yes");

  Ipopt::ApplicationReturnStatus status = app->Initialize();
  if (status != Ipopt::Solve_Succeeded) {
    ADEBUG << "*** Error during initialization!";
    return static_cast<int>(status);
  }

  status = app->OptimizeTNLP(problem);

  if (status == Ipopt::Solve_Succeeded ||
      status == Ipopt::Solved_To_Acceptable_Level) {
    // Retrieve some statistics about the solve
    Ipopt::Index iter_count = app->Statistics()->IterationCount();
    ADEBUG << "*** The problem solved in " << iter_count << " iterations!";

    Ipopt::Number final_obj = app->Statistics()->FinalObjective();
    ADEBUG << "*** The final value of the objective function is " << final_obj
           << '.';
  } else {
    ADEBUG << "Return status: " << int(status);
  }

  ptop->get_optimization_results(ptr_theta, ptr_kappa, ptr_dkappa, ptr_s, ptr_x,
                                 ptr_y);

  return status == Ipopt::Solve_Succeeded ||
         status == Ipopt::Solved_To_Acceptable_Level;
}

std::vector<common::PathPoint> SpiralReferenceLineSmoother::Interpolate(
    const std::vector<double>& theta, const std::vector<double>& kappa,
    const std::vector<double>& dkappa, const std::vector<double>& s,
    const std::vector<double>& x, const std::vector<double>& y,
    const double resolution) const {
  std::vector<common::PathPoint> smoothed_point2d;
  double start_s = 0.0;
  common::PathPoint first_point =
      to_path_point(x.front(), y.front(), start_s, theta.front(), kappa.front(),
                    dkappa.front());
  smoothed_point2d.push_back(first_point);

  for (std::size_t i = 0; i + 1 < theta.size(); ++i) {
    double start_x = x[i];
    double start_y = y[i];

    auto path_point_seg = Interpolate(
        start_x, start_y, start_s, theta[i], kappa[i], dkappa[i], theta[i + 1],
        kappa[i + 1], dkappa[i + 1], s[i], resolution);

    smoothed_point2d.insert(smoothed_point2d.end(), path_point_seg.begin(),
                            path_point_seg.end());

    start_s = smoothed_point2d.back().s();
  }
  return smoothed_point2d;
}

std::vector<common::PathPoint> SpiralReferenceLineSmoother::Interpolate(
    const double start_x, const double start_y, const double start_s,
    const double theta0, const double kappa0, const double dkappa0,
    const double theta1, const double kappa1, const double dkappa1,
    const double delta_s, const double resolution) const {
  std::vector<common::PathPoint> path_points;

  QuinticSpiralPath spiral_curve(theta0, kappa0, dkappa0, theta1, kappa1,
                                 dkappa1, delta_s);
  std::size_t num_of_points = std::ceil(delta_s / resolution) + 1;
  for (std::size_t i = 1; i <= num_of_points; ++i) {
    const double inter_s = delta_s / num_of_points * i;
    const double dx = spiral_curve.ComputeCartesianDeviationX<10>(inter_s);
    const double dy = spiral_curve.ComputeCartesianDeviationY<10>(inter_s);

    const double theta =
        common::math::NormalizeAngle(spiral_curve.Evaluate(0, inter_s));
    const double kappa = spiral_curve.Evaluate(1, inter_s);
    const double dkappa = spiral_curve.Evaluate(2, inter_s);

    auto path_point = to_path_point(start_x + dx, start_y + dy,
                                    start_s + inter_s, theta, kappa, dkappa);
    path_points.push_back(std::move(path_point));
  }
  return path_points;
}

common::PathPoint SpiralReferenceLineSmoother::to_path_point(
    const double x, const double y, const double s, const double theta,
    const double kappa, const double dkappa) const {
  common::PathPoint point;
  point.set_x(x);
  point.set_y(y);
  point.set_s(s);
  point.set_theta(theta);
  point.set_kappa(kappa);
  point.set_dkappa(dkappa);
  return point;
}

void SpiralReferenceLineSmoother::SetAnchorPoints(
    const std::vector<AnchorPoint>& anchor_points) {
  anchor_points_ = std::move(anchor_points);

  CHECK_GT(anchor_points_.size(), 1);
  zero_x_ = anchor_points_.front().path_point.x();
  zero_y_ = anchor_points_.front().path_point.y();

  std::for_each(anchor_points_.begin(), anchor_points_.end(),
      [this](AnchorPoint& p) {
        auto curr_x = p.path_point.x();
        auto curr_y = p.path_point.y();
        p.path_point.set_x(curr_x - zero_x_);
        p.path_point.set_y(curr_y - zero_y_);});
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>#include <stan/math/prim/scal/fun/squared_distance.hpp>
#include <gtest/gtest.h>
#include <stan/math/rev/core.hpp>
#include <stan/math/rev/scal/fun/value_of.hpp>
#include <stan/math/rev/scal/fun/value_of_rec.hpp>

TEST(MathRev, squared_distance) {
  double x1 = 1;
  double x2 = 4;
  stan::math::var v1, v2, f;
  std::vector<stan::math::var> vars;
  std::vector<double> grad_f;

  v1 = 1;
  v2 = 4;
  vars.push_back(v1);
  vars.push_back(v2);
  f = stan::math::squared_distance(v1, v2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(2, grad_f.size());
  EXPECT_FLOAT_EQ(-6, grad_f[0]);
  EXPECT_FLOAT_EQ(6, grad_f[1]);
  stan::math::set_zero_all_adjoints();
  vars.clear();

  v1 = 1;
  vars.push_back(v1);
  f = stan::math::squared_distance(v1, x2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(1, grad_f.size());
  EXPECT_FLOAT_EQ(-6, grad_f[0]);
  stan::math::set_zero_all_adjoints();
  vars.clear();

  v2 = 4;
  vars.push_back(v2);
  f = stan::math::squared_distance(x1, v2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(1, grad_f.size());
  EXPECT_FLOAT_EQ(6, grad_f[0]);
  stan::math::set_zero_all_adjoints();
  vars.clear();
}

TEST(MathRev, squared_distance_nan) {
  double x = 1;
  stan::math::var x_v = 1;
  double nan = std::numeric_limits<double>::quiet_NaN();
  stan::math::var nan_v = std::numeric_limits<double>::quiet_NaN();

  EXPECT_THROW(stan::math::squared_distance(x_v, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x_v, nan),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, x),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, nan),
               std::domain_error);
}

TEST(MathRev, squared_distance_inf) {
  double x = 1;
  stan::math::var x_v = 1;
  double inf = std::numeric_limits<double>::infinity();
  stan::math::var inf_v = std::numeric_limits<double>::infinity();

  EXPECT_THROW(stan::math::squared_distance(x_v, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x_v, inf),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, x),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, inf),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf, inf_v),
               std::domain_error);
}

<commit_msg>Updating test<commit_after>#include <stan/math/prim/scal/fun/squared_distance.hpp>
#include <gtest/gtest.h>
#include <stan/math/rev/core.hpp>
#include <stan/math/rev/scal/fun/value_of.hpp>
#include <stan/math/rev/scal/fun/value_of_rec.hpp>

TEST(MathRev, squared_distance) {
  double x1 = 1;
  double x2 = 4;
  stan::math::var v1, v2, f;
  std::vector<stan::math::var> vars;
  std::vector<double> grad_f;

  v1 = 1;
  v2 = 4;
  vars.push_back(v1);
  vars.push_back(v2);
  f = stan::math::squared_distance(v1, v2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(2, grad_f.size());
  EXPECT_FLOAT_EQ(-6, grad_f[0]);
  EXPECT_FLOAT_EQ(6, grad_f[1]);
  stan::math::recover_memory();
  vars.clear();

  v1 = 1;
  vars.push_back(v1);
  f = stan::math::squared_distance(v1, x2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(1, grad_f.size());
  EXPECT_FLOAT_EQ(-6, grad_f[0]);
  stan::math::recover_memory();
  vars.clear();

  v2 = 4;
  vars.push_back(v2);
  f = stan::math::squared_distance(x1, v2);
  f.grad(vars, grad_f);

  EXPECT_FLOAT_EQ(9, f.val());
  ASSERT_EQ(1, grad_f.size());
  EXPECT_FLOAT_EQ(6, grad_f[0]);
  stan::math::recover_memory();
  vars.clear();
}

TEST(MathRev, squared_distance_nan) {
  double x = 1;
  stan::math::var x_v = 1;
  double nan = std::numeric_limits<double>::quiet_NaN();
  stan::math::var nan_v = std::numeric_limits<double>::quiet_NaN();

  EXPECT_THROW(stan::math::squared_distance(x_v, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan, nan_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x_v, nan),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, x),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(nan_v, nan),
               std::domain_error);
}

TEST(MathRev, squared_distance_inf) {
  double x = 1;
  stan::math::var x_v = 1;
  double inf = std::numeric_limits<double>::infinity();
  stan::math::var inf_v = std::numeric_limits<double>::infinity();

  EXPECT_THROW(stan::math::squared_distance(x_v, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x_v, inf),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, x),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf_v, inf),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(x, inf_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf, x_v),
               std::domain_error);
  EXPECT_THROW(stan::math::squared_distance(inf, inf_v),
               std::domain_error);
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=4 sts=4 et fdm=marker cms=\ //\ %s

#ifndef INIPHILE_INCLUDE_INPUT_HPP
#define INIPHILE_INCLUDE_INPUT_HPP

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/adapted/std_pair.hpp>

#include "metagram.hpp"

namespace iniphile
{

namespace ascii = boost::spirit::ascii;

using ascii::alnum;
using ascii::alpha;
using ascii::blank;
using ascii::char_;
using ascii::digit;
using ascii::no_case;
using ascii::space;
using ascii::string;

using boost::optional;

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

using qi::lexeme;
using qi::skip;
using qi::eoi;
using qi::eol;
using qi::omit;
using phx::val;
using phx::construct;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;

using qi::on_error;
using qi::fail;

// public type
typedef metagram::config config;

template<class Iter>
struct
grammar
: qi::grammar<Iter, metagram::config()>
{
    template<class T>
    struct my
    {
        typedef qi::rule<Iter, T> rule;
    };

    grammar(std::ostream & erros)
    : grammar::base_type(start)
    { // {{{
        start
            %=  *section
            >>  eoi
        ;
        optionline
            %=  optname
            >   omit[*blank]
            >   '='
            >   omit[*space]
            >   optval
            >   eol
        ;
        section
            %=  headerline
            >   *optionline
        ;
        headerline
            %=  lexeme['[' > sectionname > ']']
            >   eol
        ;
        sectionname %= lexeme[+~char_(']')];
        optname %= bareword;
        optval %= (qstring | bareword) % +blank;

        bareword %= lexeme[+(alnum | char_("-.,_$"))];
        qstring %= lexeme['"' > *~char_('"') > '"'];

        on_error<fail>
        (
            start
          , erros
                << val("Error! Expecting ")
                << _4
                << val(" here: \"")
                << construct<std::string>(_3, _2)
                << val("\"")
                << std::endl
        );

        start.name("start");
        commentline.name("commentline");
        optionline.name("optionline");
        section.name("section");
        headerline.name("headerline");
        sectionname.name("sectionname");
        optname.name("optname");
        optval.name("optval");
        bareword.name("bareword");
        qstring.name("qstring");
        comment.name("comment");
    } // }}}
    typename my<metagram::config()>::rule start;
    typename my<void()>::rule commentline;
    typename my<metagram::assignment()>::rule optionline;
    typename my<metagram::section()>::rule section;
    typename my<metagram::sectionname()>::rule headerline;
    typename my<metagram::sectionname()>::rule sectionname;
    typename my<metagram::optname()>::rule optname;
    typename my<metagram::optval()>::rule optval;
    typename my<metagram::qstring()>::rule qstring;
    typename my<metagram::bareword()>::rule bareword;
    typename my<void()>::rule comment;
};

template<class Iter>
optional<metagram::config>
parse(Iter & first, Iter last, std::ostream & erros) // {{{
{
    grammar<Iter> g(erros);
    metagram::config cfg;
    optional<metagram::config> rv;
    bool ok = qi::parse(
        first
      , last
      , g
      , cfg
    );
    if (ok && first == last)
        rv = cfg;
    return rv;
} // }}}

} // namespace iniphile

#endif
<commit_msg>sectionname: must not span lines<commit_after>// Copyright (c) 2009 Roman Neuhauser
// Distributed under the MIT license (see LICENSE file)
// vim: sw=4 sts=4 et fdm=marker cms=\ //\ %s

#ifndef INIPHILE_INCLUDE_INPUT_HPP
#define INIPHILE_INCLUDE_INPUT_HPP

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/adapted/std_pair.hpp>

#include "metagram.hpp"

namespace iniphile
{

namespace ascii = boost::spirit::ascii;

using ascii::alnum;
using ascii::alpha;
using ascii::blank;
using ascii::char_;
using ascii::digit;
using ascii::no_case;
using ascii::space;
using ascii::string;

using boost::optional;

namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;

using qi::lexeme;
using qi::skip;
using qi::eoi;
using qi::eol;
using qi::omit;
using phx::val;
using phx::construct;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;

using qi::on_error;
using qi::fail;

// public type
typedef metagram::config config;

template<class Iter>
struct
grammar
: qi::grammar<Iter, metagram::config()>
{
    template<class T>
    struct my
    {
        typedef qi::rule<Iter, T> rule;
    };

    grammar(std::ostream & erros)
    : grammar::base_type(start)
    { // {{{
        start
            %=  *section
            >>  eoi
        ;
        optionline
            %=  optname
            >   omit[*blank]
            >   '='
            >   omit[*space]
            >   optval
            >   eol
        ;
        section
            %=  headerline
            >   *optionline
        ;
        headerline
            %=  lexeme['[' > sectionname > ']']
            >   eol
        ;
        sectionname %= lexeme[+~char_("\n\r]")];
        optname %= bareword;
        optval %= (qstring | bareword) % +blank;

        bareword %= lexeme[+(alnum | char_("-.,_$"))];
        qstring %= lexeme['"' > *~char_('"') > '"'];

        on_error<fail>
        (
            start
          , erros
                << val("Error! Expecting ")
                << _4
                << val(" here: \"")
                << construct<std::string>(_3, _2)
                << val("\"")
                << std::endl
        );

        start.name("start");
        commentline.name("commentline");
        optionline.name("optionline");
        section.name("section");
        headerline.name("headerline");
        sectionname.name("sectionname");
        optname.name("optname");
        optval.name("optval");
        bareword.name("bareword");
        qstring.name("qstring");
        comment.name("comment");
    } // }}}
    typename my<metagram::config()>::rule start;
    typename my<void()>::rule commentline;
    typename my<metagram::assignment()>::rule optionline;
    typename my<metagram::section()>::rule section;
    typename my<metagram::sectionname()>::rule headerline;
    typename my<metagram::sectionname()>::rule sectionname;
    typename my<metagram::optname()>::rule optname;
    typename my<metagram::optval()>::rule optval;
    typename my<metagram::qstring()>::rule qstring;
    typename my<metagram::bareword()>::rule bareword;
    typename my<void()>::rule comment;
};

template<class Iter>
optional<metagram::config>
parse(Iter & first, Iter last, std::ostream & erros) // {{{
{
    grammar<Iter> g(erros);
    metagram::config cfg;
    optional<metagram::config> rv;
    bool ok = qi::parse(
        first
      , last
      , g
      , cfg
    );
    if (ok && first == last)
        rv = cfg;
    return rv;
} // }}}

} // namespace iniphile

#endif
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_
#define _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_  1

#include    "../../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Private {
                namespace   PatchingDataStructures {

                    /*
                    ********************************************************************************
                    ********* PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS> ***********
                    ********************************************************************************
                    */
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableContainerHelper (PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>* rhs, IteratorOwnerID newOwnerID)
                        : inherited (*rhs)
                        , fActiveIteratorsListHead (nullptr)
                    {
                        Require (not HasActiveIterators ());
Again:
                        for (auto v = rhs->fActiveIteratorsListHead; v != nullptr; v = v->fNextActiveIterator) {
                            if (v->fOwnerID == newOwnerID) {
                                // must move it
                                rhs->RemoveIterator (v);
                                this->AddIterator (v);
                                goto Again;
                            }
                        }
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::~PatchableContainerHelper ()
                    {
                        Require (not HasActiveIterators ()); // cannot destroy container with active iterators
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    template <typename ACTUAL_ITERATOR_TYPE>
                    inline  ACTUAL_ITERATOR_TYPE*   PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::GetFirstActiveIterator () const
                    {
                        return static_cast<ACTUAL_ITERATOR_TYPE*> (fActiveIteratorsListHead);
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AssertNoIteratorsReferenceOwner (IteratorOwnerID oBeingDeleted)
                    {
#if     qDebug
                        AssertNoIteratorsReferenceOwner_ (oBeingDeleted);
#endif
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  bool    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::HasActiveIterators () const
                    {
                        return bool (fActiveIteratorsListHead != nullptr);
                    }
#if     qDebug
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AssertNoIteratorsReferenceOwner_ (IteratorOwnerID oBeingDeleted)
                    {
                        for (auto v = fActiveIteratorsListHead; v != nullptr; v = v->fNextActiveIterator) {
                            Assert (v->fOwnerID != oBeingDeleted);
                        }
                    }
#endif
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AddIterator (PatchableIteratorMinIn* pi)
                    {
                        RequireNotNull (pi);
                        Assert (pi->fNextActiveIterator == nullptr);
                        pi->fNextActiveIterator = fActiveIteratorsListHead;
                        fActiveIteratorsListHead = pi;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::RemoveIterator (PatchableIteratorMinIn* pi)
                    {
                        RequireNotNull (pi);
                        if (fActiveIteratorsListHead == pi) {
                            fActiveIteratorsListHead = pi->fNextActiveIterator;
                        }
                        else {
                            PatchableIteratorMinIn*    v = fActiveIteratorsListHead;
                            for (; v->fNextActiveIterator != pi; v = v->fNextActiveIterator) {
                                AssertNotNull (v);
                                AssertNotNull (v->fNextActiveIterator);
                            }
                            AssertNotNull (v);
                            Assert (v->fNextActiveIterator == pi);
                            v->fNextActiveIterator = pi->fNextActiveIterator;
                        }
                        pi->fNextActiveIterator = nullptr;      // unlink
                    }

                    /*
                    ********************************************************************************
                    * PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn *
                    ********************************************************************************
                    */
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    template    <typename ACTUAL_ITERATOR_TYPE>
                    inline  ACTUAL_ITERATOR_TYPE*   PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::GetNextActiveIterator () const
                    {
                        return static_cast<ACTUAL_ITERATOR_TYPE*> (fNextActiveIterator);
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  IteratorOwnerID PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::GetOwner () const
                    {
                        return fOwnerID;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::PatchableIteratorMinIn (PatchableContainerHelper* containerHelper, IteratorOwnerID ownerID)
                        : fPatchableContainer (containerHelper)
                        , fOwnerID (ownerID)
                        , fNextActiveIterator (containerHelper->fActiveIteratorsListHead)
                    {
                        RequireNotNull (containerHelper);
                        containerHelper->fActiveIteratorsListHead = this;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::PatchableIteratorMinIn (const PatchableIteratorMinIn& from)
                        : fPatchableContainer (from.fPatchableContainer)
                        , fOwnerID (from.fOwnerID)
                        , fNextActiveIterator (from.fPatchableContainer->fActiveIteratorsListHead)
                    {
                        RequireNotNull (fPatchableContainer);
                        fPatchableContainer->fActiveIteratorsListHead = this;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::~PatchableIteratorMinIn ()
                    {
                        AssertNotNull (fPatchableContainer);
                        fPatchableContainer->RemoveIterator (this);
                    }

                }
            }
        }
    }
}
#endif /* _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_ */
<commit_msg>Assertions and disable new movement of iterators feature in PatchableContainerHelper.inl to stablize recent changes and amke sure no regressions except that<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#ifndef _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_
#define _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_  1

#include    "../../../Debug/Assertions.h"

namespace   Stroika {
    namespace   Foundation {
        namespace   Containers {
            namespace   Private {
                namespace   PatchingDataStructures {

                    /*
                    ********************************************************************************
                    ********* PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS> ***********
                    ********************************************************************************
                    */
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableContainerHelper (PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>* rhs, IteratorOwnerID newOwnerID)
                        : inherited (*rhs)
                        , fActiveIteratorsListHead (nullptr)
                    {
                        Require (not HasActiveIterators ());
#if 0
                        // See if this is buggy...
Again:
                        for (auto v = rhs->fActiveIteratorsListHead; v != nullptr; v = v->fNextActiveIterator) {
                            if (v->fOwnerID == newOwnerID) {
                                // must move it
                                rhs->RemoveIterator (v);
                                this->AddIterator (v);
                                goto Again;
                            }
                        }
#endif
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::~PatchableContainerHelper ()
                    {
                        Require (not HasActiveIterators ()); // cannot destroy container with active iterators
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    template <typename ACTUAL_ITERATOR_TYPE>
                    inline  ACTUAL_ITERATOR_TYPE*   PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::GetFirstActiveIterator () const
                    {
                        return static_cast<ACTUAL_ITERATOR_TYPE*> (fActiveIteratorsListHead);
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AssertNoIteratorsReferenceOwner (IteratorOwnerID oBeingDeleted)
                    {
#if     qDebug
                        AssertNoIteratorsReferenceOwner_ (oBeingDeleted);
#endif
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  bool    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::HasActiveIterators () const
                    {
                        return bool (fActiveIteratorsListHead != nullptr);
                    }
#if     qDebug
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AssertNoIteratorsReferenceOwner_ (IteratorOwnerID oBeingDeleted)
                    {
                        for (auto v = fActiveIteratorsListHead; v != nullptr; v = v->fNextActiveIterator) {
                            Assert (v->fOwnerID != oBeingDeleted);
                        }
                    }
#endif
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::AddIterator (PatchableIteratorMinIn* pi)
                    {
                        RequireNotNull (pi);
                        Assert (pi->fNextActiveIterator == nullptr);
                        pi->fNextActiveIterator = fActiveIteratorsListHead;
                        fActiveIteratorsListHead = pi;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  void    PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::RemoveIterator (PatchableIteratorMinIn* pi)
                    {
                        RequireNotNull (pi);
                        if (fActiveIteratorsListHead == pi) {
                            fActiveIteratorsListHead = pi->fNextActiveIterator;
                        }
                        else {
                            PatchableIteratorMinIn*    v = fActiveIteratorsListHead;
                            for (; v->fNextActiveIterator != pi; v = v->fNextActiveIterator) {
                                AssertNotNull (v);
                                AssertNotNull (v->fNextActiveIterator);
                            }
                            AssertNotNull (v);
                            Assert (v->fNextActiveIterator == pi);
                            v->fNextActiveIterator = pi->fNextActiveIterator;
                        }
                        pi->fNextActiveIterator = nullptr;      // unlink
                    }

                    /*
                    ********************************************************************************
                    * PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn *
                    ********************************************************************************
                    */
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    template    <typename ACTUAL_ITERATOR_TYPE>
                    inline  ACTUAL_ITERATOR_TYPE*   PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::GetNextActiveIterator () const
                    {
                        return static_cast<ACTUAL_ITERATOR_TYPE*> (fNextActiveIterator);
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  IteratorOwnerID PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::GetOwner () const
                    {
                        return fOwnerID;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::PatchableIteratorMinIn (PatchableContainerHelper* containerHelper, IteratorOwnerID ownerID)
                        : fPatchableContainer (containerHelper)
                        , fOwnerID (ownerID)
                        , fNextActiveIterator (containerHelper->fActiveIteratorsListHead)
                    {
                        RequireNotNull (containerHelper);
                        containerHelper->fActiveIteratorsListHead = this;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::PatchableIteratorMinIn (const PatchableIteratorMinIn& from)
                        : fPatchableContainer (from.fPatchableContainer)
                        , fOwnerID (from.fOwnerID)
                        , fNextActiveIterator (from.fPatchableContainer->fActiveIteratorsListHead)
                    {
                        RequireNotNull (fPatchableContainer);
                        fPatchableContainer->fActiveIteratorsListHead = this;
                    }
                    template    <typename NON_PATCHED_DATA_STRUCTURE_CLASS>
                    inline  PatchableContainerHelper<NON_PATCHED_DATA_STRUCTURE_CLASS>::PatchableIteratorMinIn::~PatchableIteratorMinIn ()
                    {
                        AssertNotNull (fPatchableContainer);
                        fPatchableContainer->RemoveIterator (this);
                        Assert (fNextActiveIterator == nullptr);
                        // could assert owner  - fPatchableContainer - doenst contian us in list
                    }

                }
            }
        }
    }
}
#endif /* _Stroika_Foundation_Containers_Private_PatchingDataStructures_PatchableContainerHelper_inl_ */
<|endoftext|>


<commit_before>/*

Copyright (c) 2012, Arvid Norberg
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 the author 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.

*/

#include "libtorrent/policy.hpp"
#include "libtorrent/hasher.hpp"

#include "test.hpp"

using namespace libtorrent;

boost::uint32_t hash_buffer(char const* buf, int len)
{
	hasher h;
	h.update(buf, len);
	sha1_hash digest = h.final();
	boost::uint32_t ret;
	memcpy(&ret, &digest[0], 4);
	return ntohl(ret);
}

int test_main()
{

	// when the IP is the same, we hash the ports, sorted
	boost::uint32_t p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.3"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

	// when we're in the same /24, we just hash the IPs
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x7b\x01\xe6\x0c\x7b\x03", 8));

	// when we're in the same /16, we just hash the IPs masked by
	// 0xffffff55
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x17\x01\xe6\x0c\x7b\x01", 8));

	// when we're in different /16, we just hash the IPs masked by
	// 0xffff5555
	p = peer_priority(
		tcp::endpoint(address::from_string("230.120.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x51\x01\xe6\x78\x15\x01", 8));

	// IPv6 has a twice as wide mask, and we only care about the top 64 bits
	// when the IPs are the same, just hash the ports
	p = peer_priority(
		tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
		, tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

	// these IPs don't belong to the same /32, so apply the full mask
	// 0xffffffff55555555
	p = peer_priority(
		tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
		, tcp::endpoint(address::from_string("ffff:0fff:ffff:ffff::1"), 0x12c));
	TEST_EQUAL(p, hash_buffer(
		"\xff\xff\x0f\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01"
		"\xff\xff\xff\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01", 32));

	return 0;
}

<commit_msg>fix test support for platforms not supporting IPv6<commit_after>/*

Copyright (c) 2012, Arvid Norberg
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 the author 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.

*/

#include "libtorrent/policy.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/broadcast_socket.hpp" // for supports_ipv6()

#include "test.hpp"

using namespace libtorrent;

boost::uint32_t hash_buffer(char const* buf, int len)
{
	hasher h;
	h.update(buf, len);
	sha1_hash digest = h.final();
	boost::uint32_t ret;
	memcpy(&ret, &digest[0], 4);
	return ntohl(ret);
}

int test_main()
{

	// when the IP is the same, we hash the ports, sorted
	boost::uint32_t p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.3"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

	// when we're in the same /24, we just hash the IPs
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.123.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x7b\x01\xe6\x0c\x7b\x03", 8));

	// when we're in the same /16, we just hash the IPs masked by
	// 0xffffff55
	p = peer_priority(
		tcp::endpoint(address::from_string("230.12.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x17\x01\xe6\x0c\x7b\x01", 8));

	// when we're in different /16, we just hash the IPs masked by
	// 0xffff5555
	p = peer_priority(
		tcp::endpoint(address::from_string("230.120.23.1"), 0x4d2)
		, tcp::endpoint(address::from_string("230.12.123.3"), 0x12c));
	TEST_EQUAL(p, hash_buffer("\xe6\x0c\x51\x01\xe6\x78\x15\x01", 8));

	if (supports_ipv6())
	{
		// IPv6 has a twice as wide mask, and we only care about the top 64 bits
		// when the IPs are the same, just hash the ports
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer("\x01\x2c\x04\xd2", 4));

		// these IPs don't belong to the same /32, so apply the full mask
		// 0xffffffff55555555
		p = peer_priority(
			tcp::endpoint(address::from_string("ffff:ffff:ffff:ffff::1"), 0x4d2)
			, tcp::endpoint(address::from_string("ffff:0fff:ffff:ffff::1"), 0x12c));
		TEST_EQUAL(p, hash_buffer(
			"\xff\xff\x0f\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01"
			"\xff\xff\xff\xff\x55\x55\x55\x55\x00\x00\x00\x00\x00\x00\x00\x01", 32));
	}

	return 0;
}

<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/web_notification/ash_popup_alignment_delegate.h"

#include "ash/display/display_controller.h"
#include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_types.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "base/i18n/rtl.h"
#include "ui/aura/window.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_popup_collection.h"

namespace ash {

namespace {

const int kToastMarginX = 3;

// If there should be no margin for the first item, this value needs to be
// substracted to flush the message to the shelf (the width of the border +
// shadow).
const int kNoToastMarginBorderAndShadowOffset = 2;

}

AshPopupAlignmentDelegate::AshPopupAlignmentDelegate()
    : display_id_(gfx::Display::kInvalidDisplayID),
      screen_(NULL),
      root_window_(NULL),
      shelf_(NULL),
      system_tray_height_(0) {
}

AshPopupAlignmentDelegate::~AshPopupAlignmentDelegate() {
  if (screen_)
    screen_->RemoveObserver(this);
  Shell::GetInstance()->RemoveShellObserver(this);
  if (shelf_)
    shelf_->RemoveObserver(this);
}

void AshPopupAlignmentDelegate::StartObserving(gfx::Screen* screen,
                                               const gfx::Display& display) {
  screen_ = screen;
  display_id_ = display.id();
  root_window_ = ash::Shell::GetInstance()->display_controller()->
      GetRootWindowForDisplayId(display_id_);
  UpdateShelf();
  screen->AddObserver(this);
  Shell::GetInstance()->AddShellObserver(this);
  if (system_tray_height_ > 0)
    OnAutoHideStateChanged(shelf_->auto_hide_state());
}

void AshPopupAlignmentDelegate::SetSystemTrayHeight(int height) {
  system_tray_height_ = height;

  // If the shelf is shown during auto-hide state, the distance from the edge
  // should be reduced by the height of shelf's shown height.
  if (shelf_ && shelf_->visibility_state() == SHELF_AUTO_HIDE &&
      shelf_->auto_hide_state() == SHELF_AUTO_HIDE_SHOWN) {
    system_tray_height_ -= kShelfSize - ShelfLayoutManager::kAutoHideSize;
  }

  if (system_tray_height_ > 0)
    system_tray_height_ += message_center::kMarginBetweenItems;
  else
    system_tray_height_ = 0;

  if (!shelf_)
    return;

  DoUpdateIfPossible();
}

int AshPopupAlignmentDelegate::GetToastOriginX(
    const gfx::Rect& toast_bounds) const {
  // In Ash, RTL UI language mirrors the whole ash layout, so the toast
  // widgets should be at the bottom-left instead of bottom right.
  if (base::i18n::IsRTL())
    return work_area_.x() + kToastMarginX;

  if (IsFromLeft())
    return work_area_.x() + kToastMarginX;
  return work_area_.right() - kToastMarginX - toast_bounds.width();
}

int AshPopupAlignmentDelegate::GetBaseLine() const {
  return IsTopDown()
      ? work_area_.y() + kNoToastMarginBorderAndShadowOffset +
        system_tray_height_
      : work_area_.bottom() - kNoToastMarginBorderAndShadowOffset -
        system_tray_height_;
}

int AshPopupAlignmentDelegate::GetWorkAreaBottom() const {
  return work_area_.bottom() - system_tray_height_;
}

bool AshPopupAlignmentDelegate::IsTopDown() const {
  return GetAlignment() == SHELF_ALIGNMENT_TOP;
}

bool AshPopupAlignmentDelegate::IsFromLeft() const {
  return GetAlignment() == SHELF_ALIGNMENT_LEFT;
}

void AshPopupAlignmentDelegate::RecomputeAlignment(
    const gfx::Display& display) {
  // Nothing needs to be done.
}

ShelfAlignment AshPopupAlignmentDelegate::GetAlignment() const {
  return shelf_ ? shelf_->GetAlignment() : SHELF_ALIGNMENT_BOTTOM;
}

void AshPopupAlignmentDelegate::UpdateShelf() {
  if (shelf_)
    return;

  shelf_ = ShelfLayoutManager::ForShelf(root_window_);
  if (shelf_)
    shelf_->AddObserver(this);
}

void AshPopupAlignmentDelegate::OnDisplayWorkAreaInsetsChanged() {
  UpdateShelf();

  work_area_ = Shell::GetScreen()->GetDisplayNearestWindow(
      shelf_->shelf_widget()->GetNativeView()).work_area();
}

void AshPopupAlignmentDelegate::OnAutoHideStateChanged(
    ShelfAutoHideState new_state) {
  work_area_ = Shell::GetScreen()->GetDisplayNearestWindow(
      shelf_->shelf_widget()->GetNativeView()).work_area();
  int width = 0;
  if ((shelf_->visibility_state() == SHELF_AUTO_HIDE) &&
      new_state == SHELF_AUTO_HIDE_SHOWN) {
    // Since the work_area is already reduced by kAutoHideSize, the inset width
    // should be just the difference.
    width = kShelfSize - ShelfLayoutManager::kAutoHideSize;
  }
  work_area_.Inset(shelf_->SelectValueForShelfAlignment(
      gfx::Insets(0, 0, width, 0),
      gfx::Insets(0, width, 0, 0),
      gfx::Insets(0, 0, 0, width),
      gfx::Insets(width, 0, 0, 0)));

  DoUpdateIfPossible();
}

void AshPopupAlignmentDelegate::OnDisplayAdded(
    const gfx::Display& new_display) {
}

void AshPopupAlignmentDelegate::OnDisplayRemoved(
    const gfx::Display& old_display) {
}

void AshPopupAlignmentDelegate::OnDisplayMetricsChanged(
    const gfx::Display& display,
    uint32_t metrics) {
  if (display.id() == display_id_ && shelf_)
    OnAutoHideStateChanged(shelf_->auto_hide_state());
}

}  // namespace ash
<commit_msg>Reset the default work_area when start observing.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/web_notification/ash_popup_alignment_delegate.h"

#include "ash/display/display_controller.h"
#include "ash/shelf/shelf_constants.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_types.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "base/i18n/rtl.h"
#include "ui/aura/window.h"
#include "ui/gfx/display.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_popup_collection.h"

namespace ash {

namespace {

const int kToastMarginX = 3;

// If there should be no margin for the first item, this value needs to be
// substracted to flush the message to the shelf (the width of the border +
// shadow).
const int kNoToastMarginBorderAndShadowOffset = 2;

}

AshPopupAlignmentDelegate::AshPopupAlignmentDelegate()
    : display_id_(gfx::Display::kInvalidDisplayID),
      screen_(NULL),
      root_window_(NULL),
      shelf_(NULL),
      system_tray_height_(0) {
}

AshPopupAlignmentDelegate::~AshPopupAlignmentDelegate() {
  if (screen_)
    screen_->RemoveObserver(this);
  Shell::GetInstance()->RemoveShellObserver(this);
  if (shelf_)
    shelf_->RemoveObserver(this);
}

void AshPopupAlignmentDelegate::StartObserving(gfx::Screen* screen,
                                               const gfx::Display& display) {
  screen_ = screen;
  display_id_ = display.id();
  work_area_ = display.work_area();
  root_window_ = ash::Shell::GetInstance()->display_controller()->
      GetRootWindowForDisplayId(display_id_);
  UpdateShelf();
  screen->AddObserver(this);
  Shell::GetInstance()->AddShellObserver(this);
  if (system_tray_height_ > 0)
    OnAutoHideStateChanged(shelf_->auto_hide_state());
}

void AshPopupAlignmentDelegate::SetSystemTrayHeight(int height) {
  system_tray_height_ = height;

  // If the shelf is shown during auto-hide state, the distance from the edge
  // should be reduced by the height of shelf's shown height.
  if (shelf_ && shelf_->visibility_state() == SHELF_AUTO_HIDE &&
      shelf_->auto_hide_state() == SHELF_AUTO_HIDE_SHOWN) {
    system_tray_height_ -= kShelfSize - ShelfLayoutManager::kAutoHideSize;
  }

  if (system_tray_height_ > 0)
    system_tray_height_ += message_center::kMarginBetweenItems;
  else
    system_tray_height_ = 0;

  if (!shelf_)
    return;

  DoUpdateIfPossible();
}

int AshPopupAlignmentDelegate::GetToastOriginX(
    const gfx::Rect& toast_bounds) const {
  // In Ash, RTL UI language mirrors the whole ash layout, so the toast
  // widgets should be at the bottom-left instead of bottom right.
  if (base::i18n::IsRTL())
    return work_area_.x() + kToastMarginX;

  if (IsFromLeft())
    return work_area_.x() + kToastMarginX;
  return work_area_.right() - kToastMarginX - toast_bounds.width();
}

int AshPopupAlignmentDelegate::GetBaseLine() const {
  return IsTopDown()
      ? work_area_.y() + kNoToastMarginBorderAndShadowOffset +
        system_tray_height_
      : work_area_.bottom() - kNoToastMarginBorderAndShadowOffset -
        system_tray_height_;
}

int AshPopupAlignmentDelegate::GetWorkAreaBottom() const {
  return work_area_.bottom() - system_tray_height_;
}

bool AshPopupAlignmentDelegate::IsTopDown() const {
  return GetAlignment() == SHELF_ALIGNMENT_TOP;
}

bool AshPopupAlignmentDelegate::IsFromLeft() const {
  return GetAlignment() == SHELF_ALIGNMENT_LEFT;
}

void AshPopupAlignmentDelegate::RecomputeAlignment(
    const gfx::Display& display) {
  // Nothing needs to be done.
}

ShelfAlignment AshPopupAlignmentDelegate::GetAlignment() const {
  return shelf_ ? shelf_->GetAlignment() : SHELF_ALIGNMENT_BOTTOM;
}

void AshPopupAlignmentDelegate::UpdateShelf() {
  if (shelf_)
    return;

  shelf_ = ShelfLayoutManager::ForShelf(root_window_);
  if (shelf_)
    shelf_->AddObserver(this);
}

void AshPopupAlignmentDelegate::OnDisplayWorkAreaInsetsChanged() {
  UpdateShelf();

  work_area_ = Shell::GetScreen()->GetDisplayNearestWindow(
      shelf_->shelf_widget()->GetNativeView()).work_area();
}

void AshPopupAlignmentDelegate::OnAutoHideStateChanged(
    ShelfAutoHideState new_state) {
  work_area_ = Shell::GetScreen()->GetDisplayNearestWindow(
      shelf_->shelf_widget()->GetNativeView()).work_area();
  int width = 0;
  if ((shelf_->visibility_state() == SHELF_AUTO_HIDE) &&
      new_state == SHELF_AUTO_HIDE_SHOWN) {
    // Since the work_area is already reduced by kAutoHideSize, the inset width
    // should be just the difference.
    width = kShelfSize - ShelfLayoutManager::kAutoHideSize;
  }
  work_area_.Inset(shelf_->SelectValueForShelfAlignment(
      gfx::Insets(0, 0, width, 0),
      gfx::Insets(0, width, 0, 0),
      gfx::Insets(0, 0, 0, width),
      gfx::Insets(width, 0, 0, 0)));

  DoUpdateIfPossible();
}

void AshPopupAlignmentDelegate::OnDisplayAdded(
    const gfx::Display& new_display) {
}

void AshPopupAlignmentDelegate::OnDisplayRemoved(
    const gfx::Display& old_display) {
}

void AshPopupAlignmentDelegate::OnDisplayMetricsChanged(
    const gfx::Display& display,
    uint32_t metrics) {
  if (display.id() == display_id_ && shelf_)
    OnAutoHideStateChanged(shelf_->auto_hide_state());
}

}  // namespace ash
<|endoftext|>


<commit_before>// https://oj.leetcode.com/problems/maximum-subarray/
namespace MaximumSubarray {
    class Solution {
    public:
        int maxSubArray(int A[], int n) {

            int sum = 0;
            int max = INT_MIN;
            for (int i = 0; i < n; i++) {

                if (sum < 0) {
                    sum = A[i];
                } else {
                    sum += A[i];
                }

                if (sum > max) {
                    max = sum;
                }
            }

            return max;

        }
    };
}
<commit_msg>Update MaximumSubarray.cc<commit_after>// https://oj.leetcode.com/problems/maximum-subarray/
namespace MaximumSubarray {
    // O(n) solution
    class Solution {
    public:
        int maxSubArray(int A[], int n) {

            int sum = 0;
            int max = INT_MIN;
            for (int i = 0; i < n; i++) {

                if (sum < 0) {
                    sum = A[i];
                } else {
                    sum += A[i];
                }

                if (sum > max) {
                    max = sum;
                }
            }

            return max;

        }
    };

    // Divide & Conquer Solution, O(nLog(n))
    class Solution1 {
    public:
        int maxCrossSubArray(int A[], int left, int mid, int right) {
            int maxLeftSum = INT_MIN;
            int maxRightSum = INT_MIN;

            // calc left sum
            int sum = 0;
            for (int i = mid; i >= left; i--) {
                sum += A[i];
                if (sum > maxLeftSum) {
                    maxLeftSum = sum;
                }
            }

            // calc right sum
            sum = 0;
            for (int i = mid + 1; i <= right; i++) {
                sum += A[i];
                if (sum > maxRightSum) {
                    maxRightSum = sum;
                }
            }

            return maxLeftSum + maxRightSum;
        }

        int maxOneSideSubArray(int A[], int left, int right) {
            if (left == right) {
                return A[left];
            }

            int mid = (left + right) / 2;

            return max(maxCrossSubArray(A, left, mid, right),
                    max(maxOneSideSubArray(A, left, mid), maxOneSideSubArray(A, mid + 1, right)));
        }

        int maxSubArray(int A[], int n) {
            if (n == 0) {
                return 0;
            }

            return maxOneSideSubArray(A, 0, n - 1);
        }
    };
}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     test_fiff_anonymize.cpp
* @author   Lorenz Esch <lorenzesch@hotmail.com>;
* @version  1.0
* @date     September, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Lorenz Esch. 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 MNE-CPP authors 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.
*
*
* @brief    Test for anonymizing a fiff raw file
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fiff/fiff.h>

#include <iostream>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>
#include <QProcess>
#include <QScopedPointer>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffAnonyimze
*
* @brief The TestFiffAnonyimze class provides fiff anonymizing verification tests
*
*/
class TestFiffAnonyimze: public QObject
{
    Q_OBJECT

public:
    TestFiffAnonyimze();

private slots:
    void initTestCase();
    void compareData();
    void cleanupTestCase();

private:
    double epsilon;
    MatrixXd second_in_times;
};

//*************************************************************************************************************

TestFiffAnonyimze::TestFiffAnonyimze()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffAnonyimze::initTestCase()
{
    qInfo() << "TestFiffAnonyimze::initTestCase - Epsilon" << epsilon;

    // Init testing arguments
    QString sFileIn("/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif");
    QString sFileOut("/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short_anonymized.fif");

    qInfo() << "TestFiffAnonyimze::initTestCase - sFileIn" << sFileIn;
    qInfo() << "TestFiffAnonyimze::initTestCase - sFileOut" << sFileOut;

    QString program = "./mne_anonymize";
    QStringList arguments;
    arguments << "--in" << sFileIn;
    arguments << "--out" << sFileOut;

    // Pass arguments to application and anaonyimze the fiff file
    QScopedPointer<QProcess> myProcess (new QProcess);
    myProcess->start(program, arguments);
    myProcess->waitForFinished();
}

//*************************************************************************************************************

void TestFiffAnonyimze::compareData()
{
    // Open ./mne-cpp-test-data/MEG/sample/sample_audvis_raw_anonymized.fif

    // ToDo: Implement function which reads sensitive tags and checks if they were anaonymized. Use Q_VERIFY().
}

//*************************************************************************************************************

void TestFiffAnonyimze::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestFiffAnonyimze)
#include "test_fiff_anonymize.moc"
<commit_msg>Rename TestFiffAnonymize and remove second_in_times<commit_after>//=============================================================================================================
/**
* @file     test_fiff_anonymize.cpp
* @author   Lorenz Esch <lorenzesch@hotmail.com>;
* @version  1.0
* @date     September, 2019
*
* @section  LICENSE
*
* Copyright (C) 2019, Lorenz Esch. 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 MNE-CPP authors 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.
*
*
* @brief    Test for anonymizing a fiff raw file
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fiff/fiff.h>

#include <iostream>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>
#include <QProcess>
#include <QScopedPointer>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FIFFLIB;

//=============================================================================================================
/**
* DECLARE CLASS TestFiffAnonymize
*
* @brief The TestFiffAnonymize class provides fiff anonymizing verification tests
*
*/
class TestFiffAnonymize: public QObject
{
    Q_OBJECT

public:
    TestFiffAnonymize();

private slots:
    void initTestCase();
    void compareData();
    void cleanupTestCase();

private:
    double epsilon;
};

//*************************************************************************************************************

TestFiffAnonymize::TestFiffAnonymize()
: epsilon(0.000001)
{
}

//*************************************************************************************************************

void TestFiffAnonymize::initTestCase()
{
    qInfo() << "TestFiffAnonymize::initTestCase - Epsilon" << epsilon;

    // Init testing arguments
    QString sFileIn("/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif");
    QString sFileOut("/mne-cpp-test-data/MEG/sample/sample_audvis_raw_short_anonymized.fif");

    qInfo() << "TestFiffAnonymize::initTestCase - sFileIn" << sFileIn;
    qInfo() << "TestFiffAnonymize::initTestCase - sFileOut" << sFileOut;

    QString program = "./mne_anonymize";
    QStringList arguments;
    arguments << "--in" << sFileIn;
    arguments << "--out" << sFileOut;

    // Pass arguments to application and anaonyimze the fiff file
    QScopedPointer<QProcess> myProcess (new QProcess);
    myProcess->start(program, arguments);
    myProcess->waitForFinished();
}

//*************************************************************************************************************

void TestFiffAnonymize::compareData()
{
    // Open ./mne-cpp-test-data/MEG/sample/sample_audvis_raw_anonymized.fif

    // ToDo: Implement function which reads sensitive tags and checks if they were anaonymized. Use Q_VERIFY().
}

//*************************************************************************************************************

void TestFiffAnonymize::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestFiffAnonymize)
#include "test_fiff_anonymize.moc"
<|endoftext|>